Merge pull request #396 from haberman/pre-ext-opt

Optimized decoder and paved the way for parsing extensions.
pull/13171/head
Joshua Haberman 4 years ago committed by GitHub
commit 52be845c39
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 54
      cmake/google/protobuf/descriptor.upb.c
  2. 116
      upb/decode.c
  3. 11
      upb/def.c
  4. 1
      upb/msg_internal.h
  5. 13
      upbc/protoc-gen-upb.cc

@ -23,7 +23,7 @@ static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] =
const upb_msglayout google_protobuf_FileDescriptorSet_msginit = { const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
&google_protobuf_FileDescriptorSet_submsgs[0], &google_protobuf_FileDescriptorSet_submsgs[0],
&google_protobuf_FileDescriptorSet__fields[0], &google_protobuf_FileDescriptorSet__fields[0],
UPB_SIZE(8, 8), 1, false, 255, UPB_SIZE(8, 8), 1, false, 1, 255,
}; };
static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = { static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
@ -53,7 +53,7 @@ static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12]
const upb_msglayout google_protobuf_FileDescriptorProto_msginit = { const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
&google_protobuf_FileDescriptorProto_submsgs[0], &google_protobuf_FileDescriptorProto_submsgs[0],
&google_protobuf_FileDescriptorProto__fields[0], &google_protobuf_FileDescriptorProto__fields[0],
UPB_SIZE(64, 128), 12, false, 255, UPB_SIZE(64, 128), 12, false, 12, 255,
}; };
static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = { static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
@ -82,7 +82,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
const upb_msglayout google_protobuf_DescriptorProto_msginit = { const upb_msglayout google_protobuf_DescriptorProto_msginit = {
&google_protobuf_DescriptorProto_submsgs[0], &google_protobuf_DescriptorProto_submsgs[0],
&google_protobuf_DescriptorProto__fields[0], &google_protobuf_DescriptorProto__fields[0],
UPB_SIZE(48, 96), 10, false, 255, UPB_SIZE(48, 96), 10, false, 10, 255,
}; };
static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = { static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
@ -98,7 +98,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange_
const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = { const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
&google_protobuf_DescriptorProto_ExtensionRange_submsgs[0], &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
&google_protobuf_DescriptorProto_ExtensionRange__fields[0], &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
UPB_SIZE(16, 24), 3, false, 255, UPB_SIZE(16, 24), 3, false, 3, 255,
}; };
static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = { static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
@ -109,7 +109,7 @@ static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__
const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = { const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
NULL, NULL,
&google_protobuf_DescriptorProto_ReservedRange__fields[0], &google_protobuf_DescriptorProto_ReservedRange__fields[0],
UPB_SIZE(16, 16), 2, false, 255, UPB_SIZE(16, 16), 2, false, 2, 255,
}; };
static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
@ -123,7 +123,7 @@ static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1
const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = { const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
&google_protobuf_ExtensionRangeOptions_submsgs[0], &google_protobuf_ExtensionRangeOptions_submsgs[0],
&google_protobuf_ExtensionRangeOptions__fields[0], &google_protobuf_ExtensionRangeOptions__fields[0],
UPB_SIZE(8, 8), 1, false, 255, UPB_SIZE(8, 8), 1, false, 0, 255,
}; };
static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = { static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
@ -147,7 +147,7 @@ static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11
const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = { const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
&google_protobuf_FieldDescriptorProto_submsgs[0], &google_protobuf_FieldDescriptorProto_submsgs[0],
&google_protobuf_FieldDescriptorProto__fields[0], &google_protobuf_FieldDescriptorProto__fields[0],
UPB_SIZE(72, 112), 11, false, 255, UPB_SIZE(72, 112), 11, false, 10, 255,
}; };
static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = { static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
@ -162,7 +162,7 @@ static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2]
const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = { const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
&google_protobuf_OneofDescriptorProto_submsgs[0], &google_protobuf_OneofDescriptorProto_submsgs[0],
&google_protobuf_OneofDescriptorProto__fields[0], &google_protobuf_OneofDescriptorProto__fields[0],
UPB_SIZE(16, 32), 2, false, 255, UPB_SIZE(16, 32), 2, false, 2, 255,
}; };
static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = { static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
@ -182,7 +182,7 @@ static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5]
const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = { const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
&google_protobuf_EnumDescriptorProto_submsgs[0], &google_protobuf_EnumDescriptorProto_submsgs[0],
&google_protobuf_EnumDescriptorProto__fields[0], &google_protobuf_EnumDescriptorProto__fields[0],
UPB_SIZE(32, 64), 5, false, 255, UPB_SIZE(32, 64), 5, false, 5, 255,
}; };
static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = { static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
@ -193,7 +193,7 @@ static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReserve
const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = { const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
NULL, NULL,
&google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0], &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
UPB_SIZE(16, 16), 2, false, 255, UPB_SIZE(16, 16), 2, false, 2, 255,
}; };
static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = { static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
@ -209,7 +209,7 @@ static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__field
const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = { const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
&google_protobuf_EnumValueDescriptorProto_submsgs[0], &google_protobuf_EnumValueDescriptorProto_submsgs[0],
&google_protobuf_EnumValueDescriptorProto__fields[0], &google_protobuf_EnumValueDescriptorProto__fields[0],
UPB_SIZE(24, 32), 3, false, 255, UPB_SIZE(24, 32), 3, false, 3, 255,
}; };
static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = { static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
@ -226,7 +226,7 @@ static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[
const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = { const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
&google_protobuf_ServiceDescriptorProto_submsgs[0], &google_protobuf_ServiceDescriptorProto_submsgs[0],
&google_protobuf_ServiceDescriptorProto__fields[0], &google_protobuf_ServiceDescriptorProto__fields[0],
UPB_SIZE(24, 48), 3, false, 255, UPB_SIZE(24, 48), 3, false, 3, 255,
}; };
static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = { static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
@ -245,7 +245,7 @@ static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6
const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = { const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
&google_protobuf_MethodDescriptorProto_submsgs[0], &google_protobuf_MethodDescriptorProto_submsgs[0],
&google_protobuf_MethodDescriptorProto__fields[0], &google_protobuf_MethodDescriptorProto__fields[0],
UPB_SIZE(32, 64), 6, false, 255, UPB_SIZE(32, 64), 6, false, 6, 255,
}; };
static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
@ -279,7 +279,7 @@ static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
const upb_msglayout google_protobuf_FileOptions_msginit = { const upb_msglayout google_protobuf_FileOptions_msginit = {
&google_protobuf_FileOptions_submsgs[0], &google_protobuf_FileOptions_submsgs[0],
&google_protobuf_FileOptions__fields[0], &google_protobuf_FileOptions__fields[0],
UPB_SIZE(104, 192), 21, false, 255, UPB_SIZE(104, 192), 21, false, 1, 255,
}; };
static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
@ -297,7 +297,7 @@ static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
const upb_msglayout google_protobuf_MessageOptions_msginit = { const upb_msglayout google_protobuf_MessageOptions_msginit = {
&google_protobuf_MessageOptions_submsgs[0], &google_protobuf_MessageOptions_submsgs[0],
&google_protobuf_MessageOptions__fields[0], &google_protobuf_MessageOptions__fields[0],
UPB_SIZE(16, 16), 5, false, 255, UPB_SIZE(16, 16), 5, false, 3, 255,
}; };
static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
@ -317,7 +317,7 @@ static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
const upb_msglayout google_protobuf_FieldOptions_msginit = { const upb_msglayout google_protobuf_FieldOptions_msginit = {
&google_protobuf_FieldOptions_submsgs[0], &google_protobuf_FieldOptions_submsgs[0],
&google_protobuf_FieldOptions__fields[0], &google_protobuf_FieldOptions__fields[0],
UPB_SIZE(24, 24), 7, false, 255, UPB_SIZE(24, 24), 7, false, 3, 255,
}; };
static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
@ -331,7 +331,7 @@ static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
const upb_msglayout google_protobuf_OneofOptions_msginit = { const upb_msglayout google_protobuf_OneofOptions_msginit = {
&google_protobuf_OneofOptions_submsgs[0], &google_protobuf_OneofOptions_submsgs[0],
&google_protobuf_OneofOptions__fields[0], &google_protobuf_OneofOptions__fields[0],
UPB_SIZE(8, 8), 1, false, 255, UPB_SIZE(8, 8), 1, false, 0, 255,
}; };
static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
@ -347,7 +347,7 @@ static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
const upb_msglayout google_protobuf_EnumOptions_msginit = { const upb_msglayout google_protobuf_EnumOptions_msginit = {
&google_protobuf_EnumOptions_submsgs[0], &google_protobuf_EnumOptions_submsgs[0],
&google_protobuf_EnumOptions__fields[0], &google_protobuf_EnumOptions__fields[0],
UPB_SIZE(8, 16), 3, false, 255, UPB_SIZE(8, 16), 3, false, 0, 255,
}; };
static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
@ -362,7 +362,7 @@ static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
const upb_msglayout google_protobuf_EnumValueOptions_msginit = { const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
&google_protobuf_EnumValueOptions_submsgs[0], &google_protobuf_EnumValueOptions_submsgs[0],
&google_protobuf_EnumValueOptions__fields[0], &google_protobuf_EnumValueOptions__fields[0],
UPB_SIZE(8, 16), 2, false, 255, UPB_SIZE(8, 16), 2, false, 1, 255,
}; };
static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
@ -377,7 +377,7 @@ static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
const upb_msglayout google_protobuf_ServiceOptions_msginit = { const upb_msglayout google_protobuf_ServiceOptions_msginit = {
&google_protobuf_ServiceOptions_submsgs[0], &google_protobuf_ServiceOptions_submsgs[0],
&google_protobuf_ServiceOptions__fields[0], &google_protobuf_ServiceOptions__fields[0],
UPB_SIZE(8, 16), 2, false, 255, UPB_SIZE(8, 16), 2, false, 0, 255,
}; };
static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = { static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
@ -393,7 +393,7 @@ static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
const upb_msglayout google_protobuf_MethodOptions_msginit = { const upb_msglayout google_protobuf_MethodOptions_msginit = {
&google_protobuf_MethodOptions_submsgs[0], &google_protobuf_MethodOptions_submsgs[0],
&google_protobuf_MethodOptions__fields[0], &google_protobuf_MethodOptions__fields[0],
UPB_SIZE(16, 24), 3, false, 255, UPB_SIZE(16, 24), 3, false, 0, 255,
}; };
static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = { static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
@ -413,7 +413,7 @@ static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7]
const upb_msglayout google_protobuf_UninterpretedOption_msginit = { const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
&google_protobuf_UninterpretedOption_submsgs[0], &google_protobuf_UninterpretedOption_submsgs[0],
&google_protobuf_UninterpretedOption__fields[0], &google_protobuf_UninterpretedOption__fields[0],
UPB_SIZE(64, 96), 7, false, 255, UPB_SIZE(64, 96), 7, false, 0, 255,
}; };
static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = { static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
@ -424,7 +424,7 @@ static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__f
const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = { const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
NULL, NULL,
&google_protobuf_UninterpretedOption_NamePart__fields[0], &google_protobuf_UninterpretedOption_NamePart__fields[0],
UPB_SIZE(16, 32), 2, false, 255, UPB_SIZE(16, 32), 2, false, 2, 255,
}; };
static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = { static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
@ -438,7 +438,7 @@ static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
const upb_msglayout google_protobuf_SourceCodeInfo_msginit = { const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
&google_protobuf_SourceCodeInfo_submsgs[0], &google_protobuf_SourceCodeInfo_submsgs[0],
&google_protobuf_SourceCodeInfo__fields[0], &google_protobuf_SourceCodeInfo__fields[0],
UPB_SIZE(8, 8), 1, false, 255, UPB_SIZE(8, 8), 1, false, 1, 255,
}; };
static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = { static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
@ -452,7 +452,7 @@ static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields
const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = { const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
NULL, NULL,
&google_protobuf_SourceCodeInfo_Location__fields[0], &google_protobuf_SourceCodeInfo_Location__fields[0],
UPB_SIZE(32, 64), 5, false, 255, UPB_SIZE(32, 64), 5, false, 4, 255,
}; };
static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = { static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
@ -466,7 +466,7 @@ static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] =
const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = { const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
&google_protobuf_GeneratedCodeInfo_submsgs[0], &google_protobuf_GeneratedCodeInfo_submsgs[0],
&google_protobuf_GeneratedCodeInfo__fields[0], &google_protobuf_GeneratedCodeInfo__fields[0],
UPB_SIZE(8, 8), 1, false, 255, UPB_SIZE(8, 8), 1, false, 1, 255,
}; };
static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = { static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
@ -479,7 +479,7 @@ static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__f
const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = { const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
NULL, NULL,
&google_protobuf_GeneratedCodeInfo_Annotation__fields[0], &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
UPB_SIZE(24, 48), 4, false, 255, UPB_SIZE(24, 48), 4, false, 4, 255,
}; };
#include "upb/port_undef.inc" #include "upb/port_undef.inc"

@ -299,24 +299,43 @@ static void decode_munge(int type, wireval *val) {
} }
static const upb_msglayout_field *upb_find_field(const upb_msglayout *l, static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
uint32_t field_number) { uint32_t field_number,
int *last_field_index) {
static upb_msglayout_field none = {0, 0, 0, 0, 0, 0}; static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
/* Lots of optimization opportunities here. */
int i;
if (l == NULL) return &none; if (l == NULL) return &none;
for (i = 0; i < l->field_count; i++) {
if (l->fields[i].number == field_number) { size_t idx = ((size_t)field_number) - 1; // 0 wraps to SIZE_MAX
return &l->fields[i]; if (idx < l->dense_below) {
goto found;
}
/* Resume scanning from last_field_index since fields are usually in order. */
int last = *last_field_index;
for (idx = last; idx < l->field_count; idx++) {
if (l->fields[idx].number == field_number) {
goto found;
}
}
for (idx = 0; idx < last; idx++) {
if (l->fields[idx].number == field_number) {
goto found;
} }
} }
return &none; /* Unknown field. */ return &none; /* Unknown field. */
found:
UPB_ASSERT(l->fields[idx].number == field_number);
*last_field_index = idx;
return &l->fields[idx];
} }
static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout, static upb_msg *decode_newsubmsg(upb_decstate *d,
upb_msglayout const *const *submsgs,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
const upb_msglayout *subl = layout->submsgs[field->submsg_index]; const upb_msglayout *subl = submsgs[field->submsg_index];
return _upb_msg_new_inl(subl, &d->arena); return _upb_msg_new_inl(subl, &d->arena);
} }
@ -346,9 +365,10 @@ static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
UPB_FORCEINLINE UPB_FORCEINLINE
static const char *decode_tosubmsg(upb_decstate *d, const char *ptr, static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *layout, upb_msg *submsg,
upb_msglayout const *const *submsgs,
const upb_msglayout_field *field, int size) { const upb_msglayout_field *field, int size) {
const upb_msglayout *subl = layout->submsgs[field->submsg_index]; const upb_msglayout *subl = submsgs[field->submsg_index];
int saved_delta = decode_pushlimit(d, ptr, size); int saved_delta = decode_pushlimit(d, ptr, size);
if (--d->depth < 0) decode_err(d); if (--d->depth < 0) decode_err(d);
if (!decode_isdone(d, &ptr)) { if (!decode_isdone(d, &ptr)) {
@ -377,15 +397,17 @@ static const char *decode_group(upb_decstate *d, const char *ptr,
UPB_FORCEINLINE UPB_FORCEINLINE
static const char *decode_togroup(upb_decstate *d, const char *ptr, static const char *decode_togroup(upb_decstate *d, const char *ptr,
upb_msg *submsg, const upb_msglayout *layout, upb_msg *submsg,
upb_msglayout const *const *submsgs,
const upb_msglayout_field *field) { const upb_msglayout_field *field) {
const upb_msglayout *subl = layout->submsgs[field->submsg_index]; const upb_msglayout *subl = submsgs[field->submsg_index];
return decode_group(d, ptr, submsg, subl, field->number); return decode_group(d, ptr, submsg, subl, field->number);
} }
static const char *decode_toarray(upb_decstate *d, const char *ptr, static const char *decode_toarray(upb_decstate *d, const char *ptr,
upb_msg *msg, const upb_msglayout *layout, upb_msg *msg,
const upb_msglayout_field *field, wireval val, upb_msglayout const *const *submsgs,
const upb_msglayout_field *field, wireval *val,
int op) { int op) {
upb_array **arrp = UPB_PTR_AT(msg, field->offset, void); upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
upb_array *arr = *arrp; upb_array *arr = *arrp;
@ -407,27 +429,27 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
/* Append scalar value. */ /* Append scalar value. */
mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void); mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
arr->len++; arr->len++;
memcpy(mem, &val, 1 << op); memcpy(mem, val, 1 << op);
return ptr; return ptr;
case OP_STRING: case OP_STRING:
decode_verifyutf8(d, ptr, val.size); decode_verifyutf8(d, ptr, val->size);
/* Fallthrough. */ /* Fallthrough. */
case OP_BYTES: { case OP_BYTES: {
/* Append bytes. */ /* Append bytes. */
upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len; upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
arr->len++; arr->len++;
return decode_readstr(d, ptr, val.size, str); return decode_readstr(d, ptr, val->size, str);
} }
case OP_SUBMSG: { case OP_SUBMSG: {
/* Append submessage / group. */ /* Append submessage / group. */
upb_msg *submsg = decode_newsubmsg(d, layout, field); upb_msg *submsg = decode_newsubmsg(d, submsgs, field);
*UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) = *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
submsg; submsg;
arr->len++; arr->len++;
if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) { if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
return decode_togroup(d, ptr, submsg, layout, field); return decode_togroup(d, ptr, submsg, submsgs, field);
} else { } else {
return decode_tosubmsg(d, ptr, submsg, layout, field, val.size); return decode_tosubmsg(d, ptr, submsg, submsgs, field, val->size);
} }
} }
case OP_FIXPCK_LG2(2): case OP_FIXPCK_LG2(2):
@ -435,15 +457,15 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
/* Fixed packed. */ /* Fixed packed. */
int lg2 = op - OP_FIXPCK_LG2(0); int lg2 = op - OP_FIXPCK_LG2(0);
int mask = (1 << lg2) - 1; int mask = (1 << lg2) - 1;
size_t count = val.size >> lg2; size_t count = val->size >> lg2;
if ((val.size & mask) != 0) { if ((val->size & mask) != 0) {
decode_err(d); /* Length isn't a round multiple of elem size. */ decode_err(d); /* Length isn't a round multiple of elem size. */
} }
decode_reserve(d, arr, count); decode_reserve(d, arr, count);
mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
arr->len += count; arr->len += count;
memcpy(mem, ptr, val.size); /* XXX: ptr boundary. */ memcpy(mem, ptr, val->size); /* XXX: ptr boundary. */
return ptr + val.size; return ptr + val->size;
} }
case OP_VARPCK_LG2(0): case OP_VARPCK_LG2(0):
case OP_VARPCK_LG2(2): case OP_VARPCK_LG2(2):
@ -451,7 +473,7 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
/* Varint packed. */ /* Varint packed. */
int lg2 = op - OP_VARPCK_LG2(0); int lg2 = op - OP_VARPCK_LG2(0);
int scale = 1 << lg2; int scale = 1 << lg2;
int saved_limit = decode_pushlimit(d, ptr, val.size); int saved_limit = decode_pushlimit(d, ptr, val->size);
char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void); char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
while (!decode_isdone(d, &ptr)) { while (!decode_isdone(d, &ptr)) {
wireval elem; wireval elem;
@ -473,16 +495,15 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
} }
static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg, static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout, upb_msglayout const *const *submsgs,
const upb_msglayout_field *field, wireval val) { const upb_msglayout_field *field, wireval *val) {
upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *); upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
upb_map *map = *map_p; upb_map *map = *map_p;
upb_map_entry ent; upb_map_entry ent;
const upb_msglayout *entry = layout->submsgs[field->submsg_index]; const upb_msglayout *entry = submsgs[field->submsg_index];
if (!map) { if (!map) {
/* Lazily create map. */ /* Lazily create map. */
const upb_msglayout *entry = layout->submsgs[field->submsg_index];
const upb_msglayout_field *key_field = &entry->fields[0]; const upb_msglayout_field *key_field = &entry->fields[0];
const upb_msglayout_field *val_field = &entry->fields[1]; const upb_msglayout_field *val_field = &entry->fields[1];
char key_size = desctype_to_mapsize[key_field->descriptortype]; char key_size = desctype_to_mapsize[key_field->descriptortype];
@ -502,28 +523,28 @@ static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena)); ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
} }
ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size); ptr = decode_tosubmsg(d, ptr, &ent.k, submsgs, field, val->size);
_upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena); _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
return ptr; return ptr;
} }
static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg, static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout, upb_msglayout const *const *submsgs,
const upb_msglayout_field *field, wireval val, const upb_msglayout_field *field, wireval *val,
int op) { int op) {
void *mem = UPB_PTR_AT(msg, field->offset, void); void *mem = UPB_PTR_AT(msg, field->offset, void);
int type = field->descriptortype; int type = field->descriptortype;
/* Set presence if necessary. */ /* Set presence if necessary. */
if (field->presence < 0) { if (field->presence > 0) {
_upb_sethas_field(msg, field);
} else if (field->presence < 0) {
/* Oneof case */ /* Oneof case */
uint32_t *oneof_case = _upb_oneofcase_field(msg, field); uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
if (op == OP_SUBMSG && *oneof_case != field->number) { if (op == OP_SUBMSG && *oneof_case != field->number) {
memset(mem, 0, sizeof(void*)); memset(mem, 0, sizeof(void*));
} }
*oneof_case = field->number; *oneof_case = field->number;
} else if (field->presence > 0) {
_upb_sethas_field(msg, field);
} }
/* Store into message. */ /* Store into message. */
@ -532,29 +553,29 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
upb_msg **submsgp = mem; upb_msg **submsgp = mem;
upb_msg *submsg = *submsgp; upb_msg *submsg = *submsgp;
if (!submsg) { if (!submsg) {
submsg = decode_newsubmsg(d, layout, field); submsg = decode_newsubmsg(d, submsgs, field);
*submsgp = submsg; *submsgp = submsg;
} }
if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) { if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
ptr = decode_togroup(d, ptr, submsg, layout, field); ptr = decode_togroup(d, ptr, submsg, submsgs, field);
} else { } else {
ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size); ptr = decode_tosubmsg(d, ptr, submsg, submsgs, field, val->size);
} }
break; break;
} }
case OP_STRING: case OP_STRING:
decode_verifyutf8(d, ptr, val.size); decode_verifyutf8(d, ptr, val->size);
/* Fallthrough. */ /* Fallthrough. */
case OP_BYTES: case OP_BYTES:
return decode_readstr(d, ptr, val.size, mem); return decode_readstr(d, ptr, val->size, mem);
case OP_SCALAR_LG2(3): case OP_SCALAR_LG2(3):
memcpy(mem, &val, 8); memcpy(mem, val, 8);
break; break;
case OP_SCALAR_LG2(2): case OP_SCALAR_LG2(2):
memcpy(mem, &val, 4); memcpy(mem, val, 4);
break; break;
case OP_SCALAR_LG2(0): case OP_SCALAR_LG2(0):
memcpy(mem, &val, 1); memcpy(mem, val, 1);
break; break;
default: default:
UPB_UNREACHABLE(); UPB_UNREACHABLE();
@ -580,6 +601,7 @@ static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
UPB_NOINLINE UPB_NOINLINE
static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg, static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
const upb_msglayout *layout) { const upb_msglayout *layout) {
int last_field_index = 0;
while (true) { while (true) {
uint32_t tag; uint32_t tag;
const upb_msglayout_field *field; const upb_msglayout_field *field;
@ -594,7 +616,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
field_number = tag >> 3; field_number = tag >> 3;
wire_type = tag & 7; wire_type = tag & 7;
field = upb_find_field(layout, field_number); field = upb_find_field(layout, field_number, &last_field_index);
switch (wire_type) { switch (wire_type) {
case UPB_WIRE_TYPE_VARINT: case UPB_WIRE_TYPE_VARINT:
@ -646,13 +668,13 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
switch (field->label) { switch (field->label) {
case UPB_LABEL_REPEATED: case UPB_LABEL_REPEATED:
case _UPB_LABEL_PACKED: case _UPB_LABEL_PACKED:
ptr = decode_toarray(d, ptr, msg, layout, field, val, op); ptr = decode_toarray(d, ptr, msg, layout->submsgs, field, &val, op);
break; break;
case _UPB_LABEL_MAP: case _UPB_LABEL_MAP:
ptr = decode_tomap(d, ptr, msg, layout, field, val); ptr = decode_tomap(d, ptr, msg, layout->submsgs, field, &val);
break; break;
default: default:
ptr = decode_tomsg(d, ptr, msg, layout, field, val, op); ptr = decode_tomsg(d, ptr, msg, layout->submsgs, field, &val, op);
break; break;
} }
} else { } else {

@ -1018,15 +1018,22 @@ static int field_number_cmp(const void *p1, const void *p2) {
return f1->number - f2->number; return f1->number - f2->number;
} }
static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) { static void assign_layout_indices(const upb_msgdef *m, upb_msglayout *l,
upb_msglayout_field *fields) {
int i; int i;
int n = upb_msgdef_numfields(m); int n = upb_msgdef_numfields(m);
int dense_below = 0;
for (i = 0; i < n; i++) { for (i = 0; i < n; i++) {
upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number); upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
UPB_ASSERT(f); UPB_ASSERT(f);
f->layout_index = i; f->layout_index = i;
if (i < UINT8_MAX && fields[i].number == i + 1 &&
(i == 0 || fields[i-1].number == i)) {
dense_below = i + 1;
} }
} }
l->dense_below = dense_below;
}
/* This function is the dynamic equivalent of message_layout.{cc,h} in upbc. /* This function is the dynamic equivalent of message_layout.{cc,h} in upbc.
* It computes a dynamic layout for all of the fields in |m|. */ * It computes a dynamic layout for all of the fields in |m|. */
@ -1197,7 +1204,7 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
/* Sort fields by number. */ /* Sort fields by number. */
qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp); qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
assign_layout_indices(m, fields); assign_layout_indices(m, l, fields);
} }
static char *strviewdup(symtab_addctx *ctx, upb_strview view) { static char *strviewdup(symtab_addctx *ctx, upb_strview view) {

@ -65,6 +65,7 @@ struct upb_msglayout {
uint16_t size; uint16_t size;
uint16_t field_count; uint16_t field_count;
bool extendable; bool extendable;
uint8_t dense_below;
uint8_t table_mask; uint8_t table_mask;
/* To constant-initialize the tables of variable length, we need a flexible /* To constant-initialize the tables of variable length, we need a flexible
* array member, and we need to compile in C99 mode. */ * array member, and we need to compile in C99 mode. */

@ -867,6 +867,8 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output,
std::string msgname = ToCIdent(message->full_name()); std::string msgname = ToCIdent(message->full_name());
std::string fields_array_ref = "NULL"; std::string fields_array_ref = "NULL";
std::string submsgs_array_ref = "NULL"; std::string submsgs_array_ref = "NULL";
uint8_t dense_below = 0;
int dense_below_max = std::numeric_limits<decltype(dense_below)>::max();
MessageLayout layout(message); MessageLayout layout(message);
SubmsgArray submsg_array(message); SubmsgArray submsg_array(message);
@ -892,10 +894,16 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output,
fields_array_ref = "&" + fields_array_name + "[0]"; fields_array_ref = "&" + fields_array_name + "[0]";
output("static const upb_msglayout_field $0[$1] = {\n", output("static const upb_msglayout_field $0[$1] = {\n",
fields_array_name, field_number_order.size()); fields_array_name, field_number_order.size());
for (auto field : field_number_order) { for (int i = 0; i < static_cast<int>(field_number_order.size()); i++) {
auto field = field_number_order[i];
int submsg_index = 0; int submsg_index = 0;
std::string presence = "0"; std::string presence = "0";
if (i < dense_below_max && field->number() == i + 1 &&
(i == 0 || field_number_order[i - 1]->number() == i)) {
dense_below = i + 1;
}
if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) { if (field->cpp_type() == protobuf::FieldDescriptor::CPPTYPE_MESSAGE) {
submsg_index = submsg_array.GetIndex(field); submsg_index = submsg_array.GetIndex(field);
} }
@ -951,9 +959,10 @@ void WriteSource(const protobuf::FileDescriptor* file, Output& output,
output("const upb_msglayout $0 = {\n", MessageInit(message)); output("const upb_msglayout $0 = {\n", MessageInit(message));
output(" $0,\n", submsgs_array_ref); output(" $0,\n", submsgs_array_ref);
output(" $0,\n", fields_array_ref); output(" $0,\n", fields_array_ref);
output(" $0, $1, $2, $3,\n", GetSizeInit(layout.message_size()), output(" $0, $1, $2, $3, $4,\n", GetSizeInit(layout.message_size()),
field_number_order.size(), field_number_order.size(),
"false", // TODO: extendable "false", // TODO: extendable
dense_below,
table_mask table_mask
); );
if (!table.empty()) { if (!table.empty()) {

Loading…
Cancel
Save