Give all field parsers a generic table entry.

pull/13171/head
Joshua Haberman 4 years ago
parent 383ae5293e
commit 438ecaeb5a
  1. 1
      CMakeLists.txt
  2. 6
      benchmark.py
  3. 999
      generated_for_cmake/google/protobuf/descriptor.upb.c
  4. 23
      upb/decode.c
  5. 19
      upb/decode.h
  6. 37
      upb/decode_fast.c
  7. 5
      upb/def.c
  8. 10
      upb/msg.h
  9. 8
      upbc/generator.cc

@ -64,6 +64,7 @@ add_library(port
upb/port.c)
add_library(upb
upb/decode.c
upb/decode_fast.c
upb/encode.c
upb/msg.c
upb/msg.h

@ -30,12 +30,12 @@ def Run(cmd):
def Benchmark(outbase, runs=12):
tmpfile = "/tmp/bench-output.json"
Run("rm -rf {}".format(tmpfile))
Run("bazel test :all")
Run("bazel build -c opt :benchmark")
Run("CC=clang bazel test :all")
Run("CC=clang bazel build -c opt :benchmark")
Run("./bazel-bin/benchmark --benchmark_out_format=json --benchmark_out={} --benchmark_repetitions={}".format(tmpfile, runs))
Run("bazel build -c opt --copt=-g :conformance_upb")
Run("CC=clang bazel build -c opt --copt=-g :conformance_upb")
Run("cp -f bazel-bin/conformance_upb {}.bin".format(outbase))
with open(tmpfile) as f:

File diff suppressed because it is too large Load Diff

@ -275,6 +275,7 @@ static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
return _upb_msg_new(subl, d->arena);
}
UPB_FORCEINLINE
static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
const upb_msglayout *layout,
const upb_msglayout_field *field, upb_strview val) {
@ -288,6 +289,7 @@ static void decode_tosubmsg(upb_decstate *d, upb_msg *submsg,
d->depth++;
}
UPB_FORCEINLINE
static const char *decode_group(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *subl,
uint32_t number) {
@ -299,6 +301,7 @@ static const char *decode_group(upb_decstate *d, const char *ptr,
return ptr;
}
UPB_FORCEINLINE
static const char *decode_togroup(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *layout,
const upb_msglayout_field *field) {
@ -306,6 +309,7 @@ static const char *decode_togroup(upb_decstate *d, const char *ptr,
return decode_group(d, ptr, submsg, subl, field->number);
}
UPB_FORCEINLINE
static const char *decode_toarray(upb_decstate *d, const char *ptr,
upb_msg *msg, const upb_msglayout *layout,
const upb_msglayout_field *field, wireval val,
@ -398,6 +402,7 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
}
}
UPB_FORCEINLINE
static void decode_tomap(upb_decstate *d, upb_msg *msg,
const upb_msglayout *layout,
const upb_msglayout_field *field, wireval val) {
@ -434,6 +439,7 @@ static void decode_tomap(upb_decstate *d, upb_msg *msg,
_upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, d->arena);
}
UPB_FORCEINLINE
static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout,
const upb_msglayout_field *field, wireval val,
@ -491,8 +497,9 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
return ptr;
}
const char *decode_field(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout) {
UPB_FORCEINLINE
static const char *decode_field(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout) {
uint32_t tag;
const upb_msglayout_field *field;
int field_number;
@ -587,10 +594,19 @@ const char *decode_field(upb_decstate *d, const char *ptr, upb_msg *msg,
return ptr;
}
const char *fastdecode_generic(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *table, uint64_t hasbits,
uint64_t data) {
*(uint32_t*)msg |= hasbits; /* Sync hasbits. */
(void)data;
return decode_field(d, ptr, msg, table);
}
static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout) {
while (ptr < d->limit) {
ptr = decode_field(d, ptr, msg, layout);
ptr = fastdecode_dispatch(d, ptr, msg, layout, 0);
if (ptr < d->limit) ptr = decode_field(d, ptr, msg, layout);
}
if (ptr != d->limit) decode_err(d);
@ -601,6 +617,7 @@ bool upb_decode(const char *buf, size_t size, void *msg, const upb_msglayout *l,
upb_arena *arena) {
upb_decstate state;
state.limit = buf + size;
state.fastlimit = buf + size - 16;
state.arena = arena;
state.depth = 64;
state.end_group = 0;

@ -16,19 +16,6 @@ extern "C" {
bool upb_decode(const char *buf, size_t size, upb_msg *msg,
const upb_msglayout *l, upb_arena *arena);
struct upb_fasttable;
struct upb_decstate;
typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
upb_msg *msg, struct upb_fasttable *table,
uint64_t hasbits, uint64_t data);
typedef struct upb_fasttable {
_upb_field_parser *field_parser[16];
uint64_t field_data[16];
_upb_field_parser *fallback;
} upb_fasttable;
/* Internal only: data pertaining to the parse. */
typedef struct upb_decstate {
char *arena_ptr, *arena_end;
@ -43,6 +30,12 @@ typedef struct upb_decstate {
jmp_buf err;
} upb_decstate;
const char *fastdecode_dispatch(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *table, uint64_t hasbits);
const char *fastdecode_generic(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *table, uint64_t hasbits,
uint64_t data);
#ifdef __cplusplus
} /* extern "C" */
#endif

@ -3,30 +3,34 @@
#include "upb/port_def.inc"
#define UPB_PARSE_PARAMS \
upb_decstate *d, const char *ptr, upb_msg *msg, upb_fasttable *table, \
#define UPB_PARSE_PARAMS \
upb_decstate *d, const char *ptr, upb_msg *msg, const upb_msglayout *table, \
uint64_t hasbits, uint64_t data
#define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
const char *fastdecode_err(upb_decstate *d);
const char *fastdecode_reallocarr(upb_decstate *d, const char *ptr,
upb_msg *msg, upb_fasttable *table,
size_t needbytes);
UPB_NOINLINE
static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr,
upb_msg *msg, upb_fasttable *table,
uint64_t hasbits) {
const char *fastdecode_dispatch(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *table, uint64_t hasbits) {
uint16_t tag;
uint64_t data;
size_t idx;
if (UPB_UNLIKELY(ptr >= d->fastlimit)) return ptr;
memcpy(&tag, ptr, 2);
data = table->field_data[(tag & 0xf7) >> 3] ^ tag;
return table->field_parser[(tag & 0xf7) >> 3](UPB_PARSE_ARGS);
idx = (tag & 0xf8) >> 3;
data = table->field_data[idx] ^ tag;
return table->field_parser[idx](UPB_PARSE_ARGS);
}
#if 0
const char *fastdecode_err(upb_decstate *d);
const char *fastdecode_reallocarr(upb_decstate *d, const char *ptr,
upb_msg *msg, upb_msglayout *table,
size_t needbytes);
UPB_FORCEINLINE
static bool fastdecode_checktag(uint64_t data, int tagbytes) {
if (tagbytes == 1) {
@ -134,7 +138,7 @@ static void *fastdecode_getfield(upb_decstate *d, const char *ptr, upb_msg *msg,
UPB_NOINLINE
static const char *fastdecode_longstring(upb_decstate *d, const char *ptr,
upb_msg *msg, upb_fasttable *table,
upb_msg *msg, upb_msglayout *table,
uint64_t hasbits, upb_strview *dst) {
uint32_t len;
if (!fastdecode_readlongsize(ptr, &len, &ptr)) {
@ -271,7 +275,7 @@ again:
UPB_NOINLINE
const char *fastdecode_longfixedpacked(upb_decstate *d, const char *ptr,
upb_msg *msg, upb_fasttable *table,
upb_msg *msg, upb_msglayout *table,
uint64_t hasbits, void *dst);
UPB_FORCEINLINE
@ -345,9 +349,6 @@ const char *upb_prf8_1bt(UPB_PARSE_PARAMS) {
return fastdecode_fixed(UPB_PARSE_ARGS, 1, 8, CARD_r, &upb_ppf8_1bt);
}
#if 0
// Generate all fixed functions.
// {s,o,r,p} x {f4,f8} x {1bt,2bt}

@ -949,6 +949,7 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
const upb_msglayout **submsgs;
upb_msglayout_field *fields;
upb_alloc *alloc = upb_arena_alloc(symtab->arena);
size_t i;
memset(l, 0, sizeof(*l));
@ -965,6 +966,10 @@ static bool make_layout(const upb_symtab *symtab, const upb_msgdef *m) {
l->fields = fields;
l->submsgs = submsgs;
for (i = 0; i < 32; i++) {
l->field_parser[i] = &fastdecode_generic;
}
if (upb_msgdef_mapentry(m)) {
/* TODO(haberman): refactor this method so this special case is more
* elegant. */

@ -46,7 +46,17 @@ typedef struct {
uint8_t label; /* google.protobuf.Label or _UPB_LABEL_* above. */
} upb_msglayout_field;
struct upb_msglayout;
struct upb_decstate;
typedef const char *_upb_field_parser(struct upb_decstate *d, const char *ptr,
upb_msg *msg,
const struct upb_msglayout *table,
uint64_t hasbits, uint64_t data);
typedef struct upb_msglayout {
_upb_field_parser *field_parser[32];
uint64_t field_data[32];
const struct upb_msglayout *const* submsgs;
const upb_msglayout_field *fields;
/* Must be aligned to sizeof(void*). Doesn't include internal members like

@ -804,6 +804,14 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output) {
}
output("const upb_msglayout $0 = {\n", MessageInit(message));
output(" {\n");
for (int i = 0; i < 32; i++) {
output(" &fastdecode_generic,\n");
}
output(" },\n");
output(" {\n");
output(" 0\n");
output(" },\n");
output(" $0,\n", submsgs_array_ref);
output(" $0,\n", fields_array_ref);
output(" $0, $1, $2,\n", GetSizeInit(layout.message_size()),

Loading…
Cancel
Save