summaryrefslogtreecommitdiff
path: root/upb/pb
diff options
context:
space:
mode:
authorJosh Haberman <jhaberman@gmail.com>2015-01-07 18:02:09 -0800
committerJosh Haberman <jhaberman@gmail.com>2015-01-07 18:02:09 -0800
commit87fc2c516bff207f880c71526926842fd8dcc77e (patch)
tree8b9e8685170e227c927454af47f7535077295afd /upb/pb
parentd18475ae57dc62fc6dc8d9e32ffa0ce571df00bf (diff)
Changes from Google-internal development.
* JSON parser expanded to handle split buffers. * bugfix to the protobuf decoder.
Diffstat (limited to 'upb/pb')
-rw-r--r--upb/pb/compile_decoder.c17
-rw-r--r--upb/pb/compile_decoder_x64.dasc3
-rw-r--r--upb/pb/compile_decoder_x64.h7
-rw-r--r--upb/pb/decoder.c6
-rw-r--r--upb/pb/decoder.int.h4
5 files changed, 32 insertions, 5 deletions
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
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback