From 4d6585290955613b23e5ade89794fb465cb7ec3a Mon Sep 17 00:00:00 2001 From: Joshua Haberman Date: Wed, 23 Feb 2011 23:56:36 -0800 Subject: Rearrange structs to put arrays at the end, for smaller offsets. --- src/upb_decoder.c | 43 +++++++++---------------------------------- src/upb_decoder.h | 12 +++++------- src/upb_msg.h | 3 ++- 3 files changed, 16 insertions(+), 42 deletions(-) diff --git a/src/upb_decoder.c b/src/upb_decoder.c index 78fc8b1..7db8243 100644 --- a/src/upb_decoder.c +++ b/src/upb_decoder.c @@ -121,7 +121,6 @@ INLINE bool upb_decode_tag(upb_decoder *d, upb_tag *tag) { if ((*(p++) & 0x80) == 0) goto done; // likely slow: // Decode a full varint starting over from ptr. - DEBUGPRINTF("tag was >2 bytes.\n"); if (!upb_decode_varint_slow(d, &val)) return false; tag_int = upb_value_getint64(val); p = d->ptr; // Trick the next line into not overwriting us. @@ -198,7 +197,9 @@ static upb_flow_t upb_push(upb_decoder *d, upb_fielddef *f, UPB_GROUP_END_OFFSET : d->buf_stream_offset + (d->ptr - upb_string_getrobuf(d->buf)) + upb_value_getint32(submsg_len); - d->top->msgdef = upb_downcast_msgdef(f->def); + upb_msgdef *md = upb_downcast_msgdef(f->def); + d->top->msgdef = md; + d->msgdef = md; upb_dstate_setmsgend(d); upb_flow_t ret = upb_dispatch_startsubmsg(&d->dispatcher, f); if (ret == UPB_SKIPSUBMSG) { @@ -217,6 +218,7 @@ static upb_flow_t upb_push(upb_decoder *d, upb_fielddef *f, static upb_flow_t upb_pop(upb_decoder *d) { --d->top; upb_dstate_setmsgend(d); + d->msgdef = d->top->msgdef; return upb_dispatch_endsubmsg(&d->dispatcher); } @@ -227,8 +229,6 @@ void upb_decoder_run(upb_src *src, upb_status *status) { d->end = NULL; // Force a buffer pull. d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered. d->msgdef = d->top->msgdef; - //d->bytes_parsed_fast = 0; - //d->bytes_parsed_slow = 0; // TODO: handle UPB_SKIPSUBMSG #define CHECK_FLOW(expr) if ((expr) == UPB_BREAK) { /*assert(!upb_ok(status));*/ goto callback_err; } @@ -247,7 +247,6 @@ void upb_decoder_run(upb_src *src, upb_status *status) { CHECK_FLOW(upb_pop(d)); } - //const char *ptr = d->ptr; // Decodes as many fields as possible, updating d->ptr appropriately, // before falling through to the slow(er) path. #ifdef USE_ASSEMBLY_FASTPATH @@ -255,27 +254,11 @@ void upb_decoder_run(upb_src *src, upb_status *status) { fastdecode_ret ret = upb_fastdecode(d->ptr, end, d->dispatcher.top->handlers.set->value, d->dispatcher.top->handlers.closure, - d->top->msgdef->itof.array, - d->top->msgdef->itof.array_size, + d->msgdef->itof.array, + d->msgdef->itof.array_size, d->tmp); CHECK_FLOW(ret.flow); - if (ret.ptr - d->ptr > 0) { - DEBUGPRINTF("Fast path parsed %d bytes of data!\n", ret.ptr - d->ptr); - } - d->ptr = ret.ptr; - if (end - d->ptr < 12) { - if (end == d->submsg_end && end != d->end) { - DEBUGPRINTF("Off the fast path because <12 bytes of data, but ONLY because of submsg end.\n"); - } else { - DEBUGPRINTF("Off the fast path because <12 bytes of data, NOT because of submsg end.\n"); - } - } else { - DEBUGPRINTF("Off the fast path for some other reason.\n"); - } #endif - //if (d->ptr > ptr) { - // d->bytes_parsed_fast += (d->ptr - ptr); - //} // Parse/handle tag. upb_tag tag; @@ -284,7 +267,6 @@ void upb_decoder_run(upb_src *src, upb_status *status) { // Normal end-of-file. upb_clearerr(status); CHECK_FLOW(upb_dispatch_endmsg(&d->dispatcher)); - //DEBUGPRINTF("bytes parsed fast: %d, bytes parsed slow; %d\n", d->bytes_parsed_fast, d->bytes_parsed_slow); return; } else { if (status->code == UPB_EOF) { @@ -300,10 +282,8 @@ void upb_decoder_run(upb_src *src, upb_status *status) { upb_value val; switch (tag.wire_type) { case UPB_WIRE_TYPE_START_GROUP: - DEBUGPRINTF("parsing start group\n"); break; // Nothing to do now, below we will push appropriately. case UPB_WIRE_TYPE_END_GROUP: - DEBUGPRINTF("parsing end group\n"); if(d->top->end_offset != UPB_GROUP_END_OFFSET) { upb_seterr(status, UPB_ERROR, "Unexpected END_GROUP tag."); goto err; @@ -324,7 +304,7 @@ void upb_decoder_run(upb_src *src, upb_status *status) { } // Look up field by tag number. - upb_itof_ent *e = upb_msgdef_itofent(d->top->msgdef, tag.field_number); + upb_itof_ent *e = upb_msgdef_itofent(d->msgdef, tag.field_number); if (!e) { if (tag.wire_type == UPB_WIRE_TYPE_DELIMITED) @@ -357,13 +337,11 @@ void upb_decoder_run(upb_src *src, upb_status *status) { // doesn't check this, and it would slow us down, so pass for now. switch (e->field_type) { case UPB_TYPE(MESSAGE): - DEBUGPRINTF("parsing submessage\n"); case UPB_TYPE(GROUP): CHECK_FLOW(upb_push(d, f, val, e->field_type)); continue; // We have no value to dispatch. case UPB_TYPE(STRING): case UPB_TYPE(BYTES): - DEBUGPRINTF("parsing string\n"); CHECK(upb_decode_string(d, &val, &d->tmp)); break; case UPB_TYPE(SINT32): @@ -395,7 +373,6 @@ void upb_decoder_sethandlers(upb_src *src, upb_handlers *handlers) { upb_dispatcher_reset(&d->dispatcher, handlers, true); d->top = d->stack; d->buf_stream_offset = 0; - d->top->msgdef = d->toplevel_msgdef; // The top-level message is not delimited (we can keep receiving data for it // indefinitely), so we treat it like a group. d->top->end_offset = 0; @@ -408,7 +385,8 @@ void upb_decoder_init(upb_decoder *d, upb_msgdef *msgdef) { }; upb_src_init(&d->src, &vtbl); upb_dispatcher_init(&d->dispatcher); - d->toplevel_msgdef = msgdef; + d->stack[0].msgdef = msgdef; + d->stack[0].end_offset = UPB_GROUP_END_OFFSET; d->limit = &d->stack[UPB_MAX_NESTING]; d->buf = NULL; d->tmp = NULL; @@ -417,9 +395,6 @@ void upb_decoder_init(upb_decoder *d, upb_msgdef *msgdef) { void upb_decoder_reset(upb_decoder *d, upb_bytesrc *bytesrc) { d->bytesrc = bytesrc; d->top = &d->stack[0]; - d->top->msgdef = d->toplevel_msgdef; - // Never want to end top-level message, so treat it like a group. - d->top->end_offset = UPB_GROUP_END_OFFSET; } void upb_decoder_uninit(upb_decoder *d) { diff --git a/src/upb_decoder.h b/src/upb_decoder.h index d0848f8..6a9f7cc 100644 --- a/src/upb_decoder.h +++ b/src/upb_decoder.h @@ -39,13 +39,11 @@ struct _upb_decoder { upb_src src; upb_dispatcher dispatcher; upb_bytesrc *bytesrc; - upb_msgdef *toplevel_msgdef; - upb_decoder_frame stack[UPB_MAX_NESTING]; // Mutable state of the decoder. - // Where we will store any errors that occur. - upb_status *status; + // Msgdef for the current level. + upb_msgdef *msgdef; // Stack entries store the offset where the submsg ends (for groups, 0). upb_decoder_frame *top, *limit; @@ -68,10 +66,10 @@ struct _upb_decoder { // End of this submessage, relative to *ptr. const char *submsg_end; - // Msgdef for the current level. - upb_msgdef *msgdef; + // Where we will store any errors that occur. + upb_status *status; - size_t bytes_parsed_fast, bytes_parsed_slow; + upb_decoder_frame stack[UPB_MAX_NESTING]; }; // A upb_decoder decodes the binary protocol buffer format, writing the data it diff --git a/src/upb_msg.h b/src/upb_msg.h index 468af24..1e0a176 100644 --- a/src/upb_msg.h +++ b/src/upb_msg.h @@ -280,8 +280,9 @@ typedef struct { } upb_msgpopulator_frame; typedef struct { - upb_msgpopulator_frame stack[UPB_MAX_NESTING], *top, *limit; + upb_msgpopulator_frame *top, *limit; upb_status status; + upb_msgpopulator_frame stack[UPB_MAX_NESTING]; } upb_msgpopulator; void upb_msgpopulator_init(upb_msgpopulator *p); -- cgit v1.2.3