Avoid passing too many params to fallback.

pull/13171/head
Joshua Haberman 4 years ago
parent 763a3f6293
commit 34b98bc030
  1. 36
      upb/decode_fast.c

@ -52,22 +52,23 @@ const char *upb_psf32_2bt(UPB_PARSE_PARAMS) {
}
UPB_FORCEINLINE
static const char *fastdecode_longvarint_impl(UPB_PARSE_PARAMS, int64_t res1,
int valbytes) {
static const char *fastdecode_longvarint_impl(UPB_PARSE_PARAMS, int valbytes) {
char *field = (char *)data;
// The algorithm relies on sign extension to set all high bits when the varint
// continues. This way it can use "and" to aggregate in to the result.
const int8_t *p = (const int8_t*)(ptr);
int64_t res1 = *p;
uint64_t ones = res1; // save the useful high bit 1's in res1
uint64_t byte;
int64_t res2, res3;
int sign_bit;
// However this requires the low bits after shifting to be 1's as well. On
// x86_64 a shld from a single register filled with enough 1's in the high
// bits can accomplish all this in one instruction. It so happens that res1
// has 57 high bits of ones, which is enough for the largest shift done.
assert(res1 >> 7 == -1);
uint64_t ones = res1; // save the useful high bit 1's in res1
uint64_t byte;
int64_t res2, res3;
int sign_bit;
#define SHLD(n) byte = ((byte << (n * 7)) | (ones >> (64 - (n * 7))))
@ -155,22 +156,21 @@ done2 : {
}
UPB_NOINLINE
static const char *fastdecode_longvarint32(UPB_PARSE_PARAMS, int64_t val) {
return fastdecode_longvarint_impl(d, ptr, msg, table, hasbits, data, val, 4);
static const char *fastdecode_longvarint32(UPB_PARSE_PARAMS) {
return fastdecode_longvarint_impl(d, ptr, msg, table, hasbits, data, 4);
}
UPB_NOINLINE
static const char *fastdecode_longvarint64(UPB_PARSE_PARAMS, int64_t val) {
return fastdecode_longvarint_impl(d, ptr, msg, table, hasbits, data, val, 8);
static const char *fastdecode_longvarint64(UPB_PARSE_PARAMS) {
return fastdecode_longvarint_impl(d, ptr, msg, table, hasbits, data, 8);
}
UPB_FORCEINLINE
static const char *fastdecode_longvarint(UPB_PARSE_PARAMS, int64_t val,
int valbytes) {
static const char *fastdecode_longvarint(UPB_PARSE_PARAMS, int valbytes) {
if (valbytes == 4) {
return fastdecode_longvarint32(d, ptr, msg, table, hasbits, data, val);
return fastdecode_longvarint32(d, ptr, msg, table, hasbits, data);
} else if (valbytes == 8) {
return fastdecode_longvarint64(d, ptr, msg, table, hasbits, data, val);
return fastdecode_longvarint64(d, ptr, msg, table, hasbits, data);
}
UPB_UNREACHABLE();
}
@ -178,17 +178,17 @@ static const char *fastdecode_longvarint(UPB_PARSE_PARAMS, int64_t val,
UPB_FORCEINLINE
static const char *fastdecode_scalarvarint(UPB_PARSE_PARAMS, int tagbytes,
int valbytes) {
int64_t val;
uint64_t val = 0;
void *field;
if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) return ptr;
ptr += tagbytes;
hasbits |= data;
field = (char*)msg + (data >> 48);
val = *ptr;
if (UPB_UNLIKELY(val < 0)) {
if (UPB_UNLIKELY(*ptr < 0)) {
return fastdecode_longvarint(d, ptr, msg, table, hasbits, (uint64_t)field,
val, valbytes);
valbytes);
}
val = *ptr;
memcpy(field, &val, valbytes);
return fastdecode_dispatch(d, ptr + 1, msg, table, hasbits);
}

Loading…
Cancel
Save