From 87fc2c516bff207f880c71526926842fd8dcc77e Mon Sep 17 00:00:00 2001 From: Josh Haberman Date: Wed, 7 Jan 2015 18:02:09 -0800 Subject: Changes from Google-internal development. * JSON parser expanded to handle split buffers. * bugfix to the protobuf decoder. --- upb/pb/compile_decoder.c | 17 +++++++++++++++-- upb/pb/compile_decoder_x64.dasc | 3 +++ upb/pb/compile_decoder_x64.h | 7 ++++++- upb/pb/decoder.c | 6 +++++- upb/pb/decoder.int.h | 4 +++- 5 files changed, 32 insertions(+), 5 deletions(-) (limited to 'upb/pb') diff --git a/upb/pb/compile_decoder.c b/upb/pb/compile_decoder.c index 64689f6..11aa4e9 100644 --- a/upb/pb/compile_decoder.c +++ b/upb/pb/compile_decoder.c @@ -302,6 +302,7 @@ static void putop(compiler *c, opcode op, ...) { case OP_SETDELIM: case OP_HALT: case OP_RET: + case OP_DISPATCH: put32(c, op); break; case OP_PARSE_DOUBLE: @@ -382,7 +383,7 @@ const char *upb_pbdecoder_getopname(unsigned int op) { OP(ENDSUBMSG), OP(STARTSTR), OP(STRING), OP(ENDSTR), OP(CALL), OP(RET), OP(PUSHLENDELIM), OP(PUSHTAGDELIM), OP(SETDELIM), OP(CHECKDELIM), OP(BRANCH), OP(TAG1), OP(TAG2), OP(TAGN), OP(SETDISPATCH), OP(POP), - OP(SETBIGGROUPNUM), OP(HALT), + OP(SETBIGGROUPNUM), OP(DISPATCH), OP(HALT), }; return op > OP_HALT ? names[0] : names[op]; #undef OP @@ -414,6 +415,7 @@ static void dumpbc(uint32_t *p, uint32_t *end, FILE *f) { upb_handlers_msgdef(method->dest_handlers_))); break; } + case OP_DISPATCH: case OP_STARTMSG: case OP_ENDMSG: case OP_PUSHLENDELIM: @@ -759,6 +761,7 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) { putop(c, OP_SETDISPATCH, &method->dispatch); putsel(c, OP_STARTMSG, UPB_STARTMSG_SELECTOR, h); label(c, LABEL_FIELD); + uint32_t* start_pc = c->pc; upb_msg_iter i; for(upb_msg_begin(&i, md); !upb_msg_done(&i); upb_msg_next(&i)) { const upb_fielddef *f = upb_msg_iter_field(&i); @@ -774,8 +777,18 @@ static void compile_method(compiler *c, upb_pbdecodermethod *method) { } } + // If there were no fields, or if no handlers were defined, we need to + // generate a non-empty loop body so that we can at least dispatch for unknown + // fields and check for the end of the message. + if (c->pc == start_pc) { + // Check for end-of-message. + putop(c, OP_CHECKDELIM, LABEL_ENDMSG); + // Unconditionally dispatch. + putop(c, OP_DISPATCH, 0); + } + // For now we just loop back to the last field of the message (or if none, - // the DISPATCH opcode for the message. + // the DISPATCH opcode for the message). putop(c, OP_BRANCH, -LABEL_FIELD); // Insert both a label and a dispatch table entry for this end-of-msg. diff --git a/upb/pb/compile_decoder_x64.dasc b/upb/pb/compile_decoder_x64.dasc index bac1ac2..3181cab 100644 --- a/upb/pb/compile_decoder_x64.dasc +++ b/upb/pb/compile_decoder_x64.dasc @@ -1124,6 +1124,9 @@ static void jitbytecode(jitcompiler *jc) { jittag(jc, tag, arg >> 8, (int8_t)arg, method); break; } + case OP_DISPATCH: + | call =>jmptarget(jc, &method->dispatch) + break; case OP_HALT: assert(false); } diff --git a/upb/pb/compile_decoder_x64.h b/upb/pb/compile_decoder_x64.h index ba3636e..ef4459d 100644 --- a/upb/pb/compile_decoder_x64.h +++ b/upb/pb/compile_decoder_x64.h @@ -1680,6 +1680,11 @@ static void jitbytecode(jitcompiler *jc) { jittag(jc, tag, arg >> 8, (int8_t)arg, method); break; } + case OP_DISPATCH: + //| call =>jmptarget(jc, &method->dispatch) + dasm_put(Dst, 2151, jmptarget(jc, &method->dispatch)); +# 1129 "upb/pb/compile_decoder_x64.dasc" + break; case OP_HALT: assert(false); } @@ -1688,5 +1693,5 @@ static void jitbytecode(jitcompiler *jc) { asmlabel(jc, "eof"); //| nop dasm_put(Dst, 1909); -# 1134 "upb/pb/compile_decoder_x64.dasc" +# 1137 "upb/pb/compile_decoder_x64.dasc" } diff --git a/upb/pb/decoder.c b/upb/pb/decoder.c index ec8c03f..04ca413 100644 --- a/upb/pb/decoder.c +++ b/upb/pb/decoder.c @@ -801,6 +801,9 @@ size_t upb_pbdecoder_decode(void *closure, const void *hd, const char *buf, if (result == DECODE_MISMATCH) goto badtag; if (result >= 0) return result; }) + VMCASE(OP_DISPATCH, { + CHECK_RETURN(dispatch(d)); + }) VMCASE(OP_HALT, { return size; }) @@ -859,7 +862,8 @@ bool upb_pbdecoder_end(void *closure, const void *handler_data) { // Rewind from OP_TAG* to OP_CHECKDELIM. assert(getop(*d->pc) == OP_TAG1 || getop(*d->pc) == OP_TAG2 || - getop(*d->pc) == OP_TAGN); + getop(*d->pc) == OP_TAGN || + getop(*d->pc == OP_DISPATCH)); d->pc = p; } upb_pbdecoder_decode(closure, handler_data, &dummy, 0, NULL); diff --git a/upb/pb/decoder.int.h b/upb/pb/decoder.int.h index 9b35b70..302701e 100644 --- a/upb/pb/decoder.int.h +++ b/upb/pb/decoder.int.h @@ -66,7 +66,9 @@ typedef enum { // | unused (24) | opc | // | upb_inttable* (32 or 64) | - OP_HALT = 36, // No arg. + OP_DISPATCH = 36, // No arg. + + OP_HALT = 37, // No arg. } opcode; #define OP_MAX OP_HALT -- cgit v1.2.3