Table-driven supports repeated sub-messages.

pull/13171/head
Joshua Haberman 4 years ago
parent f173642db4
commit 88b1ec7784
  1. 2
      upb/decode.h
  2. 129
      upb/decode_fast.c
  3. 10
      upbc/generator.cc

@ -89,8 +89,10 @@ const char *upb_pos_1bt(UPB_PARSE_PARAMS);
const char *upb_pos_2bt(UPB_PARSE_PARAMS);
const char *upb_psm_1bt(UPB_PARSE_PARAMS);
const char *upb_pom_1bt(UPB_PARSE_PARAMS);
const char *upb_prm_1bt(UPB_PARSE_PARAMS);
const char *upb_psm_2bt(UPB_PARSE_PARAMS);
const char *upb_pom_2bt(UPB_PARSE_PARAMS);
const char *upb_prm_2bt(UPB_PARSE_PARAMS);
#undef F
#undef TYPES

@ -56,8 +56,18 @@ UPB_FORCEINLINE uint64_t fastdecode_munge(uint64_t val, int valbytes, bool zigza
}
UPB_FORCEINLINE
static void *fastdecode_getfield_ofs(upb_msg *msg, size_t ofs, uint64_t *data,
uint64_t *hasbits, upb_card card) {
static uint16_t fastdecode_readtag(const char *ptr, int tagbytes) {
uint16_t ret = 0;
memcpy(&ret, ptr, tagbytes);
return ret;
}
UPB_FORCEINLINE
static void *fastdecode_getfield_ofs(upb_decstate *d, const char *ptr,
upb_msg *msg, size_t ofs, uint64_t *data,
uint64_t *hasbits, upb_array **outarr,
int tagbytes, int valbytes,
upb_card card) {
void *field = (char *)msg + ofs;
switch (card) {
@ -69,17 +79,51 @@ static void *fastdecode_getfield_ofs(upb_msg *msg, size_t ofs, uint64_t *data,
*case_ptr = (*data >> 32) & 0xffff;
return field;
}
case CARD_r:
UPB_ASSERT(false); /* NYI */
case CARD_r: {
uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
upb_array **arr_p = field;
upb_array *arr;
uint64_t elem_avail;
uint16_t expected_tag;
*hasbits >>= 16;
*(uint32_t*)msg |= *hasbits;
*hasbits = 0;
if (UPB_LIKELY(!*arr_p)) {
size_t need = (valbytes * 4) + sizeof(upb_array);
if (UPB_UNLIKELY((size_t)(d->arena_end - d->arena_ptr) < need)) {
*data = 0;
return NULL;
}
arr = (void*)d->arena_ptr;
field = arr + 1;
arr->data = _upb_array_tagptr(field, elem_size_lg2);
*arr_p = arr;
arr->size = 4;
arr->len = 0;
elem_avail = 4;
d->arena_ptr += need;
} else {
arr = *arr_p;
field = _upb_array_ptr(arr);
elem_avail = arr->size - arr->len;
field = (char*)field + (arr->len * valbytes);
}
expected_tag = fastdecode_readtag(ptr, tagbytes);
*data = elem_avail | ((uint64_t)expected_tag << 32);
*outarr = arr;
return field;
}
default:
UPB_UNREACHABLE();
}
}
UPB_FORCEINLINE
static void *fastdecode_getfield(upb_msg *msg, uint64_t *data,
uint64_t *hasbits, upb_card card) {
return fastdecode_getfield_ofs(msg, *data >> 48, data, hasbits, card);
static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
uint64_t *data, uint64_t *hasbits,
int tagbytes, int valbytes, upb_card card) {
return fastdecode_getfield_ofs(d, ptr, msg, *data >> 48, data, hasbits, NULL,
tagbytes, valbytes, card);
}
/* varint fields **************************************************************/
@ -92,7 +136,8 @@ static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes,
if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
return fastdecode_generic(UPB_PARSE_ARGS);;
}
dst = fastdecode_getfield(msg, &data, &hasbits, card);
dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, tagbytes, valbytes,
card);
if (UPB_UNLIKELY(ptr[tagbytes] < 0)) {
return fastdecode_generic(UPB_PARSE_ARGS);
}
@ -158,7 +203,8 @@ static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes,
return fastdecode_generic(UPB_PARSE_ARGS);
}
dst = fastdecode_getfield(msg, &data, &hasbits, card);
dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, tagbytes,
sizeof(upb_strview), card);
len = ptr[tagbytes];
if (UPB_UNLIKELY(len < 0)) {
return fastdecode_generic(UPB_PARSE_ARGS);
@ -198,30 +244,46 @@ static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
const upb_msglayout_field *field = &table->fields[data >> 48];
size_t ofs = field->offset;
const upb_msglayout *subl = table->submsgs[field->submsg_index];
upb_array *arr;
upb_msg **submsg;
int64_t len;
if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
return fastdecode_generic(UPB_PARSE_ARGS);
}
submsg = fastdecode_getfield_ofs(msg, ofs, &data, &hasbits, card);
len = ptr[tagbytes];
if (UPB_UNLIKELY(len < 0)) {
return fastdecode_generic(UPB_PARSE_ARGS);
}
ptr += tagbytes + 1;
if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, len, d->limit))) {
return fastdecode_err(d);
}
if (!*submsg) {
*submsg = decode_newmsg(d, subl);
submsg = fastdecode_getfield_ofs(d, ptr, msg, ofs, &data, &hasbits, &arr,
tagbytes, sizeof(upb_msg *), card);
again:
if (card == CARD_r) {
if (UPB_UNLIKELY((uint32_t)data == 0)) {
return fastdecode_generic(UPB_PARSE_ARGS);
}
}
saved_limit = d->limit;
if (--d->depth < 0) return fastdecode_err(d);
d->limit = ptr + len;
d->fastlimit = UPB_MIN(d->limit, d->fastend);
{
int64_t len = ptr[tagbytes];
if (UPB_UNLIKELY(len < 0)) {
return fastdecode_generic(UPB_PARSE_ARGS);
}
ptr += tagbytes + 1;
if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, len, d->limit))) {
return fastdecode_err(d);
}
if (card == CARD_r || !*submsg) {
*submsg = decode_newmsg(d, subl);
}
if (card == CARD_r) {
size_t elem_ofs = (size_t)(submsg - (upb_msg **)_upb_array_ptr(arr));
UPB_ASSERT(elem_ofs == arr->len);
arr->len++;
}
saved_limit = d->limit;
if (--d->depth < 0) return fastdecode_err(d);
d->limit = ptr + len;
d->fastlimit = UPB_MIN(d->limit, d->fastend);
}
ptr = fastdecode_dispatch(d, ptr, *submsg, subl, 0);
if (ptr != d->limit) return fastdecode_err(d);
@ -231,6 +293,15 @@ static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
if (d->end_group != 0) return fastdecode_err(d);
d->depth++;
if (card == CARD_r) {
if (UPB_LIKELY(ptr < d->fastlimit) &&
fastdecode_readtag(ptr, tagbytes) == (uint16_t)(data >> 32)) {
data--;
submsg++;
goto again;
}
}
return fastdecode_dispatch(d, ptr, msg, table, hasbits);
}
@ -242,6 +313,10 @@ const char *upb_pom_1bt(UPB_PARSE_PARAMS) {
return fastdecode_submsg(UPB_PARSE_ARGS, 1, CARD_o);
}
const char *upb_prm_1bt(UPB_PARSE_PARAMS) {
return fastdecode_submsg(UPB_PARSE_ARGS, 1, CARD_r);
}
const char *upb_psm_2bt(UPB_PARSE_PARAMS) {
return fastdecode_submsg(UPB_PARSE_ARGS, 2, CARD_s);
}
@ -249,3 +324,7 @@ const char *upb_psm_2bt(UPB_PARSE_PARAMS) {
const char *upb_pom_2bt(UPB_PARSE_PARAMS) {
return fastdecode_submsg(UPB_PARSE_ARGS, 2, CARD_o);
}
const char *upb_prm_2bt(UPB_PARSE_PARAMS) {
return fastdecode_submsg(UPB_PARSE_ARGS, 2, CARD_r);
}

@ -738,6 +738,9 @@ void TryFillTableEntry(const protobuf::Descriptor* message,
wire_type = 2;
break;
case protobuf::FieldDescriptor::TYPE_MESSAGE:
if (field->is_map()) {
return; // Not supported yet (ever?).
}
type = "m";
wire_type = 2;
break;
@ -747,7 +750,12 @@ void TryFillTableEntry(const protobuf::Descriptor* message,
switch (field->label()) {
case protobuf::FieldDescriptor::LABEL_REPEATED:
return; // Not supported yet.
if (field->type() == protobuf::FieldDescriptor::TYPE_MESSAGE) {
cardinality = "r";
break;
} else {
return; // Not supported yet.
}
case protobuf::FieldDescriptor::LABEL_OPTIONAL:
case protobuf::FieldDescriptor::LABEL_REQUIRED:
if (field->real_containing_oneof()) {

Loading…
Cancel
Save