summaryrefslogtreecommitdiff
path: root/src/upb_decoder_x86.dasc
diff options
context:
space:
mode:
Diffstat (limited to 'src/upb_decoder_x86.dasc')
-rw-r--r--src/upb_decoder_x86.dasc74
1 files changed, 47 insertions, 27 deletions
diff --git a/src/upb_decoder_x86.dasc b/src/upb_decoder_x86.dasc
index 71df08f..ecd9899 100644
--- a/src/upb_decoder_x86.dasc
+++ b/src/upb_decoder_x86.dasc
@@ -88,7 +88,7 @@ void __attribute__((noinline)) __jit_debug_register_code() { __asm__ __volatile_
|// Checks PTR for end-of-buffer.
|.macro check_eob, m
| cmp PTR, DECODER->effective_end
-|| if (m->is_group) {
+|| if (m->endgroup_f) {
| jae ->exit_jit
|| } else {
| jae =>m->jit_endofbuf_pclabel
@@ -136,13 +136,13 @@ void __attribute__((noinline)) __jit_debug_register_code() { __asm__ __volatile_
| and edx, 0x7
| cmp ecx, m->max_field_number // Bounds-check the field.
| ja ->exit_jit // In the future; could be unknown label
-| mov rcx, qword [rcx*8 + m->tablearray] // TODO: support hybrid array/hash tables.
-| jmp rcx // Dispatch: unpredictable jump.
+| mov rax, qword [rcx*8 + m->tablearray] // TODO: support hybrid array/hash tables.
+| jmp rax // Dispatch: unpredictable jump.
|.endmacro
|
|.macro setmsgend, m
| mov rsi, DECODER->jit_end
-|| if (m->is_group) {
+|| if (m->endgroup_f) {
| mov64 rax, 0xffffffffffffffff
| mov qword DECODER->submsg_end, rax
| mov DECODER->effective_end, rsi
@@ -153,9 +153,9 @@ void __attribute__((noinline)) __jit_debug_register_code() { __asm__ __volatile_
| add rax, qword DECODER->buf
| mov DECODER->submsg_end, rax // submsg_end = d->buf + f->end_offset
| cmp rax, rsi
-| jb >1
+| jb >8
| mov rax, rsi // effective_end = min(d->submsg_end, d->jit_end)
-|1:
+|8:
| mov DECODER->effective_end, rax
|| }
|.endmacro
@@ -228,8 +228,8 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
// We check the wire type (which must be loaded in edx) because the
// table is keyed on field number, not type.
|=>f->jit_pclabel:
- | cmp edx, upb_types[f->type].native_wire_type
- | jne ->exit_jit // In the future: could be an unknown field.
+ | cmp edx, (tag & 0x7)
+ | jne ->exit_jit // In the future: could be an unknown field or packed.
|=>f->jit_pclabel_notypecheck:
|1: // Label for repeating this field.
@@ -305,10 +305,12 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| jmp =>m->jit_endofmsg_pclabel
return;
+ // Will dispatch callbacks and call submessage in a second.
case UPB_TYPE(MESSAGE):
| decode_varint tag_size
+ break;
case UPB_TYPE(GROUP):
- // Will dispatch callbacks and call submessage in a second.
+ | add PTR, tag_size
break;
default: abort();
@@ -340,10 +342,15 @@ static void upb_decoder_jit_field(upb_decoder *d, uint32_t tag, uint32_t next_ta
| jae ->exit_jit // Frame stack overflow.
| mov qword FRAME:rax->f, f
| mov qword FRAME:rax->closure, rdx
- | mov rsi, PTR
- | sub rsi, DECODER->buf
- | add r12d, esi
- | mov dword FRAME:rax->end_offset, r12d // = (d->ptr - d->buf) + delim_len
+ if (f->type == UPB_TYPE(MESSAGE)) {
+ | mov rsi, PTR
+ | sub rsi, DECODER->buf
+ | add r12d, esi
+ | mov dword FRAME:rax->end_offset, r12d // = (d->ptr - d->buf) + delim_len
+ } else {
+ assert(f->type == UPB_TYPE(GROUP));
+ | mov dword FRAME:rax->end_offset, -1U
+ }
| mov CLOSURE, rdx
| mov DECODER->dispatcher.top, rax
| mov FRAME, rax
@@ -440,11 +447,10 @@ static void upb_decoder_jit_msg(upb_decoder *d, upb_handlers_msgent *m) {
free(keys);
- if (m->is_group) {
- // Create a fake fieldent for handling "end group."
- upb_handlers_fieldent f = {0, UPB_TYPE_ENDGROUP, 0, UPB_NO_VALUE, {NULL}, NULL, 0, 0, 0, false};
- upb_decoder_jit_field(d, last_tag, m->groupnum, m, last_f, &f);
- upb_decoder_jit_field(d, m->groupnum, 0, m, &f, NULL);
+ if (m->endgroup_f) {
+ uint32_t tag = m->endgroup_f->number << 3 | UPB_WIRE_TYPE_END_GROUP;
+ upb_decoder_jit_field(d, last_tag, tag, m, last_f, m->endgroup_f);
+ upb_decoder_jit_field(d, tag, 0, m, m->endgroup_f, NULL);
} else {
upb_decoder_jit_field(d, last_tag, 0, m, last_f, NULL);
}
@@ -452,7 +458,7 @@ static void upb_decoder_jit_msg(upb_decoder *d, upb_handlers_msgent *m) {
// --------- New code section (does not fall through) ------------------------
// End-of-buf / end-of-message.
- if (!m->is_group) {
+ if (!m->endgroup_f) {
// This case doesn't exist for groups, because there eob really means
// eob, so that case just exits the jit directly.
|=>m->jit_endofbuf_pclabel:
@@ -479,6 +485,9 @@ static void upb_decoder_jit_msg(upb_decoder *d, upb_handlers_msgent *m) {
}
+static const char *dbgfmt =
+ "JIT encountered unknown field! wt=%d, fn=%d\n";
+
static void upb_decoder_jit(upb_decoder *d) {
| push rbp
| mov rbp, rsp
@@ -512,7 +521,10 @@ static void upb_decoder_jit(upb_decoder *d) {
| leave
| ret
|=>0:
- | callp &abort
+ | mov rdi, stderr
+ | mov rsi, dbgfmt
+ | callp fprintf
+ | callp abort
}
void upb_decoder_jit_assignfieldlabs(upb_handlers_fieldent *f,
@@ -522,7 +534,8 @@ void upb_decoder_jit_assignfieldlabs(upb_handlers_fieldent *f,
f->jit_submsg_done_pclabel = (*pclabel_count)++;
}
-void upb_decoder_jit_assignmsglabs(upb_handlers_msgent *m,
+void upb_decoder_jit_assignmsglabs(upb_handlers *h,
+ upb_handlers_msgent *m,
uint32_t *pclabel_count) {
m->jit_startmsg_pclabel = (*pclabel_count)++;
m->jit_endofbuf_pclabel = (*pclabel_count)++;
@@ -537,9 +550,17 @@ void upb_decoder_jit_assignmsglabs(upb_handlers_msgent *m,
m->max_field_number = UPB_MAX(m->max_field_number, key);
upb_handlers_fieldent *f = upb_inttable_iter_value(i);
upb_decoder_jit_assignfieldlabs(f, pclabel_count);
+ if (f->type == UPB_TYPE(GROUP)) {
+ upb_handlers_msgent *sub_m = upb_handlers_getmsgent(h, f);
+ sub_m->endgroup_f = malloc(sizeof(*sub_m->endgroup_f));
+ memcpy(sub_m->endgroup_f, f, sizeof(*f));
+ sub_m->endgroup_f->type = UPB_TYPE_ENDGROUP;
+ upb_decoder_jit_assignfieldlabs(sub_m->endgroup_f, pclabel_count);
+ }
}
// XXX: Won't work for large field numbers; will need to use a upb_table.
- m->tablearray = malloc((m->max_field_number + 1) * sizeof(void*));
+ // +2 to cover group case, in case group number is larger than all tags.
+ m->tablearray = malloc((m->max_field_number + 2) * sizeof(void*));
}
// Second pass: for messages that have only one parent, link them to the field
@@ -551,10 +572,6 @@ void upb_decoder_jit_assignmsglabs2(upb_handlers *h, upb_handlers_msgent *m) {
upb_handlers_fieldent *f = upb_inttable_iter_value(i);
if (upb_issubmsgtype(f->type)) {
upb_handlers_msgent *sub_m = upb_handlers_getmsgent(h, f);
- if (f->type == UPB_TYPE(GROUP)) {
- sub_m->is_group = true;
- sub_m->groupnum = upb_inttable_iter_key(i);
- }
if (sub_m->jit_parent_field_done_pclabel == UPB_NONE) {
sub_m->jit_parent_field_done_pclabel = f->jit_submsg_done_pclabel;
} else {
@@ -569,7 +586,7 @@ void upb_decoder_makejit(upb_decoder *d) {
uint32_t pclabel_count = 1;
upb_handlers *h = d->dispatcher.handlers;
for (int i = 0; i < h->msgs_len; i++)
- upb_decoder_jit_assignmsglabs(&h->msgs[i], &pclabel_count);
+ upb_decoder_jit_assignmsglabs(h, &h->msgs[i], &pclabel_count);
for (int i = 0; i < h->msgs_len; i++)
upb_decoder_jit_assignmsglabs2(h, &h->msgs[i]);
@@ -608,6 +625,9 @@ void upb_decoder_makejit(upb_decoder *d) {
m->tablearray[j] = d->jit_code + dasm_getpclabel(d, 0);
}
}
+ if (m->endgroup_f) {
+ m->tablearray[m->endgroup_f->number] = d->jit_code + dasm_getpclabel(d, m->endgroup_f->jit_pclabel);
+ }
}
// Create debug info.
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback