Track buffer end instead of buffer length, for a small perf improvement.

pull/13171/head
Joshua Haberman 14 years ago
parent 5edfe9a4c9
commit f9a6f67e27
  1. 46
      src/upb_decoder.c
  2. 6
      src/upb_decoder.h
  3. 29
      src/upb_def.h
  4. 2
      src/upb_stream.h

@ -81,6 +81,33 @@ done:
return true;
}
typedef struct {
const char *newbuf;
uint64_t val;
} retval;
retval upb_decode_varint_fast64(const char *p) {
uint64_t ret;
uint64_t b;
retval r = {(void*)0, 0};
b = *(p++); ret = (b & 0x7f) ; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 7; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 14; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 21; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 28; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 35; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 42; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 49; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 56; if(!(b & 0x80)) goto done;
b = *(p++); ret |= (b & 0x7f) << 63; if(!(b & 0x80)) goto done;
return r;
done:
r.val = ret;
r.newbuf = p;
return r;
}
#endif
@ -98,7 +125,10 @@ INLINE int64_t upb_zzdec_64(uint64_t n) { return (n >> 1) ^ -(int64_t)(n & 1); }
INLINE void upb_decoder_advance(upb_decoder *d, size_t len) {
d->ptr += len;
d->len -= len;
}
INLINE size_t upb_decoder_bufleft(upb_decoder *d) {
return d->end - d->ptr;
}
INLINE void upb_dstate_setmsgend(upb_decoder *d) {
@ -113,7 +143,7 @@ static upb_flow_t upb_pop(upb_decoder *d);
// from the stream to "data", adjusting the dstate appropriately.
static bool upb_getbuf(upb_decoder *d, void *data, size_t bytes_wanted) {
while (1) {
size_t to_copy = UPB_MIN(bytes_wanted, d->len);
size_t to_copy = UPB_MIN(bytes_wanted, upb_decoder_bufleft(d));
memcpy(data, d->ptr, to_copy);
upb_decoder_advance(d, to_copy);
bytes_wanted -= to_copy;
@ -127,7 +157,7 @@ static bool upb_getbuf(upb_decoder *d, void *data, size_t bytes_wanted) {
upb_string_recycle(&d->buf);
if (!upb_bytesrc_getstr(d->bytesrc, d->buf, d->status)) return false;
d->ptr = upb_string_getrobuf(d->buf);
d->len = upb_string_len(d->buf);
d->end = d->ptr + upb_string_len(d->buf);
}
}
@ -171,7 +201,7 @@ INLINE bool upb_decode_tag(upb_decoder *d, upb_tag *tag) {
uint32_t tag_int;
upb_value val;
// Nearly all tag varints will be either 1 byte (1-16) or 2 bytes (17-2048).
if (d->len < 2) goto slow; // unlikely.
if (upb_decoder_bufleft(d) < 2) goto slow; // unlikely.
tag_int = *p & 0x7f;
if ((*(p++) & 0x80) == 0) goto done; // predictable if fields are in order
tag_int |= (*p & 0x7f) << 7;
@ -189,7 +219,7 @@ done:
}
INLINE bool upb_decode_varint(upb_decoder *d, upb_value *val) {
if (d->len >= 16) {
if (upb_decoder_bufleft(d) >= 16) {
// Common (fast) case.
uint64_t val64;
const char *p = d->ptr;
@ -203,7 +233,7 @@ INLINE bool upb_decode_varint(upb_decoder *d, upb_value *val) {
}
INLINE bool upb_decode_fixed(upb_decoder *d, size_t bytes, upb_value *val) {
if (d->len >= bytes) {
if (upb_decoder_bufleft(d) >= bytes) {
// Common (fast) case.
memcpy(val, d->ptr, bytes);
upb_decoder_advance(d, bytes);
@ -219,7 +249,7 @@ INLINE bool upb_decode_string(upb_decoder *d, upb_value *val,
upb_string **str) {
upb_string_recycle(str);
uint32_t strlen = upb_value_getint32(*val);
if (d->len >= strlen) {
if (upb_decoder_bufleft(d) >= strlen) {
// Common (fast) case.
upb_string_substr(*str, d->buf, d->ptr - upb_string_getrobuf(d->buf), strlen);
upb_decoder_advance(d, strlen);
@ -278,7 +308,7 @@ void upb_decoder_run(upb_src *src, upb_status *status) {
upb_decoder *d = (upb_decoder*)src;
d->status = status;
d->ptr = NULL;
d->len = 0; // Force a buffer pull.
d->end = NULL; // Force a buffer pull.
d->submsg_end = (void*)0x1; // But don't let end-of-message get triggered.
d->msgdef = d->top->msgdef;

@ -62,12 +62,12 @@ struct _upb_decoder {
// Our current position in the data buffer.
const char *ptr;
// End of this buffer, relative to *ptr.
const char *end;
// End of this submessage, relative to *ptr.
const char *submsg_end;
// Number of bytes available at ptr.
size_t len;
// Msgdef for the current level.
upb_msgdef *msgdef;
};

@ -88,29 +88,26 @@ INLINE void upb_def_unref(upb_def *def) {
// is either a field of a upb_msgdef or contained inside a upb_extensiondef.
// It is also reference-counted.
typedef struct _upb_fielddef {
upb_value default_value;
uint8_t type;
uint8_t label;
// True if we own a ref on "def" (above). This is true unless this edge is
// part of a cycle.
bool owned;
uint8_t set_bit_mask;
upb_string *name;
int32_t number;
int16_t field_index; // Indicates set bit.
uint16_t set_bit_offset;
uint32_t byte_offset; // Where in a upb_msg to find the data.
upb_value default_value;
upb_string *name;
struct _upb_msgdef *msgdef;
// For the case of an enum or a submessage, points to the def for that type.
upb_def *def;
upb_atomic_refcount_t refcount;
uint32_t byte_offset; // Where in a upb_msg to find the data.
// These are set only when this fielddef is part of a msgdef.
upb_field_number_t number;
upb_field_count_t field_index; // Indicates set bit.
upb_fieldtype_t type;
upb_label_t label;
// True if we own a ref on "def" (above). This is true unless this edge is
// part of a cycle.
bool owned;
uint8_t set_bit_mask;
uint16_t set_bit_offset;
} upb_fielddef;
// A variety of tests about the type of a field.

@ -60,7 +60,7 @@ struct _upb_fielddef;
// continue or not.
typedef enum {
// Caller should continue sending values to the sink.
UPB_CONTINUE,
UPB_CONTINUE = 0,
// Stop processing for now; check status for details. If no status was set,
// a generic error will be returned. If the error is resumable, it is not

Loading…
Cancel
Save