summaryrefslogtreecommitdiff
path: root/upb/msg.c
diff options
context:
space:
mode:
authorJoshua Haberman <jhaberman@gmail.com>2012-03-24 11:24:16 -0700
committerJoshua Haberman <jhaberman@gmail.com>2012-03-24 11:24:16 -0700
commit86bad61b76a260ffc442acffbe58feee67df45e5 (patch)
treee375e62ff6d7fea9fb810830e66118e67b4ec2c8 /upb/msg.c
parentdb59a5198f890ecdcac1227b0bb998160acac5c6 (diff)
Sync from internal Google development.
Many improvements, too many to mention. One significant perf regression warrants investigation: omitfp.parsetoproto2_googlemessage1.upb_jit: 343 -> 252 (-26.53) plain.parsetoproto2_googlemessage1.upb_jit: 334 -> 251 (-24.85) 25% regression for this benchmark is bad, but since I don't think there's any fundamental design issue that caused it I'm going to go ahead with the commit anyway. Can investigate and fix later. Other benchmarks were neutral or showed slight improvement.
Diffstat (limited to 'upb/msg.c')
-rw-r--r--upb/msg.c322
1 files changed, 10 insertions, 312 deletions
diff --git a/upb/msg.c b/upb/msg.c
index 77521e5..c671b7b 100644
--- a/upb/msg.c
+++ b/upb/msg.c
@@ -4,101 +4,12 @@
* Copyright (c) 2010 Google Inc. See LICENSE for details.
* Author: Josh Haberman <jhaberman@gmail.com>
*
- * Data structure for storing a message of protobuf data.
*/
#include "upb/upb.h"
#include "upb/msg.h"
-void upb_msg_clear(void *msg, const upb_msgdef *md) {
- assert(msg != NULL);
- memset(msg, 0, md->hasbit_bytes);
- // TODO: set primitive fields to defaults?
-}
-
-void *upb_stdarray_append(upb_stdarray *a, size_t type_size) {
- assert(a != NULL);
- assert(a->len <= a->size);
- if (a->len == a->size) {
- size_t old_size = a->size;
- a->size = old_size == 0 ? 8 : (old_size * 2);
- a->ptr = realloc(a->ptr, a->size * type_size);
- memset(&a->ptr[old_size * type_size], 0, (a->size - old_size) * type_size);
- }
- return &a->ptr[a->len++ * type_size];
-}
-
-#if 0
-static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
- upb_dispatcher *d);
-
-static upb_flow_t upb_msg_pushval(upb_value val, upb_fielddef *f,
- upb_dispatcher *d, upb_fhandlers *hf) {
- if (upb_issubmsg(f)) {
- upb_msg *msg = upb_value_getmsg(val);
- upb_dispatch_startsubmsg(d, hf);
- upb_msg_dispatch(msg, upb_downcast_msgdef(f->def), d);
- upb_dispatch_endsubmsg(d);
- } else {
- upb_dispatch_value(d, hf, val);
- }
- return UPB_CONTINUE;
-}
-
-static upb_flow_t upb_msg_dispatch(upb_msg *msg, upb_msgdef *md,
- upb_dispatcher *d) {
- upb_msg_iter i;
- for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
- upb_fielddef *f = upb_msg_iter_field(i);
- if (!upb_msg_has(msg, f)) continue;
- upb_fhandlers *hf = upb_dispatcher_lookup(d, f->number);
- if (!hf) continue;
- upb_value val = upb_msg_get(msg, f);
- if (upb_isarray(f)) {
- upb_array *arr = upb_value_getarr(val);
- for (uint32_t j = 0; j < upb_array_len(arr); ++j) {
- upb_msg_pushval(upb_array_get(arr, f, j), f, d, hf);
- }
- } else {
- upb_msg_pushval(val, f, d, hf);
- }
- }
- return UPB_CONTINUE;
-}
-
-void upb_msg_runhandlers(upb_msg *msg, upb_msgdef *md, upb_handlers *h,
- void *closure, upb_status *status) {
- upb_dispatcher d;
- upb_dispatcher_init(&d, h, NULL, NULL, NULL);
- upb_dispatcher_reset(&d, closure);
-
- upb_dispatch_startmsg(&d);
- upb_msg_dispatch(msg, md, &d);
- upb_dispatch_endmsg(&d, status);
-
- upb_dispatcher_uninit(&d);
-}
-#endif
-
-/* Standard writers. **********************************************************/
-
-void upb_stdmsg_sethas(void *_m, upb_value fval) {
- assert(_m != NULL);
- char *m = _m;
- const upb_fielddef *f = upb_value_getfielddef(fval);
- if (f->hasbit >= 0)
- m[(uint32_t)f->hasbit / 8] |= (1 << ((uint32_t)f->hasbit % 8));
-}
-
-bool upb_stdmsg_has(const void *_m, upb_value fval) {
- assert(_m != NULL);
- const char *m = _m;
- const upb_fielddef *f = upb_value_getfielddef(fval);
- return f->hasbit < 0 ||
- (m[(uint32_t)f->hasbit / 8] & (1 << ((uint32_t)f->hasbit % 8)));
-}
-
-#define UPB_ACCESSORS(type, ctype) \
+#define UPB_ACCESSOR(type, ctype) \
upb_flow_t upb_stdmsg_set ## type (void *_m, upb_value fval, \
upb_value val) { \
assert(_m != NULL); \
@@ -108,230 +19,17 @@ bool upb_stdmsg_has(const void *_m, upb_value fval) {
*(ctype*)&m[f->offset] = upb_value_get ## type(val); \
return UPB_CONTINUE; \
} \
- \
- upb_flow_t upb_stdmsg_set ## type ## _r(void *a, upb_value _fval, \
- upb_value val) { \
- (void)_fval; \
- assert(a != NULL); \
- ctype *p = upb_stdarray_append((upb_stdarray*)a, sizeof(ctype)); \
- *p = upb_value_get ## type(val); \
- return UPB_CONTINUE; \
- } \
- \
- upb_value upb_stdmsg_get ## type(const void *_m, upb_value fval) { \
- assert(_m != NULL); \
- const uint8_t *m = _m; \
- const upb_fielddef *f = upb_value_getfielddef(fval); \
- upb_value ret; \
- upb_value_set ## type(&ret, *(ctype*)&m[f->offset]); \
- return ret; \
- } \
- upb_value upb_stdmsg_seqget ## type(const void *i) { \
- assert(i != NULL); \
- upb_value val; \
- upb_value_set ## type(&val, *(ctype*)i); \
- return val; \
- }
-UPB_ACCESSORS(double, double)
-UPB_ACCESSORS(float, float)
-UPB_ACCESSORS(int32, int32_t)
-UPB_ACCESSORS(int64, int64_t)
-UPB_ACCESSORS(uint32, uint32_t)
-UPB_ACCESSORS(uint64, uint64_t)
-UPB_ACCESSORS(bool, bool)
-UPB_ACCESSORS(ptr, void*)
+UPB_ACCESSOR(double, double)
+UPB_ACCESSOR(float, float)
+UPB_ACCESSOR(int32, int32_t)
+UPB_ACCESSOR(int64, int64_t)
+UPB_ACCESSOR(uint32, uint32_t)
+UPB_ACCESSOR(uint64, uint64_t)
+UPB_ACCESSOR(bool, bool)
+UPB_ACCESSOR(ptr, void*)
#undef UPB_ACCESSORS
-static void _upb_stdmsg_setstr(void *_dst, upb_value src) {
- upb_stdarray **dstp = _dst;
- upb_stdarray *dst = *dstp;
- if (!dst) {
- dst = malloc(sizeof(*dst));
- dst->size = 0;
- dst->ptr = NULL;
- *dstp = dst;
- }
- dst->len = 0;
- const upb_byteregion *bytes = upb_value_getbyteregion(src);
- uint32_t len = upb_byteregion_len(bytes);
- if (len > dst->size) {
- dst->size = len;
- dst->ptr = realloc(dst->ptr, dst->size);
- }
- dst->len = len;
- upb_byteregion_copyall(bytes, dst->ptr);
-}
-
-upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) {
- assert(_m != NULL);
- char *m = _m;
- const upb_fielddef *f = upb_value_getfielddef(fval);
- // Hasbit automatically set by the handlers.
- _upb_stdmsg_setstr(&m[f->offset], val);
- return UPB_CONTINUE;
-}
-
-upb_flow_t upb_stdmsg_setstr_r(void *a, upb_value fval, upb_value val) {
- assert(a != NULL);
- (void)fval;
- _upb_stdmsg_setstr(upb_stdarray_append((upb_stdarray*)a, sizeof(void*)), val);
- return UPB_CONTINUE;
-}
-
-upb_value upb_stdmsg_getstr(const void *m, upb_value fval) {
- assert(m != NULL);
- return upb_stdmsg_getptr(m, fval);
-}
-
-upb_value upb_stdmsg_seqgetstr(const void *i) {
- assert(i != NULL);
- return upb_stdmsg_seqgetptr(i);
-}
-
-void *upb_stdmsg_new(const upb_msgdef *md) {
- void *m = malloc(md->size);
- memset(m, 0, md->size);
- upb_msg_clear(m, md);
- return m;
-}
-
-void upb_stdseq_free(void *s, upb_fielddef *f) {
- upb_stdarray *a = s;
- if (upb_issubmsg(f) || upb_isstring(f)) {
- void **p = (void**)a->ptr;
- for (uint32_t i = 0; i < a->size; i++) {
- if (upb_issubmsg(f)) {
- upb_stdmsg_free(p[i], upb_downcast_msgdef(f->def));
- } else {
- upb_stdarray *str = p[i];
- free(str->ptr);
- free(str);
- }
- }
- }
- free(a->ptr);
- free(a);
-}
-
-void upb_stdmsg_free(void *m, const upb_msgdef *md) {
- if (m == NULL) return;
- upb_msg_iter i;
- for(i = upb_msg_begin(md); !upb_msg_done(i); i = upb_msg_next(md, i)) {
- upb_fielddef *f = upb_msg_iter_field(i);
- if (!upb_isseq(f) && !upb_issubmsg(f) && !upb_isstring(f)) continue;
- void *subp = upb_value_getptr(upb_stdmsg_getptr(m, f->fval));
- if (subp == NULL) continue;
- if (upb_isseq(f)) {
- upb_stdseq_free(subp, f);
- } else if (upb_issubmsg(f)) {
- upb_stdmsg_free(subp, upb_downcast_msgdef(f->def));
- } else {
- upb_stdarray *str = subp;
- free(str->ptr);
- free(str);
- }
- }
- free(m);
-}
-
-upb_sflow_t upb_stdmsg_startseq(void *_m, upb_value fval) {
- char *m = _m;
- const upb_fielddef *f = upb_value_getfielddef(fval);
- upb_stdarray **arr = (void*)&m[f->offset];
- if (!upb_stdmsg_has(_m, fval)) {
- if (!*arr) {
- *arr = malloc(sizeof(**arr));
- (*arr)->size = 0;
- (*arr)->ptr = NULL;
- }
- (*arr)->len = 0;
- upb_stdmsg_sethas(m, fval);
- }
- return UPB_CONTINUE_WITH(*arr);
-}
-
-void upb_stdmsg_recycle(void **m, const upb_msgdef *md) {
- if (*m)
- upb_msg_clear(*m, md);
- else
- *m = upb_stdmsg_new(md);
-}
-
-upb_sflow_t upb_stdmsg_startsubmsg(void *_m, upb_value fval) {
- assert(_m != NULL);
- char *m = _m;
- const upb_fielddef *f = upb_value_getfielddef(fval);
- void **subm = (void*)&m[f->offset];
- if (!upb_stdmsg_has(m, fval)) {
- upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def));
- upb_stdmsg_sethas(m, fval);
- }
- return UPB_CONTINUE_WITH(*subm);
-}
-
-upb_sflow_t upb_stdmsg_startsubmsg_r(void *a, upb_value fval) {
- assert(a != NULL);
- const upb_fielddef *f = upb_value_getfielddef(fval);
- void **subm = upb_stdarray_append((upb_stdarray*)a, sizeof(void*));
- upb_stdmsg_recycle(subm, upb_downcast_msgdef(f->def));
- return UPB_CONTINUE_WITH(*subm);
-}
-
-const void *upb_stdmsg_seqbegin(const void *_a) {
- const upb_stdarray *a = _a;
- return a->len > 0 ? a->ptr : NULL;
-}
-
-#define NEXTFUNC(size) \
- const void *upb_stdmsg_ ## size ## byte_seqnext(const void *_a, const void *iter) {\
- const upb_stdarray *a = _a; \
- const void *next = (char*)iter + size; \
- return (char*)next < (char*)a->ptr + (a->len * size) ? next : NULL; \
- }
-
-NEXTFUNC(8)
-NEXTFUNC(4)
-NEXTFUNC(1)
-
-#define STDMSG(type, size) { static upb_accessor_vtbl vtbl = { \
- &upb_stdmsg_startsubmsg, \
- &upb_stdmsg_set ## type, \
- &upb_stdmsg_startseq, \
- &upb_stdmsg_startsubmsg_r, \
- &upb_stdmsg_set ## type ## _r, \
- &upb_stdmsg_has, \
- &upb_stdmsg_getptr, \
- &upb_stdmsg_get ## type, \
- &upb_stdmsg_seqbegin, \
- &upb_stdmsg_ ## size ## byte_seqnext, \
- &upb_stdmsg_seqget ## type}; \
- return &vtbl; }
-
-upb_accessor_vtbl *upb_stdmsg_accessor(upb_fielddef *f) {
- switch (f->type) {
- case UPB_TYPE(DOUBLE): STDMSG(double, 8)
- case UPB_TYPE(FLOAT): STDMSG(float, 4)
- case UPB_TYPE(UINT64):
- case UPB_TYPE(FIXED64): STDMSG(uint64, 8)
- case UPB_TYPE(INT64):
- case UPB_TYPE(SFIXED64):
- case UPB_TYPE(SINT64): STDMSG(int64, 8)
- case UPB_TYPE(INT32):
- case UPB_TYPE(SINT32):
- case UPB_TYPE(ENUM):
- case UPB_TYPE(SFIXED32): STDMSG(int32, 4)
- case UPB_TYPE(UINT32):
- case UPB_TYPE(FIXED32): STDMSG(uint32, 4)
- case UPB_TYPE(BOOL): STDMSG(bool, 1)
- case UPB_TYPE(STRING):
- case UPB_TYPE(BYTES):
- case UPB_TYPE(GROUP):
- case UPB_TYPE(MESSAGE): STDMSG(str, 8) // TODO: 32-bit
- }
- return NULL;
-}
-
static void upb_accessors_onfreg(void *c, upb_fhandlers *fh,
const upb_fielddef *f) {
(void)c;
@@ -344,7 +42,7 @@ static void upb_accessors_onfreg(void *c, upb_fhandlers *fh,
} else {
upb_fhandlers_setvalue(fh, f->accessor->set);
upb_fhandlers_setstartsubmsg(fh, f->accessor->startsubmsg);
- upb_fhandlers_setvaluehasbit(fh, f->hasbit);
+ upb_fhandlers_sethasbit(fh, f->hasbit);
}
}
}
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback