From 2fdc9df97eab06f2b42c1a9a87bc01d5e9feedd7 Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Thu, 31 Dec 2009 20:42:56 -0800 Subject: Other than a couple memory leaks, "make descriptorgen" works again! --- src/upb_data.c | 22 ++++++++++++++++------ src/upb_data.h | 22 ++++++++++++---------- src/upb_def.c | 14 +++++++++----- 3 files changed, 37 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/upb_data.c b/src/upb_data.c index 084a03c..8de0c62 100644 --- a/src/upb_data.c +++ b/src/upb_data.c @@ -41,7 +41,7 @@ static void data_unref(void *d, struct upb_fielddef *f) { } INLINE void data_init(upb_data *d, int flags) { - d->v = flags; + d->v = REFCOUNT_ONE | flags; } static void check_not_frozen(upb_data *d) { @@ -100,7 +100,10 @@ void upb_string_resize(upb_string *s, upb_strlen_t byte_len) { upb_string *upb_string_getref(upb_string *s, int ref_flags) { if(_upb_data_incref(&s->common.base, ref_flags)) return s; - return upb_strdup(s); + upb_string *copy = upb_strdup(s); + if(ref_flags == UPB_REF_FROZEN) + upb_data_setflag(©->common.base, UPB_DATA_FROZEN); + return copy; } upb_string *upb_strreadfile(const char *filename) { @@ -200,13 +203,18 @@ static void array_set_size(upb_array *a, upb_arraylen_t newsize) { } } -void upb_array_resize(upb_array *a, upb_strlen_t len) { +void upb_array_resize(upb_array *a, struct upb_fielddef *f, upb_strlen_t len) { check_not_frozen(&a->common.base); - if(array_get_size(a) < len) { + 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); + a->common.elements._void = realloc(a->common.elements._void, new_size * type_size); array_set_size(a, new_size); + memset(UPB_INDEX(a->common.elements._void, old_size, type_size), + 0, + (new_size - old_size) * type_size); } a->common.len = len; } @@ -269,9 +277,11 @@ static union upb_value_ptr get_value_ptr(upb_msg *msg, struct upb_fielddef *f) } upb_array_truncate(*p.arr); upb_msg_sethas(msg, f); + } else { + assert(*p.arr); } upb_arraylen_t oldlen = upb_array_len(*p.arr); - upb_array_resize(*p.arr, oldlen + 1); + upb_array_resize(*p.arr, f, oldlen + 1); p = _upb_array_getptr(*p.arr, f, oldlen); } return p; diff --git a/src/upb_data.h b/src/upb_data.h index 872f237..2a7940e 100644 --- a/src/upb_data.h +++ b/src/upb_data.h @@ -130,8 +130,9 @@ typedef enum { // Attempts to increment the reference on d with the given type of ref. If // this is not possible, returns false. INLINE bool _upb_data_incref(upb_data *d, upb_reftype reftype) { - if((reftype == UPB_REF_FROZEN && !upb_data_hasflag(d, UPB_DATA_FROZEN)) || - (reftype == UPB_REF_MUTABLE && upb_data_hasflag(d, UPB_DATA_FROZEN)) || + bool frozen = upb_data_hasflag(d, UPB_DATA_FROZEN); + if((reftype == UPB_REF_FROZEN && !frozen) || + (reftype == UPB_REF_MUTABLE && frozen) || (upb_data_hasflag(d, UPB_DATA_HEAPALLOCATED) && !upb_data_hasflag(d, UPB_DATA_REFCOUNTED))) { return false; @@ -306,7 +307,7 @@ upb_string *upb_strreadfile(const char *filename); // must not dynamically allocate this type. typedef upb_string upb_static_string; #define UPB_STRLIT_LEN(str, len) {0 | UPB_DATA_FROZEN, len, str} -#define UPB_STRLIT(str) {{0 | UPB_DATA_FROZEN, sizeof(str), str}} +#define UPB_STRLIT(str) {{0 | UPB_DATA_FROZEN, sizeof(str)-1, str}} // Allows using upb_strings in printf, ie: // upb_string str = UPB_STRLIT("Hello, World!\n"); @@ -359,6 +360,11 @@ typedef struct type ## _array { \ // empty. Caller owns one ref on it. upb_array *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; +} + // INTERNAL-ONLY: // Frees the given message and releases references on members. void _upb_array_free(upb_array *a, struct upb_fielddef *f); @@ -366,7 +372,8 @@ void _upb_array_free(upb_array *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, int elem) { + struct upb_fielddef *f, + upb_arraylen_t elem) { assert(elem < upb_array_len(a)); size_t type_size = upb_type_info[f->type].size; union upb_value_ptr p = {._void = &a->common.elements.uint8[elem * type_size]}; @@ -405,11 +412,6 @@ INLINE void upb_array_append_default(upb_array *a, struct upb_fielddef *f, union upb_value val); #endif -// Returns the current number of elements in the array. -INLINE size_t upb_array_len(upb_array *a) { - return a->common.len; -} - INLINE void upb_array_truncate(upb_array *a) { a->common.len = 0; } @@ -447,7 +449,7 @@ INLINE void upb_msg_unref(upb_msg *msg, struct upb_msgdef *md) { // Tests whether the given field is explicitly set, or whether it will return // a default. INLINE bool upb_msg_has(upb_msg *msg, struct upb_fielddef *f) { - return msg->data[f->field_index/8] % (1 << (f->field_index % 8)); + return (msg->data[f->field_index/8] & (1 << (f->field_index % 8))) != 0; } // Returns the current value if set, or the default value if not set, of the diff --git a/src/upb_def.c b/src/upb_def.c index be5c181..f824910 100644 --- a/src/upb_def.c +++ b/src/upb_def.c @@ -287,7 +287,7 @@ static struct upb_msgdef *msgdef_new(struct upb_fielddef **fields, m->set_flags_bytes = div_round_up(m->num_fields, 8); // These are incremented in the loop. m->num_required_fields = 0; - m->size = m->set_flags_bytes; + m->size = m->set_flags_bytes + 4; // 4 for the refcount. m->fields = malloc(sizeof(struct upb_fielddef) * num_fields); size_t max_align = 0; @@ -300,8 +300,9 @@ static struct upb_msgdef *msgdef_new(struct upb_fielddef **fields, // multiple of that type's alignment. Also, the size of the structure as // a whole must be a multiple of the greatest alignment of any member. */ f->field_index = i; - f->byte_offset = ALIGN_UP(m->size, type_info->align); - m->size = f->byte_offset + type_info->size; + size_t offset = ALIGN_UP(m->size, type_info->align); + f->byte_offset = offset - 4; // Offsets are relative to the refcount. + m->size = offset + type_info->size; max_align = UPB_MAX(max_align, type_info->align); if(f->label == UPB_LABEL(REQUIRED)) { // We currently rely on the fact that required fields are always sorted @@ -516,7 +517,7 @@ static void insert_message(struct upb_strtable *t, int num_fields = d->set_flags.has.field ? d->field->len : 0; struct symtab_ent e; - e.e.key = fqname; // Donating our ref to the table. + e.e.key = fqname; 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]; @@ -530,7 +531,7 @@ static void insert_message(struct upb_strtable *t, } free(fielddefs); - if(!upb_ok(status)) return; + if(!upb_ok(status)) goto error; upb_strtable_insert(t, &e.e); @@ -542,6 +543,9 @@ static void insert_message(struct upb_strtable *t, 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); + +error: + upb_string_unref(fqname); } static bool find_cycles(struct upb_msgdef *m, int search_depth, -- cgit v1.2.3