pull/13171/head
Gerben Stavenga 4 years ago
parent 36662b3735
commit 4053805759
  1. 77
      upb/decode_fast.c
  2. 3
      upbc/generator.cc

@ -87,9 +87,6 @@ static void *fastdecode_getfield_ofs(upb_decstate *d, const char *ptr,
const size_t initial_len = 8; const size_t initial_len = 8;
size_t need = (valbytes * initial_len) + sizeof(upb_array); size_t need = (valbytes * initial_len) + sizeof(upb_array);
if (UPB_UNLIKELY((size_t)(d->arena_end - d->arena_ptr) < need)) { if (UPB_UNLIKELY((size_t)(d->arena_end - d->arena_ptr) < need)) {
*outarr = NULL;
*data = 0;
*end = NULL;
return NULL; return NULL;
} }
arr = (void*)d->arena_ptr; arr = (void*)d->arena_ptr;
@ -262,40 +259,25 @@ const char *upb_pos_2bt(UPB_PARSE_PARAMS) {
/* message fields *************************************************************/ /* message fields *************************************************************/
UPB_FORCEINLINE
bool fastdecode_boundscheck2(const char *ptr, unsigned len, const char *end) {
uintptr_t uptr = (uintptr_t)ptr;
uintptr_t uend = (uintptr_t)end;
uintptr_t res = uptr + len;
return res < uptr || res > uend;
}
UPB_NOINLINE static UPB_NOINLINE static
const char *fastdecode_lendelim_submsg(upb_decstate *d, const char *ptr, upb_msg *msg, const char *fastdecode_lendelim_submsg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *table, uint64_t hasbits, const char* saved_limit) { const upb_msglayout *table, uint64_t hasbits, const char* saved_limit) {
uint32_t len = (uint8_t)ptr[-1]; size_t len = (uint8_t)ptr[-1];
if (UPB_UNLIKELY(len & 0x80)) { if (UPB_UNLIKELY(len & 0x80)) {
ptr++; for (int i = 0; i < 3; i++) {
uint32_t byte = (uint8_t)ptr[-1];
len += (byte - 1) << 7;
if (UPB_UNLIKELY(byte & 0x80)) {
ptr++; ptr++;
uint32_t byte = (uint8_t)ptr[-1]; size_t byte = (uint8_t)ptr[-1];
len += (byte - 1) << 14; len += (byte - 1) << (7 + 7 * i);
if (UPB_UNLIKELY(byte & 0x80)) { if (UPB_LIKELY((byte & 0x80) == 0)) goto done;
ptr++;
uint32_t byte = (uint8_t)ptr[-1];
len += (byte - 1) << 21;
if (UPB_UNLIKELY(byte & 0x80)) {
ptr++;
uint32_t byte = (uint8_t)ptr[-1];
len += (byte - 1) << 28;
if (UPB_UNLIKELY(byte >= 8)) return fastdecode_err(d);
}
}
} }
ptr++;
size_t byte = (uint8_t)ptr[-1];
// len is limited by 2gb not 4gb, hence 8 and not 16 as normally expected for a 32 bit varint.
if (UPB_UNLIKELY(byte >= 8)) return fastdecode_err(d);
len += (byte - 1) << 28;
} }
if (UPB_UNLIKELY(fastdecode_boundscheck2(ptr, len, saved_limit))) { done:
if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, len, saved_limit))) {
return fastdecode_err(d); return fastdecode_err(d);
} }
d->limit = ptr + len; d->limit = ptr + len;
@ -318,11 +300,16 @@ static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
upb_array *arr; upb_array *arr;
void *end; void *end;
uint32_t submsg_idx = data; uint32_t submsg_idx = data;
submsg_idx >>= 16; asm("" : "+r" (submsg_idx)); submsg_idx >>= 16;
const upb_msglayout *subl = table->submsgs[submsg_idx]; const upb_msglayout *subl = table->submsgs[submsg_idx];
submsg = fastdecode_getfield_ofs(d, ptr, msg, &data, &hasbits, &arr, &end, submsg = fastdecode_getfield_ofs(d, ptr, msg, &data, &hasbits, &arr, &end,
sizeof(upb_msg *), card, true); sizeof(upb_msg *), card, true);
if (card == CARD_r) {
if (UPB_UNLIKELY(!submsg)) {
RETURN_GENERIC("need array resize\n");
}
}
if (card == CARD_s) { if (card == CARD_s) {
*(uint32_t*)msg |= hasbits >> 16; *(uint32_t*)msg |= hasbits >> 16;
hasbits = 0; hasbits = 0;
@ -334,24 +321,20 @@ static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
again: again:
if (card == CARD_r) { if (card == CARD_r) {
if (UPB_UNLIKELY(submsg == end)) { if (UPB_UNLIKELY(submsg == end)) {
if (UPB_LIKELY(arr != NULL)) { size_t old_size = arr->size;
size_t old_size = arr->size; size_t old_bytes = old_size * sizeof(upb_msg*);
size_t old_bytes = old_size * sizeof(upb_msg*); size_t new_size = old_size * 2;
size_t new_size = old_size * 2; size_t new_bytes = new_size * sizeof(upb_msg*);
size_t new_bytes = new_size * sizeof(upb_msg*); char *old_ptr = _upb_array_ptr(arr);
char *old_ptr = _upb_array_ptr(arr); if (UPB_UNLIKELY((size_t)(d->arena_end - d->arena_ptr) < new_bytes)) {
if (UPB_UNLIKELY((size_t)(d->arena_end - d->arena_ptr) < new_bytes)) {
goto repeated_generic;
}
memcpy(d->arena_ptr, old_ptr, old_bytes);
arr->size = new_size;
arr->data = _upb_array_tagptr(d->arena_ptr, 3);
submsg = (void*)(d->arena_ptr + (old_size * sizeof(upb_msg*)));
end = (void*)(d->arena_ptr + (new_size * sizeof(upb_msg*)));
d->arena_ptr += new_bytes;
} else {
goto repeated_generic; goto repeated_generic;
} }
memcpy(d->arena_ptr, old_ptr, old_bytes);
arr->size = new_size;
arr->data = _upb_array_tagptr(d->arena_ptr, 3);
submsg = (void*)(d->arena_ptr + (old_size * sizeof(upb_msg*)));
end = (void*)(d->arena_ptr + (new_size * sizeof(upb_msg*)));
d->arena_ptr += new_bytes;
} }
} }

@ -795,6 +795,9 @@ void TryFillTableEntry(const protobuf::Descriptor* message,
if (layout.HasHasbit(field)) { if (layout.HasHasbit(field)) {
hasbit_index = layout.GetHasbitIndex(field); hasbit_index = layout.GetHasbitIndex(field);
if (hasbit_index > 31) return; if (hasbit_index > 31) return;
// thas hasbits mask in the parser occupies bits 16-48
// in the 64 bit register.
hasbit_index += 16; // account for the shifted hasbits
} }
MessageLayout::Size data; MessageLayout::Size data;

Loading…
Cancel
Save