diff options
-rw-r--r-- | benchmarks/parsetoproto2.upb.cc | 9 | ||||
-rw-r--r-- | upb/def.c | 2 | ||||
-rw-r--r-- | upb/handlers.c | 4 | ||||
-rw-r--r-- | upb/handlers.h | 12 | ||||
-rw-r--r-- | upb/msg.c | 5 | ||||
-rw-r--r-- | upb/pb/decoder_x86.dasc | 21 |
6 files changed, 33 insertions, 20 deletions
diff --git a/benchmarks/parsetoproto2.upb.cc b/benchmarks/parsetoproto2.upb.cc index 74d0680..75cff88 100644 --- a/benchmarks/parsetoproto2.upb.cc +++ b/benchmarks/parsetoproto2.upb.cc @@ -42,7 +42,6 @@ PROTO2_APPEND(bool, bool) upb_flow_t proto2_setstr(void *m, upb_value fval, upb_value val) { assert(m != NULL); - upb_stdmsg_sethas(m, fval); upb_fielddef *f = upb_value_getfielddef(fval); std::string **str = (std::string**)UPB_INDEX(m, f->offset, 1); if (*str == f->default_ptr) *str = new std::string; @@ -72,7 +71,6 @@ upb_sflow_t proto2_startseq(void *m, upb_value fval) { upb_sflow_t proto2_startsubmsg(void *m, upb_value fval) { assert(m != NULL); upb_fielddef *f = upb_value_getfielddef(fval); - upb_stdmsg_sethas(m, fval); google::protobuf::Message *prototype = (google::protobuf::Message*)f->prototype; void **subm = (void**)UPB_INDEX(m, f->offset, 1); if (*subm == NULL || *subm == f->default_ptr) @@ -183,8 +181,13 @@ static void layout_msgdef_from_proto2(upb_msgdef *upb_md, uint32_t hasbit = (r->has_bits_offset_ * 8) + proto2_f->index(); // Encapsulation violation END + if (upb_isseq(upb_f)) { + // proto2 does not store hasbits for repeated fields. + upb_f->hasbit = -1; + } else { + upb_f->hasbit = hasbit; + } upb_f->offset = data_offset; - upb_f->hasbit = hasbit; upb_fielddef_setaccessor(upb_f, proto2_accessor(upb_f)); if (upb_isstring(upb_f) && !upb_isseq(upb_f)) { @@ -212,7 +212,7 @@ upb_fielddef *upb_fielddef_new() { f->finalized = false; f->type = 0; f->label = UPB_LABEL(OPTIONAL); - f->hasbit = 0; + f->hasbit = -1; f->offset = 0; f->number = 0; // not a valid field number. f->hasdefault = false; diff --git a/upb/handlers.c b/upb/handlers.c index d02a32a..b6d0244 100644 --- a/upb/handlers.c +++ b/upb/handlers.c @@ -31,7 +31,7 @@ static upb_fhandlers *_upb_mhandlers_newfhandlers(upb_mhandlers *m, uint32_t n, if (f) abort(); upb_fhandlers new_f = {false, type, repeated, repeated && upb_isprimitivetype(type), UPB_ATOMIC_INIT(0), - n, m, NULL, UPB_NO_VALUE, NULL, NULL, NULL, NULL, NULL, + n, -1, m, NULL, UPB_NO_VALUE, NULL, NULL, NULL, NULL, NULL, #ifdef UPB_USE_JIT_X64 0, 0, 0, #endif @@ -156,7 +156,7 @@ upb_mhandlers *upb_handlers_regmsgdef(upb_handlers *h, upb_msgdef *m, static upb_fhandlers toplevel_f = { false, UPB_TYPE(GROUP), false, false, UPB_ATOMIC_INIT(0), 0, - NULL, NULL, // submsg + -1, NULL, NULL, // submsg #ifdef NDEBUG {{0}}, #else diff --git a/upb/handlers.h b/upb/handlers.h index db28705..3a9509a 100644 --- a/upb/handlers.h +++ b/upb/handlers.h @@ -141,6 +141,7 @@ typedef struct _upb_fieldent { bool is_repeated_primitive; upb_atomic_t refcount; uint32_t number; + int32_t valuehasbit; struct _upb_mhandlers *msg; struct _upb_mhandlers *submsg; // Set iff upb_issubmsgtype(type) == true. upb_value fval; @@ -174,6 +175,11 @@ UPB_FHANDLERS_ACCESSORS(startseq, upb_startfield_handler*) UPB_FHANDLERS_ACCESSORS(endseq, upb_endfield_handler*) UPB_FHANDLERS_ACCESSORS(msg, struct _upb_mhandlers*) UPB_FHANDLERS_ACCESSORS(submsg, struct _upb_mhandlers*) +// If set to >= 0, the hasbit will automatically be set after the corresponding +// callback is called (when a JIT is enabled, this can be significantly more +// efficient than setting the hasbit yourself inside the callback). Could add +// this for seq and submsg also, but doesn't look like a win at the moment. +UPB_FHANDLERS_ACCESSORS(valuehasbit, int32_t) /* upb_mhandlers **************************************************************/ @@ -357,11 +363,17 @@ INLINE upb_fhandlers *upb_dispatcher_lookup(upb_dispatcher *d, uint32_t n) { void _upb_dispatcher_unwind(upb_dispatcher *d, upb_flow_t flow); +INLINE void _upb_dispatcher_sethas(void *_p, int32_t hasbit) { + char *p = (char*)_p; + if (hasbit >= 0) p[hasbit / 8] |= (1 << (hasbit % 8)); +} + // Dispatch functions -- call the user handler and handle errors. INLINE void upb_dispatch_value(upb_dispatcher *d, upb_fhandlers *f, upb_value val) { upb_flow_t flow = UPB_CONTINUE; if (f->value) flow = f->value(d->top->closure, f->fval, val); + _upb_dispatcher_sethas(d->top->closure, f->valuehasbit); if (flow != UPB_CONTINUE) _upb_dispatcher_unwind(d, flow); } void upb_dispatch_startmsg(upb_dispatcher *d); @@ -102,7 +102,7 @@ bool upb_stdmsg_has(void *_m, upb_value fval) { assert(_m != NULL); \ upb_fielddef *f = upb_value_getfielddef(fval); \ uint8_t *m = _m; \ - upb_stdmsg_sethas(_m, fval); \ + /* Hasbit is set automatically by the handlers. */ \ *(ctype*)&m[f->offset] = upb_value_get ## type(val); \ return UPB_CONTINUE; \ } \ @@ -164,7 +164,7 @@ upb_flow_t upb_stdmsg_setstr(void *_m, upb_value fval, upb_value val) { assert(_m != NULL); char *m = _m; upb_fielddef *f = upb_value_getfielddef(fval); - upb_stdmsg_sethas(_m, fval); + // Hasbit automatically set by the handlers. _upb_stdmsg_setstr(&m[f->offset], val); return UPB_CONTINUE; } @@ -340,6 +340,7 @@ static void upb_accessors_onfreg(void *c, upb_fhandlers *fh, upb_fielddef *f) { } else { upb_fhandlers_setvalue(fh, f->accessor->set); upb_fhandlers_setstartsubmsg(fh, f->accessor->startsubmsg); + upb_fhandlers_setvaluehasbit(fh, f->hasbit); } } } diff --git a/upb/pb/decoder_x86.dasc b/upb/pb/decoder_x86.dasc index 3028086..fe15174 100644 --- a/upb/pb/decoder_x86.dasc +++ b/upb/pb/decoder_x86.dasc @@ -126,7 +126,7 @@ void upb_reg_jit_gdb(upb_decoder *d) { |.type FRAME, upb_dispatcher_frame, r13 |.type STRREF, upb_strref, r14 |.type DECODER, upb_decoder, r15 -|.type STDARRAY, upb_stdarray, r15 +|.type STDARRAY, upb_stdarray | |.macro callp, addr || if ((uintptr_t)addr < 0xffffffff) { @@ -273,6 +273,13 @@ void upb_reg_jit_gdb(upb_decoder *d) { | mov64 ARG2_64, f->fval.val.uint64 || } |.endmacro +| +|.macro sethas, reg, hasbit +|| if (hasbit >= 0) { +| or byte [reg + (hasbit / 8)], (1 << (hasbit % 8)) +|| } +|.endmacro + #include <stdlib.h> #include "upb/pb/varint.h" @@ -369,14 +376,6 @@ static void upb_decoder_jit_decodefield(upb_decoder *d, upb_mhandlers *m, } } -// DEPENDS: closure is in ARG1_64 -static void upb_decoder_jit_sethas(upb_decoder *d, upb_fielddef *f) { - if (f->hasbit < 0) return; - size_t byte = f->hasbit / 8; - uint8_t bit = 1 << (f->hasbit % 8); - | or byte [ARG1_64 + byte], bit -} - #if 0 // These appear not to speed things up, but keeping around for // further experimentation. @@ -465,15 +464,12 @@ static void upb_decoder_jit_callcb(upb_decoder *d, upb_fhandlers *f) { f->value == &upb_stdmsg_setuint64 || f->value == &upb_stdmsg_setptr || f->value == &upb_stdmsg_setdouble) { - upb_decoder_jit_sethas(d, fd); | mov [ARG1_64 + fd->offset], ARG3_64 } else if (f->value == &upb_stdmsg_setint32 || f->value == &upb_stdmsg_setuint32 || f->value == &upb_stdmsg_setfloat) { - upb_decoder_jit_sethas(d, fd); | mov [ARG1_64 + fd->offset], ARG3_32 } else if (f->value == &upb_stdmsg_setbool) { - upb_decoder_jit_sethas(d, fd); | mov [ARG1_64 + fd->offset], ARG3_8 #if 0 // These appear not to speed things up, but keeping around for @@ -495,6 +491,7 @@ static void upb_decoder_jit_callcb(upb_decoder *d, upb_fhandlers *f) { | loadfval f | callp f->value } + | sethas CLOSURE, f->valuehasbit } // TODO: Handle UPB_SKIPSUBMSG, UPB_BREAK } |