summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJoshua Haberman <joshua@reverberate.org>2010-01-05 18:30:36 -0800
committerJoshua Haberman <joshua@reverberate.org>2010-01-05 18:30:36 -0800
commit5864888c6e7424af70d84802b55879f406d2d7b2 (patch)
tree3608dbcc1ef7f34542835221743c8fcbe9e3b128 /src
parentd75197375876538332d6d81aa4e8edd13b8f26c1 (diff)
parent6a8dfa5f26500b90aa9ecab418abba98d1e4e356 (diff)
Merge branch 'data-refactoring'. Ported benchmarks.
Conflicts: src/upb_data.c src/upb_data.h
Diffstat (limited to 'src')
-rw-r--r--src/upb.h16
-rw-r--r--src/upb_data.c81
-rw-r--r--src/upb_data.h104
-rw-r--r--src/upb_def.c39
-rw-r--r--src/upb_text.c2
5 files changed, 137 insertions, 105 deletions
diff --git a/src/upb.h b/src/upb.h
index 2809418..2c0a23d 100644
--- a/src/upb.h
+++ b/src/upb.h
@@ -125,11 +125,10 @@ struct upb_tag {
// INTERNAL-ONLY: never refer to these types with a tag ("union", "struct").
// Always use the typedefs.
-union _upb_array;
struct _upb_msg;
-typedef union _upb_array upb_array;
typedef struct _upb_msg upb_msg;
+
typedef upb_atomic_refcount_t upb_data;
typedef uint32_t upb_strlen_t;
@@ -143,6 +142,15 @@ typedef union {
upb_data *base;
} upb_strptr;
+typedef uint32_t upb_arraylen_t;
+
+typedef union {
+ // Must be first, for the UPB_STATIC_ARRAY_PTR_INIT() macro.
+ struct upb_norefcount_array *norefcount;
+ struct upb_refcounted_array *refcounted;
+ upb_data *base;
+} upb_arrayptr;
+
// A single .proto value. The owner must have an out-of-band way of knowing
// the type, so that it knows which union member to use.
union upb_value {
@@ -154,7 +162,7 @@ union upb_value {
uint64_t uint64;
bool _bool;
upb_strptr str;
- upb_array *arr;
+ upb_arrayptr arr;
upb_msg *msg;
upb_data *data;
};
@@ -171,7 +179,7 @@ union upb_value_ptr {
uint64_t *uint64;
bool *_bool;
upb_strptr *str;
- upb_array **arr;
+ upb_arrayptr *arr;
upb_msg **msg;
upb_data **data;
void *_void;
diff --git a/src/upb_data.c b/src/upb_data.c
index 1bb76aa..a0a588a 100644
--- a/src/upb_data.c
+++ b/src/upb_data.c
@@ -57,11 +57,11 @@ static void check_not_frozen(upb_data *d) {
/* upb_string *******************************************************************/
-static char *_upb_string_setptr(upb_strptr s, char *ptr) {
+void _upb_string_setptr(upb_strptr s, char *ptr) {
if(upb_data_hasflag(s.base, UPB_DATA_REFCOUNTED))
- return s.refcounted->ptr = ptr;
+ s.refcounted->ptr = ptr;
else
- return s.norefcount->ptr = ptr;
+ s.norefcount->ptr = ptr;
}
static void _upb_string_set_bytelen(upb_strptr s, upb_strlen_t newlen) {
@@ -182,64 +182,79 @@ int upb_strcmp(upb_strptr s1, upb_strptr s2) {
/* upb_array ******************************************************************/
-upb_array *upb_array_new() {
- upb_array *a = malloc(sizeof(upb_refcounted_array));
- data_init(&a->common.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
- a->refcounted.size = 0;
- a->common.len = 0;
- a->common.elements._void = NULL;
+static void _upb_array_setptr(upb_arrayptr a, void *ptr) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
+ a.refcounted->elements._void = ptr;
+ else
+ a.norefcount->elements._void = ptr;
+}
+
+static void _upb_array_setlen(upb_arrayptr a, upb_strlen_t newlen) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
+ a.refcounted->len = newlen;
+ } else {
+ a.norefcount->len = newlen;
+ }
+}
+
+upb_arrayptr upb_array_new() {
+ upb_arrayptr a;
+ a.refcounted = malloc(sizeof(struct upb_refcounted_array));
+ data_init(a.base, UPB_DATA_HEAPALLOCATED | UPB_DATA_REFCOUNTED);
+ a.refcounted->size = 0;
+ a.refcounted->len = 0;
+ a.refcounted->elements._void = NULL;
return a;
}
// ONLY handles refcounted arrays for the moment.
-void _upb_array_free(upb_array *a, struct upb_fielddef *f)
+void _upb_array_free(upb_arrayptr a, struct upb_fielddef *f)
{
if(upb_elem_ismm(f)) {
- for(upb_arraylen_t i = 0; i < a->refcounted.size; i++) {
+ for(upb_arraylen_t i = 0; i < a.refcounted->size; i++) {
union upb_value_ptr p = _upb_array_getptr(a, f, i);
if(!*p.data) continue;
data_elem_unref(p, f);
}
}
- if(a->refcounted.size != 0) free(a->common.elements._void);
- free(a);
+ if(a.refcounted->size != 0) free(a.refcounted->elements._void);
+ free(a.refcounted);
}
-static upb_arraylen_t array_get_size(upb_array *a) {
- if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
- return a->refcounted.size;
+static upb_arraylen_t array_get_size(upb_arrayptr a) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
+ return a.refcounted->size;
} else {
- return (a->norefcount.size_and_flags & 0xFFFFFFF8) >> 3;
+ return (a.norefcount->base.v & 0xFFFFFFF8) >> 3;
}
}
-static void array_set_size(upb_array *a, upb_arraylen_t newsize) {
- if(upb_data_hasflag(&a->common.base, UPB_DATA_REFCOUNTED)) {
- a->refcounted.size = newsize;
+static void array_set_size(upb_arrayptr a, upb_arraylen_t newsize) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED)) {
+ a.refcounted->size = newsize;
} else {
- a->norefcount.size_and_flags &= 0x7;
- a->norefcount.size_and_flags |= (newsize << 3);
+ a.norefcount->base.v &= 0x7;
+ a.norefcount->base.v |= (newsize << 3);
}
}
-void upb_array_resize(upb_array *a, struct upb_fielddef *f, upb_strlen_t len) {
- check_not_frozen(&a->common.base);
+void upb_array_resize(upb_arrayptr a, struct upb_fielddef *f, upb_strlen_t len) {
+ check_not_frozen(a.base);
size_t type_size = upb_type_info[f->type].size;
upb_arraylen_t old_size = array_get_size(a);
if(old_size < len) {
// Need to resize.
size_t new_size = round_up_to_pow2(len);
- a->common.elements._void = realloc(a->common.elements._void, new_size * type_size);
+ _upb_array_setptr(a, realloc(_upb_array_getptr_raw(a, 0, 0)._void, new_size * type_size));
array_set_size(a, new_size);
- memset(UPB_INDEX(a->common.elements._void, old_size, type_size),
+ memset(_upb_array_getptr_raw(a, old_size, type_size)._void,
0,
(new_size - old_size) * type_size);
}
- a->common.len = len;
+ _upb_array_setlen(a, len);
}
-
/* upb_msg ********************************************************************/
static void upb_msg_sethas(upb_msg *msg, struct upb_fielddef *f) {
@@ -289,19 +304,15 @@ static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f)
union upb_value_ptr p = _upb_msg_getptr(msg, f);
if(upb_isarray(f)) {
if(!upb_msg_has(msg, f)) {
- if(!*p.arr || !upb_data_only(*p.data)) {
- printf("Initializing array field " UPB_STRFMT "\n", UPB_STRARG(f->name));
- if(*p.arr)
+ if(upb_array_isnull(*p.arr) || !upb_data_only(*p.data)) {
+ if(!upb_array_isnull(*p.arr))
upb_array_unref(*p.arr, f);
*p.arr = upb_array_new();
- } else {
- printf("REUSING array field " UPB_STRFMT "\n", UPB_STRARG(f->name));
}
upb_array_truncate(*p.arr);
upb_msg_sethas(msg, f);
} else {
- printf("APPENDING TO EXISTING array field " UPB_STRFMT "\n", UPB_STRARG(f->name));
- assert(*p.arr);
+ assert(!upb_array_isnull(*p.arr));
}
upb_arraylen_t oldlen = upb_array_len(*p.arr);
upb_array_resize(*p.arr, f, oldlen + 1);
diff --git a/src/upb_data.h b/src/upb_data.h
index 15e87c5..98243ce 100644
--- a/src/upb_data.h
+++ b/src/upb_data.h
@@ -213,9 +213,7 @@ upb_strptr upb_string_getref(upb_strptr s, int ref_flags);
#define UPB_STRING_NULL_INITIALIZER {NULL}
static const upb_strptr UPB_STRING_NULL = UPB_STRING_NULL_INITIALIZER;
-INLINE bool upb_string_isnull(upb_strptr s) {
- return s.base == NULL;
-}
+INLINE bool upb_string_isnull(upb_strptr s) { return s.base == NULL; }
// The caller releases a ref on src, which it must previously have owned a ref
// on.
@@ -350,70 +348,77 @@ typedef struct upb_norefcount_string upb_static_string;
/* upb_array ******************************************************************/
-typedef uint32_t upb_arraylen_t;
-
// The comments attached to upb_string above also apply here.
-typedef struct {
- upb_data base;
- upb_arraylen_t len;
- union upb_value_ptr elements;
-} upb_array_common;
-
-typedef struct {
- uint32_t size_and_flags;
+struct upb_norefcount_array {
+ upb_data base; // We co-opt the refcount for the size.
upb_arraylen_t len;
union upb_value_ptr elements;
-} upb_norefcount_array;
+};
-typedef struct {
+struct upb_refcounted_array {
upb_data base;
upb_arraylen_t len;
union upb_value_ptr elements;
upb_arraylen_t size;
-} upb_refcounted_array;
-
-union _upb_array {
- upb_norefcount_array norefcount;
- upb_array_common common;
- upb_refcounted_array refcounted;
};
-// This type can be used either to perform read-only access on an array,
-// or to statically define a non-reference-counted static array.
-#define UPB_DEFINE_MSG_ARRAY(type) \
-typedef struct type ## _array { \
- upb_data base; \
- upb_arraylen_t len;\
- type **elements; \
-} type ## _array; \
+typedef struct upb_norefcount_array upb_static_array;
+#define UPB_STATIC_ARRAY_INIT(arr, len) {{0 | UPB_DATA_FROZEN}, len, {._void=arr}}
+#define UPB_STATIC_ARRAY_PTR_TYPED_INIT(static_arr) {{&static_arr}}
+
+#define UPB_ARRAY_NULL_INITIALIZER {NULL}
+static const upb_arrayptr UPB_ARRAY_NULL = UPB_ARRAY_NULL_INITIALIZER;
+INLINE bool upb_array_isnull(upb_arrayptr a) { return a.base == NULL; }
+INLINE bool upb_array_ptreql(upb_arrayptr a1, upb_arrayptr a2) {
+ return a1.base == a2.base;
+}
-#define UPB_MSG_ARRAY(type) struct type ## _array
+#define UPB_MSG_ARRAYPTR(type) type ## _array
+#define UPB_DEFINE_MSG_ARRAY(type) \
+typedef struct { upb_arrayptr ptr; } UPB_MSG_ARRAYPTR(type); \
+INLINE upb_arraylen_t type ## _array_len(UPB_MSG_ARRAYPTR(type) a) { \
+ return upb_array_len(a.ptr); \
+} \
+INLINE type* type ## _array_get(UPB_MSG_ARRAYPTR(type) a, upb_arraylen_t elem) { \
+ return *(type**)_upb_array_getptr_raw(a.ptr, elem, sizeof(void*))._void; \
+}
// Constructs a newly-allocated, reference-counted array which starts out
// empty. Caller owns one ref on it.
-upb_array *upb_array_new(void);
+upb_arrayptr upb_array_new(void);
// Returns the current number of elements in the array.
-INLINE size_t upb_array_len(upb_array *a) {
- return a->common.len;
+INLINE size_t upb_array_len(upb_arrayptr a) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
+ return a.refcounted->len;
+ else
+ return a.norefcount->len;
}
// INTERNAL-ONLY:
// Frees the given message and releases references on members.
-void _upb_array_free(upb_array *a, struct upb_fielddef *f);
+void _upb_array_free(upb_arrayptr a, struct upb_fielddef *f);
// INTERNAL-ONLY:
// Returns a pointer to the given elem.
-INLINE union upb_value_ptr _upb_array_getptr(upb_array *a,
- struct upb_fielddef *f,
- upb_arraylen_t elem) {
- size_t type_size = upb_type_info[f->type].size;
+INLINE union upb_value_ptr _upb_array_getptr_raw(upb_arrayptr a,
+ upb_arraylen_t elem,
+ size_t type_size) {
union upb_value_ptr p;
- p._void = &a->common.elements.uint8[elem * type_size];
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
+ p._void = &a.refcounted->elements.uint8[elem * type_size];
+ else
+ p._void = &a.norefcount->elements.uint8[elem * type_size];
return p;
}
-INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
+INLINE union upb_value_ptr _upb_array_getptr(upb_arrayptr a,
+ struct upb_fielddef *f,
+ upb_arraylen_t elem) {
+ return _upb_array_getptr_raw(a, elem, upb_type_info[f->type].size);
+}
+
+INLINE union upb_value upb_array_get(upb_arrayptr a, struct upb_fielddef *f,
upb_arraylen_t elem) {
assert(elem < upb_array_len(a));
return upb_value_read(_upb_array_getptr(a, f, elem), f->type);
@@ -421,33 +426,36 @@ INLINE union upb_value upb_array_get(upb_array *a, struct upb_fielddef *f,
// The caller releases a ref on the given array, which it must previously have
// owned a ref on.
-INLINE void upb_array_unref(upb_array *a, struct upb_fielddef *f) {
- if(_upb_data_unref(&a->common.base)) _upb_array_free(a, f);
+INLINE void upb_array_unref(upb_arrayptr a, struct upb_fielddef *f) {
+ if(_upb_data_unref(a.base)) _upb_array_free(a, f);
}
#if 0
// Returns an array to which caller owns a ref, and contains the same contents
// as src. The returned value may be a copy of src, if the requested flags
// were incompatible with src's.
-INLINE upb_array *upb_array_getref(upb_array *src, int ref_flags);
+INLINE upb_arrayptr upb_array_getref(upb_arrayptr src, int ref_flags);
// Sets the given element in the array to val. The current length of the array
// must be greater than elem. If the field type is dynamic, the array will
// take a ref on val and release a ref on what was previously in the array.
-INLINE void upb_array_set(upb_array *a, struct upb_fielddef *f, int elem,
+INLINE void upb_array_set(upb_arrayptr a, struct upb_fielddef *f, int elem,
union upb_value val);
// Note that array_append will attempt to take a reference on the given value,
// so to avoid a copy use append_default and get.
-INLINE void upb_array_append(upb_array *a, struct upb_fielddef *f,
+INLINE void upb_array_append(upb_arrayptr a, struct upb_fielddef *f,
union upb_value val);
-INLINE void upb_array_append_default(upb_array *a, struct upb_fielddef *f,
+INLINE void upb_array_append_default(upb_arrayptr a, struct upb_fielddef *f,
union upb_value val);
#endif
-INLINE void upb_array_truncate(upb_array *a) {
- a->common.len = 0;
+INLINE void upb_array_truncate(upb_arrayptr a) {
+ if(upb_data_hasflag(a.base, UPB_DATA_REFCOUNTED))
+ a.refcounted->len = 0;
+ else
+ a.norefcount->len = 0;
}
diff --git a/src/upb_def.c b/src/upb_def.c
index 4f57407..24a57a6 100644
--- a/src/upb_def.c
+++ b/src/upb_def.c
@@ -364,12 +364,14 @@ static struct upb_enumdef *enumdef_new(google_protobuf_EnumDescriptorProto *ed,
{
struct upb_enumdef *e = malloc(sizeof(*e));
upb_def_init(&e->base, UPB_DEF_ENUM, fqname);
- int num_values = ed->set_flags.has.value ? ed->value->len : 0;
+ int num_values = ed->set_flags.has.value ?
+ google_protobuf_EnumValueDescriptorProto_array_len(ed->value) : 0;
upb_strtable_init(&e->ntoi, num_values, sizeof(struct ntoi_ent));
upb_inttable_init(&e->iton, num_values, sizeof(struct iton_ent));
for(int i = 0; i < num_values; i++) {
- google_protobuf_EnumValueDescriptorProto *value = ed->value->elements[i];
+ google_protobuf_EnumValueDescriptorProto *value =
+ google_protobuf_EnumValueDescriptorProto_array_get(ed->value, i);
struct ntoi_ent ntoi_ent = {{value->name, 0}, value->number};
struct iton_ent iton_ent = {{value->number, 0}, value->name};
upb_strtable_insert(&e->ntoi, &ntoi_ent.e);
@@ -521,20 +523,22 @@ static void insert_message(struct upb_strtable *t,
upb_strptr fqname = try_define(t, base, name, status);
if(upb_string_isnull(fqname)) return;
- int num_fields = d->set_flags.has.field ? d->field->len : 0;
+ int num_fields = d->set_flags.has.field ?
+ google_protobuf_FieldDescriptorProto_array_len(d->field) : 0;
struct symtab_ent e;
e.e.key = fqname;
// Gather our list of fields, sorting if necessary.
struct upb_fielddef **fielddefs = malloc(sizeof(*fielddefs) * num_fields);
for (int i = 0; i < num_fields; i++) {
- google_protobuf_FieldDescriptorProto *fd = d->field->elements[i];
+ google_protobuf_FieldDescriptorProto *fd =
+ google_protobuf_FieldDescriptorProto_array_get(d->field, i);
fielddefs[i] = fielddef_new(fd);
}
- if(sort) fielddef_sort(fielddefs, d->field->len);
+ if(sort) fielddef_sort(fielddefs, num_fields);
// Create the msgdef with that list of fields.
- e.def = UPB_UPCAST(msgdef_new(fielddefs, d->field->len, fqname, status));
+ e.def = UPB_UPCAST(msgdef_new(fielddefs, num_fields, fqname, status));
// Cleanup.
for (int i = 0; i < num_fields; i++) fielddef_free(fielddefs[i]);
@@ -546,12 +550,12 @@ static void insert_message(struct upb_strtable *t,
/* Add nested messages and enums. */
if(d->set_flags.has.nested_type)
- for(unsigned int i = 0; i < d->nested_type->len; i++)
- insert_message(t, d->nested_type->elements[i], fqname, sort, status);
+ for(unsigned int i = 0; i < google_protobuf_DescriptorProto_array_len(d->nested_type); i++)
+ insert_message(t, google_protobuf_DescriptorProto_array_get(d->nested_type, i), fqname, sort, status);
if(d->set_flags.has.enum_type)
- for(unsigned int i = 0; i < d->enum_type->len; i++)
- insert_enum(t, d->enum_type->elements[i], fqname, status);
+ for(unsigned int i = 0; i < google_protobuf_EnumDescriptorProto_array_len(d->enum_type); i++)
+ insert_enum(t, google_protobuf_EnumDescriptorProto_array_get(d->enum_type, i), fqname, status);
error:
// Free the ref we got from try_define().
@@ -618,12 +622,12 @@ static void addfd(struct upb_strtable *addto, struct upb_strtable *existingdefs,
}
if(fd->set_flags.has.message_type)
- for(unsigned int i = 0; i < fd->message_type->len; i++)
- insert_message(addto, fd->message_type->elements[i], pkg, sort, status);
+ for(unsigned int i = 0; i < google_protobuf_DescriptorProto_array_len(fd->message_type); i++)
+ insert_message(addto, google_protobuf_DescriptorProto_array_get(fd->message_type, i), pkg, sort, status);
if(fd->set_flags.has.enum_type)
- for(unsigned int i = 0; i < fd->enum_type->len; i++)
- insert_enum(addto, fd->enum_type->elements[i], pkg, status);
+ for(unsigned int i = 0; i < google_protobuf_EnumDescriptorProto_array_len(fd->enum_type); i++)
+ insert_enum(addto, google_protobuf_EnumDescriptorProto_array_get(fd->enum_type, i), pkg, status);
upb_string_unref(pkg);
@@ -686,8 +690,9 @@ struct upb_symtab *upb_symtab_new()
upb_strtable_init(&s->psymtab, 16, sizeof(struct symtab_ent));
// Add descriptor.proto types to private symtable so we can parse descriptors.
+ // We know there is only 1.
google_protobuf_FileDescriptorProto *fd =
- upb_file_descriptor_set->file->elements[0]; // We know there is only 1.
+ google_protobuf_FileDescriptorProto_array_get(upb_file_descriptor_set->file, 0);
struct upb_status status = UPB_STATUS_INIT;
addfd(&s->psymtab, &s->symtab, fd, false, &status);
if(!upb_ok(&status)) {
@@ -782,8 +787,8 @@ void upb_symtab_addfds(struct upb_symtab *s,
{ // Read lock scope
upb_rwlock_rdlock(&s->lock);
- for(uint32_t i = 0; i < fds->file->len; i++) {
- addfd(&tmp, &s->symtab, fds->file->elements[i], true, status);
+ for(uint32_t i = 0; i < google_protobuf_FileDescriptorProto_array_len(fds->file); i++) {
+ addfd(&tmp, &s->symtab, google_protobuf_FileDescriptorProto_array_get(fds->file, i), true, status);
if(!upb_ok(status)) {
free_symtab(&tmp);
upb_rwlock_unlock(&s->lock);
diff --git a/src/upb_text.c b/src/upb_text.c
index 225b344..3981715 100644
--- a/src/upb_text.c
+++ b/src/upb_text.c
@@ -92,7 +92,7 @@ static void printmsg(struct upb_text_printer *printer,
if(!upb_msg_has(msg, f)) continue;
union upb_value v = upb_msg_get(msg, f);
if(upb_isarray(f)) {
- upb_array *arr = v.arr;
+ upb_arrayptr arr = v.arr;
for(uint32_t j = 0; j < upb_array_len(arr); j++) {
union upb_value elem = upb_array_get(arr, f, j);
printval(printer, elem, f, stream);
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback