google-protobuf 3.17.0-x86-linux → 3.18.0.rc.1-x86-linux

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of google-protobuf might be problematic. Click here for more details.

@@ -17,5 +17,4 @@ end
17
17
  $objs = ["protobuf.o", "convert.o", "defs.o", "message.o",
18
18
  "repeated_field.o", "map.o", "ruby-upb.o", "wrap_memcpy.o"]
19
19
 
20
- find_header('third_party/wyhash/wyhash.h', '../../../..')
21
20
  create_makefile("google/protobuf_c")
@@ -167,7 +167,8 @@ VALUE Map_deep_copy(VALUE obj) {
167
167
  new_arena_rb);
168
168
  }
169
169
 
170
- const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
170
+ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef* field,
171
+ upb_arena* arena) {
171
172
  const upb_fielddef* key_field = map_field_key(field);
172
173
  const upb_fielddef* value_field = map_field_value(field);
173
174
  TypeInfo value_type_info = TypeInfo_get(value_field);
@@ -189,6 +190,7 @@ const upb_map* Map_GetUpbMap(VALUE val, const upb_fielddef *field) {
189
190
  rb_raise(cTypeError, "Map value type has wrong message/enum class");
190
191
  }
191
192
 
193
+ Arena_fuse(self->arena, arena);
192
194
  return self->map;
193
195
  }
194
196
 
@@ -236,7 +238,7 @@ static VALUE Map_merge_into_self(VALUE _self, VALUE hashmap) {
236
238
  upb_msg *self_msg = Map_GetMutable(_self);
237
239
  size_t iter = UPB_MAP_BEGIN;
238
240
 
239
- upb_arena_fuse(arena, Arena_get(other->arena));
241
+ Arena_fuse(other->arena, arena);
240
242
 
241
243
  if (self->key_type != other->key_type ||
242
244
  self->value_type_info.type != other->value_type_info.type ||
@@ -511,7 +513,7 @@ static VALUE Map_dup(VALUE _self) {
511
513
  upb_arena *arena = Arena_get(new_self->arena);
512
514
  upb_map *new_map = Map_GetMutable(new_map_rb);
513
515
 
514
- upb_arena_fuse(arena, Arena_get(self->arena));
516
+ Arena_fuse(self->arena, arena);
515
517
 
516
518
  while (upb_mapiter_next(self->map, &iter)) {
517
519
  upb_msgval key = upb_mapiter_key(self->map, iter);
@@ -44,7 +44,8 @@ VALUE Map_GetRubyWrapper(upb_map *map, upb_fieldtype_t key_type,
44
44
  // Gets the underlying upb_map for this Ruby map object, which must have
45
45
  // key/value type that match |field|. If this is not a map or the type doesn't
46
46
  // match, raises an exception.
47
- const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field);
47
+ const upb_map *Map_GetUpbMap(VALUE val, const upb_fielddef *field,
48
+ upb_arena *arena);
48
49
 
49
50
  // Implements #inspect for this map by appending its contents to |b|.
50
51
  void Map_Inspect(StringBuilder *b, const upb_map *map, upb_fieldtype_t key_type,
@@ -35,7 +35,6 @@
35
35
  #include "map.h"
36
36
  #include "protobuf.h"
37
37
  #include "repeated_field.h"
38
- #include "third_party/wyhash/wyhash.h"
39
38
 
40
39
  static VALUE cParseError = Qnil;
41
40
  static ID descriptor_instancevar_interned;
@@ -277,9 +276,9 @@ static void Message_setfield(upb_msg* msg, const upb_fielddef* f, VALUE val,
277
276
  upb_arena* arena) {
278
277
  upb_msgval msgval;
279
278
  if (upb_fielddef_ismap(f)) {
280
- msgval.map_val = Map_GetUpbMap(val, f);
279
+ msgval.map_val = Map_GetUpbMap(val, f, arena);
281
280
  } else if (upb_fielddef_isseq(f)) {
282
- msgval.array_val = RepeatedField_GetUpbArray(val, f);
281
+ msgval.array_val = RepeatedField_GetUpbArray(val, f, arena);
283
282
  } else {
284
283
  if (val == Qnil &&
285
284
  (upb_fielddef_issubmsg(f) || upb_fielddef_realcontainingoneof(f))) {
@@ -660,7 +659,7 @@ static VALUE Message_dup(VALUE _self) {
660
659
  // TODO(copy unknown fields?)
661
660
  // TODO(use official upb msg copy function)
662
661
  memcpy((upb_msg*)new_msg_self->msg, self->msg, size);
663
- upb_arena_fuse(Arena_get(new_msg_self->arena), Arena_get(self->arena));
662
+ Arena_fuse(self->arena, Arena_get(new_msg_self->arena));
664
663
  return new_msg;
665
664
  }
666
665
 
@@ -717,7 +716,7 @@ uint64_t Message_Hash(const upb_msg* msg, const upb_msgdef* m, uint64_t seed) {
717
716
  &size);
718
717
 
719
718
  if (data) {
720
- uint64_t ret = wyhash(data, size, seed, _wyp);
719
+ uint64_t ret = Wyhash(data, size, seed, kWyhashSalt);
721
720
  upb_arena_free(arena);
722
721
  return ret;
723
722
  } else {
@@ -794,6 +793,14 @@ static VALUE Message_CreateHash(const upb_msg *msg, const upb_msgdef *m) {
794
793
  VALUE msg_value;
795
794
  VALUE msg_key;
796
795
 
796
+ if (!is_proto2 && upb_fielddef_issubmsg(field) &&
797
+ !upb_fielddef_isseq(field) && !upb_msg_has(msg, field)) {
798
+ // TODO: Legacy behavior, remove when we fix the is_proto2 differences.
799
+ msg_key = ID2SYM(rb_intern(upb_fielddef_name(field)));
800
+ rb_hash_aset(hash, msg_key, Qnil);
801
+ continue;
802
+ }
803
+
797
804
  // Do not include fields that are not present (oneof or optional fields).
798
805
  if (is_proto2 && upb_fielddef_haspresence(field) &&
799
806
  !upb_msg_has(msg, field)) {
@@ -1306,7 +1313,7 @@ const upb_msg* Message_GetUpbMessage(VALUE value, const upb_msgdef* m,
1306
1313
  }
1307
1314
 
1308
1315
  Message* self = ruby_to_Message(value);
1309
- upb_arena_fuse(arena, Arena_get(self->arena));
1316
+ Arena_fuse(self->arena, arena);
1310
1317
 
1311
1318
  return self->msg;
1312
1319
  }
@@ -204,6 +204,16 @@ upb_arena *Arena_get(VALUE _arena) {
204
204
  return arena->arena;
205
205
  }
206
206
 
207
+ void Arena_fuse(VALUE _arena, upb_arena *other) {
208
+ Arena *arena;
209
+ TypedData_Get_Struct(_arena, Arena, &Arena_type, arena);
210
+ if (!upb_arena_fuse(arena->arena, other)) {
211
+ rb_raise(rb_eRuntimeError,
212
+ "Unable to fuse arenas. This should never happen since Ruby does "
213
+ "not use initial blocks");
214
+ }
215
+ }
216
+
207
217
  VALUE Arena_new() {
208
218
  return Arena_alloc(cArena);
209
219
  }
@@ -55,6 +55,10 @@ const upb_fielddef* map_field_value(const upb_fielddef* field);
55
55
  VALUE Arena_new();
56
56
  upb_arena *Arena_get(VALUE arena);
57
57
 
58
+ // Fuses this arena to another, throwing a Ruby exception if this is not
59
+ // possible.
60
+ void Arena_fuse(VALUE arena, upb_arena *other);
61
+
58
62
  // Pins this Ruby object to the lifetime of this arena, so that as long as the
59
63
  // arena is alive this object will not be collected.
60
64
  //
@@ -34,7 +34,6 @@
34
34
  #include "defs.h"
35
35
  #include "message.h"
36
36
  #include "protobuf.h"
37
- #include "third_party/wyhash/wyhash.h"
38
37
 
39
38
  // -----------------------------------------------------------------------------
40
39
  // Repeated field container type.
@@ -149,7 +148,8 @@ VALUE RepeatedField_deep_copy(VALUE _self) {
149
148
  return new_rptfield;
150
149
  }
151
150
 
152
- const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field) {
151
+ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef* field,
152
+ upb_arena* arena) {
153
153
  RepeatedField* self;
154
154
  TypeInfo type_info = TypeInfo_get(field);
155
155
 
@@ -167,6 +167,7 @@ const upb_array* RepeatedField_GetUpbArray(VALUE val, const upb_fielddef *field)
167
167
  rb_raise(cTypeError, "Repeated field array has wrong message/enum class");
168
168
  }
169
169
 
170
+ Arena_fuse(self->arena, arena);
170
171
  return self->array;
171
172
  }
172
173
 
@@ -412,7 +413,7 @@ static VALUE RepeatedField_dup(VALUE _self) {
412
413
  int size = upb_array_size(self->array);
413
414
  int i;
414
415
 
415
- upb_arena_fuse(arena, Arena_get(self->arena));
416
+ Arena_fuse(self->arena, arena);
416
417
 
417
418
  for (i = 0; i < size; i++) {
418
419
  upb_msgval msgval = upb_array_get(self->array, i);
@@ -44,7 +44,8 @@ VALUE RepeatedField_GetRubyWrapper(upb_array* msg, TypeInfo type_info,
44
44
  // Gets the underlying upb_array for this Ruby RepeatedField object, which must
45
45
  // have a type that matches |f|. If this is not a repeated field or the type
46
46
  // doesn't match, raises an exception.
47
- const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f);
47
+ const upb_array* RepeatedField_GetUpbArray(VALUE value, const upb_fielddef* f,
48
+ upb_arena* arena);
48
49
 
49
50
  // Implements #inspect for this repeated field by appending its contents to |b|.
50
51
  void RepeatedField_Inspect(StringBuilder* b, const upb_array* array,
@@ -1,27 +1,54 @@
1
1
  /* Amalgamated source file */
2
2
  #include "ruby-upb.h"
3
3
  /*
4
- * This is where we define macros used across upb.
5
- *
6
- * All of these macros are undef'd in port_undef.inc to avoid leaking them to
7
- * users.
8
- *
9
- * The correct usage is:
10
- *
11
- * #include "upb/foobar.h"
12
- * #include "upb/baz.h"
13
- *
14
- * // MUST be last included header.
15
- * #include "upb/port_def.inc"
16
- *
17
- * // Code for this file.
18
- * // <...>
19
- *
20
- * // Can be omitted for .c files, required for .h.
21
- * #include "upb/port_undef.inc"
22
- *
23
- * This file is private and must not be included by users!
24
- */
4
+ * Copyright (c) 2009-2021, Google LLC
5
+ * All rights reserved.
6
+ *
7
+ * Redistribution and use in source and binary forms, with or without
8
+ * modification, are permitted provided that the following conditions are met:
9
+ * * Redistributions of source code must retain the above copyright
10
+ * notice, this list of conditions and the following disclaimer.
11
+ * * Redistributions in binary form must reproduce the above copyright
12
+ * notice, this list of conditions and the following disclaimer in the
13
+ * documentation and/or other materials provided with the distribution.
14
+ * * Neither the name of Google LLC nor the
15
+ * names of its contributors may be used to endorse or promote products
16
+ * derived from this software without specific prior written permission.
17
+ *
18
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
19
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ * DISCLAIMED. IN NO EVENT SHALL Google LLC BE LIABLE FOR ANY
22
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
24
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
25
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
27
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
+ */
29
+
30
+ /*
31
+ * This is where we define macros used across upb.
32
+ *
33
+ * All of these macros are undef'd in port_undef.inc to avoid leaking them to
34
+ * users.
35
+ *
36
+ * The correct usage is:
37
+ *
38
+ * #include "upb/foobar.h"
39
+ * #include "upb/baz.h"
40
+ *
41
+ * // MUST be last included header.
42
+ * #include "upb/port_def.inc"
43
+ *
44
+ * // Code for this file.
45
+ * // <...>
46
+ *
47
+ * // Can be omitted for .c files, required for .h.
48
+ * #include "upb/port_undef.inc"
49
+ *
50
+ * This file is private and must not be included by users!
51
+ */
25
52
 
26
53
  #if !((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \
27
54
  (defined(__cplusplus) && __cplusplus >= 201103L) || \
@@ -137,9 +164,40 @@
137
164
  #define UPB_LONGJMP(buf, val) longjmp(buf, val)
138
165
  #endif
139
166
 
167
+ /* UPB_PTRADD(ptr, ofs): add pointer while avoiding "NULL + 0" UB */
168
+ #define UPB_PTRADD(ptr, ofs) ((ofs) ? (ptr) + (ofs) : (ptr))
169
+
140
170
  /* Configure whether fasttable is switched on or not. *************************/
141
171
 
142
- #if defined(__x86_64__) && defined(__GNUC__)
172
+ #ifdef __has_attribute
173
+ #define UPB_HAS_ATTRIBUTE(x) __has_attribute(x)
174
+ #else
175
+ #define UPB_HAS_ATTRIBUTE(x) 0
176
+ #endif
177
+
178
+ #if UPB_HAS_ATTRIBUTE(musttail)
179
+ #define UPB_MUSTTAIL __attribute__((musttail))
180
+ #else
181
+ #define UPB_MUSTTAIL
182
+ #endif
183
+
184
+ #undef UPB_HAS_ATTRIBUTE
185
+
186
+ /* This check is not fully robust: it does not require that we have "musttail"
187
+ * support available. We need tail calls to avoid consuming arbitrary amounts
188
+ * of stack space.
189
+ *
190
+ * GCC/Clang can mostly be trusted to generate tail calls as long as
191
+ * optimization is enabled, but, debug builds will not generate tail calls
192
+ * unless "musttail" is available.
193
+ *
194
+ * We should probably either:
195
+ * 1. require that the compiler supports musttail.
196
+ * 2. add some fallback code for when musttail isn't available (ie. return
197
+ * instead of tail calling). This is safe and portable, but this comes at
198
+ * a CPU cost.
199
+ */
200
+ #if (defined(__x86_64__) || defined(__aarch64__)) && defined(__GNUC__)
143
201
  #define UPB_FASTTABLE_SUPPORTED 1
144
202
  #else
145
203
  #define UPB_FASTTABLE_SUPPORTED 0
@@ -150,7 +208,7 @@
150
208
  * for example for testing or benchmarking. */
151
209
  #if defined(UPB_ENABLE_FASTTABLE)
152
210
  #if !UPB_FASTTABLE_SUPPORTED
153
- #error fasttable is x86-64 + Clang/GCC only
211
+ #error fasttable is x86-64/ARM64 only and requires GCC or Clang.
154
212
  #endif
155
213
  #define UPB_FASTTABLE 1
156
214
  /* Define UPB_TRY_ENABLE_FASTTABLE to use fasttable if possible.
@@ -194,8 +252,9 @@ void __asan_unpoison_memory_region(void const volatile *addr, size_t size);
194
252
  ((void)(addr), (void)(size))
195
253
  #define UPB_UNPOISON_MEMORY_REGION(addr, size) \
196
254
  ((void)(addr), (void)(size))
197
- #endif
255
+ #endif
198
256
 
257
+ /** upb/decode.c ************************************************************/
199
258
 
200
259
  #include <setjmp.h>
201
260
  #include <string.h>
@@ -465,24 +524,43 @@ static void decode_munge(int type, wireval *val) {
465
524
  }
466
525
 
467
526
  static const upb_msglayout_field *upb_find_field(const upb_msglayout *l,
468
- uint32_t field_number) {
527
+ uint32_t field_number,
528
+ int *last_field_index) {
469
529
  static upb_msglayout_field none = {0, 0, 0, 0, 0, 0};
470
530
 
471
- /* Lots of optimization opportunities here. */
472
- int i;
473
531
  if (l == NULL) return &none;
474
- for (i = 0; i < l->field_count; i++) {
475
- if (l->fields[i].number == field_number) {
476
- return &l->fields[i];
532
+
533
+ size_t idx = ((size_t)field_number) - 1; // 0 wraps to SIZE_MAX
534
+ if (idx < l->dense_below) {
535
+ goto found;
536
+ }
537
+
538
+ /* Resume scanning from last_field_index since fields are usually in order. */
539
+ int last = *last_field_index;
540
+ for (idx = last; idx < l->field_count; idx++) {
541
+ if (l->fields[idx].number == field_number) {
542
+ goto found;
543
+ }
544
+ }
545
+
546
+ for (idx = 0; idx < last; idx++) {
547
+ if (l->fields[idx].number == field_number) {
548
+ goto found;
477
549
  }
478
550
  }
479
551
 
480
552
  return &none; /* Unknown field. */
553
+
554
+ found:
555
+ UPB_ASSERT(l->fields[idx].number == field_number);
556
+ *last_field_index = idx;
557
+ return &l->fields[idx];
481
558
  }
482
559
 
483
- static upb_msg *decode_newsubmsg(upb_decstate *d, const upb_msglayout *layout,
560
+ static upb_msg *decode_newsubmsg(upb_decstate *d,
561
+ upb_msglayout const *const *submsgs,
484
562
  const upb_msglayout_field *field) {
485
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
563
+ const upb_msglayout *subl = submsgs[field->submsg_index];
486
564
  return _upb_msg_new_inl(subl, &d->arena);
487
565
  }
488
566
 
@@ -512,9 +590,10 @@ static const char *decode_readstr(upb_decstate *d, const char *ptr, int size,
512
590
 
513
591
  UPB_FORCEINLINE
514
592
  static const char *decode_tosubmsg(upb_decstate *d, const char *ptr,
515
- upb_msg *submsg, const upb_msglayout *layout,
593
+ upb_msg *submsg,
594
+ upb_msglayout const *const *submsgs,
516
595
  const upb_msglayout_field *field, int size) {
517
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
596
+ const upb_msglayout *subl = submsgs[field->submsg_index];
518
597
  int saved_delta = decode_pushlimit(d, ptr, size);
519
598
  if (--d->depth < 0) decode_err(d);
520
599
  if (!decode_isdone(d, &ptr)) {
@@ -543,15 +622,17 @@ static const char *decode_group(upb_decstate *d, const char *ptr,
543
622
 
544
623
  UPB_FORCEINLINE
545
624
  static const char *decode_togroup(upb_decstate *d, const char *ptr,
546
- upb_msg *submsg, const upb_msglayout *layout,
625
+ upb_msg *submsg,
626
+ upb_msglayout const *const *submsgs,
547
627
  const upb_msglayout_field *field) {
548
- const upb_msglayout *subl = layout->submsgs[field->submsg_index];
628
+ const upb_msglayout *subl = submsgs[field->submsg_index];
549
629
  return decode_group(d, ptr, submsg, subl, field->number);
550
630
  }
551
631
 
552
632
  static const char *decode_toarray(upb_decstate *d, const char *ptr,
553
- upb_msg *msg, const upb_msglayout *layout,
554
- const upb_msglayout_field *field, wireval val,
633
+ upb_msg *msg,
634
+ upb_msglayout const *const *submsgs,
635
+ const upb_msglayout_field *field, wireval *val,
555
636
  int op) {
556
637
  upb_array **arrp = UPB_PTR_AT(msg, field->offset, void);
557
638
  upb_array *arr = *arrp;
@@ -573,27 +654,27 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
573
654
  /* Append scalar value. */
574
655
  mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << op, void);
575
656
  arr->len++;
576
- memcpy(mem, &val, 1 << op);
657
+ memcpy(mem, val, 1 << op);
577
658
  return ptr;
578
659
  case OP_STRING:
579
- decode_verifyutf8(d, ptr, val.size);
660
+ decode_verifyutf8(d, ptr, val->size);
580
661
  /* Fallthrough. */
581
662
  case OP_BYTES: {
582
663
  /* Append bytes. */
583
664
  upb_strview *str = (upb_strview*)_upb_array_ptr(arr) + arr->len;
584
665
  arr->len++;
585
- return decode_readstr(d, ptr, val.size, str);
666
+ return decode_readstr(d, ptr, val->size, str);
586
667
  }
587
668
  case OP_SUBMSG: {
588
669
  /* Append submessage / group. */
589
- upb_msg *submsg = decode_newsubmsg(d, layout, field);
670
+ upb_msg *submsg = decode_newsubmsg(d, submsgs, field);
590
671
  *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void *), upb_msg *) =
591
672
  submsg;
592
673
  arr->len++;
593
674
  if (UPB_UNLIKELY(field->descriptortype == UPB_DTYPE_GROUP)) {
594
- return decode_togroup(d, ptr, submsg, layout, field);
675
+ return decode_togroup(d, ptr, submsg, submsgs, field);
595
676
  } else {
596
- return decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
677
+ return decode_tosubmsg(d, ptr, submsg, submsgs, field, val->size);
597
678
  }
598
679
  }
599
680
  case OP_FIXPCK_LG2(2):
@@ -601,15 +682,15 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
601
682
  /* Fixed packed. */
602
683
  int lg2 = op - OP_FIXPCK_LG2(0);
603
684
  int mask = (1 << lg2) - 1;
604
- size_t count = val.size >> lg2;
605
- if ((val.size & mask) != 0) {
685
+ size_t count = val->size >> lg2;
686
+ if ((val->size & mask) != 0) {
606
687
  decode_err(d); /* Length isn't a round multiple of elem size. */
607
688
  }
608
689
  decode_reserve(d, arr, count);
609
690
  mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
610
691
  arr->len += count;
611
- memcpy(mem, ptr, val.size); /* XXX: ptr boundary. */
612
- return ptr + val.size;
692
+ memcpy(mem, ptr, val->size); /* XXX: ptr boundary. */
693
+ return ptr + val->size;
613
694
  }
614
695
  case OP_VARPCK_LG2(0):
615
696
  case OP_VARPCK_LG2(2):
@@ -617,7 +698,7 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
617
698
  /* Varint packed. */
618
699
  int lg2 = op - OP_VARPCK_LG2(0);
619
700
  int scale = 1 << lg2;
620
- int saved_limit = decode_pushlimit(d, ptr, val.size);
701
+ int saved_limit = decode_pushlimit(d, ptr, val->size);
621
702
  char *out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
622
703
  while (!decode_isdone(d, &ptr)) {
623
704
  wireval elem;
@@ -639,16 +720,15 @@ static const char *decode_toarray(upb_decstate *d, const char *ptr,
639
720
  }
640
721
 
641
722
  static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
642
- const upb_msglayout *layout,
643
- const upb_msglayout_field *field, wireval val) {
723
+ upb_msglayout const *const *submsgs,
724
+ const upb_msglayout_field *field, wireval *val) {
644
725
  upb_map **map_p = UPB_PTR_AT(msg, field->offset, upb_map *);
645
726
  upb_map *map = *map_p;
646
727
  upb_map_entry ent;
647
- const upb_msglayout *entry = layout->submsgs[field->submsg_index];
728
+ const upb_msglayout *entry = submsgs[field->submsg_index];
648
729
 
649
730
  if (!map) {
650
731
  /* Lazily create map. */
651
- const upb_msglayout *entry = layout->submsgs[field->submsg_index];
652
732
  const upb_msglayout_field *key_field = &entry->fields[0];
653
733
  const upb_msglayout_field *val_field = &entry->fields[1];
654
734
  char key_size = desctype_to_mapsize[key_field->descriptortype];
@@ -668,28 +748,28 @@ static const char *decode_tomap(upb_decstate *d, const char *ptr, upb_msg *msg,
668
748
  ent.v.val = upb_value_ptr(_upb_msg_new(entry->submsgs[0], &d->arena));
669
749
  }
670
750
 
671
- ptr = decode_tosubmsg(d, ptr, &ent.k, layout, field, val.size);
751
+ ptr = decode_tosubmsg(d, ptr, &ent.k, submsgs, field, val->size);
672
752
  _upb_map_set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
673
753
  return ptr;
674
754
  }
675
755
 
676
756
  static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
677
- const upb_msglayout *layout,
678
- const upb_msglayout_field *field, wireval val,
757
+ upb_msglayout const *const *submsgs,
758
+ const upb_msglayout_field *field, wireval *val,
679
759
  int op) {
680
760
  void *mem = UPB_PTR_AT(msg, field->offset, void);
681
761
  int type = field->descriptortype;
682
762
 
683
763
  /* Set presence if necessary. */
684
- if (field->presence < 0) {
764
+ if (field->presence > 0) {
765
+ _upb_sethas_field(msg, field);
766
+ } else if (field->presence < 0) {
685
767
  /* Oneof case */
686
768
  uint32_t *oneof_case = _upb_oneofcase_field(msg, field);
687
769
  if (op == OP_SUBMSG && *oneof_case != field->number) {
688
770
  memset(mem, 0, sizeof(void*));
689
771
  }
690
772
  *oneof_case = field->number;
691
- } else if (field->presence > 0) {
692
- _upb_sethas_field(msg, field);
693
773
  }
694
774
 
695
775
  /* Store into message. */
@@ -698,29 +778,29 @@ static const char *decode_tomsg(upb_decstate *d, const char *ptr, upb_msg *msg,
698
778
  upb_msg **submsgp = mem;
699
779
  upb_msg *submsg = *submsgp;
700
780
  if (!submsg) {
701
- submsg = decode_newsubmsg(d, layout, field);
781
+ submsg = decode_newsubmsg(d, submsgs, field);
702
782
  *submsgp = submsg;
703
783
  }
704
784
  if (UPB_UNLIKELY(type == UPB_DTYPE_GROUP)) {
705
- ptr = decode_togroup(d, ptr, submsg, layout, field);
785
+ ptr = decode_togroup(d, ptr, submsg, submsgs, field);
706
786
  } else {
707
- ptr = decode_tosubmsg(d, ptr, submsg, layout, field, val.size);
787
+ ptr = decode_tosubmsg(d, ptr, submsg, submsgs, field, val->size);
708
788
  }
709
789
  break;
710
790
  }
711
791
  case OP_STRING:
712
- decode_verifyutf8(d, ptr, val.size);
792
+ decode_verifyutf8(d, ptr, val->size);
713
793
  /* Fallthrough. */
714
794
  case OP_BYTES:
715
- return decode_readstr(d, ptr, val.size, mem);
795
+ return decode_readstr(d, ptr, val->size, mem);
716
796
  case OP_SCALAR_LG2(3):
717
- memcpy(mem, &val, 8);
797
+ memcpy(mem, val, 8);
718
798
  break;
719
799
  case OP_SCALAR_LG2(2):
720
- memcpy(mem, &val, 4);
800
+ memcpy(mem, val, 4);
721
801
  break;
722
802
  case OP_SCALAR_LG2(0):
723
- memcpy(mem, &val, 1);
803
+ memcpy(mem, val, 1);
724
804
  break;
725
805
  default:
726
806
  UPB_UNREACHABLE();
@@ -746,6 +826,7 @@ static bool decode_tryfastdispatch(upb_decstate *d, const char **ptr,
746
826
  UPB_NOINLINE
747
827
  static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
748
828
  const upb_msglayout *layout) {
829
+ int last_field_index = 0;
749
830
  while (true) {
750
831
  uint32_t tag;
751
832
  const upb_msglayout_field *field;
@@ -760,7 +841,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
760
841
  field_number = tag >> 3;
761
842
  wire_type = tag & 7;
762
843
 
763
- field = upb_find_field(layout, field_number);
844
+ field = upb_find_field(layout, field_number, &last_field_index);
764
845
 
765
846
  switch (wire_type) {
766
847
  case UPB_WIRE_TYPE_VARINT:
@@ -785,7 +866,7 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
785
866
  case UPB_WIRE_TYPE_DELIMITED: {
786
867
  int ndx = field->descriptortype;
787
868
  uint64_t size;
788
- if (_upb_isrepeated(field)) ndx += 18;
869
+ if (_upb_getmode(field) == _UPB_MODE_ARRAY) ndx += 18;
789
870
  ptr = decode_varint64(d, ptr, &size);
790
871
  if (size >= INT32_MAX ||
791
872
  ptr - d->end + (int32_t)size > d->limit) {
@@ -809,17 +890,18 @@ static const char *decode_msg(upb_decstate *d, const char *ptr, upb_msg *msg,
809
890
 
810
891
  if (op >= 0) {
811
892
  /* Parse, using op for dispatch. */
812
- switch (field->label) {
813
- case UPB_LABEL_REPEATED:
814
- case _UPB_LABEL_PACKED:
815
- ptr = decode_toarray(d, ptr, msg, layout, field, val, op);
893
+ switch (_upb_getmode(field)) {
894
+ case _UPB_MODE_ARRAY:
895
+ ptr = decode_toarray(d, ptr, msg, layout->submsgs, field, &val, op);
816
896
  break;
817
- case _UPB_LABEL_MAP:
818
- ptr = decode_tomap(d, ptr, msg, layout, field, val);
897
+ case _UPB_MODE_MAP:
898
+ ptr = decode_tomap(d, ptr, msg, layout->submsgs, field, &val);
819
899
  break;
820
- default:
821
- ptr = decode_tomsg(d, ptr, msg, layout, field, val, op);
900
+ case _UPB_MODE_SCALAR:
901
+ ptr = decode_tomsg(d, ptr, msg, layout->submsgs, field, &val, op);
822
902
  break;
903
+ default:
904
+ UPB_UNREACHABLE();
823
905
  }
824
906
  } else {
825
907
  unknown:
@@ -865,7 +947,8 @@ static bool decode_top(struct upb_decstate *d, const char *buf, void *msg,
865
947
  }
866
948
 
867
949
  bool _upb_decode(const char *buf, size_t size, void *msg,
868
- const upb_msglayout *l, upb_arena *arena, int options) {
950
+ const upb_msglayout *l, const upb_extreg *extreg, int options,
951
+ upb_arena *arena) {
869
952
  bool ok;
870
953
  upb_decstate state;
871
954
  unsigned depth = (unsigned)options >> 16;
@@ -891,7 +974,7 @@ bool _upb_decode(const char *buf, size_t size, void *msg,
891
974
  state.end_group = DECODE_NOGROUP;
892
975
  state.arena.head = arena->head;
893
976
  state.arena.last_size = arena->last_size;
894
- state.arena.cleanups = arena->cleanups;
977
+ state.arena.cleanup_metadata = arena->cleanup_metadata;
895
978
  state.arena.parent = arena;
896
979
 
897
980
  if (UPB_UNLIKELY(UPB_SETJMP(state.err))) {
@@ -902,7 +985,7 @@ bool _upb_decode(const char *buf, size_t size, void *msg,
902
985
 
903
986
  arena->head.ptr = state.arena.head.ptr;
904
987
  arena->head.end = state.arena.head.end;
905
- arena->cleanups = state.arena.cleanups;
988
+ arena->cleanup_metadata = state.arena.cleanup_metadata;
906
989
  return ok;
907
990
  }
908
991
 
@@ -911,6 +994,8 @@ bool _upb_decode(const char *buf, size_t size, void *msg,
911
994
  #undef OP_VARPCK_LG2
912
995
  #undef OP_STRING
913
996
  #undef OP_SUBMSG
997
+
998
+ /** upb/encode.c ************************************************************/
914
999
  /* We encode backwards, to avoid pre-computing lengths (one-pass encode). */
915
1000
 
916
1001
 
@@ -1065,7 +1150,7 @@ static void encode_fixedarray(upb_encstate *e, const upb_array *arr,
1065
1150
  }
1066
1151
  }
1067
1152
 
1068
- static void encode_message(upb_encstate *e, const char *msg,
1153
+ static void encode_message(upb_encstate *e, const upb_msg *msg,
1069
1154
  const upb_msglayout *m, size_t *size);
1070
1155
 
1071
1156
  static void encode_scalar(upb_encstate *e, const void *_field_mem,
@@ -1157,10 +1242,10 @@ static void encode_scalar(upb_encstate *e, const void *_field_mem,
1157
1242
  encode_tag(e, f->number, wire_type);
1158
1243
  }
1159
1244
 
1160
- static void encode_array(upb_encstate *e, const char *field_mem,
1245
+ static void encode_array(upb_encstate *e, const upb_msg *msg,
1161
1246
  const upb_msglayout *m, const upb_msglayout_field *f) {
1162
- const upb_array *arr = *(const upb_array**)field_mem;
1163
- bool packed = f->label == _UPB_LABEL_PACKED;
1247
+ const upb_array *arr = *UPB_PTR_AT(msg, f->offset, upb_array*);
1248
+ bool packed = f->mode & _UPB_MODE_IS_PACKED;
1164
1249
  size_t pre_len = e->limit - e->ptr;
1165
1250
 
1166
1251
  if (arr == NULL || arr->len == 0) {
@@ -1276,9 +1361,9 @@ static void encode_mapentry(upb_encstate *e, uint32_t number,
1276
1361
  encode_tag(e, number, UPB_WIRE_TYPE_DELIMITED);
1277
1362
  }
1278
1363
 
1279
- static void encode_map(upb_encstate *e, const char *field_mem,
1364
+ static void encode_map(upb_encstate *e, const upb_msg *msg,
1280
1365
  const upb_msglayout *m, const upb_msglayout_field *f) {
1281
- const upb_map *map = *(const upb_map**)field_mem;
1366
+ const upb_map *map = *UPB_PTR_AT(msg, f->offset, const upb_map*);
1282
1367
  const upb_msglayout *layout = m->submsgs[f->submsg_index];
1283
1368
  UPB_ASSERT(layout->field_count == 2);
1284
1369
 
@@ -1324,7 +1409,7 @@ static void encode_scalarfield(upb_encstate *e, const char *msg,
1324
1409
  encode_scalar(e, msg + f->offset, m, f, skip_empty);
1325
1410
  }
1326
1411
 
1327
- static void encode_message(upb_encstate *e, const char *msg,
1412
+ static void encode_message(upb_encstate *e, const upb_msg *msg,
1328
1413
  const upb_msglayout *m, size_t *size) {
1329
1414
  size_t pre_len = e->limit - e->ptr;
1330
1415
  const upb_msglayout_field *f = &m->fields[m->field_count];
@@ -1341,12 +1426,18 @@ static void encode_message(upb_encstate *e, const char *msg,
1341
1426
 
1342
1427
  while (f != first) {
1343
1428
  f--;
1344
- if (_upb_isrepeated(f)) {
1345
- encode_array(e, msg + f->offset, m, f);
1346
- } else if (f->label == _UPB_LABEL_MAP) {
1347
- encode_map(e, msg + f->offset, m, f);
1348
- } else {
1349
- encode_scalarfield(e, msg, m, f);
1429
+ switch (_upb_getmode(f)) {
1430
+ case _UPB_MODE_ARRAY:
1431
+ encode_array(e, msg, m, f);
1432
+ break;
1433
+ case _UPB_MODE_MAP:
1434
+ encode_map(e, msg, m, f);
1435
+ break;
1436
+ case _UPB_MODE_SCALAR:
1437
+ encode_scalarfield(e, msg, m, f);
1438
+ break;
1439
+ default:
1440
+ UPB_UNREACHABLE();
1350
1441
  }
1351
1442
  }
1352
1443
 
@@ -1386,12 +1477,12 @@ char *upb_encode_ex(const void *msg, const upb_msglayout *l, int options,
1386
1477
  return ret;
1387
1478
  }
1388
1479
 
1389
-
1480
+ /** upb/msg.c ************************************************************/
1390
1481
 
1391
1482
 
1392
1483
  /** upb_msg *******************************************************************/
1393
1484
 
1394
- static const size_t overhead = sizeof(upb_msg_internal);
1485
+ static const size_t overhead = sizeof(upb_msg_internaldata);
1395
1486
 
1396
1487
  static const upb_msg_internal *upb_msg_getinternal_const(const upb_msg *msg) {
1397
1488
  ptrdiff_t size = sizeof(upb_msg_internal);
@@ -1407,49 +1498,107 @@ void _upb_msg_clear(upb_msg *msg, const upb_msglayout *l) {
1407
1498
  memset(mem, 0, upb_msg_sizeof(l));
1408
1499
  }
1409
1500
 
1501
+ static bool realloc_internal(upb_msg *msg, size_t need, upb_arena *arena) {
1502
+ upb_msg_internal *in = upb_msg_getinternal(msg);
1503
+ if (!in->internal) {
1504
+ /* No internal data, allocate from scratch. */
1505
+ size_t size = UPB_MAX(128, _upb_lg2ceilsize(need + overhead));
1506
+ upb_msg_internaldata *internal = upb_arena_malloc(arena, size);
1507
+ if (!internal) return false;
1508
+ internal->size = size;
1509
+ internal->unknown_end = overhead;
1510
+ internal->ext_begin = size;
1511
+ in->internal = internal;
1512
+ } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
1513
+ /* Internal data is too small, reallocate. */
1514
+ size_t new_size = _upb_lg2ceilsize(in->internal->size + need);
1515
+ size_t ext_bytes = in->internal->size - in->internal->ext_begin;
1516
+ size_t new_ext_begin = new_size - ext_bytes;
1517
+ upb_msg_internaldata *internal =
1518
+ upb_arena_realloc(arena, in->internal, in->internal->size, new_size);
1519
+ if (!internal) return false;
1520
+ if (ext_bytes) {
1521
+ /* Need to move extension data to the end. */
1522
+ char *ptr = (char*)internal;
1523
+ memmove(ptr + new_ext_begin, ptr + internal->ext_begin, ext_bytes);
1524
+ }
1525
+ internal->ext_begin = new_ext_begin;
1526
+ internal->size = new_size;
1527
+ in->internal = internal;
1528
+ }
1529
+ UPB_ASSERT(in->internal->ext_begin - in->internal->unknown_end >= need);
1530
+ return true;
1531
+ }
1532
+
1410
1533
  bool _upb_msg_addunknown(upb_msg *msg, const char *data, size_t len,
1411
1534
  upb_arena *arena) {
1412
-
1535
+ if (!realloc_internal(msg, len, arena)) return false;
1413
1536
  upb_msg_internal *in = upb_msg_getinternal(msg);
1414
- if (!in->unknown) {
1415
- size_t size = 128;
1416
- while (size < len) size *= 2;
1417
- in->unknown = upb_arena_malloc(arena, size + overhead);
1418
- if (!in->unknown) return false;
1419
- in->unknown->size = size;
1420
- in->unknown->len = 0;
1421
- } else if (in->unknown->size - in->unknown->len < len) {
1422
- size_t need = in->unknown->len + len;
1423
- size_t size = in->unknown->size;
1424
- while (size < need) size *= 2;
1425
- in->unknown = upb_arena_realloc(
1426
- arena, in->unknown, in->unknown->size + overhead, size + overhead);
1427
- if (!in->unknown) return false;
1428
- in->unknown->size = size;
1429
- }
1430
- memcpy(UPB_PTR_AT(in->unknown + 1, in->unknown->len, char), data, len);
1431
- in->unknown->len += len;
1537
+ memcpy(UPB_PTR_AT(in->internal, in->internal->unknown_end, char), data, len);
1538
+ in->internal->unknown_end += len;
1432
1539
  return true;
1433
1540
  }
1434
1541
 
1435
1542
  void _upb_msg_discardunknown_shallow(upb_msg *msg) {
1436
1543
  upb_msg_internal *in = upb_msg_getinternal(msg);
1437
- if (in->unknown) {
1438
- in->unknown->len = 0;
1544
+ if (in->internal) {
1545
+ in->internal->unknown_end = overhead;
1439
1546
  }
1440
1547
  }
1441
1548
 
1442
1549
  const char *upb_msg_getunknown(const upb_msg *msg, size_t *len) {
1443
1550
  const upb_msg_internal *in = upb_msg_getinternal_const(msg);
1444
- if (in->unknown) {
1445
- *len = in->unknown->len;
1446
- return (char*)(in->unknown + 1);
1551
+ if (in->internal) {
1552
+ *len = in->internal->unknown_end - overhead;
1553
+ return (char*)(in->internal + 1);
1447
1554
  } else {
1448
1555
  *len = 0;
1449
1556
  return NULL;
1450
1557
  }
1451
1558
  }
1452
1559
 
1560
+ const upb_msg_ext *_upb_msg_getexts(const upb_msg *msg, size_t *count) {
1561
+ const upb_msg_internal *in = upb_msg_getinternal_const(msg);
1562
+ if (in->internal) {
1563
+ *count =
1564
+ (in->internal->size - in->internal->ext_begin) / sizeof(upb_msg_ext);
1565
+ return UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
1566
+ } else {
1567
+ *count = 0;
1568
+ return NULL;
1569
+ }
1570
+ }
1571
+
1572
+ const upb_msg_ext *_upb_msg_getext(const upb_msg *msg,
1573
+ const upb_msglayout_ext *e) {
1574
+ size_t n;
1575
+ const upb_msg_ext *ext = _upb_msg_getexts(msg, &n);
1576
+
1577
+ /* For now we use linear search exclusively to find extensions. If this
1578
+ * becomes an issue due to messages with lots of extensions, we can introduce
1579
+ * a table of some sort. */
1580
+ for (size_t i = 0; i < n; i++) {
1581
+ if (ext[i].ext == e) {
1582
+ return &ext[i];
1583
+ }
1584
+ }
1585
+
1586
+ return NULL;
1587
+ }
1588
+
1589
+ upb_msg_ext *_upb_msg_getorcreateext(upb_msg *msg, const upb_msglayout_ext *e,
1590
+ upb_arena *arena) {
1591
+ upb_msg_ext *ext = (upb_msg_ext*)_upb_msg_getext(msg, e);
1592
+ if (ext) return ext;
1593
+ if (!realloc_internal(msg, sizeof(upb_msg_ext), arena)) return NULL;
1594
+ upb_msg_internal *in = upb_msg_getinternal(msg);
1595
+ in->internal->ext_begin -= sizeof(upb_msg_ext);
1596
+ ext = UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
1597
+ memset(ext, 0, sizeof(upb_msg_ext));
1598
+ ext->ext = e;
1599
+ return ext;
1600
+ }
1601
+
1453
1602
  /** upb_array *****************************************************************/
1454
1603
 
1455
1604
  bool _upb_array_realloc(upb_array *arr, size_t min_size, upb_arena *arena) {
@@ -1517,7 +1666,7 @@ upb_map *_upb_map_new(upb_arena *a, size_t key_size, size_t value_size) {
1517
1666
  return NULL;
1518
1667
  }
1519
1668
 
1520
- upb_strtable_init2(&map->table, UPB_CTYPE_INT32, 4, upb_arena_alloc(a));
1669
+ upb_strtable_init(&map->table, 4, a);
1521
1670
  map->key_size = key_size;
1522
1671
  map->val_size = value_size;
1523
1672
 
@@ -1638,15 +1787,73 @@ bool _upb_mapsorter_pushmap(_upb_mapsorter *s, upb_descriptortype_t key_type,
1638
1787
  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
1639
1788
  return true;
1640
1789
  }
1790
+
1791
+ /** upb_extreg ****************************************************************/
1792
+
1793
+ struct upb_extreg {
1794
+ upb_arena *arena;
1795
+ upb_strtable exts; /* Key is upb_msglayout* concatenated with fieldnum. */
1796
+ };
1797
+
1798
+ #define EXTREG_KEY_SIZE (sizeof(upb_msglayout*) + sizeof(uint32_t))
1799
+
1800
+ static void extreg_key(char *buf, const upb_msglayout *l, uint32_t fieldnum) {
1801
+ memcpy(buf, &l, sizeof(l));
1802
+ memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
1803
+ }
1804
+
1805
+ upb_extreg *upb_extreg_new(upb_arena *arena) {
1806
+ upb_extreg *r = upb_arena_malloc(arena, sizeof(*r));
1807
+ if (!r) return NULL;
1808
+ r->arena = arena;
1809
+ if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
1810
+ return r;
1811
+ }
1812
+
1813
+ bool _upb_extreg_add(upb_extreg *r, const upb_msglayout_ext *e, size_t count) {
1814
+ char buf[EXTREG_KEY_SIZE];
1815
+ const upb_msglayout_ext *start = e;
1816
+ const upb_msglayout_ext *end = e + count;
1817
+ for (; e < end; e++) {
1818
+ extreg_key(buf, e->extendee, e->field.number);
1819
+ if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
1820
+ upb_value_constptr(e), r->arena)) {
1821
+ goto failure;
1822
+ }
1823
+ }
1824
+ return true;
1825
+
1826
+ failure:
1827
+ /* Back out the entries previously added. */
1828
+ for (end = e, e = start; e < end; e++) {
1829
+ extreg_key(buf, e->extendee, e->field.number);
1830
+ upb_strtable_remove(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
1831
+ }
1832
+ return false;
1833
+ }
1834
+
1835
+ const upb_msglayout_field *_upb_extreg_get(const upb_extreg *r,
1836
+ const upb_msglayout *l,
1837
+ uint32_t num) {
1838
+ char buf[EXTREG_KEY_SIZE];
1839
+ upb_value v;
1840
+ extreg_key(buf, l, num);
1841
+ if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
1842
+ return upb_value_getconstptr(v);
1843
+ } else {
1844
+ return NULL;
1845
+ }
1846
+ }
1847
+
1848
+ /** upb/table.c ************************************************************/
1641
1849
  /*
1642
- ** upb_table Implementation
1643
- **
1644
- ** Implementation is heavily inspired by Lua's ltable.c.
1645
- */
1850
+ * upb_table Implementation
1851
+ *
1852
+ * Implementation is heavily inspired by Lua's ltable.c.
1853
+ */
1646
1854
 
1647
1855
  #include <string.h>
1648
1856
 
1649
- #include "third_party/wyhash/wyhash.h"
1650
1857
 
1651
1858
  /* Must be last. */
1652
1859
 
@@ -1663,9 +1870,15 @@ static const double MAX_LOAD = 0.85;
1663
1870
  * cache effects). The lower this is, the more memory we'll use. */
1664
1871
  static const double MIN_DENSITY = 0.1;
1665
1872
 
1666
- bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
1873
+ static bool is_pow2(uint64_t v) { return v == 0 || (v & (v - 1)) == 0; }
1667
1874
 
1668
- int log2ceil(uint64_t v) {
1875
+ static upb_value _upb_value_val(uint64_t val) {
1876
+ upb_value ret;
1877
+ _upb_value_setval(&ret, val);
1878
+ return ret;
1879
+ }
1880
+
1881
+ static int log2ceil(uint64_t v) {
1669
1882
  int ret = 0;
1670
1883
  bool pow2 = is_pow2(v);
1671
1884
  while (v >>= 1) ret++;
@@ -1673,11 +1886,7 @@ int log2ceil(uint64_t v) {
1673
1886
  return UPB_MIN(UPB_MAXARRSIZE, ret);
1674
1887
  }
1675
1888
 
1676
- char *upb_strdup(const char *s, upb_alloc *a) {
1677
- return upb_strdup2(s, strlen(s), a);
1678
- }
1679
-
1680
- char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
1889
+ char *upb_strdup2(const char *s, size_t len, upb_arena *a) {
1681
1890
  size_t n;
1682
1891
  char *p;
1683
1892
 
@@ -1686,7 +1895,7 @@ char *upb_strdup2(const char *s, size_t len, upb_alloc *a) {
1686
1895
  /* Always null-terminate, even if binary data; but don't rely on the input to
1687
1896
  * have a null-terminating byte since it may be a raw binary buffer. */
1688
1897
  n = len + 1;
1689
- p = upb_malloc(a, n);
1898
+ p = upb_arena_malloc(a, n);
1690
1899
  if (p) {
1691
1900
  memcpy(p, s, len);
1692
1901
  p[len] = 0;
@@ -1721,16 +1930,24 @@ typedef bool eqlfunc_t(upb_tabkey k1, lookupkey_t k2);
1721
1930
 
1722
1931
  /* Base table (shared code) ***************************************************/
1723
1932
 
1724
- /* For when we need to cast away const. */
1725
- static upb_tabent *mutable_entries(upb_table *t) {
1726
- return (upb_tabent*)t->entries;
1933
+ static uint32_t upb_inthash(uintptr_t key) {
1934
+ return (uint32_t)key;
1935
+ }
1936
+
1937
+ static const upb_tabent *upb_getentry(const upb_table *t, uint32_t hash) {
1938
+ return t->entries + (hash & t->mask);
1727
1939
  }
1728
1940
 
1941
+ static bool upb_arrhas(upb_tabval key) {
1942
+ return key.val != (uint64_t)-1;
1943
+ }
1944
+
1945
+
1729
1946
  static bool isfull(upb_table *t) {
1730
1947
  return t->count == t->max_count;
1731
1948
  }
1732
1949
 
1733
- static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
1950
+ static bool init(upb_table *t, uint8_t size_lg2, upb_arena *a) {
1734
1951
  size_t bytes;
1735
1952
 
1736
1953
  t->count = 0;
@@ -1739,21 +1956,17 @@ static bool init(upb_table *t, uint8_t size_lg2, upb_alloc *a) {
1739
1956
  t->max_count = upb_table_size(t) * MAX_LOAD;
1740
1957
  bytes = upb_table_size(t) * sizeof(upb_tabent);
1741
1958
  if (bytes > 0) {
1742
- t->entries = upb_malloc(a, bytes);
1959
+ t->entries = upb_arena_malloc(a, bytes);
1743
1960
  if (!t->entries) return false;
1744
- memset(mutable_entries(t), 0, bytes);
1961
+ memset(t->entries, 0, bytes);
1745
1962
  } else {
1746
1963
  t->entries = NULL;
1747
1964
  }
1748
1965
  return true;
1749
1966
  }
1750
1967
 
1751
- static void uninit(upb_table *t, upb_alloc *a) {
1752
- upb_free(a, mutable_entries(t));
1753
- }
1754
-
1755
1968
  static upb_tabent *emptyent(upb_table *t, upb_tabent *e) {
1756
- upb_tabent *begin = mutable_entries(t);
1969
+ upb_tabent *begin = t->entries;
1757
1970
  upb_tabent *end = begin + upb_table_size(t);
1758
1971
  for (e = e + 1; e < end; e++) {
1759
1972
  if (upb_tabent_isempty(e)) return e;
@@ -1903,9 +2116,9 @@ static size_t begin(const upb_table *t) {
1903
2116
 
1904
2117
  /* A simple "subclass" of upb_table that only adds a hash function for strings. */
1905
2118
 
1906
- static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
2119
+ static upb_tabkey strcopy(lookupkey_t k2, upb_arena *a) {
1907
2120
  uint32_t len = (uint32_t) k2.str.len;
1908
- char *str = upb_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
2121
+ char *str = upb_arena_malloc(a, k2.str.len + sizeof(uint32_t) + 1);
1909
2122
  if (str == NULL) return 0;
1910
2123
  memcpy(str, &len, sizeof(uint32_t));
1911
2124
  if (k2.str.len) memcpy(str + sizeof(uint32_t), k2.str.str, k2.str.len);
@@ -1913,8 +2126,143 @@ static upb_tabkey strcopy(lookupkey_t k2, upb_alloc *a) {
1913
2126
  return (uintptr_t)str;
1914
2127
  }
1915
2128
 
2129
+ /* Adapted from ABSL's wyhash. */
2130
+
2131
+ static uint64_t UnalignedLoad64(const void *p) {
2132
+ uint64_t val;
2133
+ memcpy(&val, p, 8);
2134
+ return val;
2135
+ }
2136
+
2137
+ static uint32_t UnalignedLoad32(const void *p) {
2138
+ uint32_t val;
2139
+ memcpy(&val, p, 4);
2140
+ return val;
2141
+ }
2142
+
2143
+ #if defined(_MSC_VER) && defined(_M_X64)
2144
+ #include <intrin.h>
2145
+ #endif
2146
+
2147
+ /* Computes a * b, returning the low 64 bits of the result and storing the high
2148
+ * 64 bits in |*high|. */
2149
+ static uint64_t upb_umul128(uint64_t v0, uint64_t v1, uint64_t* out_high) {
2150
+ #ifdef __SIZEOF_INT128__
2151
+ __uint128_t p = v0;
2152
+ p *= v1;
2153
+ *out_high = (uint64_t)(p >> 64);
2154
+ return (uint64_t)p;
2155
+ #elif defined(_MSC_VER) && defined(_M_X64)
2156
+ return _umul128(v0, v1, out_high);
2157
+ #else
2158
+ uint64_t a32 = v0 >> 32;
2159
+ uint64_t a00 = v0 & 0xffffffff;
2160
+ uint64_t b32 = v1 >> 32;
2161
+ uint64_t b00 = v1 & 0xffffffff;
2162
+ uint64_t high = a32 * b32;
2163
+ uint64_t low = a00 * b00;
2164
+ uint64_t mid1 = a32 * b00;
2165
+ uint64_t mid2 = a00 * b32;
2166
+ low += (mid1 << 32) + (mid2 << 32);
2167
+ // Omit carry bit, for mixing we do not care about exact numerical precision.
2168
+ high += (mid1 >> 32) + (mid2 >> 32);
2169
+ *out_high = high;
2170
+ return low;
2171
+ #endif
2172
+ }
2173
+
2174
+ static uint64_t WyhashMix(uint64_t v0, uint64_t v1) {
2175
+ uint64_t high;
2176
+ uint64_t low = upb_umul128(v0, v1, &high);
2177
+ return low ^ high;
2178
+ }
2179
+
2180
+ uint64_t Wyhash(const void *data, size_t len, uint64_t seed,
2181
+ const uint64_t salt[]) {
2182
+ const uint8_t* ptr = (const uint8_t*)data;
2183
+ uint64_t starting_length = (uint64_t)len;
2184
+ uint64_t current_state = seed ^ salt[0];
2185
+
2186
+ if (len > 64) {
2187
+ // If we have more than 64 bytes, we're going to handle chunks of 64
2188
+ // bytes at a time. We're going to build up two separate hash states
2189
+ // which we will then hash together.
2190
+ uint64_t duplicated_state = current_state;
2191
+
2192
+ do {
2193
+ uint64_t a = UnalignedLoad64(ptr);
2194
+ uint64_t b = UnalignedLoad64(ptr + 8);
2195
+ uint64_t c = UnalignedLoad64(ptr + 16);
2196
+ uint64_t d = UnalignedLoad64(ptr + 24);
2197
+ uint64_t e = UnalignedLoad64(ptr + 32);
2198
+ uint64_t f = UnalignedLoad64(ptr + 40);
2199
+ uint64_t g = UnalignedLoad64(ptr + 48);
2200
+ uint64_t h = UnalignedLoad64(ptr + 56);
2201
+
2202
+ uint64_t cs0 = WyhashMix(a ^ salt[1], b ^ current_state);
2203
+ uint64_t cs1 = WyhashMix(c ^ salt[2], d ^ current_state);
2204
+ current_state = (cs0 ^ cs1);
2205
+
2206
+ uint64_t ds0 = WyhashMix(e ^ salt[3], f ^ duplicated_state);
2207
+ uint64_t ds1 = WyhashMix(g ^ salt[4], h ^ duplicated_state);
2208
+ duplicated_state = (ds0 ^ ds1);
2209
+
2210
+ ptr += 64;
2211
+ len -= 64;
2212
+ } while (len > 64);
2213
+
2214
+ current_state = current_state ^ duplicated_state;
2215
+ }
2216
+
2217
+ // We now have a data `ptr` with at most 64 bytes and the current state
2218
+ // of the hashing state machine stored in current_state.
2219
+ while (len > 16) {
2220
+ uint64_t a = UnalignedLoad64(ptr);
2221
+ uint64_t b = UnalignedLoad64(ptr + 8);
2222
+
2223
+ current_state = WyhashMix(a ^ salt[1], b ^ current_state);
2224
+
2225
+ ptr += 16;
2226
+ len -= 16;
2227
+ }
2228
+
2229
+ // We now have a data `ptr` with at most 16 bytes.
2230
+ uint64_t a = 0;
2231
+ uint64_t b = 0;
2232
+ if (len > 8) {
2233
+ // When we have at least 9 and at most 16 bytes, set A to the first 64
2234
+ // bits of the input and B to the last 64 bits of the input. Yes, they will
2235
+ // overlap in the middle if we are working with less than the full 16
2236
+ // bytes.
2237
+ a = UnalignedLoad64(ptr);
2238
+ b = UnalignedLoad64(ptr + len - 8);
2239
+ } else if (len > 3) {
2240
+ // If we have at least 4 and at most 8 bytes, set A to the first 32
2241
+ // bits and B to the last 32 bits.
2242
+ a = UnalignedLoad32(ptr);
2243
+ b = UnalignedLoad32(ptr + len - 4);
2244
+ } else if (len > 0) {
2245
+ // If we have at least 1 and at most 3 bytes, read all of the provided
2246
+ // bits into A, with some adjustments.
2247
+ a = ((ptr[0] << 16) | (ptr[len >> 1] << 8) | ptr[len - 1]);
2248
+ b = 0;
2249
+ } else {
2250
+ a = 0;
2251
+ b = 0;
2252
+ }
2253
+
2254
+ uint64_t w = WyhashMix(a ^ salt[1], b ^ current_state);
2255
+ uint64_t z = salt[1] ^ starting_length;
2256
+ return WyhashMix(w, z);
2257
+ }
2258
+
2259
+ const uint64_t kWyhashSalt[5] = {
2260
+ 0x243F6A8885A308D3ULL, 0x13198A2E03707344ULL, 0xA4093822299F31D0ULL,
2261
+ 0x082EFA98EC4E6C89ULL, 0x452821E638D01377ULL,
2262
+ };
2263
+
1916
2264
  static uint32_t table_hash(const char *p, size_t n) {
1917
- return wyhash(p, n, 0, _wyp);
2265
+ return Wyhash(p, n, 0, kWyhashSalt);
1918
2266
  }
1919
2267
 
1920
2268
  static uint32_t strhash(upb_tabkey key) {
@@ -1929,9 +2277,7 @@ static bool streql(upb_tabkey k1, lookupkey_t k2) {
1929
2277
  return len == k2.str.len && (len == 0 || memcmp(str, k2.str.str, len) == 0);
1930
2278
  }
1931
2279
 
1932
- bool upb_strtable_init2(upb_strtable *t, upb_ctype_t ctype,
1933
- size_t expected_size, upb_alloc *a) {
1934
- UPB_UNUSED(ctype); /* TODO(haberman): rm */
2280
+ bool upb_strtable_init(upb_strtable *t, size_t expected_size, upb_arena *a) {
1935
2281
  // Multiply by approximate reciprocal of MAX_LOAD (0.85), with pow2 denominator.
1936
2282
  size_t need_entries = (expected_size + 1) * 1204 / 1024;
1937
2283
  UPB_ASSERT(need_entries >= expected_size * 0.85);
@@ -1945,14 +2291,7 @@ void upb_strtable_clear(upb_strtable *t) {
1945
2291
  memset((char*)t->t.entries, 0, bytes);
1946
2292
  }
1947
2293
 
1948
- void upb_strtable_uninit2(upb_strtable *t, upb_alloc *a) {
1949
- size_t i;
1950
- for (i = 0; i < upb_table_size(&t->t); i++)
1951
- upb_free(a, (void*)t->t.entries[i].key);
1952
- uninit(&t->t, a);
1953
- }
1954
-
1955
- bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
2294
+ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_arena *a) {
1956
2295
  upb_strtable new_table;
1957
2296
  upb_strtable_iter i;
1958
2297
 
@@ -1961,17 +2300,15 @@ bool upb_strtable_resize(upb_strtable *t, size_t size_lg2, upb_alloc *a) {
1961
2300
  upb_strtable_begin(&i, t);
1962
2301
  for ( ; !upb_strtable_done(&i); upb_strtable_next(&i)) {
1963
2302
  upb_strview key = upb_strtable_iter_key(&i);
1964
- upb_strtable_insert3(
1965
- &new_table, key.data, key.size,
1966
- upb_strtable_iter_value(&i), a);
2303
+ upb_strtable_insert(&new_table, key.data, key.size,
2304
+ upb_strtable_iter_value(&i), a);
1967
2305
  }
1968
- upb_strtable_uninit2(t, a);
1969
2306
  *t = new_table;
1970
2307
  return true;
1971
2308
  }
1972
2309
 
1973
- bool upb_strtable_insert3(upb_strtable *t, const char *k, size_t len,
1974
- upb_value v, upb_alloc *a) {
2310
+ bool upb_strtable_insert(upb_strtable *t, const char *k, size_t len,
2311
+ upb_value v, upb_arena *a) {
1975
2312
  lookupkey_t key;
1976
2313
  upb_tabkey tabkey;
1977
2314
  uint32_t hash;
@@ -1998,19 +2335,11 @@ bool upb_strtable_lookup2(const upb_strtable *t, const char *key, size_t len,
1998
2335
  return lookup(&t->t, strkey2(key, len), v, hash, &streql);
1999
2336
  }
2000
2337
 
2001
- bool upb_strtable_remove3(upb_strtable *t, const char *key, size_t len,
2002
- upb_value *val, upb_alloc *alloc) {
2338
+ bool upb_strtable_remove(upb_strtable *t, const char *key, size_t len,
2339
+ upb_value *val) {
2003
2340
  uint32_t hash = table_hash(key, len);
2004
2341
  upb_tabkey tabkey;
2005
- if (rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql)) {
2006
- if (alloc) {
2007
- /* Arena-based allocs don't need to free and won't pass this. */
2008
- upb_free(alloc, (void*)tabkey);
2009
- }
2010
- return true;
2011
- } else {
2012
- return false;
2013
- }
2342
+ return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
2014
2343
  }
2015
2344
 
2016
2345
  /* Iteration */
@@ -2108,7 +2437,7 @@ static void check(upb_inttable *t) {
2108
2437
  }
2109
2438
 
2110
2439
  bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
2111
- upb_alloc *a) {
2440
+ upb_arena *a) {
2112
2441
  size_t array_bytes;
2113
2442
 
2114
2443
  if (!init(&t->t, hsize_lg2, a)) return false;
@@ -2117,9 +2446,8 @@ bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
2117
2446
  t->array_size = UPB_MAX(1, asize);
2118
2447
  t->array_count = 0;
2119
2448
  array_bytes = t->array_size * sizeof(upb_value);
2120
- t->array = upb_malloc(a, array_bytes);
2449
+ t->array = upb_arena_malloc(a, array_bytes);
2121
2450
  if (!t->array) {
2122
- uninit(&t->t, a);
2123
2451
  return false;
2124
2452
  }
2125
2453
  memset(mutable_array(t), 0xff, array_bytes);
@@ -2127,18 +2455,12 @@ bool upb_inttable_sizedinit(upb_inttable *t, size_t asize, int hsize_lg2,
2127
2455
  return true;
2128
2456
  }
2129
2457
 
2130
- bool upb_inttable_init2(upb_inttable *t, upb_ctype_t ctype, upb_alloc *a) {
2131
- UPB_UNUSED(ctype); /* TODO(haberman): rm */
2458
+ bool upb_inttable_init(upb_inttable *t, upb_arena *a) {
2132
2459
  return upb_inttable_sizedinit(t, 0, 4, a);
2133
2460
  }
2134
2461
 
2135
- void upb_inttable_uninit2(upb_inttable *t, upb_alloc *a) {
2136
- uninit(&t->t, a);
2137
- upb_free(a, mutable_array(t));
2138
- }
2139
-
2140
- bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
2141
- upb_alloc *a) {
2462
+ bool upb_inttable_insert(upb_inttable *t, uintptr_t key, upb_value val,
2463
+ upb_arena *a) {
2142
2464
  upb_tabval tabval;
2143
2465
  tabval.val = val.val;
2144
2466
  UPB_ASSERT(upb_arrhas(tabval)); /* This will reject (uint64_t)-1. Fix this. */
@@ -2169,7 +2491,6 @@ bool upb_inttable_insert2(upb_inttable *t, uintptr_t key, upb_value val,
2169
2491
 
2170
2492
  UPB_ASSERT(t->t.count == new_table.count);
2171
2493
 
2172
- uninit(&t->t, a);
2173
2494
  t->t = new_table;
2174
2495
  }
2175
2496
  insert(&t->t, intkey(key), key, val, upb_inthash(key), &inthash, &inteql);
@@ -2213,21 +2534,7 @@ bool upb_inttable_remove(upb_inttable *t, uintptr_t key, upb_value *val) {
2213
2534
  return success;
2214
2535
  }
2215
2536
 
2216
- bool upb_inttable_insertptr2(upb_inttable *t, const void *key, upb_value val,
2217
- upb_alloc *a) {
2218
- return upb_inttable_insert2(t, (uintptr_t)key, val, a);
2219
- }
2220
-
2221
- bool upb_inttable_lookupptr(const upb_inttable *t, const void *key,
2222
- upb_value *v) {
2223
- return upb_inttable_lookup(t, (uintptr_t)key, v);
2224
- }
2225
-
2226
- bool upb_inttable_removeptr(upb_inttable *t, const void *key, upb_value *val) {
2227
- return upb_inttable_remove(t, (uintptr_t)key, val);
2228
- }
2229
-
2230
- void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
2537
+ void upb_inttable_compact(upb_inttable *t, upb_arena *a) {
2231
2538
  /* A power-of-two histogram of the table keys. */
2232
2539
  size_t counts[UPB_MAXARRSIZE + 1] = {0};
2233
2540
 
@@ -2275,12 +2582,11 @@ void upb_inttable_compact2(upb_inttable *t, upb_alloc *a) {
2275
2582
  upb_inttable_begin(&i, t);
2276
2583
  for (; !upb_inttable_done(&i); upb_inttable_next(&i)) {
2277
2584
  uintptr_t k = upb_inttable_iter_key(&i);
2278
- upb_inttable_insert2(&new_t, k, upb_inttable_iter_value(&i), a);
2585
+ upb_inttable_insert(&new_t, k, upb_inttable_iter_value(&i), a);
2279
2586
  }
2280
2587
  UPB_ASSERT(new_t.array_size == arr_size);
2281
2588
  UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
2282
2589
  }
2283
- upb_inttable_uninit2(t, a);
2284
2590
  *t = new_t;
2285
2591
  }
2286
2592
 
@@ -2354,6 +2660,7 @@ bool upb_inttable_iter_isequal(const upb_inttable_iter *i1,
2354
2660
  i1->array_part == i2->array_part;
2355
2661
  }
2356
2662
 
2663
+ /** upb/upb.c ************************************************************/
2357
2664
 
2358
2665
  #include <errno.h>
2359
2666
  #include <stdarg.h>
@@ -2420,6 +2727,19 @@ static void *upb_global_allocfunc(upb_alloc *alloc, void *ptr, size_t oldsize,
2420
2727
  }
2421
2728
  }
2422
2729
 
2730
+ static uint32_t *upb_cleanup_pointer(uintptr_t cleanup_metadata) {
2731
+ return (uint32_t *)(cleanup_metadata & ~0x1);
2732
+ }
2733
+
2734
+ static bool upb_cleanup_has_initial_block(uintptr_t cleanup_metadata) {
2735
+ return cleanup_metadata & 0x1;
2736
+ }
2737
+
2738
+ static uintptr_t upb_cleanup_metadata(uint32_t *cleanup,
2739
+ bool has_initial_block) {
2740
+ return (uintptr_t)cleanup | has_initial_block;
2741
+ }
2742
+
2423
2743
  upb_alloc upb_alloc_global = {&upb_global_allocfunc};
2424
2744
 
2425
2745
  /* upb_arena ******************************************************************/
@@ -2465,7 +2785,8 @@ static void upb_arena_addblock(upb_arena *a, upb_arena *root, void *ptr,
2465
2785
 
2466
2786
  a->head.ptr = UPB_PTR_AT(block, memblock_reserve, char);
2467
2787
  a->head.end = UPB_PTR_AT(block, size, char);
2468
- a->cleanups = &block->cleanups;
2788
+ a->cleanup_metadata = upb_cleanup_metadata(
2789
+ &block->cleanups, upb_cleanup_has_initial_block(a->cleanup_metadata));
2469
2790
 
2470
2791
  UPB_POISON_MEMORY_REGION(a->head.ptr, a->head.end - a->head.ptr);
2471
2792
  }
@@ -2513,6 +2834,7 @@ upb_arena *arena_initslow(void *mem, size_t n, upb_alloc *alloc) {
2513
2834
  a->refcount = 1;
2514
2835
  a->freelist = NULL;
2515
2836
  a->freelist_tail = NULL;
2837
+ a->cleanup_metadata = upb_cleanup_metadata(NULL, false);
2516
2838
 
2517
2839
  upb_arena_addblock(a, a, mem, n);
2518
2840
 
@@ -2540,7 +2862,7 @@ upb_arena *upb_arena_init(void *mem, size_t n, upb_alloc *alloc) {
2540
2862
  a->head.ptr = mem;
2541
2863
  a->head.end = UPB_PTR_AT(mem, n - sizeof(*a), char);
2542
2864
  a->freelist = NULL;
2543
- a->cleanups = NULL;
2865
+ a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
2544
2866
 
2545
2867
  return a;
2546
2868
  }
@@ -2575,15 +2897,17 @@ void upb_arena_free(upb_arena *a) {
2575
2897
 
2576
2898
  bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
2577
2899
  cleanup_ent *ent;
2900
+ uint32_t* cleanups = upb_cleanup_pointer(a->cleanup_metadata);
2578
2901
 
2579
- if (!a->cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
2902
+ if (!cleanups || _upb_arenahas(a) < sizeof(cleanup_ent)) {
2580
2903
  if (!upb_arena_allocblock(a, 128)) return false; /* Out of memory. */
2581
2904
  UPB_ASSERT(_upb_arenahas(a) >= sizeof(cleanup_ent));
2905
+ cleanups = upb_cleanup_pointer(a->cleanup_metadata);
2582
2906
  }
2583
2907
 
2584
2908
  a->head.end -= sizeof(cleanup_ent);
2585
2909
  ent = (cleanup_ent*)a->head.end;
2586
- (*a->cleanups)++;
2910
+ (*cleanups)++;
2587
2911
  UPB_UNPOISON_MEMORY_REGION(ent, sizeof(cleanup_ent));
2588
2912
 
2589
2913
  ent->cleanup = func;
@@ -2592,11 +2916,18 @@ bool upb_arena_addcleanup(upb_arena *a, void *ud, upb_cleanup_func *func) {
2592
2916
  return true;
2593
2917
  }
2594
2918
 
2595
- void upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
2919
+ bool upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
2596
2920
  upb_arena *r1 = arena_findroot(a1);
2597
2921
  upb_arena *r2 = arena_findroot(a2);
2598
2922
 
2599
- if (r1 == r2) return; /* Already fused. */
2923
+ if (r1 == r2) return true; /* Already fused. */
2924
+
2925
+ /* Do not fuse initial blocks since we cannot lifetime extend them. */
2926
+ if (upb_cleanup_has_initial_block(r1->cleanup_metadata)) return false;
2927
+ if (upb_cleanup_has_initial_block(r2->cleanup_metadata)) return false;
2928
+
2929
+ /* Only allow fuse with a common allocator */
2930
+ if (r1->block_alloc != r2->block_alloc) return false;
2600
2931
 
2601
2932
  /* We want to join the smaller tree to the larger tree.
2602
2933
  * So swap first if they are backwards. */
@@ -2614,12 +2945,15 @@ void upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
2614
2945
  r1->freelist = r2->freelist;
2615
2946
  }
2616
2947
  r2->parent = r1;
2948
+ return true;
2617
2949
  }
2618
- // Fast decoder: ~3x the speed of decode.c, but x86-64 specific.
2950
+
2951
+ /** upb/decode_fast.c ************************************************************/
2952
+ // Fast decoder: ~3x the speed of decode.c, but requires x86-64/ARM64.
2619
2953
  // Also the table size grows by 2x.
2620
2954
  //
2621
- // Could potentially be ported to ARM64 or other 64-bit archs that pass at
2622
- // least six arguments in registers.
2955
+ // Could potentially be ported to other 64-bit archs that pass at least six
2956
+ // arguments in registers and have 8 unused high bits in pointers.
2623
2957
  //
2624
2958
  // The overall design is to create specialized functions for every possible
2625
2959
  // field type (eg. oneof boolean field with a 1 byte tag) and then dispatch
@@ -2639,8 +2973,10 @@ void upb_arena_fuse(upb_arena *a1, upb_arena *a2) {
2639
2973
 
2640
2974
  #define UPB_PARSE_ARGS d, ptr, msg, table, hasbits, data
2641
2975
 
2642
- #define RETURN_GENERIC(m) \
2643
- /* fprintf(stderr, m); */ \
2976
+ #define RETURN_GENERIC(m) \
2977
+ /* Uncomment either of these for debugging purposes. */ \
2978
+ /* fprintf(stderr, m); */ \
2979
+ /*__builtin_trap(); */ \
2644
2980
  return fastdecode_generic(d, ptr, msg, table, hasbits, 0);
2645
2981
 
2646
2982
  typedef enum {
@@ -2651,21 +2987,18 @@ typedef enum {
2651
2987
  } upb_card;
2652
2988
 
2653
2989
  UPB_NOINLINE
2654
- static const char *fastdecode_isdonefallback(upb_decstate *d, const char *ptr,
2655
- upb_msg *msg, intptr_t table,
2656
- uint64_t hasbits, int overrun) {
2990
+ static const char *fastdecode_isdonefallback(UPB_PARSE_PARAMS) {
2991
+ int overrun = data;
2657
2992
  ptr = decode_isdonefallback_inl(d, ptr, overrun);
2658
2993
  if (ptr == NULL) {
2659
2994
  return fastdecode_err(d);
2660
2995
  }
2661
- uint16_t tag = fastdecode_loadtag(ptr);
2662
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
2996
+ data = fastdecode_loadtag(ptr);
2997
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
2663
2998
  }
2664
2999
 
2665
3000
  UPB_FORCEINLINE
2666
- static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr,
2667
- upb_msg *msg, intptr_t table,
2668
- uint64_t hasbits) {
3001
+ static const char *fastdecode_dispatch(UPB_PARSE_PARAMS) {
2669
3002
  if (UPB_UNLIKELY(ptr >= d->limit_ptr)) {
2670
3003
  int overrun = ptr - d->end;
2671
3004
  if (UPB_LIKELY(overrun == d->limit)) {
@@ -2673,21 +3006,22 @@ static const char *fastdecode_dispatch(upb_decstate *d, const char *ptr,
2673
3006
  *(uint32_t*)msg |= hasbits; // Sync hasbits.
2674
3007
  return ptr;
2675
3008
  } else {
2676
- return fastdecode_isdonefallback(d, ptr, msg, table, hasbits, overrun);
3009
+ data = overrun;
3010
+ UPB_MUSTTAIL return fastdecode_isdonefallback(UPB_PARSE_ARGS);
2677
3011
  }
2678
3012
  }
2679
3013
 
2680
3014
  // Read two bytes of tag data (for a one-byte tag, the high byte is junk).
2681
- uint16_t tag = fastdecode_loadtag(ptr);
2682
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, tag);
3015
+ data = fastdecode_loadtag(ptr);
3016
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS);
2683
3017
  }
2684
3018
 
2685
3019
  UPB_FORCEINLINE
2686
- static bool fastdecode_checktag(uint64_t data, int tagbytes) {
3020
+ static bool fastdecode_checktag(uint16_t data, int tagbytes) {
2687
3021
  if (tagbytes == 1) {
2688
3022
  return (data & 0xff) == 0;
2689
3023
  } else {
2690
- return (data & 0xffff) == 0;
3024
+ return data == 0;
2691
3025
  }
2692
3026
  }
2693
3027
 
@@ -2911,6 +3245,14 @@ static bool fastdecode_flippacked(uint64_t *data, int tagbytes) {
2911
3245
  return fastdecode_checktag(*data, tagbytes);
2912
3246
  }
2913
3247
 
3248
+ #define FASTDECODE_CHECKPACKED(tagbytes, card, func) \
3249
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
3250
+ if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) { \
3251
+ UPB_MUSTTAIL return func(UPB_PARSE_ARGS); \
3252
+ } \
3253
+ RETURN_GENERIC("packed check tag mismatch\n"); \
3254
+ }
3255
+
2914
3256
  /* varint fields **************************************************************/
2915
3257
 
2916
3258
  UPB_FORCEINLINE
@@ -2953,57 +3295,50 @@ done:
2953
3295
  return ptr;
2954
3296
  }
2955
3297
 
2956
- UPB_FORCEINLINE
2957
- static const char *fastdecode_unpackedvarint(UPB_PARSE_PARAMS, int tagbytes,
2958
- int valbytes, upb_card card,
2959
- bool zigzag,
2960
- _upb_field_parser *packed) {
2961
- uint64_t val;
2962
- void *dst;
2963
- fastdecode_arr farr;
2964
-
2965
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
2966
- if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
2967
- return packed(UPB_PARSE_ARGS);
2968
- }
2969
- RETURN_GENERIC("varint field tag mismatch\n");
2970
- }
2971
-
2972
- dst =
2973
- fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
2974
- if (card == CARD_r) {
2975
- if (UPB_UNLIKELY(!dst)) {
2976
- RETURN_GENERIC("need array resize\n");
2977
- }
2978
- }
2979
-
2980
- again:
2981
- if (card == CARD_r) {
2982
- dst = fastdecode_resizearr(d, dst, &farr, valbytes);
2983
- }
2984
-
2985
- ptr += tagbytes;
2986
- ptr = fastdecode_varint64(ptr, &val);
2987
- if (ptr == NULL) return fastdecode_err(d);
2988
- val = fastdecode_munge(val, valbytes, zigzag);
2989
- memcpy(dst, &val, valbytes);
2990
-
2991
- if (card == CARD_r) {
2992
- fastdecode_nextret ret =
2993
- fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
2994
- switch (ret.next) {
2995
- case FD_NEXT_SAMEFIELD:
2996
- dst = ret.dst;
2997
- goto again;
2998
- case FD_NEXT_OTHERFIELD:
2999
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3000
- case FD_NEXT_ATLIMIT:
3001
- return ptr;
3002
- }
3003
- }
3004
-
3005
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3006
- }
3298
+ #define FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
3299
+ valbytes, card, zigzag, packed) \
3300
+ uint64_t val; \
3301
+ void *dst; \
3302
+ fastdecode_arr farr; \
3303
+ \
3304
+ FASTDECODE_CHECKPACKED(tagbytes, card, packed); \
3305
+ \
3306
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
3307
+ card); \
3308
+ if (card == CARD_r) { \
3309
+ if (UPB_UNLIKELY(!dst)) { \
3310
+ RETURN_GENERIC("need array resize\n"); \
3311
+ } \
3312
+ } \
3313
+ \
3314
+ again: \
3315
+ if (card == CARD_r) { \
3316
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
3317
+ } \
3318
+ \
3319
+ ptr += tagbytes; \
3320
+ ptr = fastdecode_varint64(ptr, &val); \
3321
+ if (ptr == NULL) \
3322
+ return fastdecode_err(d); \
3323
+ val = fastdecode_munge(val, valbytes, zigzag); \
3324
+ memcpy(dst, &val, valbytes); \
3325
+ \
3326
+ if (card == CARD_r) { \
3327
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
3328
+ d, dst, &ptr, &farr, data, tagbytes, valbytes); \
3329
+ switch (ret.next) { \
3330
+ case FD_NEXT_SAMEFIELD: \
3331
+ dst = ret.dst; \
3332
+ goto again; \
3333
+ case FD_NEXT_OTHERFIELD: \
3334
+ data = ret.tag; \
3335
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3336
+ case FD_NEXT_ATLIMIT: \
3337
+ return ptr; \
3338
+ } \
3339
+ } \
3340
+ \
3341
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3007
3342
 
3008
3343
  typedef struct {
3009
3344
  uint8_t valbytes;
@@ -3032,50 +3367,37 @@ static const char *fastdecode_topackedvarint(upb_decstate *d, const char *ptr,
3032
3367
  return ptr;
3033
3368
  }
3034
3369
 
3035
- UPB_FORCEINLINE
3036
- static const char *fastdecode_packedvarint(UPB_PARSE_PARAMS, int tagbytes,
3037
- int valbytes, bool zigzag,
3038
- _upb_field_parser *unpacked) {
3039
- fastdecode_varintdata ctx = {valbytes, zigzag};
3040
-
3041
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
3042
- if (fastdecode_flippacked(&data, tagbytes)) {
3043
- return unpacked(UPB_PARSE_ARGS);
3044
- } else {
3045
- RETURN_GENERIC("varint field tag mismatch\n");
3046
- }
3047
- }
3048
-
3049
- ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr,
3050
- valbytes, CARD_r);
3051
- if (UPB_UNLIKELY(!ctx.dst)) {
3052
- RETURN_GENERIC("need array resize\n");
3370
+ #define FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
3371
+ valbytes, zigzag, unpacked) \
3372
+ fastdecode_varintdata ctx = {valbytes, zigzag}; \
3373
+ \
3374
+ FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked); \
3375
+ \
3376
+ ctx.dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &ctx.farr, \
3377
+ valbytes, CARD_r); \
3378
+ if (UPB_UNLIKELY(!ctx.dst)) { \
3379
+ RETURN_GENERIC("need array resize\n"); \
3380
+ } \
3381
+ \
3382
+ ptr += tagbytes; \
3383
+ ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx); \
3384
+ \
3385
+ if (UPB_UNLIKELY(ptr == NULL)) { \
3386
+ return fastdecode_err(d); \
3387
+ } \
3388
+ \
3389
+ UPB_MUSTTAIL return fastdecode_dispatch(d, ptr, msg, table, hasbits, 0);
3390
+
3391
+ #define FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
3392
+ valbytes, card, zigzag, unpacked, packed) \
3393
+ if (card == CARD_p) { \
3394
+ FASTDECODE_PACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
3395
+ valbytes, zigzag, unpacked); \
3396
+ } else { \
3397
+ FASTDECODE_UNPACKEDVARINT(d, ptr, msg, table, hasbits, data, tagbytes, \
3398
+ valbytes, card, zigzag, packed); \
3053
3399
  }
3054
3400
 
3055
- ptr += tagbytes;
3056
- ptr = fastdecode_delimited(d, ptr, &fastdecode_topackedvarint, &ctx);
3057
-
3058
- if (UPB_UNLIKELY(ptr == NULL)) {
3059
- return fastdecode_err(d);
3060
- }
3061
-
3062
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3063
- }
3064
-
3065
- UPB_FORCEINLINE
3066
- static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes,
3067
- int valbytes, upb_card card, bool zigzag,
3068
- _upb_field_parser *unpacked,
3069
- _upb_field_parser *packed) {
3070
- if (card == CARD_p) {
3071
- return fastdecode_packedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, zigzag,
3072
- unpacked);
3073
- } else {
3074
- return fastdecode_unpackedvarint(UPB_PARSE_ARGS, tagbytes, valbytes, card,
3075
- zigzag, packed);
3076
- }
3077
- }
3078
-
3079
3401
  #define z_ZZ true
3080
3402
  #define b_ZZ false
3081
3403
  #define v_ZZ false
@@ -3086,10 +3408,10 @@ static const char *fastdecode_varint(UPB_PARSE_PARAMS, int tagbytes,
3086
3408
  #define F(card, type, valbytes, tagbytes) \
3087
3409
  UPB_NOINLINE \
3088
3410
  const char *upb_p##card##type##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3089
- return fastdecode_varint(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \
3090
- type##_ZZ, \
3091
- &upb_pr##type##valbytes##_##tagbytes##bt, \
3092
- &upb_pp##type##valbytes##_##tagbytes##bt); \
3411
+ FASTDECODE_VARINT(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
3412
+ CARD_##card, type##_ZZ, \
3413
+ upb_pr##type##valbytes##_##tagbytes##bt, \
3414
+ upb_pp##type##valbytes##_##tagbytes##bt); \
3093
3415
  }
3094
3416
 
3095
3417
  #define TYPES(card, tagbytes) \
@@ -3117,126 +3439,110 @@ TAGBYTES(p)
3117
3439
  #undef F
3118
3440
  #undef TYPES
3119
3441
  #undef TAGBYTES
3442
+ #undef FASTDECODE_UNPACKEDVARINT
3443
+ #undef FASTDECODE_PACKEDVARINT
3444
+ #undef FASTDECODE_VARINT
3120
3445
 
3121
3446
 
3122
3447
  /* fixed fields ***************************************************************/
3123
3448
 
3124
- UPB_FORCEINLINE
3125
- static const char *fastdecode_unpackedfixed(UPB_PARSE_PARAMS, int tagbytes,
3126
- int valbytes, upb_card card,
3127
- _upb_field_parser *packed) {
3128
- void *dst;
3129
- fastdecode_arr farr;
3130
-
3131
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
3132
- if (card == CARD_r && fastdecode_flippacked(&data, tagbytes)) {
3133
- return packed(UPB_PARSE_ARGS);
3134
- }
3135
- RETURN_GENERIC("fixed field tag mismatch\n");
3136
- }
3137
-
3138
- dst =
3139
- fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, card);
3140
- if (card == CARD_r) {
3141
- if (UPB_UNLIKELY(!dst)) {
3142
- RETURN_GENERIC("couldn't allocate array in arena\n");
3143
- }
3144
- }
3145
-
3146
-
3147
- again:
3148
- if (card == CARD_r) {
3149
- dst = fastdecode_resizearr(d, dst, &farr, valbytes);
3150
- }
3151
-
3152
- ptr += tagbytes;
3153
- memcpy(dst, ptr, valbytes);
3154
- ptr += valbytes;
3155
-
3156
- if (card == CARD_r) {
3157
- fastdecode_nextret ret =
3158
- fastdecode_nextrepeated(d, dst, &ptr, &farr, data, tagbytes, valbytes);
3159
- switch (ret.next) {
3160
- case FD_NEXT_SAMEFIELD:
3161
- dst = ret.dst;
3162
- goto again;
3163
- case FD_NEXT_OTHERFIELD:
3164
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3165
- case FD_NEXT_ATLIMIT:
3166
- return ptr;
3167
- }
3168
- }
3169
-
3170
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3171
- }
3172
-
3173
- UPB_FORCEINLINE
3174
- static const char *fastdecode_packedfixed(UPB_PARSE_PARAMS, int tagbytes,
3175
- int valbytes,
3176
- _upb_field_parser *unpacked) {
3177
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
3178
- if (fastdecode_flippacked(&data, tagbytes)) {
3179
- return unpacked(UPB_PARSE_ARGS);
3180
- } else {
3181
- RETURN_GENERIC("varint field tag mismatch\n");
3182
- }
3183
- }
3184
-
3185
- ptr += tagbytes;
3186
- int size = (uint8_t)ptr[0];
3187
- ptr++;
3188
- if (size & 0x80) {
3189
- ptr = fastdecode_longsize(ptr, &size);
3190
- }
3191
-
3192
- if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr)) ||
3193
- (size % valbytes) != 0) {
3194
- return fastdecode_err(d);
3195
- }
3196
-
3197
- upb_array **arr_p = fastdecode_fieldmem(msg, data);
3198
- upb_array *arr = *arr_p;
3199
- uint8_t elem_size_lg2 = __builtin_ctz(valbytes);
3200
- int elems = size / valbytes;
3201
-
3202
- if (UPB_LIKELY(!arr)) {
3203
- *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2);
3204
- if (!arr) {
3205
- return fastdecode_err(d);
3206
- }
3207
- } else {
3208
- _upb_array_resize(arr, elems, &d->arena);
3449
+ #define FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
3450
+ valbytes, card, packed) \
3451
+ void *dst; \
3452
+ fastdecode_arr farr; \
3453
+ \
3454
+ FASTDECODE_CHECKPACKED(tagbytes, card, packed) \
3455
+ \
3456
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, valbytes, \
3457
+ card); \
3458
+ if (card == CARD_r) { \
3459
+ if (UPB_UNLIKELY(!dst)) { \
3460
+ RETURN_GENERIC("couldn't allocate array in arena\n"); \
3461
+ } \
3462
+ } \
3463
+ \
3464
+ again: \
3465
+ if (card == CARD_r) { \
3466
+ dst = fastdecode_resizearr(d, dst, &farr, valbytes); \
3467
+ } \
3468
+ \
3469
+ ptr += tagbytes; \
3470
+ memcpy(dst, ptr, valbytes); \
3471
+ ptr += valbytes; \
3472
+ \
3473
+ if (card == CARD_r) { \
3474
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
3475
+ d, dst, &ptr, &farr, data, tagbytes, valbytes); \
3476
+ switch (ret.next) { \
3477
+ case FD_NEXT_SAMEFIELD: \
3478
+ dst = ret.dst; \
3479
+ goto again; \
3480
+ case FD_NEXT_OTHERFIELD: \
3481
+ data = ret.tag; \
3482
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3483
+ case FD_NEXT_ATLIMIT: \
3484
+ return ptr; \
3485
+ } \
3486
+ } \
3487
+ \
3488
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3489
+
3490
+ #define FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
3491
+ valbytes, unpacked) \
3492
+ FASTDECODE_CHECKPACKED(tagbytes, CARD_r, unpacked) \
3493
+ \
3494
+ ptr += tagbytes; \
3495
+ int size = (uint8_t)ptr[0]; \
3496
+ ptr++; \
3497
+ if (size & 0x80) { \
3498
+ ptr = fastdecode_longsize(ptr, &size); \
3499
+ } \
3500
+ \
3501
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr) || \
3502
+ (size % valbytes) != 0)) { \
3503
+ return fastdecode_err(d); \
3504
+ } \
3505
+ \
3506
+ upb_array **arr_p = fastdecode_fieldmem(msg, data); \
3507
+ upb_array *arr = *arr_p; \
3508
+ uint8_t elem_size_lg2 = __builtin_ctz(valbytes); \
3509
+ int elems = size / valbytes; \
3510
+ \
3511
+ if (UPB_LIKELY(!arr)) { \
3512
+ *arr_p = arr = _upb_array_new(&d->arena, elems, elem_size_lg2); \
3513
+ if (!arr) { \
3514
+ return fastdecode_err(d); \
3515
+ } \
3516
+ } else { \
3517
+ _upb_array_resize(arr, elems, &d->arena); \
3518
+ } \
3519
+ \
3520
+ char *dst = _upb_array_ptr(arr); \
3521
+ memcpy(dst, ptr, size); \
3522
+ arr->len = elems; \
3523
+ \
3524
+ ptr += size; \
3525
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3526
+
3527
+ #define FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
3528
+ valbytes, card, unpacked, packed) \
3529
+ if (card == CARD_p) { \
3530
+ FASTDECODE_PACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
3531
+ valbytes, unpacked); \
3532
+ } else { \
3533
+ FASTDECODE_UNPACKEDFIXED(d, ptr, msg, table, hasbits, data, tagbytes, \
3534
+ valbytes, card, packed); \
3209
3535
  }
3210
3536
 
3211
- char *dst = _upb_array_ptr(arr);
3212
- memcpy(dst, ptr, size);
3213
- arr->len = elems;
3214
-
3215
- return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
3216
- }
3217
-
3218
- UPB_FORCEINLINE
3219
- static const char *fastdecode_fixed(UPB_PARSE_PARAMS, int tagbytes,
3220
- int valbytes, upb_card card,
3221
- _upb_field_parser *unpacked,
3222
- _upb_field_parser *packed) {
3223
- if (card == CARD_p) {
3224
- return fastdecode_packedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, unpacked);
3225
- } else {
3226
- return fastdecode_unpackedfixed(UPB_PARSE_ARGS, tagbytes, valbytes, card,
3227
- packed);
3228
- }
3229
- }
3230
-
3231
3537
  /* Generate all combinations:
3232
3538
  * {s,o,r,p} x {f4,f8} x {1bt,2bt} */
3233
3539
 
3234
- #define F(card, valbytes, tagbytes) \
3235
- UPB_NOINLINE \
3236
- const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3237
- return fastdecode_fixed(UPB_PARSE_ARGS, tagbytes, valbytes, CARD_##card, \
3238
- &upb_ppf##valbytes##_##tagbytes##bt, \
3239
- &upb_prf##valbytes##_##tagbytes##bt); \
3540
+ #define F(card, valbytes, tagbytes) \
3541
+ UPB_NOINLINE \
3542
+ const char *upb_p##card##f##valbytes##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3543
+ FASTDECODE_FIXED(d, ptr, msg, table, hasbits, data, tagbytes, valbytes, \
3544
+ CARD_##card, upb_ppf##valbytes##_##tagbytes##bt, \
3545
+ upb_prf##valbytes##_##tagbytes##bt); \
3240
3546
  }
3241
3547
 
3242
3548
  #define TYPES(card, tagbytes) \
@@ -3255,6 +3561,8 @@ TAGBYTES(p)
3255
3561
  #undef F
3256
3562
  #undef TYPES
3257
3563
  #undef TAGBYTES
3564
+ #undef FASTDECODE_UNPACKEDFIXED
3565
+ #undef FASTDECODE_PACKEDFIXED
3258
3566
 
3259
3567
  /* string fields **************************************************************/
3260
3568
 
@@ -3266,56 +3574,54 @@ typedef const char *fastdecode_copystr_func(struct upb_decstate *d,
3266
3574
  UPB_NOINLINE
3267
3575
  static const char *fastdecode_verifyutf8(upb_decstate *d, const char *ptr,
3268
3576
  upb_msg *msg, intptr_t table,
3269
- uint64_t hasbits, upb_strview *dst) {
3577
+ uint64_t hasbits, uint64_t data) {
3578
+ upb_strview *dst = (upb_strview*)data;
3270
3579
  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
3271
3580
  return fastdecode_err(d);
3272
3581
  }
3273
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3274
- }
3275
-
3276
- UPB_FORCEINLINE
3277
- static const char *fastdecode_longstring(struct upb_decstate *d,
3278
- const char *ptr, upb_msg *msg,
3279
- intptr_t table, uint64_t hasbits,
3280
- upb_strview *dst,
3281
- bool validate_utf8) {
3282
- int size = (uint8_t)ptr[0]; // Could plumb through hasbits.
3283
- ptr++;
3284
- if (size & 0x80) {
3285
- ptr = fastdecode_longsize(ptr, &size);
3286
- }
3287
-
3288
- if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) {
3289
- dst->size = 0;
3290
- return fastdecode_err(d);
3291
- }
3292
-
3293
- if (d->alias) {
3294
- dst->data = ptr;
3295
- dst->size = size;
3296
- } else {
3297
- char *data = upb_arena_malloc(&d->arena, size);
3298
- if (!data) {
3299
- return fastdecode_err(d);
3300
- }
3301
- memcpy(data, ptr, size);
3302
- dst->data = data;
3303
- dst->size = size;
3304
- }
3305
-
3306
- if (validate_utf8) {
3307
- return fastdecode_verifyutf8(d, ptr + size, msg, table, hasbits, dst);
3308
- } else {
3309
- return fastdecode_dispatch(d, ptr + size, msg, table, hasbits);
3582
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3583
+ }
3584
+
3585
+ #define FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, validate_utf8) \
3586
+ int size = (uint8_t)ptr[0]; /* Could plumb through hasbits. */ \
3587
+ ptr++; \
3588
+ if (size & 0x80) { \
3589
+ ptr = fastdecode_longsize(ptr, &size); \
3590
+ } \
3591
+ \
3592
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->limit_ptr))) { \
3593
+ dst->size = 0; \
3594
+ return fastdecode_err(d); \
3595
+ } \
3596
+ \
3597
+ if (d->alias) { \
3598
+ dst->data = ptr; \
3599
+ dst->size = size; \
3600
+ } else { \
3601
+ char *data = upb_arena_malloc(&d->arena, size); \
3602
+ if (!data) { \
3603
+ return fastdecode_err(d); \
3604
+ } \
3605
+ memcpy(data, ptr, size); \
3606
+ dst->data = data; \
3607
+ dst->size = size; \
3608
+ } \
3609
+ \
3610
+ ptr += size; \
3611
+ if (validate_utf8) { \
3612
+ data = (uint64_t)dst; \
3613
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
3614
+ } else { \
3615
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
3310
3616
  }
3311
- }
3312
3617
 
3313
3618
  UPB_NOINLINE
3314
3619
  static const char *fastdecode_longstring_utf8(struct upb_decstate *d,
3315
- const char *ptr, upb_msg *msg,
3316
- intptr_t table, uint64_t hasbits,
3317
- upb_strview *dst) {
3318
- return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, true);
3620
+ const char *ptr, upb_msg *msg,
3621
+ intptr_t table, uint64_t hasbits,
3622
+ uint64_t data) {
3623
+ upb_strview *dst = (upb_strview*)data;
3624
+ FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
3319
3625
  }
3320
3626
 
3321
3627
  UPB_NOINLINE
@@ -3323,8 +3629,9 @@ static const char *fastdecode_longstring_noutf8(struct upb_decstate *d,
3323
3629
  const char *ptr, upb_msg *msg,
3324
3630
  intptr_t table,
3325
3631
  uint64_t hasbits,
3326
- upb_strview *dst) {
3327
- return fastdecode_longstring(d, ptr, msg, table, hasbits, dst, false);
3632
+ uint64_t data) {
3633
+ upb_strview *dst = (upb_strview*)data;
3634
+ FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
3328
3635
  }
3329
3636
 
3330
3637
  UPB_FORCEINLINE
@@ -3337,156 +3644,165 @@ static void fastdecode_docopy(upb_decstate *d, const char *ptr, uint32_t size,
3337
3644
  UPB_POISON_MEMORY_REGION(data + size, copy - size);
3338
3645
  }
3339
3646
 
3340
- UPB_FORCEINLINE
3341
- static const char *fastdecode_copystring(UPB_PARSE_PARAMS, int tagbytes,
3342
- upb_card card, bool validate_utf8) {
3343
- upb_strview *dst;
3344
- fastdecode_arr farr;
3345
- int64_t size;
3346
- size_t arena_has;
3347
- size_t common_has;
3348
- char *buf;
3349
-
3350
- UPB_ASSERT(!d->alias);
3351
- UPB_ASSERT(fastdecode_checktag(data, tagbytes));
3352
-
3353
- dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
3354
- sizeof(upb_strview), card);
3355
-
3356
- again:
3357
- if (card == CARD_r) {
3358
- dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
3359
- }
3360
-
3361
- size = (uint8_t)ptr[tagbytes];
3362
- ptr += tagbytes + 1;
3363
- dst->size = size;
3364
-
3365
- buf = d->arena.head.ptr;
3366
- arena_has = _upb_arenahas(&d->arena);
3367
- common_has = UPB_MIN(arena_has, (d->end - ptr) + 16);
3368
-
3369
- if (UPB_LIKELY(size <= 15 - tagbytes)) {
3370
- if (arena_has < 16) goto longstr;
3371
- d->arena.head.ptr += 16;
3372
- memcpy(buf, ptr - tagbytes - 1, 16);
3373
- dst->data = buf + tagbytes + 1;
3374
- } else if (UPB_LIKELY(size <= 32)) {
3375
- if (UPB_UNLIKELY(common_has < 32)) goto longstr;
3376
- fastdecode_docopy(d, ptr, size, 32, buf, dst);
3377
- } else if (UPB_LIKELY(size <= 64)) {
3378
- if (UPB_UNLIKELY(common_has < 64)) goto longstr;
3379
- fastdecode_docopy(d, ptr, size, 64, buf, dst);
3380
- } else if (UPB_LIKELY(size < 128)) {
3381
- if (UPB_UNLIKELY(common_has < 128)) goto longstr;
3382
- fastdecode_docopy(d, ptr, size, 128, buf, dst);
3383
- } else {
3384
- goto longstr;
3385
- }
3386
-
3387
- ptr += size;
3388
-
3389
- if (card == CARD_r) {
3390
- if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
3391
- return fastdecode_err(d);
3392
- }
3393
- fastdecode_nextret ret = fastdecode_nextrepeated(
3394
- d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
3395
- switch (ret.next) {
3396
- case FD_NEXT_SAMEFIELD:
3397
- dst = ret.dst;
3398
- goto again;
3399
- case FD_NEXT_OTHERFIELD:
3400
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3401
- case FD_NEXT_ATLIMIT:
3402
- return ptr;
3403
- }
3404
- }
3405
-
3406
- if (card != CARD_r && validate_utf8) {
3407
- return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
3408
- }
3409
-
3410
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3411
-
3412
- longstr:
3413
- ptr--;
3414
- if (validate_utf8) {
3415
- return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
3416
- } else {
3417
- return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
3418
- }
3419
- }
3420
-
3421
- UPB_FORCEINLINE
3422
- static const char *fastdecode_string(UPB_PARSE_PARAMS, int tagbytes,
3423
- upb_card card, _upb_field_parser *copyfunc,
3424
- bool validate_utf8) {
3425
- upb_strview *dst;
3426
- fastdecode_arr farr;
3427
- int64_t size;
3428
-
3429
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
3430
- RETURN_GENERIC("string field tag mismatch\n");
3431
- }
3432
-
3433
- if (UPB_UNLIKELY(!d->alias)) {
3434
- return copyfunc(UPB_PARSE_ARGS);
3435
- }
3436
-
3437
- dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
3438
- sizeof(upb_strview), card);
3439
-
3440
- again:
3441
- if (card == CARD_r) {
3442
- dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview));
3443
- }
3444
-
3445
- size = (int8_t)ptr[tagbytes];
3446
- ptr += tagbytes + 1;
3447
- dst->data = ptr;
3448
- dst->size = size;
3449
-
3450
- if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) {
3451
- ptr--;
3452
- if (validate_utf8) {
3453
- return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, dst);
3454
- } else {
3455
- return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, dst);
3456
- }
3457
- }
3458
-
3459
- ptr += size;
3460
-
3461
- if (card == CARD_r) {
3462
- if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) {
3463
- return fastdecode_err(d);
3464
- }
3465
- fastdecode_nextret ret = fastdecode_nextrepeated(
3466
- d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview));
3467
- switch (ret.next) {
3468
- case FD_NEXT_SAMEFIELD:
3469
- dst = ret.dst;
3470
- if (UPB_UNLIKELY(!d->alias)) {
3471
- // Buffer flipped and we can't alias any more. Bounce to copyfunc(),
3472
- // but via dispatch since we need to reload table data also.
3473
- fastdecode_commitarr(dst, &farr, sizeof(upb_strview));
3474
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3475
- }
3476
- goto again;
3477
- case FD_NEXT_OTHERFIELD:
3478
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3479
- case FD_NEXT_ATLIMIT:
3480
- return ptr;
3481
- }
3482
- }
3483
-
3484
- if (card != CARD_r && validate_utf8) {
3485
- return fastdecode_verifyutf8(d, ptr, msg, table, hasbits, dst);
3486
- }
3487
-
3488
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3489
- }
3647
+ #define FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
3648
+ card, validate_utf8) \
3649
+ upb_strview *dst; \
3650
+ fastdecode_arr farr; \
3651
+ int64_t size; \
3652
+ size_t arena_has; \
3653
+ size_t common_has; \
3654
+ char *buf; \
3655
+ \
3656
+ UPB_ASSERT(!d->alias); \
3657
+ UPB_ASSERT(fastdecode_checktag(data, tagbytes)); \
3658
+ \
3659
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
3660
+ sizeof(upb_strview), card); \
3661
+ \
3662
+ again: \
3663
+ if (card == CARD_r) { \
3664
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); \
3665
+ } \
3666
+ \
3667
+ size = (uint8_t)ptr[tagbytes]; \
3668
+ ptr += tagbytes + 1; \
3669
+ dst->size = size; \
3670
+ \
3671
+ buf = d->arena.head.ptr; \
3672
+ arena_has = _upb_arenahas(&d->arena); \
3673
+ common_has = UPB_MIN(arena_has, (d->end - ptr) + 16); \
3674
+ \
3675
+ if (UPB_LIKELY(size <= 15 - tagbytes)) { \
3676
+ if (arena_has < 16) \
3677
+ goto longstr; \
3678
+ d->arena.head.ptr += 16; \
3679
+ memcpy(buf, ptr - tagbytes - 1, 16); \
3680
+ dst->data = buf + tagbytes + 1; \
3681
+ } else if (UPB_LIKELY(size <= 32)) { \
3682
+ if (UPB_UNLIKELY(common_has < 32)) \
3683
+ goto longstr; \
3684
+ fastdecode_docopy(d, ptr, size, 32, buf, dst); \
3685
+ } else if (UPB_LIKELY(size <= 64)) { \
3686
+ if (UPB_UNLIKELY(common_has < 64)) \
3687
+ goto longstr; \
3688
+ fastdecode_docopy(d, ptr, size, 64, buf, dst); \
3689
+ } else if (UPB_LIKELY(size < 128)) { \
3690
+ if (UPB_UNLIKELY(common_has < 128)) \
3691
+ goto longstr; \
3692
+ fastdecode_docopy(d, ptr, size, 128, buf, dst); \
3693
+ } else { \
3694
+ goto longstr; \
3695
+ } \
3696
+ \
3697
+ ptr += size; \
3698
+ \
3699
+ if (card == CARD_r) { \
3700
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
3701
+ return fastdecode_err(d); \
3702
+ } \
3703
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
3704
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); \
3705
+ switch (ret.next) { \
3706
+ case FD_NEXT_SAMEFIELD: \
3707
+ dst = ret.dst; \
3708
+ goto again; \
3709
+ case FD_NEXT_OTHERFIELD: \
3710
+ data = ret.tag; \
3711
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3712
+ case FD_NEXT_ATLIMIT: \
3713
+ return ptr; \
3714
+ } \
3715
+ } \
3716
+ \
3717
+ if (card != CARD_r && validate_utf8) { \
3718
+ data = (uint64_t)dst; \
3719
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
3720
+ } \
3721
+ \
3722
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS); \
3723
+ \
3724
+ longstr: \
3725
+ ptr--; \
3726
+ if (validate_utf8) { \
3727
+ UPB_MUSTTAIL return fastdecode_longstring_utf8(d, ptr, msg, table, \
3728
+ hasbits, (uint64_t)dst); \
3729
+ } else { \
3730
+ UPB_MUSTTAIL return fastdecode_longstring_noutf8(d, ptr, msg, table, \
3731
+ hasbits, (uint64_t)dst); \
3732
+ }
3733
+
3734
+ #define FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, card, \
3735
+ copyfunc, validate_utf8) \
3736
+ upb_strview *dst; \
3737
+ fastdecode_arr farr; \
3738
+ int64_t size; \
3739
+ \
3740
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
3741
+ RETURN_GENERIC("string field tag mismatch\n"); \
3742
+ } \
3743
+ \
3744
+ if (UPB_UNLIKELY(!d->alias)) { \
3745
+ UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS); \
3746
+ } \
3747
+ \
3748
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
3749
+ sizeof(upb_strview), card); \
3750
+ \
3751
+ again: \
3752
+ if (card == CARD_r) { \
3753
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_strview)); \
3754
+ } \
3755
+ \
3756
+ size = (int8_t)ptr[tagbytes]; \
3757
+ ptr += tagbytes + 1; \
3758
+ dst->data = ptr; \
3759
+ dst->size = size; \
3760
+ \
3761
+ if (UPB_UNLIKELY(fastdecode_boundscheck(ptr, size, d->end))) { \
3762
+ ptr--; \
3763
+ if (validate_utf8) { \
3764
+ return fastdecode_longstring_utf8(d, ptr, msg, table, hasbits, \
3765
+ (uint64_t)dst); \
3766
+ } else { \
3767
+ return fastdecode_longstring_noutf8(d, ptr, msg, table, hasbits, \
3768
+ (uint64_t)dst); \
3769
+ } \
3770
+ } \
3771
+ \
3772
+ ptr += size; \
3773
+ \
3774
+ if (card == CARD_r) { \
3775
+ if (validate_utf8 && !decode_verifyutf8_inl(dst->data, dst->size)) { \
3776
+ return fastdecode_err(d); \
3777
+ } \
3778
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
3779
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_strview)); \
3780
+ switch (ret.next) { \
3781
+ case FD_NEXT_SAMEFIELD: \
3782
+ dst = ret.dst; \
3783
+ if (UPB_UNLIKELY(!d->alias)) { \
3784
+ /* Buffer flipped and we can't alias any more. Bounce to */ \
3785
+ /* copyfunc(), but via dispatch since we need to reload table */ \
3786
+ /* data also. */ \
3787
+ fastdecode_commitarr(dst, &farr, sizeof(upb_strview)); \
3788
+ data = ret.tag; \
3789
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3790
+ } \
3791
+ goto again; \
3792
+ case FD_NEXT_OTHERFIELD: \
3793
+ data = ret.tag; \
3794
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3795
+ case FD_NEXT_ATLIMIT: \
3796
+ return ptr; \
3797
+ } \
3798
+ } \
3799
+ \
3800
+ if (card != CARD_r && validate_utf8) { \
3801
+ data = (uint64_t)dst; \
3802
+ UPB_MUSTTAIL return fastdecode_verifyutf8(UPB_PARSE_ARGS); \
3803
+ } \
3804
+ \
3805
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3490
3806
 
3491
3807
  /* Generate all combinations:
3492
3808
  * {p,c} x {s,o,r} x {s, b} x {1bt,2bt} */
@@ -3494,16 +3810,16 @@ again:
3494
3810
  #define s_VALIDATE true
3495
3811
  #define b_VALIDATE false
3496
3812
 
3497
- #define F(card, tagbytes, type) \
3498
- UPB_NOINLINE \
3499
- const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3500
- return fastdecode_copystring(UPB_PARSE_ARGS, tagbytes, CARD_##card, \
3501
- type##_VALIDATE); \
3502
- } \
3503
- const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3504
- return fastdecode_string(UPB_PARSE_ARGS, tagbytes, CARD_##card, \
3505
- &upb_c##card##type##_##tagbytes##bt, \
3506
- type##_VALIDATE); \
3813
+ #define F(card, tagbytes, type) \
3814
+ UPB_NOINLINE \
3815
+ const char *upb_c##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3816
+ FASTDECODE_COPYSTRING(d, ptr, msg, table, hasbits, data, tagbytes, \
3817
+ CARD_##card, type##_VALIDATE); \
3818
+ } \
3819
+ const char *upb_p##card##type##_##tagbytes##bt(UPB_PARSE_PARAMS) { \
3820
+ FASTDECODE_STRING(d, ptr, msg, table, hasbits, data, tagbytes, \
3821
+ CARD_##card, upb_c##card##type##_##tagbytes##bt, \
3822
+ type##_VALIDATE); \
3507
3823
  }
3508
3824
 
3509
3825
  #define UTF8(card, tagbytes) \
@@ -3522,6 +3838,9 @@ TAGBYTES(r)
3522
3838
  #undef b_VALIDATE
3523
3839
  #undef F
3524
3840
  #undef TAGBYTES
3841
+ #undef FASTDECODE_LONGSTRING
3842
+ #undef FASTDECODE_COPYSTRING
3843
+ #undef FASTDECODE_STRING
3525
3844
 
3526
3845
  /* message fields *************************************************************/
3527
3846
 
@@ -3554,82 +3873,82 @@ UPB_FORCEINLINE
3554
3873
  static const char *fastdecode_tosubmsg(upb_decstate *d, const char *ptr,
3555
3874
  void *ctx) {
3556
3875
  fastdecode_submsgdata *submsg = ctx;
3557
- ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0);
3876
+ ptr = fastdecode_dispatch(d, ptr, submsg->msg, submsg->table, 0, 0);
3558
3877
  UPB_ASSUME(ptr != NULL);
3559
3878
  return ptr;
3560
3879
  }
3561
3880
 
3562
- UPB_FORCEINLINE
3563
- static const char *fastdecode_submsg(UPB_PARSE_PARAMS, int tagbytes,
3564
- int msg_ceil_bytes, upb_card card) {
3565
-
3566
- if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) {
3567
- RETURN_GENERIC("submessage field tag mismatch\n");
3568
- }
3569
-
3570
- if (--d->depth == 0) return fastdecode_err(d);
3571
-
3572
- upb_msg **dst;
3573
- uint32_t submsg_idx = (data >> 16) & 0xff;
3574
- const upb_msglayout *tablep = decode_totablep(table);
3575
- const upb_msglayout *subtablep = tablep->submsgs[submsg_idx];
3576
- fastdecode_submsgdata submsg = {decode_totable(subtablep)};
3577
- fastdecode_arr farr;
3578
-
3579
- if (subtablep->table_mask == (uint8_t)-1) {
3580
- RETURN_GENERIC("submessage doesn't have fast tables.");
3581
- }
3582
-
3583
- dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,
3584
- sizeof(upb_msg *), card);
3585
-
3586
- if (card == CARD_s) {
3587
- *(uint32_t*)msg |= hasbits;
3588
- hasbits = 0;
3589
- }
3590
-
3591
- again:
3592
- if (card == CARD_r) {
3593
- dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg*));
3594
- }
3595
-
3596
- submsg.msg = *dst;
3597
-
3598
- if (card == CARD_r || UPB_LIKELY(!submsg.msg)) {
3599
- *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes);
3600
- }
3601
-
3602
- ptr += tagbytes;
3603
- ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg);
3604
-
3605
- if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) {
3606
- return fastdecode_err(d);
3607
- }
3608
-
3609
- if (card == CARD_r) {
3610
- fastdecode_nextret ret = fastdecode_nextrepeated(
3611
- d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *));
3612
- switch (ret.next) {
3613
- case FD_NEXT_SAMEFIELD:
3614
- dst = ret.dst;
3615
- goto again;
3616
- case FD_NEXT_OTHERFIELD:
3617
- d->depth++;
3618
- return fastdecode_tagdispatch(d, ptr, msg, table, hasbits, ret.tag);
3619
- case FD_NEXT_ATLIMIT:
3620
- d->depth++;
3621
- return ptr;
3622
- }
3623
- }
3624
-
3625
- d->depth++;
3626
- return fastdecode_dispatch(d, ptr, msg, table, hasbits);
3627
- }
3628
-
3629
- #define F(card, tagbytes, size_ceil, ceil_arg) \
3630
- const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \
3631
- UPB_PARSE_PARAMS) { \
3632
- return fastdecode_submsg(UPB_PARSE_ARGS, tagbytes, ceil_arg, CARD_##card); \
3881
+ #define FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, \
3882
+ msg_ceil_bytes, card) \
3883
+ \
3884
+ if (UPB_UNLIKELY(!fastdecode_checktag(data, tagbytes))) { \
3885
+ RETURN_GENERIC("submessage field tag mismatch\n"); \
3886
+ } \
3887
+ \
3888
+ if (--d->depth == 0) return fastdecode_err(d); \
3889
+ \
3890
+ upb_msg **dst; \
3891
+ uint32_t submsg_idx = (data >> 16) & 0xff; \
3892
+ const upb_msglayout *tablep = decode_totablep(table); \
3893
+ const upb_msglayout *subtablep = tablep->submsgs[submsg_idx]; \
3894
+ fastdecode_submsgdata submsg = {decode_totable(subtablep)}; \
3895
+ fastdecode_arr farr; \
3896
+ \
3897
+ if (subtablep->table_mask == (uint8_t)-1) { \
3898
+ RETURN_GENERIC("submessage doesn't have fast tables."); \
3899
+ } \
3900
+ \
3901
+ dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr, \
3902
+ sizeof(upb_msg *), card); \
3903
+ \
3904
+ if (card == CARD_s) { \
3905
+ *(uint32_t *)msg |= hasbits; \
3906
+ hasbits = 0; \
3907
+ } \
3908
+ \
3909
+ again: \
3910
+ if (card == CARD_r) { \
3911
+ dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_msg *)); \
3912
+ } \
3913
+ \
3914
+ submsg.msg = *dst; \
3915
+ \
3916
+ if (card == CARD_r || UPB_LIKELY(!submsg.msg)) { \
3917
+ *dst = submsg.msg = decode_newmsg_ceil(d, subtablep, msg_ceil_bytes); \
3918
+ } \
3919
+ \
3920
+ ptr += tagbytes; \
3921
+ ptr = fastdecode_delimited(d, ptr, fastdecode_tosubmsg, &submsg); \
3922
+ \
3923
+ if (UPB_UNLIKELY(ptr == NULL || d->end_group != DECODE_NOGROUP)) { \
3924
+ return fastdecode_err(d); \
3925
+ } \
3926
+ \
3927
+ if (card == CARD_r) { \
3928
+ fastdecode_nextret ret = fastdecode_nextrepeated( \
3929
+ d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_msg *)); \
3930
+ switch (ret.next) { \
3931
+ case FD_NEXT_SAMEFIELD: \
3932
+ dst = ret.dst; \
3933
+ goto again; \
3934
+ case FD_NEXT_OTHERFIELD: \
3935
+ d->depth++; \
3936
+ data = ret.tag; \
3937
+ UPB_MUSTTAIL return fastdecode_tagdispatch(UPB_PARSE_ARGS); \
3938
+ case FD_NEXT_ATLIMIT: \
3939
+ d->depth++; \
3940
+ return ptr; \
3941
+ } \
3942
+ } \
3943
+ \
3944
+ d->depth++; \
3945
+ UPB_MUSTTAIL return fastdecode_dispatch(UPB_PARSE_ARGS);
3946
+
3947
+ #define F(card, tagbytes, size_ceil, ceil_arg) \
3948
+ const char *upb_p##card##m_##tagbytes##bt_max##size_ceil##b( \
3949
+ UPB_PARSE_PARAMS) { \
3950
+ FASTDECODE_SUBMSG(d, ptr, msg, table, hasbits, data, tagbytes, ceil_arg, \
3951
+ CARD_##card); \
3633
3952
  }
3634
3953
 
3635
3954
  #define SIZES(card, tagbytes) \
@@ -3650,9 +3969,11 @@ TAGBYTES(r)
3650
3969
  #undef TAGBYTES
3651
3970
  #undef SIZES
3652
3971
  #undef F
3972
+ #undef FASTDECODE_SUBMSG
3653
3973
 
3654
3974
  #endif /* UPB_FASTTABLE */
3655
- /* This file was generated by upbc (the upb compiler) from the input
3975
+
3976
+ /** bazel-out/k8-fastbuild/bin/external/com_google_protobuf/google/protobuf/descriptor.upb.c ************************************************************//* This file was generated by upbc (the upb compiler) from the input
3656
3977
  * file:
3657
3978
  *
3658
3979
  * google/protobuf/descriptor.proto
@@ -3668,13 +3989,13 @@ static const upb_msglayout *const google_protobuf_FileDescriptorSet_submsgs[1] =
3668
3989
  };
3669
3990
 
3670
3991
  static const upb_msglayout_field google_protobuf_FileDescriptorSet__fields[1] = {
3671
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
3992
+ {1, UPB_SIZE(0, 0), 0, 0, 11, _UPB_MODE_ARRAY},
3672
3993
  };
3673
3994
 
3674
3995
  const upb_msglayout google_protobuf_FileDescriptorSet_msginit = {
3675
3996
  &google_protobuf_FileDescriptorSet_submsgs[0],
3676
3997
  &google_protobuf_FileDescriptorSet__fields[0],
3677
- UPB_SIZE(8, 8), 1, false, 255,
3998
+ UPB_SIZE(8, 8), 1, false, 1, 255,
3678
3999
  };
3679
4000
 
3680
4001
  static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6] = {
@@ -3687,24 +4008,24 @@ static const upb_msglayout *const google_protobuf_FileDescriptorProto_submsgs[6]
3687
4008
  };
3688
4009
 
3689
4010
  static const upb_msglayout_field google_protobuf_FileDescriptorProto__fields[12] = {
3690
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3691
- {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
3692
- {3, UPB_SIZE(36, 72), 0, 0, 12, 3},
3693
- {4, UPB_SIZE(40, 80), 0, 0, 11, 3},
3694
- {5, UPB_SIZE(44, 88), 0, 1, 11, 3},
3695
- {6, UPB_SIZE(48, 96), 0, 4, 11, 3},
3696
- {7, UPB_SIZE(52, 104), 0, 2, 11, 3},
3697
- {8, UPB_SIZE(28, 56), 3, 3, 11, 1},
3698
- {9, UPB_SIZE(32, 64), 4, 5, 11, 1},
3699
- {10, UPB_SIZE(56, 112), 0, 0, 5, 3},
3700
- {11, UPB_SIZE(60, 120), 0, 0, 5, 3},
3701
- {12, UPB_SIZE(20, 40), 5, 0, 12, 1},
4011
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4012
+ {2, UPB_SIZE(12, 24), 2, 0, 12, _UPB_MODE_SCALAR},
4013
+ {3, UPB_SIZE(36, 72), 0, 0, 12, _UPB_MODE_ARRAY},
4014
+ {4, UPB_SIZE(40, 80), 0, 0, 11, _UPB_MODE_ARRAY},
4015
+ {5, UPB_SIZE(44, 88), 0, 1, 11, _UPB_MODE_ARRAY},
4016
+ {6, UPB_SIZE(48, 96), 0, 4, 11, _UPB_MODE_ARRAY},
4017
+ {7, UPB_SIZE(52, 104), 0, 2, 11, _UPB_MODE_ARRAY},
4018
+ {8, UPB_SIZE(28, 56), 3, 3, 11, _UPB_MODE_SCALAR},
4019
+ {9, UPB_SIZE(32, 64), 4, 5, 11, _UPB_MODE_SCALAR},
4020
+ {10, UPB_SIZE(56, 112), 0, 0, 5, _UPB_MODE_ARRAY},
4021
+ {11, UPB_SIZE(60, 120), 0, 0, 5, _UPB_MODE_ARRAY},
4022
+ {12, UPB_SIZE(20, 40), 5, 0, 12, _UPB_MODE_SCALAR},
3702
4023
  };
3703
4024
 
3704
4025
  const upb_msglayout google_protobuf_FileDescriptorProto_msginit = {
3705
4026
  &google_protobuf_FileDescriptorProto_submsgs[0],
3706
4027
  &google_protobuf_FileDescriptorProto__fields[0],
3707
- UPB_SIZE(64, 128), 12, false, 255,
4028
+ UPB_SIZE(64, 128), 12, false, 12, 255,
3708
4029
  };
3709
4030
 
3710
4031
  static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
@@ -3718,22 +4039,22 @@ static const upb_msglayout *const google_protobuf_DescriptorProto_submsgs[7] = {
3718
4039
  };
3719
4040
 
3720
4041
  static const upb_msglayout_field google_protobuf_DescriptorProto__fields[10] = {
3721
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3722
- {2, UPB_SIZE(16, 32), 0, 4, 11, 3},
3723
- {3, UPB_SIZE(20, 40), 0, 0, 11, 3},
3724
- {4, UPB_SIZE(24, 48), 0, 3, 11, 3},
3725
- {5, UPB_SIZE(28, 56), 0, 1, 11, 3},
3726
- {6, UPB_SIZE(32, 64), 0, 4, 11, 3},
3727
- {7, UPB_SIZE(12, 24), 2, 5, 11, 1},
3728
- {8, UPB_SIZE(36, 72), 0, 6, 11, 3},
3729
- {9, UPB_SIZE(40, 80), 0, 2, 11, 3},
3730
- {10, UPB_SIZE(44, 88), 0, 0, 12, 3},
4042
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4043
+ {2, UPB_SIZE(16, 32), 0, 4, 11, _UPB_MODE_ARRAY},
4044
+ {3, UPB_SIZE(20, 40), 0, 0, 11, _UPB_MODE_ARRAY},
4045
+ {4, UPB_SIZE(24, 48), 0, 3, 11, _UPB_MODE_ARRAY},
4046
+ {5, UPB_SIZE(28, 56), 0, 1, 11, _UPB_MODE_ARRAY},
4047
+ {6, UPB_SIZE(32, 64), 0, 4, 11, _UPB_MODE_ARRAY},
4048
+ {7, UPB_SIZE(12, 24), 2, 5, 11, _UPB_MODE_SCALAR},
4049
+ {8, UPB_SIZE(36, 72), 0, 6, 11, _UPB_MODE_ARRAY},
4050
+ {9, UPB_SIZE(40, 80), 0, 2, 11, _UPB_MODE_ARRAY},
4051
+ {10, UPB_SIZE(44, 88), 0, 0, 12, _UPB_MODE_ARRAY},
3731
4052
  };
3732
4053
 
3733
4054
  const upb_msglayout google_protobuf_DescriptorProto_msginit = {
3734
4055
  &google_protobuf_DescriptorProto_submsgs[0],
3735
4056
  &google_protobuf_DescriptorProto__fields[0],
3736
- UPB_SIZE(48, 96), 10, false, 255,
4057
+ UPB_SIZE(48, 96), 10, false, 10, 255,
3737
4058
  };
3738
4059
 
3739
4060
  static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
@@ -3741,26 +4062,26 @@ static const upb_msglayout *const google_protobuf_DescriptorProto_ExtensionRange
3741
4062
  };
3742
4063
 
3743
4064
  static const upb_msglayout_field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
3744
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
3745
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
3746
- {3, UPB_SIZE(12, 16), 3, 0, 11, 1},
4065
+ {1, UPB_SIZE(4, 4), 1, 0, 5, _UPB_MODE_SCALAR},
4066
+ {2, UPB_SIZE(8, 8), 2, 0, 5, _UPB_MODE_SCALAR},
4067
+ {3, UPB_SIZE(12, 16), 3, 0, 11, _UPB_MODE_SCALAR},
3747
4068
  };
3748
4069
 
3749
4070
  const upb_msglayout google_protobuf_DescriptorProto_ExtensionRange_msginit = {
3750
4071
  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
3751
4072
  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
3752
- UPB_SIZE(16, 24), 3, false, 255,
4073
+ UPB_SIZE(16, 24), 3, false, 3, 255,
3753
4074
  };
3754
4075
 
3755
4076
  static const upb_msglayout_field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
3756
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
3757
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
4077
+ {1, UPB_SIZE(4, 4), 1, 0, 5, _UPB_MODE_SCALAR},
4078
+ {2, UPB_SIZE(8, 8), 2, 0, 5, _UPB_MODE_SCALAR},
3758
4079
  };
3759
4080
 
3760
4081
  const upb_msglayout google_protobuf_DescriptorProto_ReservedRange_msginit = {
3761
4082
  NULL,
3762
4083
  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
3763
- UPB_SIZE(16, 16), 2, false, 255,
4084
+ UPB_SIZE(16, 16), 2, false, 2, 255,
3764
4085
  };
3765
4086
 
3766
4087
  static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[1] = {
@@ -3768,13 +4089,13 @@ static const upb_msglayout *const google_protobuf_ExtensionRangeOptions_submsgs[
3768
4089
  };
3769
4090
 
3770
4091
  static const upb_msglayout_field google_protobuf_ExtensionRangeOptions__fields[1] = {
3771
- {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
4092
+ {999, UPB_SIZE(0, 0), 0, 0, 11, _UPB_MODE_ARRAY},
3772
4093
  };
3773
4094
 
3774
4095
  const upb_msglayout google_protobuf_ExtensionRangeOptions_msginit = {
3775
4096
  &google_protobuf_ExtensionRangeOptions_submsgs[0],
3776
4097
  &google_protobuf_ExtensionRangeOptions__fields[0],
3777
- UPB_SIZE(8, 8), 1, false, 255,
4098
+ UPB_SIZE(8, 8), 1, false, 0, 255,
3778
4099
  };
3779
4100
 
3780
4101
  static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1] = {
@@ -3782,23 +4103,23 @@ static const upb_msglayout *const google_protobuf_FieldDescriptorProto_submsgs[1
3782
4103
  };
3783
4104
 
3784
4105
  static const upb_msglayout_field google_protobuf_FieldDescriptorProto__fields[11] = {
3785
- {1, UPB_SIZE(24, 24), 1, 0, 12, 1},
3786
- {2, UPB_SIZE(32, 40), 2, 0, 12, 1},
3787
- {3, UPB_SIZE(12, 12), 3, 0, 5, 1},
3788
- {4, UPB_SIZE(4, 4), 4, 0, 14, 1},
3789
- {5, UPB_SIZE(8, 8), 5, 0, 14, 1},
3790
- {6, UPB_SIZE(40, 56), 6, 0, 12, 1},
3791
- {7, UPB_SIZE(48, 72), 7, 0, 12, 1},
3792
- {8, UPB_SIZE(64, 104), 8, 0, 11, 1},
3793
- {9, UPB_SIZE(16, 16), 9, 0, 5, 1},
3794
- {10, UPB_SIZE(56, 88), 10, 0, 12, 1},
3795
- {17, UPB_SIZE(20, 20), 11, 0, 8, 1},
4106
+ {1, UPB_SIZE(24, 24), 1, 0, 12, _UPB_MODE_SCALAR},
4107
+ {2, UPB_SIZE(32, 40), 2, 0, 12, _UPB_MODE_SCALAR},
4108
+ {3, UPB_SIZE(12, 12), 3, 0, 5, _UPB_MODE_SCALAR},
4109
+ {4, UPB_SIZE(4, 4), 4, 0, 14, _UPB_MODE_SCALAR},
4110
+ {5, UPB_SIZE(8, 8), 5, 0, 14, _UPB_MODE_SCALAR},
4111
+ {6, UPB_SIZE(40, 56), 6, 0, 12, _UPB_MODE_SCALAR},
4112
+ {7, UPB_SIZE(48, 72), 7, 0, 12, _UPB_MODE_SCALAR},
4113
+ {8, UPB_SIZE(64, 104), 8, 0, 11, _UPB_MODE_SCALAR},
4114
+ {9, UPB_SIZE(16, 16), 9, 0, 5, _UPB_MODE_SCALAR},
4115
+ {10, UPB_SIZE(56, 88), 10, 0, 12, _UPB_MODE_SCALAR},
4116
+ {17, UPB_SIZE(20, 20), 11, 0, 8, _UPB_MODE_SCALAR},
3796
4117
  };
3797
4118
 
3798
4119
  const upb_msglayout google_protobuf_FieldDescriptorProto_msginit = {
3799
4120
  &google_protobuf_FieldDescriptorProto_submsgs[0],
3800
4121
  &google_protobuf_FieldDescriptorProto__fields[0],
3801
- UPB_SIZE(72, 112), 11, false, 255,
4122
+ UPB_SIZE(72, 112), 11, false, 10, 255,
3802
4123
  };
3803
4124
 
3804
4125
  static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1] = {
@@ -3806,14 +4127,14 @@ static const upb_msglayout *const google_protobuf_OneofDescriptorProto_submsgs[1
3806
4127
  };
3807
4128
 
3808
4129
  static const upb_msglayout_field google_protobuf_OneofDescriptorProto__fields[2] = {
3809
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3810
- {2, UPB_SIZE(12, 24), 2, 0, 11, 1},
4130
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4131
+ {2, UPB_SIZE(12, 24), 2, 0, 11, _UPB_MODE_SCALAR},
3811
4132
  };
3812
4133
 
3813
4134
  const upb_msglayout google_protobuf_OneofDescriptorProto_msginit = {
3814
4135
  &google_protobuf_OneofDescriptorProto_submsgs[0],
3815
4136
  &google_protobuf_OneofDescriptorProto__fields[0],
3816
- UPB_SIZE(16, 32), 2, false, 255,
4137
+ UPB_SIZE(16, 32), 2, false, 2, 255,
3817
4138
  };
3818
4139
 
3819
4140
  static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3] = {
@@ -3823,28 +4144,28 @@ static const upb_msglayout *const google_protobuf_EnumDescriptorProto_submsgs[3]
3823
4144
  };
3824
4145
 
3825
4146
  static const upb_msglayout_field google_protobuf_EnumDescriptorProto__fields[5] = {
3826
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3827
- {2, UPB_SIZE(16, 32), 0, 2, 11, 3},
3828
- {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
3829
- {4, UPB_SIZE(20, 40), 0, 0, 11, 3},
3830
- {5, UPB_SIZE(24, 48), 0, 0, 12, 3},
4147
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4148
+ {2, UPB_SIZE(16, 32), 0, 2, 11, _UPB_MODE_ARRAY},
4149
+ {3, UPB_SIZE(12, 24), 2, 1, 11, _UPB_MODE_SCALAR},
4150
+ {4, UPB_SIZE(20, 40), 0, 0, 11, _UPB_MODE_ARRAY},
4151
+ {5, UPB_SIZE(24, 48), 0, 0, 12, _UPB_MODE_ARRAY},
3831
4152
  };
3832
4153
 
3833
4154
  const upb_msglayout google_protobuf_EnumDescriptorProto_msginit = {
3834
4155
  &google_protobuf_EnumDescriptorProto_submsgs[0],
3835
4156
  &google_protobuf_EnumDescriptorProto__fields[0],
3836
- UPB_SIZE(32, 64), 5, false, 255,
4157
+ UPB_SIZE(32, 64), 5, false, 5, 255,
3837
4158
  };
3838
4159
 
3839
4160
  static const upb_msglayout_field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
3840
- {1, UPB_SIZE(4, 4), 1, 0, 5, 1},
3841
- {2, UPB_SIZE(8, 8), 2, 0, 5, 1},
4161
+ {1, UPB_SIZE(4, 4), 1, 0, 5, _UPB_MODE_SCALAR},
4162
+ {2, UPB_SIZE(8, 8), 2, 0, 5, _UPB_MODE_SCALAR},
3842
4163
  };
3843
4164
 
3844
4165
  const upb_msglayout google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
3845
4166
  NULL,
3846
4167
  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
3847
- UPB_SIZE(16, 16), 2, false, 255,
4168
+ UPB_SIZE(16, 16), 2, false, 2, 255,
3848
4169
  };
3849
4170
 
3850
4171
  static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
@@ -3852,15 +4173,15 @@ static const upb_msglayout *const google_protobuf_EnumValueDescriptorProto_subms
3852
4173
  };
3853
4174
 
3854
4175
  static const upb_msglayout_field google_protobuf_EnumValueDescriptorProto__fields[3] = {
3855
- {1, UPB_SIZE(8, 8), 1, 0, 12, 1},
3856
- {2, UPB_SIZE(4, 4), 2, 0, 5, 1},
3857
- {3, UPB_SIZE(16, 24), 3, 0, 11, 1},
4176
+ {1, UPB_SIZE(8, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4177
+ {2, UPB_SIZE(4, 4), 2, 0, 5, _UPB_MODE_SCALAR},
4178
+ {3, UPB_SIZE(16, 24), 3, 0, 11, _UPB_MODE_SCALAR},
3858
4179
  };
3859
4180
 
3860
4181
  const upb_msglayout google_protobuf_EnumValueDescriptorProto_msginit = {
3861
4182
  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
3862
4183
  &google_protobuf_EnumValueDescriptorProto__fields[0],
3863
- UPB_SIZE(24, 32), 3, false, 255,
4184
+ UPB_SIZE(24, 32), 3, false, 3, 255,
3864
4185
  };
3865
4186
 
3866
4187
  static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs[2] = {
@@ -3869,15 +4190,15 @@ static const upb_msglayout *const google_protobuf_ServiceDescriptorProto_submsgs
3869
4190
  };
3870
4191
 
3871
4192
  static const upb_msglayout_field google_protobuf_ServiceDescriptorProto__fields[3] = {
3872
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3873
- {2, UPB_SIZE(16, 32), 0, 0, 11, 3},
3874
- {3, UPB_SIZE(12, 24), 2, 1, 11, 1},
4193
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4194
+ {2, UPB_SIZE(16, 32), 0, 0, 11, _UPB_MODE_ARRAY},
4195
+ {3, UPB_SIZE(12, 24), 2, 1, 11, _UPB_MODE_SCALAR},
3875
4196
  };
3876
4197
 
3877
4198
  const upb_msglayout google_protobuf_ServiceDescriptorProto_msginit = {
3878
4199
  &google_protobuf_ServiceDescriptorProto_submsgs[0],
3879
4200
  &google_protobuf_ServiceDescriptorProto__fields[0],
3880
- UPB_SIZE(24, 48), 3, false, 255,
4201
+ UPB_SIZE(24, 48), 3, false, 3, 255,
3881
4202
  };
3882
4203
 
3883
4204
  static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[1] = {
@@ -3885,18 +4206,18 @@ static const upb_msglayout *const google_protobuf_MethodDescriptorProto_submsgs[
3885
4206
  };
3886
4207
 
3887
4208
  static const upb_msglayout_field google_protobuf_MethodDescriptorProto__fields[6] = {
3888
- {1, UPB_SIZE(4, 8), 1, 0, 12, 1},
3889
- {2, UPB_SIZE(12, 24), 2, 0, 12, 1},
3890
- {3, UPB_SIZE(20, 40), 3, 0, 12, 1},
3891
- {4, UPB_SIZE(28, 56), 4, 0, 11, 1},
3892
- {5, UPB_SIZE(1, 1), 5, 0, 8, 1},
3893
- {6, UPB_SIZE(2, 2), 6, 0, 8, 1},
4209
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4210
+ {2, UPB_SIZE(12, 24), 2, 0, 12, _UPB_MODE_SCALAR},
4211
+ {3, UPB_SIZE(20, 40), 3, 0, 12, _UPB_MODE_SCALAR},
4212
+ {4, UPB_SIZE(28, 56), 4, 0, 11, _UPB_MODE_SCALAR},
4213
+ {5, UPB_SIZE(1, 1), 5, 0, 8, _UPB_MODE_SCALAR},
4214
+ {6, UPB_SIZE(2, 2), 6, 0, 8, _UPB_MODE_SCALAR},
3894
4215
  };
3895
4216
 
3896
4217
  const upb_msglayout google_protobuf_MethodDescriptorProto_msginit = {
3897
4218
  &google_protobuf_MethodDescriptorProto_submsgs[0],
3898
4219
  &google_protobuf_MethodDescriptorProto__fields[0],
3899
- UPB_SIZE(32, 64), 6, false, 255,
4220
+ UPB_SIZE(32, 64), 6, false, 6, 255,
3900
4221
  };
3901
4222
 
3902
4223
  static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
@@ -3904,33 +4225,33 @@ static const upb_msglayout *const google_protobuf_FileOptions_submsgs[1] = {
3904
4225
  };
3905
4226
 
3906
4227
  static const upb_msglayout_field google_protobuf_FileOptions__fields[21] = {
3907
- {1, UPB_SIZE(20, 24), 1, 0, 12, 1},
3908
- {8, UPB_SIZE(28, 40), 2, 0, 12, 1},
3909
- {9, UPB_SIZE(4, 4), 3, 0, 14, 1},
3910
- {10, UPB_SIZE(8, 8), 4, 0, 8, 1},
3911
- {11, UPB_SIZE(36, 56), 5, 0, 12, 1},
3912
- {16, UPB_SIZE(9, 9), 6, 0, 8, 1},
3913
- {17, UPB_SIZE(10, 10), 7, 0, 8, 1},
3914
- {18, UPB_SIZE(11, 11), 8, 0, 8, 1},
3915
- {20, UPB_SIZE(12, 12), 9, 0, 8, 1},
3916
- {23, UPB_SIZE(13, 13), 10, 0, 8, 1},
3917
- {27, UPB_SIZE(14, 14), 11, 0, 8, 1},
3918
- {31, UPB_SIZE(15, 15), 12, 0, 8, 1},
3919
- {36, UPB_SIZE(44, 72), 13, 0, 12, 1},
3920
- {37, UPB_SIZE(52, 88), 14, 0, 12, 1},
3921
- {39, UPB_SIZE(60, 104), 15, 0, 12, 1},
3922
- {40, UPB_SIZE(68, 120), 16, 0, 12, 1},
3923
- {41, UPB_SIZE(76, 136), 17, 0, 12, 1},
3924
- {42, UPB_SIZE(16, 16), 18, 0, 8, 1},
3925
- {44, UPB_SIZE(84, 152), 19, 0, 12, 1},
3926
- {45, UPB_SIZE(92, 168), 20, 0, 12, 1},
3927
- {999, UPB_SIZE(100, 184), 0, 0, 11, 3},
4228
+ {1, UPB_SIZE(20, 24), 1, 0, 12, _UPB_MODE_SCALAR},
4229
+ {8, UPB_SIZE(28, 40), 2, 0, 12, _UPB_MODE_SCALAR},
4230
+ {9, UPB_SIZE(4, 4), 3, 0, 14, _UPB_MODE_SCALAR},
4231
+ {10, UPB_SIZE(8, 8), 4, 0, 8, _UPB_MODE_SCALAR},
4232
+ {11, UPB_SIZE(36, 56), 5, 0, 12, _UPB_MODE_SCALAR},
4233
+ {16, UPB_SIZE(9, 9), 6, 0, 8, _UPB_MODE_SCALAR},
4234
+ {17, UPB_SIZE(10, 10), 7, 0, 8, _UPB_MODE_SCALAR},
4235
+ {18, UPB_SIZE(11, 11), 8, 0, 8, _UPB_MODE_SCALAR},
4236
+ {20, UPB_SIZE(12, 12), 9, 0, 8, _UPB_MODE_SCALAR},
4237
+ {23, UPB_SIZE(13, 13), 10, 0, 8, _UPB_MODE_SCALAR},
4238
+ {27, UPB_SIZE(14, 14), 11, 0, 8, _UPB_MODE_SCALAR},
4239
+ {31, UPB_SIZE(15, 15), 12, 0, 8, _UPB_MODE_SCALAR},
4240
+ {36, UPB_SIZE(44, 72), 13, 0, 12, _UPB_MODE_SCALAR},
4241
+ {37, UPB_SIZE(52, 88), 14, 0, 12, _UPB_MODE_SCALAR},
4242
+ {39, UPB_SIZE(60, 104), 15, 0, 12, _UPB_MODE_SCALAR},
4243
+ {40, UPB_SIZE(68, 120), 16, 0, 12, _UPB_MODE_SCALAR},
4244
+ {41, UPB_SIZE(76, 136), 17, 0, 12, _UPB_MODE_SCALAR},
4245
+ {42, UPB_SIZE(16, 16), 18, 0, 8, _UPB_MODE_SCALAR},
4246
+ {44, UPB_SIZE(84, 152), 19, 0, 12, _UPB_MODE_SCALAR},
4247
+ {45, UPB_SIZE(92, 168), 20, 0, 12, _UPB_MODE_SCALAR},
4248
+ {999, UPB_SIZE(100, 184), 0, 0, 11, _UPB_MODE_ARRAY},
3928
4249
  };
3929
4250
 
3930
4251
  const upb_msglayout google_protobuf_FileOptions_msginit = {
3931
4252
  &google_protobuf_FileOptions_submsgs[0],
3932
4253
  &google_protobuf_FileOptions__fields[0],
3933
- UPB_SIZE(104, 192), 21, false, 255,
4254
+ UPB_SIZE(104, 192), 21, false, 1, 255,
3934
4255
  };
3935
4256
 
3936
4257
  static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
@@ -3938,17 +4259,17 @@ static const upb_msglayout *const google_protobuf_MessageOptions_submsgs[1] = {
3938
4259
  };
3939
4260
 
3940
4261
  static const upb_msglayout_field google_protobuf_MessageOptions__fields[5] = {
3941
- {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
3942
- {2, UPB_SIZE(2, 2), 2, 0, 8, 1},
3943
- {3, UPB_SIZE(3, 3), 3, 0, 8, 1},
3944
- {7, UPB_SIZE(4, 4), 4, 0, 8, 1},
3945
- {999, UPB_SIZE(8, 8), 0, 0, 11, 3},
4262
+ {1, UPB_SIZE(1, 1), 1, 0, 8, _UPB_MODE_SCALAR},
4263
+ {2, UPB_SIZE(2, 2), 2, 0, 8, _UPB_MODE_SCALAR},
4264
+ {3, UPB_SIZE(3, 3), 3, 0, 8, _UPB_MODE_SCALAR},
4265
+ {7, UPB_SIZE(4, 4), 4, 0, 8, _UPB_MODE_SCALAR},
4266
+ {999, UPB_SIZE(8, 8), 0, 0, 11, _UPB_MODE_ARRAY},
3946
4267
  };
3947
4268
 
3948
4269
  const upb_msglayout google_protobuf_MessageOptions_msginit = {
3949
4270
  &google_protobuf_MessageOptions_submsgs[0],
3950
4271
  &google_protobuf_MessageOptions__fields[0],
3951
- UPB_SIZE(16, 16), 5, false, 255,
4272
+ UPB_SIZE(16, 16), 5, false, 3, 255,
3952
4273
  };
3953
4274
 
3954
4275
  static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
@@ -3956,19 +4277,19 @@ static const upb_msglayout *const google_protobuf_FieldOptions_submsgs[1] = {
3956
4277
  };
3957
4278
 
3958
4279
  static const upb_msglayout_field google_protobuf_FieldOptions__fields[7] = {
3959
- {1, UPB_SIZE(4, 4), 1, 0, 14, 1},
3960
- {2, UPB_SIZE(12, 12), 2, 0, 8, 1},
3961
- {3, UPB_SIZE(13, 13), 3, 0, 8, 1},
3962
- {5, UPB_SIZE(14, 14), 4, 0, 8, 1},
3963
- {6, UPB_SIZE(8, 8), 5, 0, 14, 1},
3964
- {10, UPB_SIZE(15, 15), 6, 0, 8, 1},
3965
- {999, UPB_SIZE(16, 16), 0, 0, 11, 3},
4280
+ {1, UPB_SIZE(4, 4), 1, 0, 14, _UPB_MODE_SCALAR},
4281
+ {2, UPB_SIZE(12, 12), 2, 0, 8, _UPB_MODE_SCALAR},
4282
+ {3, UPB_SIZE(13, 13), 3, 0, 8, _UPB_MODE_SCALAR},
4283
+ {5, UPB_SIZE(14, 14), 4, 0, 8, _UPB_MODE_SCALAR},
4284
+ {6, UPB_SIZE(8, 8), 5, 0, 14, _UPB_MODE_SCALAR},
4285
+ {10, UPB_SIZE(15, 15), 6, 0, 8, _UPB_MODE_SCALAR},
4286
+ {999, UPB_SIZE(16, 16), 0, 0, 11, _UPB_MODE_ARRAY},
3966
4287
  };
3967
4288
 
3968
4289
  const upb_msglayout google_protobuf_FieldOptions_msginit = {
3969
4290
  &google_protobuf_FieldOptions_submsgs[0],
3970
4291
  &google_protobuf_FieldOptions__fields[0],
3971
- UPB_SIZE(24, 24), 7, false, 255,
4292
+ UPB_SIZE(24, 24), 7, false, 3, 255,
3972
4293
  };
3973
4294
 
3974
4295
  static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
@@ -3976,13 +4297,13 @@ static const upb_msglayout *const google_protobuf_OneofOptions_submsgs[1] = {
3976
4297
  };
3977
4298
 
3978
4299
  static const upb_msglayout_field google_protobuf_OneofOptions__fields[1] = {
3979
- {999, UPB_SIZE(0, 0), 0, 0, 11, 3},
4300
+ {999, UPB_SIZE(0, 0), 0, 0, 11, _UPB_MODE_ARRAY},
3980
4301
  };
3981
4302
 
3982
4303
  const upb_msglayout google_protobuf_OneofOptions_msginit = {
3983
4304
  &google_protobuf_OneofOptions_submsgs[0],
3984
4305
  &google_protobuf_OneofOptions__fields[0],
3985
- UPB_SIZE(8, 8), 1, false, 255,
4306
+ UPB_SIZE(8, 8), 1, false, 0, 255,
3986
4307
  };
3987
4308
 
3988
4309
  static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
@@ -3990,15 +4311,15 @@ static const upb_msglayout *const google_protobuf_EnumOptions_submsgs[1] = {
3990
4311
  };
3991
4312
 
3992
4313
  static const upb_msglayout_field google_protobuf_EnumOptions__fields[3] = {
3993
- {2, UPB_SIZE(1, 1), 1, 0, 8, 1},
3994
- {3, UPB_SIZE(2, 2), 2, 0, 8, 1},
3995
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
4314
+ {2, UPB_SIZE(1, 1), 1, 0, 8, _UPB_MODE_SCALAR},
4315
+ {3, UPB_SIZE(2, 2), 2, 0, 8, _UPB_MODE_SCALAR},
4316
+ {999, UPB_SIZE(4, 8), 0, 0, 11, _UPB_MODE_ARRAY},
3996
4317
  };
3997
4318
 
3998
4319
  const upb_msglayout google_protobuf_EnumOptions_msginit = {
3999
4320
  &google_protobuf_EnumOptions_submsgs[0],
4000
4321
  &google_protobuf_EnumOptions__fields[0],
4001
- UPB_SIZE(8, 16), 3, false, 255,
4322
+ UPB_SIZE(8, 16), 3, false, 0, 255,
4002
4323
  };
4003
4324
 
4004
4325
  static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] = {
@@ -4006,14 +4327,14 @@ static const upb_msglayout *const google_protobuf_EnumValueOptions_submsgs[1] =
4006
4327
  };
4007
4328
 
4008
4329
  static const upb_msglayout_field google_protobuf_EnumValueOptions__fields[2] = {
4009
- {1, UPB_SIZE(1, 1), 1, 0, 8, 1},
4010
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
4330
+ {1, UPB_SIZE(1, 1), 1, 0, 8, _UPB_MODE_SCALAR},
4331
+ {999, UPB_SIZE(4, 8), 0, 0, 11, _UPB_MODE_ARRAY},
4011
4332
  };
4012
4333
 
4013
4334
  const upb_msglayout google_protobuf_EnumValueOptions_msginit = {
4014
4335
  &google_protobuf_EnumValueOptions_submsgs[0],
4015
4336
  &google_protobuf_EnumValueOptions__fields[0],
4016
- UPB_SIZE(8, 16), 2, false, 255,
4337
+ UPB_SIZE(8, 16), 2, false, 1, 255,
4017
4338
  };
4018
4339
 
4019
4340
  static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
@@ -4021,14 +4342,14 @@ static const upb_msglayout *const google_protobuf_ServiceOptions_submsgs[1] = {
4021
4342
  };
4022
4343
 
4023
4344
  static const upb_msglayout_field google_protobuf_ServiceOptions__fields[2] = {
4024
- {33, UPB_SIZE(1, 1), 1, 0, 8, 1},
4025
- {999, UPB_SIZE(4, 8), 0, 0, 11, 3},
4345
+ {33, UPB_SIZE(1, 1), 1, 0, 8, _UPB_MODE_SCALAR},
4346
+ {999, UPB_SIZE(4, 8), 0, 0, 11, _UPB_MODE_ARRAY},
4026
4347
  };
4027
4348
 
4028
4349
  const upb_msglayout google_protobuf_ServiceOptions_msginit = {
4029
4350
  &google_protobuf_ServiceOptions_submsgs[0],
4030
4351
  &google_protobuf_ServiceOptions__fields[0],
4031
- UPB_SIZE(8, 16), 2, false, 255,
4352
+ UPB_SIZE(8, 16), 2, false, 0, 255,
4032
4353
  };
4033
4354
 
4034
4355
  static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
@@ -4036,15 +4357,15 @@ static const upb_msglayout *const google_protobuf_MethodOptions_submsgs[1] = {
4036
4357
  };
4037
4358
 
4038
4359
  static const upb_msglayout_field google_protobuf_MethodOptions__fields[3] = {
4039
- {33, UPB_SIZE(8, 8), 1, 0, 8, 1},
4040
- {34, UPB_SIZE(4, 4), 2, 0, 14, 1},
4041
- {999, UPB_SIZE(12, 16), 0, 0, 11, 3},
4360
+ {33, UPB_SIZE(8, 8), 1, 0, 8, _UPB_MODE_SCALAR},
4361
+ {34, UPB_SIZE(4, 4), 2, 0, 14, _UPB_MODE_SCALAR},
4362
+ {999, UPB_SIZE(12, 16), 0, 0, 11, _UPB_MODE_ARRAY},
4042
4363
  };
4043
4364
 
4044
4365
  const upb_msglayout google_protobuf_MethodOptions_msginit = {
4045
4366
  &google_protobuf_MethodOptions_submsgs[0],
4046
4367
  &google_protobuf_MethodOptions__fields[0],
4047
- UPB_SIZE(16, 24), 3, false, 255,
4368
+ UPB_SIZE(16, 24), 3, false, 0, 255,
4048
4369
  };
4049
4370
 
4050
4371
  static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1] = {
@@ -4052,30 +4373,30 @@ static const upb_msglayout *const google_protobuf_UninterpretedOption_submsgs[1]
4052
4373
  };
4053
4374
 
4054
4375
  static const upb_msglayout_field google_protobuf_UninterpretedOption__fields[7] = {
4055
- {2, UPB_SIZE(56, 80), 0, 0, 11, 3},
4056
- {3, UPB_SIZE(32, 32), 1, 0, 12, 1},
4057
- {4, UPB_SIZE(8, 8), 2, 0, 4, 1},
4058
- {5, UPB_SIZE(16, 16), 3, 0, 3, 1},
4059
- {6, UPB_SIZE(24, 24), 4, 0, 1, 1},
4060
- {7, UPB_SIZE(40, 48), 5, 0, 12, 1},
4061
- {8, UPB_SIZE(48, 64), 6, 0, 12, 1},
4376
+ {2, UPB_SIZE(56, 80), 0, 0, 11, _UPB_MODE_ARRAY},
4377
+ {3, UPB_SIZE(32, 32), 1, 0, 12, _UPB_MODE_SCALAR},
4378
+ {4, UPB_SIZE(8, 8), 2, 0, 4, _UPB_MODE_SCALAR},
4379
+ {5, UPB_SIZE(16, 16), 3, 0, 3, _UPB_MODE_SCALAR},
4380
+ {6, UPB_SIZE(24, 24), 4, 0, 1, _UPB_MODE_SCALAR},
4381
+ {7, UPB_SIZE(40, 48), 5, 0, 12, _UPB_MODE_SCALAR},
4382
+ {8, UPB_SIZE(48, 64), 6, 0, 12, _UPB_MODE_SCALAR},
4062
4383
  };
4063
4384
 
4064
4385
  const upb_msglayout google_protobuf_UninterpretedOption_msginit = {
4065
4386
  &google_protobuf_UninterpretedOption_submsgs[0],
4066
4387
  &google_protobuf_UninterpretedOption__fields[0],
4067
- UPB_SIZE(64, 96), 7, false, 255,
4388
+ UPB_SIZE(64, 96), 7, false, 0, 255,
4068
4389
  };
4069
4390
 
4070
4391
  static const upb_msglayout_field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
4071
- {1, UPB_SIZE(4, 8), 1, 0, 12, 2},
4072
- {2, UPB_SIZE(1, 1), 2, 0, 8, 2},
4392
+ {1, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4393
+ {2, UPB_SIZE(1, 1), 2, 0, 8, _UPB_MODE_SCALAR},
4073
4394
  };
4074
4395
 
4075
4396
  const upb_msglayout google_protobuf_UninterpretedOption_NamePart_msginit = {
4076
4397
  NULL,
4077
4398
  &google_protobuf_UninterpretedOption_NamePart__fields[0],
4078
- UPB_SIZE(16, 32), 2, false, 255,
4399
+ UPB_SIZE(16, 32), 2, false, 2, 255,
4079
4400
  };
4080
4401
 
4081
4402
  static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
@@ -4083,27 +4404,27 @@ static const upb_msglayout *const google_protobuf_SourceCodeInfo_submsgs[1] = {
4083
4404
  };
4084
4405
 
4085
4406
  static const upb_msglayout_field google_protobuf_SourceCodeInfo__fields[1] = {
4086
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
4407
+ {1, UPB_SIZE(0, 0), 0, 0, 11, _UPB_MODE_ARRAY},
4087
4408
  };
4088
4409
 
4089
4410
  const upb_msglayout google_protobuf_SourceCodeInfo_msginit = {
4090
4411
  &google_protobuf_SourceCodeInfo_submsgs[0],
4091
4412
  &google_protobuf_SourceCodeInfo__fields[0],
4092
- UPB_SIZE(8, 8), 1, false, 255,
4413
+ UPB_SIZE(8, 8), 1, false, 1, 255,
4093
4414
  };
4094
4415
 
4095
4416
  static const upb_msglayout_field google_protobuf_SourceCodeInfo_Location__fields[5] = {
4096
- {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_LABEL_PACKED},
4097
- {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_LABEL_PACKED},
4098
- {3, UPB_SIZE(4, 8), 1, 0, 12, 1},
4099
- {4, UPB_SIZE(12, 24), 2, 0, 12, 1},
4100
- {6, UPB_SIZE(28, 56), 0, 0, 12, 3},
4417
+ {1, UPB_SIZE(20, 40), 0, 0, 5, _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED},
4418
+ {2, UPB_SIZE(24, 48), 0, 0, 5, _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED},
4419
+ {3, UPB_SIZE(4, 8), 1, 0, 12, _UPB_MODE_SCALAR},
4420
+ {4, UPB_SIZE(12, 24), 2, 0, 12, _UPB_MODE_SCALAR},
4421
+ {6, UPB_SIZE(28, 56), 0, 0, 12, _UPB_MODE_ARRAY},
4101
4422
  };
4102
4423
 
4103
4424
  const upb_msglayout google_protobuf_SourceCodeInfo_Location_msginit = {
4104
4425
  NULL,
4105
4426
  &google_protobuf_SourceCodeInfo_Location__fields[0],
4106
- UPB_SIZE(32, 64), 5, false, 255,
4427
+ UPB_SIZE(32, 64), 5, false, 4, 255,
4107
4428
  };
4108
4429
 
4109
4430
  static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] = {
@@ -4111,30 +4432,31 @@ static const upb_msglayout *const google_protobuf_GeneratedCodeInfo_submsgs[1] =
4111
4432
  };
4112
4433
 
4113
4434
  static const upb_msglayout_field google_protobuf_GeneratedCodeInfo__fields[1] = {
4114
- {1, UPB_SIZE(0, 0), 0, 0, 11, 3},
4435
+ {1, UPB_SIZE(0, 0), 0, 0, 11, _UPB_MODE_ARRAY},
4115
4436
  };
4116
4437
 
4117
4438
  const upb_msglayout google_protobuf_GeneratedCodeInfo_msginit = {
4118
4439
  &google_protobuf_GeneratedCodeInfo_submsgs[0],
4119
4440
  &google_protobuf_GeneratedCodeInfo__fields[0],
4120
- UPB_SIZE(8, 8), 1, false, 255,
4441
+ UPB_SIZE(8, 8), 1, false, 1, 255,
4121
4442
  };
4122
4443
 
4123
4444
  static const upb_msglayout_field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
4124
- {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_LABEL_PACKED},
4125
- {2, UPB_SIZE(12, 16), 1, 0, 12, 1},
4126
- {3, UPB_SIZE(4, 4), 2, 0, 5, 1},
4127
- {4, UPB_SIZE(8, 8), 3, 0, 5, 1},
4445
+ {1, UPB_SIZE(20, 32), 0, 0, 5, _UPB_MODE_ARRAY | _UPB_MODE_IS_PACKED},
4446
+ {2, UPB_SIZE(12, 16), 1, 0, 12, _UPB_MODE_SCALAR},
4447
+ {3, UPB_SIZE(4, 4), 2, 0, 5, _UPB_MODE_SCALAR},
4448
+ {4, UPB_SIZE(8, 8), 3, 0, 5, _UPB_MODE_SCALAR},
4128
4449
  };
4129
4450
 
4130
4451
  const upb_msglayout google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
4131
4452
  NULL,
4132
4453
  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
4133
- UPB_SIZE(24, 48), 4, false, 255,
4454
+ UPB_SIZE(24, 48), 4, false, 4, 255,
4134
4455
  };
4135
4456
 
4136
4457
 
4137
4458
 
4459
+ /** upb/def.c ************************************************************/
4138
4460
 
4139
4461
  #include <ctype.h>
4140
4462
  #include <errno.h>
@@ -4172,7 +4494,6 @@ struct upb_fielddef {
4172
4494
  uint32_t number_;
4173
4495
  uint16_t index_;
4174
4496
  uint16_t layout_index;
4175
- uint32_t selector_base; /* Used to index into a upb::Handlers table. */
4176
4497
  bool is_extension_;
4177
4498
  bool lazy_;
4178
4499
  bool packed_;
@@ -4185,8 +4506,6 @@ struct upb_msgdef {
4185
4506
  const upb_msglayout *layout;
4186
4507
  const upb_filedef *file;
4187
4508
  const char *full_name;
4188
- uint32_t selector_count;
4189
- uint32_t submsg_field_count;
4190
4509
 
4191
4510
  /* Tables for looking up fields by number and name. */
4192
4511
  upb_inttable itof;
@@ -4316,30 +4635,6 @@ int cmp_fields(const void *p1, const void *p2) {
4316
4635
  return field_rank(f1) - field_rank(f2);
4317
4636
  }
4318
4637
 
4319
- /* A few implementation details of handlers. We put these here to avoid
4320
- * a def -> handlers dependency. */
4321
-
4322
- #define UPB_STATIC_SELECTOR_COUNT 3 /* Warning: also in upb/handlers.h. */
4323
-
4324
- static uint32_t upb_handlers_selectorbaseoffset(const upb_fielddef *f) {
4325
- return upb_fielddef_isseq(f) ? 2 : 0;
4326
- }
4327
-
4328
- static uint32_t upb_handlers_selectorcount(const upb_fielddef *f) {
4329
- uint32_t ret = 1;
4330
- if (upb_fielddef_isseq(f)) ret += 2; /* STARTSEQ/ENDSEQ */
4331
- if (upb_fielddef_isstring(f)) ret += 2; /* [STRING]/STARTSTR/ENDSTR */
4332
- if (upb_fielddef_issubmsg(f)) {
4333
- /* ENDSUBMSG (STARTSUBMSG is at table beginning) */
4334
- ret += 0;
4335
- if (upb_fielddef_lazy(f)) {
4336
- /* STARTSTR/ENDSTR/STRING (for lazy) */
4337
- ret += 3;
4338
- }
4339
- }
4340
- return ret;
4341
- }
4342
-
4343
4638
  static void upb_status_setoom(upb_status *status) {
4344
4639
  upb_status_seterrmsg(status, "out of memory");
4345
4640
  }
@@ -4431,8 +4726,7 @@ bool upb_enumdef_ntoi(const upb_enumdef *def, const char *name,
4431
4726
 
4432
4727
  const char *upb_enumdef_iton(const upb_enumdef *def, int32_t num) {
4433
4728
  upb_value v;
4434
- return upb_inttable_lookup32(&def->iton, num, &v) ?
4435
- upb_value_getcstr(v) : NULL;
4729
+ return upb_inttable_lookup(&def->iton, num, &v) ? upb_value_getcstr(v) : NULL;
4436
4730
  }
4437
4731
 
4438
4732
  const char *upb_enum_iter_name(upb_enum_iter *iter) {
@@ -4521,10 +4815,6 @@ const char *upb_fielddef_jsonname(const upb_fielddef *f) {
4521
4815
  return f->json_name;
4522
4816
  }
4523
4817
 
4524
- uint32_t upb_fielddef_selectorbase(const upb_fielddef *f) {
4525
- return f->selector_base;
4526
- }
4527
-
4528
4818
  const upb_filedef *upb_fielddef_file(const upb_fielddef *f) {
4529
4819
  return f->file;
4530
4820
  }
@@ -4687,18 +4977,10 @@ upb_syntax_t upb_msgdef_syntax(const upb_msgdef *m) {
4687
4977
  return m->file->syntax;
4688
4978
  }
4689
4979
 
4690
- size_t upb_msgdef_selectorcount(const upb_msgdef *m) {
4691
- return m->selector_count;
4692
- }
4693
-
4694
- uint32_t upb_msgdef_submsgfieldcount(const upb_msgdef *m) {
4695
- return m->submsg_field_count;
4696
- }
4697
-
4698
4980
  const upb_fielddef *upb_msgdef_itof(const upb_msgdef *m, uint32_t i) {
4699
4981
  upb_value val;
4700
- return upb_inttable_lookup32(&m->itof, i, &val) ?
4701
- upb_value_getconstptr(val) : NULL;
4982
+ return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
4983
+ : NULL;
4702
4984
  }
4703
4985
 
4704
4986
  const upb_fielddef *upb_msgdef_ntof(const upb_msgdef *m, const char *name,
@@ -4906,8 +5188,8 @@ const upb_fielddef *upb_oneofdef_ntof(const upb_oneofdef *o,
4906
5188
 
4907
5189
  const upb_fielddef *upb_oneofdef_itof(const upb_oneofdef *o, uint32_t num) {
4908
5190
  upb_value val;
4909
- return upb_inttable_lookup32(&o->itof, num, &val) ?
4910
- upb_value_getptr(val) : NULL;
5191
+ return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
5192
+ : NULL;
4911
5193
  }
4912
5194
 
4913
5195
  void upb_oneof_begin(upb_oneof_iter *iter, const upb_oneofdef *o) {
@@ -4987,7 +5269,6 @@ void upb_symtab_free(upb_symtab *s) {
4987
5269
 
4988
5270
  upb_symtab *upb_symtab_new(void) {
4989
5271
  upb_symtab *s = upb_gmalloc(sizeof(*s));
4990
- upb_alloc *alloc;
4991
5272
 
4992
5273
  if (!s) {
4993
5274
  return NULL;
@@ -4995,10 +5276,9 @@ upb_symtab *upb_symtab_new(void) {
4995
5276
 
4996
5277
  s->arena = upb_arena_new();
4997
5278
  s->bytes_loaded = 0;
4998
- alloc = upb_arena_alloc(s->arena);
4999
5279
 
5000
- if (!upb_strtable_init2(&s->syms, UPB_CTYPE_CONSTPTR, 32, alloc) ||
5001
- !upb_strtable_init2(&s->files, UPB_CTYPE_CONSTPTR, 4, alloc)) {
5280
+ if (!upb_strtable_init(&s->syms, 32, s->arena) ||
5281
+ !upb_strtable_init(&s->files, 4, s->arena)) {
5002
5282
  upb_arena_free(s->arena);
5003
5283
  upb_gfree(s);
5004
5284
  s = NULL;
@@ -5054,8 +5334,7 @@ int upb_symtab_filecount(const upb_symtab *s) {
5054
5334
  typedef struct {
5055
5335
  upb_symtab *symtab;
5056
5336
  upb_filedef *file; /* File we are building. */
5057
- upb_arena *file_arena; /* Allocate defs here. */
5058
- upb_alloc *alloc; /* Alloc of file_arena, for tables. */
5337
+ upb_arena *arena; /* Allocate defs here. */
5059
5338
  const upb_msglayout **layouts; /* NULL if we should build layouts. */
5060
5339
  upb_status *status; /* Record errors here. */
5061
5340
  jmp_buf err; /* longjmp() on error. */
@@ -5077,7 +5356,7 @@ static void symtab_oomerr(symtab_addctx *ctx) {
5077
5356
  }
5078
5357
 
5079
5358
  void *symtab_alloc(symtab_addctx *ctx, size_t bytes) {
5080
- void *ret = upb_arena_malloc(ctx->file_arena, bytes);
5359
+ void *ret = upb_arena_malloc(ctx->arena, bytes);
5081
5360
  if (!ret) symtab_oomerr(ctx);
5082
5361
  return ret;
5083
5362
  }
@@ -5167,13 +5446,44 @@ static int field_number_cmp(const void *p1, const void *p2) {
5167
5446
  return f1->number - f2->number;
5168
5447
  }
5169
5448
 
5170
- static void assign_layout_indices(const upb_msgdef *m, upb_msglayout_field *fields) {
5449
+ static void assign_layout_indices(const upb_msgdef *m, upb_msglayout *l,
5450
+ upb_msglayout_field *fields) {
5171
5451
  int i;
5172
5452
  int n = upb_msgdef_numfields(m);
5453
+ int dense_below = 0;
5173
5454
  for (i = 0; i < n; i++) {
5174
5455
  upb_fielddef *f = (upb_fielddef*)upb_msgdef_itof(m, fields[i].number);
5175
5456
  UPB_ASSERT(f);
5176
5457
  f->layout_index = i;
5458
+ if (i < UINT8_MAX && fields[i].number == i + 1 &&
5459
+ (i == 0 || fields[i-1].number == i)) {
5460
+ dense_below = i + 1;
5461
+ }
5462
+ }
5463
+ l->dense_below = dense_below;
5464
+ }
5465
+
5466
+ static void fill_fieldlayout(upb_msglayout_field *field, const upb_fielddef *f) {
5467
+ field->number = upb_fielddef_number(f);
5468
+ field->descriptortype = upb_fielddef_descriptortype(f);
5469
+
5470
+ if (field->descriptortype == UPB_DTYPE_STRING &&
5471
+ f->file->syntax == UPB_SYNTAX_PROTO2) {
5472
+ /* See TableDescriptorType() in upbc/generator.cc for details and
5473
+ * rationale. */
5474
+ field->descriptortype = UPB_DTYPE_BYTES;
5475
+ }
5476
+
5477
+ if (upb_fielddef_ismap(f)) {
5478
+ field->mode = _UPB_MODE_MAP;
5479
+ } else if (upb_fielddef_isseq(f)) {
5480
+ field->mode = _UPB_MODE_ARRAY;
5481
+ } else {
5482
+ field->mode = _UPB_MODE_SCALAR;
5483
+ }
5484
+
5485
+ if (upb_fielddef_packed(f)) {
5486
+ field->mode |= _UPB_MODE_IS_PACKED;
5177
5487
  }
5178
5488
  }
5179
5489
 
@@ -5184,13 +5494,21 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
5184
5494
  upb_msg_field_iter it;
5185
5495
  upb_msg_oneof_iter oit;
5186
5496
  size_t hasbit;
5187
- size_t submsg_count = m->submsg_field_count;
5497
+ size_t field_count = upb_msgdef_numfields(m);
5498
+ size_t submsg_count = 0;
5188
5499
  const upb_msglayout **submsgs;
5189
5500
  upb_msglayout_field *fields;
5190
5501
 
5191
5502
  memset(l, 0, sizeof(*l) + sizeof(_upb_fasttable_entry));
5192
5503
 
5193
- fields = symtab_alloc(ctx, upb_msgdef_numfields(m) * sizeof(*fields));
5504
+ /* Count sub-messages. */
5505
+ for (size_t i = 0; i < field_count; i++) {
5506
+ if (upb_fielddef_issubmsg(&m->fields[i])) {
5507
+ submsg_count++;
5508
+ }
5509
+ }
5510
+
5511
+ fields = symtab_alloc(ctx, field_count * sizeof(*fields));
5194
5512
  submsgs = symtab_alloc(ctx, submsg_count * sizeof(*submsgs));
5195
5513
 
5196
5514
  l->field_count = upb_msgdef_numfields(m);
@@ -5210,8 +5528,8 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
5210
5528
  const upb_fielddef *val = upb_msgdef_itof(m, 2);
5211
5529
  fields[0].number = 1;
5212
5530
  fields[1].number = 2;
5213
- fields[0].label = UPB_LABEL_OPTIONAL;
5214
- fields[1].label = UPB_LABEL_OPTIONAL;
5531
+ fields[0].mode = _UPB_MODE_SCALAR;
5532
+ fields[1].mode = _UPB_MODE_SCALAR;
5215
5533
  fields[0].presence = 0;
5216
5534
  fields[1].presence = 0;
5217
5535
  fields[0].descriptortype = upb_fielddef_descriptortype(key);
@@ -5247,22 +5565,7 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
5247
5565
  upb_fielddef* f = upb_msg_iter_field(&it);
5248
5566
  upb_msglayout_field *field = &fields[upb_fielddef_index(f)];
5249
5567
 
5250
- field->number = upb_fielddef_number(f);
5251
- field->descriptortype = upb_fielddef_descriptortype(f);
5252
- field->label = upb_fielddef_label(f);
5253
-
5254
- if (field->descriptortype == UPB_DTYPE_STRING &&
5255
- f->file->syntax == UPB_SYNTAX_PROTO2) {
5256
- /* See TableDescriptorType() in upbc/generator.cc for details and
5257
- * rationale. */
5258
- field->descriptortype = UPB_DTYPE_BYTES;
5259
- }
5260
-
5261
- if (upb_fielddef_ismap(f)) {
5262
- field->label = _UPB_LABEL_MAP;
5263
- } else if (upb_fielddef_packed(f)) {
5264
- field->label = _UPB_LABEL_PACKED;
5265
- }
5568
+ fill_fieldlayout(field, f);
5266
5569
 
5267
5570
  if (upb_fielddef_issubmsg(f)) {
5268
5571
  const upb_msgdef *subm = upb_fielddef_msgsubdef(f);
@@ -5338,54 +5641,11 @@ static void make_layout(symtab_addctx *ctx, const upb_msgdef *m) {
5338
5641
 
5339
5642
  /* Sort fields by number. */
5340
5643
  qsort(fields, upb_msgdef_numfields(m), sizeof(*fields), field_number_cmp);
5341
- assign_layout_indices(m, fields);
5342
- }
5343
-
5344
- static void assign_msg_indices(symtab_addctx *ctx, upb_msgdef *m) {
5345
- /* Sort fields. upb internally relies on UPB_TYPE_MESSAGE fields having the
5346
- * lowest indexes, but we do not publicly guarantee this. */
5347
- upb_msg_field_iter j;
5348
- int i;
5349
- uint32_t selector;
5350
- int n = upb_msgdef_numfields(m);
5351
- upb_fielddef **fields;
5352
-
5353
- if (n == 0) {
5354
- m->selector_count = UPB_STATIC_SELECTOR_COUNT;
5355
- m->submsg_field_count = 0;
5356
- return;
5357
- }
5358
-
5359
- fields = upb_gmalloc(n * sizeof(*fields));
5360
-
5361
- m->submsg_field_count = 0;
5362
- for(i = 0, upb_msg_field_begin(&j, m);
5363
- !upb_msg_field_done(&j);
5364
- upb_msg_field_next(&j), i++) {
5365
- upb_fielddef *f = upb_msg_iter_field(&j);
5366
- UPB_ASSERT(f->msgdef == m);
5367
- if (upb_fielddef_issubmsg(f)) {
5368
- m->submsg_field_count++;
5369
- }
5370
- fields[i] = f;
5371
- }
5372
-
5373
- qsort(fields, n, sizeof(*fields), cmp_fields);
5374
-
5375
- selector = UPB_STATIC_SELECTOR_COUNT + m->submsg_field_count;
5376
- for (i = 0; i < n; i++) {
5377
- upb_fielddef *f = fields[i];
5378
- f->index_ = i;
5379
- f->selector_base = selector + upb_handlers_selectorbaseoffset(f);
5380
- selector += upb_handlers_selectorcount(f);
5381
- }
5382
- m->selector_count = selector;
5383
-
5384
- upb_gfree(fields);
5644
+ assign_layout_indices(m, l, fields);
5385
5645
  }
5386
5646
 
5387
5647
  static char *strviewdup(symtab_addctx *ctx, upb_strview view) {
5388
- return upb_strdup2(view.data, view.size, ctx->alloc);
5648
+ return upb_strdup2(view.data, view.size, ctx->arena);
5389
5649
  }
5390
5650
 
5391
5651
  static bool streql2(const char *a, size_t n, const char *b) {
@@ -5496,9 +5756,9 @@ static void symtab_add(symtab_addctx *ctx, const char *name, upb_value v) {
5496
5756
  if (upb_strtable_lookup(&ctx->symtab->syms, name, NULL)) {
5497
5757
  symtab_errf(ctx, "duplicate symbol '%s'", name);
5498
5758
  }
5499
- upb_alloc *alloc = upb_arena_alloc(ctx->symtab->arena);
5500
5759
  size_t len = strlen(name);
5501
- CHK_OOM(upb_strtable_insert3(&ctx->symtab->syms, name, len, v, alloc));
5760
+ CHK_OOM(upb_strtable_insert(&ctx->symtab->syms, name, len, v,
5761
+ ctx->symtab->arena));
5502
5762
  }
5503
5763
 
5504
5764
  /* Given a symbol and the base symbol inside which it is defined, find the
@@ -5531,7 +5791,8 @@ static const void *symtab_resolve(symtab_addctx *ctx, const upb_fielddef *f,
5531
5791
  }
5532
5792
 
5533
5793
  notfound:
5534
- symtab_errf(ctx, "couldn't resolve name '%s'", sym.data);
5794
+ symtab_errf(ctx, "couldn't resolve name '" UPB_STRVIEW_FORMAT "'",
5795
+ UPB_STRVIEW_ARGS(sym));
5535
5796
  }
5536
5797
 
5537
5798
  static void create_oneofdef(
@@ -5549,10 +5810,10 @@ static void create_oneofdef(
5549
5810
 
5550
5811
  v = pack_def(o, UPB_DEFTYPE_ONEOF);
5551
5812
  symtab_add(ctx, o->full_name, v);
5552
- CHK_OOM(upb_strtable_insert3(&m->ntof, name.data, name.size, v, ctx->alloc));
5813
+ CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, v, ctx->arena));
5553
5814
 
5554
- CHK_OOM(upb_inttable_init2(&o->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
5555
- CHK_OOM(upb_strtable_init2(&o->ntof, UPB_CTYPE_CONSTPTR, 4, ctx->alloc));
5815
+ CHK_OOM(upb_inttable_init(&o->itof, ctx->arena));
5816
+ CHK_OOM(upb_strtable_init(&o->ntof, 4, ctx->arena));
5556
5817
  }
5557
5818
 
5558
5819
  static str_t *newstr(symtab_addctx *ctx, const char *data, size_t len) {
@@ -5608,8 +5869,7 @@ static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
5608
5869
  break;
5609
5870
  }
5610
5871
  case UPB_TYPE_INT64: {
5611
- /* XXX: Need to write our own strtoll, since it's not available in c89. */
5612
- int64_t val = strtol(str, &end, 0);
5872
+ long long val = strtoll(str, &end, 0);
5613
5873
  if (val > INT64_MAX || val < INT64_MIN || errno == ERANGE || *end) {
5614
5874
  goto invalid;
5615
5875
  }
@@ -5625,8 +5885,7 @@ static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
5625
5885
  break;
5626
5886
  }
5627
5887
  case UPB_TYPE_UINT64: {
5628
- /* XXX: Need to write our own strtoull, since it's not available in c89. */
5629
- uint64_t val = strtoul(str, &end, 0);
5888
+ unsigned long long val = strtoull(str, &end, 0);
5630
5889
  if (val > UINT64_MAX || errno == ERANGE || *end) {
5631
5890
  goto invalid;
5632
5891
  }
@@ -5642,8 +5901,7 @@ static void parse_default(symtab_addctx *ctx, const char *str, size_t len,
5642
5901
  break;
5643
5902
  }
5644
5903
  case UPB_TYPE_FLOAT: {
5645
- /* XXX: Need to write our own strtof, since it's not available in c89. */
5646
- float val = strtod(str, &end);
5904
+ float val = strtof(str, &end);
5647
5905
  if (errno == ERANGE || *end) {
5648
5906
  goto invalid;
5649
5907
  }
@@ -5709,7 +5967,6 @@ static void set_default_default(symtab_addctx *ctx, upb_fielddef *f) {
5709
5967
  static void create_fielddef(
5710
5968
  symtab_addctx *ctx, const char *prefix, upb_msgdef *m,
5711
5969
  const google_protobuf_FieldDescriptorProto *field_proto) {
5712
- upb_alloc *alloc = ctx->alloc;
5713
5970
  upb_fielddef *f;
5714
5971
  const google_protobuf_FieldOptions *options;
5715
5972
  upb_strview name;
@@ -5745,7 +6002,8 @@ static void create_fielddef(
5745
6002
  upb_value v, field_v, json_v;
5746
6003
  size_t json_size;
5747
6004
 
5748
- f = (upb_fielddef*)&m->fields[m->field_count++];
6005
+ f = (upb_fielddef*)&m->fields[m->field_count];
6006
+ f->index_ = m->field_count++;
5749
6007
  f->msgdef = m;
5750
6008
  f->is_extension_ = false;
5751
6009
 
@@ -5766,12 +6024,12 @@ static void create_fielddef(
5766
6024
  v = upb_value_constptr(f);
5767
6025
  json_size = strlen(json_name);
5768
6026
 
5769
- CHK_OOM(
5770
- upb_strtable_insert3(&m->ntof, name.data, name.size, field_v, alloc));
5771
- CHK_OOM(upb_inttable_insert2(&m->itof, field_number, v, alloc));
6027
+ CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, field_v,
6028
+ ctx->arena));
6029
+ CHK_OOM(upb_inttable_insert(&m->itof, field_number, v, ctx->arena));
5772
6030
 
5773
6031
  if (strcmp(shortname, json_name) != 0) {
5774
- upb_strtable_insert3(&m->ntof, json_name, json_size, json_v, alloc);
6032
+ upb_strtable_insert(&m->ntof, json_name, json_size, json_v, ctx->arena);
5775
6033
  }
5776
6034
 
5777
6035
  if (ctx->layouts) {
@@ -5834,15 +6092,16 @@ static void create_fielddef(
5834
6092
  symtab_errf(ctx, "oneof_index out of range (%s)", f->full_name);
5835
6093
  }
5836
6094
 
5837
- oneof = (upb_oneofdef*)&m->oneofs[oneof_index];
6095
+ oneof = (upb_oneofdef *)&m->oneofs[oneof_index];
5838
6096
  f->oneof = oneof;
5839
6097
 
5840
6098
  oneof->field_count++;
5841
6099
  if (f->proto3_optional_) {
5842
6100
  oneof->synthetic = true;
5843
6101
  }
5844
- CHK_OOM(upb_inttable_insert2(&oneof->itof, f->number_, v, alloc));
5845
- CHK_OOM(upb_strtable_insert3(&oneof->ntof, name.data, name.size, v, alloc));
6102
+ CHK_OOM(upb_inttable_insert(&oneof->itof, f->number_, v, ctx->arena));
6103
+ CHK_OOM(
6104
+ upb_strtable_insert(&oneof->ntof, name.data, name.size, v, ctx->arena));
5846
6105
  } else {
5847
6106
  f->oneof = NULL;
5848
6107
  if (f->proto3_optional_) {
@@ -5885,8 +6144,8 @@ static void create_enumdef(
5885
6144
  symtab_add(ctx, e->full_name, pack_def(e, UPB_DEFTYPE_ENUM));
5886
6145
 
5887
6146
  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n);
5888
- CHK_OOM(upb_strtable_init2(&e->ntoi, UPB_CTYPE_INT32, n, ctx->alloc));
5889
- CHK_OOM(upb_inttable_init2(&e->iton, UPB_CTYPE_CSTR, ctx->alloc));
6147
+ CHK_OOM(upb_strtable_init(&e->ntoi, n, ctx->arena));
6148
+ CHK_OOM(upb_inttable_init(&e->iton, ctx->arena));
5890
6149
 
5891
6150
  e->file = ctx->file;
5892
6151
  e->defaultval = 0;
@@ -5913,16 +6172,15 @@ static void create_enumdef(
5913
6172
  }
5914
6173
 
5915
6174
  CHK_OOM(name2)
5916
- CHK_OOM(
5917
- upb_strtable_insert3(&e->ntoi, name2, strlen(name2), v, ctx->alloc));
6175
+ CHK_OOM(upb_strtable_insert(&e->ntoi, name2, strlen(name2), v, ctx->arena));
5918
6176
 
5919
6177
  if (!upb_inttable_lookup(&e->iton, num, NULL)) {
5920
6178
  upb_value v = upb_value_cstr(name2);
5921
- CHK_OOM(upb_inttable_insert2(&e->iton, num, v, ctx->alloc));
6179
+ CHK_OOM(upb_inttable_insert(&e->iton, num, v, ctx->arena));
5922
6180
  }
5923
6181
  }
5924
6182
 
5925
- upb_inttable_compact2(&e->iton, ctx->alloc);
6183
+ upb_inttable_compact(&e->iton, ctx->arena);
5926
6184
  }
5927
6185
 
5928
6186
  static void create_msgdef(symtab_addctx *ctx, const char *prefix,
@@ -5946,9 +6204,8 @@ static void create_msgdef(symtab_addctx *ctx, const char *prefix,
5946
6204
  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
5947
6205
  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
5948
6206
 
5949
- CHK_OOM(upb_inttable_init2(&m->itof, UPB_CTYPE_CONSTPTR, ctx->alloc));
5950
- CHK_OOM(upb_strtable_init2(&m->ntof, UPB_CTYPE_CONSTPTR, n_oneof + n_field,
5951
- ctx->alloc));
6207
+ CHK_OOM(upb_inttable_init(&m->itof, ctx->arena));
6208
+ CHK_OOM(upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena));
5952
6209
 
5953
6210
  m->file = ctx->file;
5954
6211
  m->map_entry = false;
@@ -5980,10 +6237,9 @@ static void create_msgdef(symtab_addctx *ctx, const char *prefix,
5980
6237
  create_fielddef(ctx, m->full_name, m, fields[i]);
5981
6238
  }
5982
6239
 
5983
- assign_msg_indices(ctx, m);
5984
6240
  finalize_oneofs(ctx, m);
5985
6241
  assign_msg_wellknowntype(m);
5986
- upb_inttable_compact2(&m->itof, ctx->alloc);
6242
+ upb_inttable_compact(&m->itof, ctx->arena);
5987
6243
 
5988
6244
  /* This message is built. Now build nested messages and enums. */
5989
6245
 
@@ -6095,13 +6351,18 @@ static void build_filedef(
6095
6351
  const upb_strview* strs;
6096
6352
  size_t i, n;
6097
6353
 
6098
- count_types_in_file(file_proto, file);
6354
+ file->symtab = ctx->symtab;
6099
6355
 
6356
+ /* One pass to count and allocate. */
6357
+ file->msg_count = 0;
6358
+ file->enum_count = 0;
6359
+ file->ext_count = 0;
6360
+ count_types_in_file(file_proto, file);
6100
6361
  file->msgs = symtab_alloc(ctx, sizeof(*file->msgs) * file->msg_count);
6101
6362
  file->enums = symtab_alloc(ctx, sizeof(*file->enums) * file->enum_count);
6102
6363
  file->exts = symtab_alloc(ctx, sizeof(*file->exts) * file->ext_count);
6103
6364
 
6104
- /* We increment these as defs are added. */
6365
+ /* In the second pass we increment these as defs are added. */
6105
6366
  file->msg_count = 0;
6106
6367
  file->enum_count = 0;
6107
6368
  file->ext_count = 0;
@@ -6212,61 +6473,61 @@ static void build_filedef(
6212
6473
  }
6213
6474
 
6214
6475
  static void remove_filedef(upb_symtab *s, upb_filedef *file) {
6215
- upb_alloc *alloc = upb_arena_alloc(s->arena);
6216
6476
  int i;
6217
6477
  for (i = 0; i < file->msg_count; i++) {
6218
6478
  const char *name = file->msgs[i].full_name;
6219
- upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
6479
+ upb_strtable_remove(&s->syms, name, strlen(name), NULL);
6220
6480
  }
6221
6481
  for (i = 0; i < file->enum_count; i++) {
6222
6482
  const char *name = file->enums[i].full_name;
6223
- upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
6483
+ upb_strtable_remove(&s->syms, name, strlen(name), NULL);
6224
6484
  }
6225
6485
  for (i = 0; i < file->ext_count; i++) {
6226
6486
  const char *name = file->exts[i].full_name;
6227
- upb_strtable_remove3(&s->syms, name, strlen(name), NULL, alloc);
6487
+ upb_strtable_remove(&s->syms, name, strlen(name), NULL);
6228
6488
  }
6229
6489
  }
6230
6490
 
6231
6491
  static const upb_filedef *_upb_symtab_addfile(
6232
6492
  upb_symtab *s, const google_protobuf_FileDescriptorProto *file_proto,
6233
6493
  const upb_msglayout **layouts, upb_status *status) {
6234
- upb_arena *file_arena = upb_arena_new();
6235
- upb_filedef *file;
6236
6494
  symtab_addctx ctx;
6495
+ upb_strview name = google_protobuf_FileDescriptorProto_name(file_proto);
6237
6496
 
6238
- if (!file_arena) return NULL;
6239
-
6240
- file = upb_arena_malloc(file_arena, sizeof(*file));
6241
- if (!file) goto done;
6497
+ if (upb_strtable_lookup2(&s->files, name.data, name.size, NULL)) {
6498
+ upb_status_seterrf(status, "duplicate file name (%.*s)",
6499
+ UPB_STRVIEW_ARGS(name));
6500
+ return NULL;
6501
+ }
6242
6502
 
6243
- ctx.file = file;
6244
6503
  ctx.symtab = s;
6245
- ctx.file_arena = file_arena;
6246
- ctx.alloc = upb_arena_alloc(file_arena);
6247
6504
  ctx.layouts = layouts;
6248
6505
  ctx.status = status;
6506
+ ctx.file = NULL;
6507
+ ctx.arena = upb_arena_new();
6249
6508
 
6250
- file->msg_count = 0;
6251
- file->enum_count = 0;
6252
- file->ext_count = 0;
6253
- file->symtab = s;
6509
+ if (!ctx.arena) {
6510
+ upb_status_setoom(status);
6511
+ return NULL;
6512
+ }
6254
6513
 
6255
6514
  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
6256
6515
  UPB_ASSERT(!upb_ok(status));
6257
- remove_filedef(s, file);
6258
- file = NULL;
6516
+ if (ctx.file) {
6517
+ remove_filedef(s, ctx.file);
6518
+ ctx.file = NULL;
6519
+ }
6259
6520
  } else {
6260
- build_filedef(&ctx, file, file_proto);
6261
- upb_strtable_insert3(&s->files, file->name, strlen(file->name),
6262
- upb_value_constptr(file), ctx.alloc);
6521
+ ctx.file = symtab_alloc(&ctx, sizeof(*ctx.file));
6522
+ build_filedef(&ctx, ctx.file, file_proto);
6523
+ upb_strtable_insert(&s->files, name.data, name.size,
6524
+ upb_value_constptr(ctx.file), ctx.arena);
6263
6525
  UPB_ASSERT(upb_ok(status));
6264
- upb_arena_fuse(s->arena, file_arena);
6526
+ upb_arena_fuse(s->arena, ctx.arena);
6265
6527
  }
6266
6528
 
6267
- done:
6268
- upb_arena_free(file_arena);
6269
- return file;
6529
+ upb_arena_free(ctx.arena);
6530
+ return ctx.file;
6270
6531
  }
6271
6532
 
6272
6533
  const upb_filedef *upb_symtab_addfile(
@@ -6299,7 +6560,8 @@ bool _upb_symtab_loaddefinit(upb_symtab *s, const upb_def_init *init) {
6299
6560
  }
6300
6561
 
6301
6562
  file = google_protobuf_FileDescriptorProto_parse_ex(
6302
- init->descriptor.data, init->descriptor.size, arena, UPB_DECODE_ALIAS);
6563
+ init->descriptor.data, init->descriptor.size, NULL, UPB_DECODE_ALIAS,
6564
+ arena);
6303
6565
  s->bytes_loaded += init->descriptor.size;
6304
6566
 
6305
6567
  if (!file) {
@@ -6333,6 +6595,7 @@ upb_arena *_upb_symtab_arena(const upb_symtab *s) {
6333
6595
 
6334
6596
  #undef CHK_OOM
6335
6597
 
6598
+ /** upb/reflection.c ************************************************************/
6336
6599
 
6337
6600
  #include <string.h>
6338
6601
 
@@ -6443,40 +6706,7 @@ upb_msgval upb_msg_get(const upb_msg *msg, const upb_fielddef *f) {
6443
6706
  if (!upb_fielddef_haspresence(f) || upb_msg_has(msg, f)) {
6444
6707
  return _upb_msg_getraw(msg, f);
6445
6708
  } else {
6446
- /* TODO(haberman): change upb_fielddef to not require this switch(). */
6447
- upb_msgval val = {0};
6448
- switch (upb_fielddef_type(f)) {
6449
- case UPB_TYPE_INT32:
6450
- case UPB_TYPE_ENUM:
6451
- val.int32_val = upb_fielddef_defaultint32(f);
6452
- break;
6453
- case UPB_TYPE_INT64:
6454
- val.int64_val = upb_fielddef_defaultint64(f);
6455
- break;
6456
- case UPB_TYPE_UINT32:
6457
- val.uint32_val = upb_fielddef_defaultuint32(f);
6458
- break;
6459
- case UPB_TYPE_UINT64:
6460
- val.uint64_val = upb_fielddef_defaultuint64(f);
6461
- break;
6462
- case UPB_TYPE_FLOAT:
6463
- val.float_val = upb_fielddef_defaultfloat(f);
6464
- break;
6465
- case UPB_TYPE_DOUBLE:
6466
- val.double_val = upb_fielddef_defaultdouble(f);
6467
- break;
6468
- case UPB_TYPE_BOOL:
6469
- val.bool_val = upb_fielddef_defaultbool(f);
6470
- break;
6471
- case UPB_TYPE_STRING:
6472
- case UPB_TYPE_BYTES:
6473
- val.str_val.data = upb_fielddef_defaultstr(f, &val.str_val.size);
6474
- break;
6475
- case UPB_TYPE_MESSAGE:
6476
- val.msg_val = NULL;
6477
- break;
6478
- }
6479
- return val;
6709
+ return upb_fielddef_default(f);
6480
6710
  }
6481
6711
  }
6482
6712
 
@@ -6736,6 +6966,7 @@ upb_msgval upb_mapiter_value(const upb_map *map, size_t iter) {
6736
6966
 
6737
6967
  /* void upb_mapiter_setvalue(upb_map *map, size_t iter, upb_msgval value); */
6738
6968
 
6969
+ /** upb/json_decode.c ************************************************************/
6739
6970
 
6740
6971
  #include <errno.h>
6741
6972
  #include <float.h>
@@ -7646,17 +7877,17 @@ static void jsondec_field(jsondec *d, upb_msg *msg, const upb_msgdef *m) {
7646
7877
  return;
7647
7878
  }
7648
7879
 
7649
- if (upb_fielddef_realcontainingoneof(f) &&
7650
- upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
7651
- jsondec_err(d, "More than one field for this oneof.");
7652
- }
7653
-
7654
7880
  if (jsondec_peek(d) == JD_NULL && !jsondec_isvalue(f)) {
7655
7881
  /* JSON "null" indicates a default value, so no need to set anything. */
7656
7882
  jsondec_null(d);
7657
7883
  return;
7658
7884
  }
7659
7885
 
7886
+ if (upb_fielddef_realcontainingoneof(f) &&
7887
+ upb_msg_whichoneof(msg, upb_fielddef_containingoneof(f))) {
7888
+ jsondec_err(d, "More than one field for this oneof.");
7889
+ }
7890
+
7660
7891
  preserved = d->debug_field;
7661
7892
  d->debug_field = f;
7662
7893
 
@@ -8160,6 +8391,9 @@ bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
8160
8391
  const upb_msgdef *m, const upb_symtab *any_pool,
8161
8392
  int options, upb_arena *arena, upb_status *status) {
8162
8393
  jsondec d;
8394
+
8395
+ if (size == 0) return true;
8396
+
8163
8397
  d.ptr = buf;
8164
8398
  d.end = buf + size;
8165
8399
  d.arena = arena;
@@ -8178,6 +8412,7 @@ bool upb_json_decode(const char *buf, size_t size, upb_msg *msg,
8178
8412
  return true;
8179
8413
  }
8180
8414
 
8415
+ /** upb/json_encode.c ************************************************************/
8181
8416
 
8182
8417
  #include <ctype.h>
8183
8418
  #include <float.h>
@@ -8207,7 +8442,7 @@ static void jsonenc_scalar(jsonenc *e, upb_msgval val, const upb_fielddef *f);
8207
8442
  static void jsonenc_msgfield(jsonenc *e, const upb_msg *msg,
8208
8443
  const upb_msgdef *m);
8209
8444
  static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
8210
- const upb_msgdef *m);
8445
+ const upb_msgdef *m, bool first);
8211
8446
  static void jsonenc_value(jsonenc *e, const upb_msg *msg, const upb_msgdef *m);
8212
8447
 
8213
8448
  UPB_NORETURN static void jsonenc_err(jsonenc *e, const char *msg) {
@@ -8238,8 +8473,10 @@ static void jsonenc_putbytes(jsonenc *e, const void *data, size_t len) {
8238
8473
  memcpy(e->ptr, data, len);
8239
8474
  e->ptr += len;
8240
8475
  } else {
8241
- if (have) memcpy(e->ptr, data, have);
8242
- e->ptr += have;
8476
+ if (have) {
8477
+ memcpy(e->ptr, data, have);
8478
+ e->ptr += have;
8479
+ }
8243
8480
  e->overflow += (len - have);
8244
8481
  }
8245
8482
  }
@@ -8261,7 +8498,7 @@ static void jsonenc_printf(jsonenc *e, const char *fmt, ...) {
8261
8498
  if (UPB_LIKELY(have > n)) {
8262
8499
  e->ptr += n;
8263
8500
  } else {
8264
- e->ptr += have;
8501
+ e->ptr = UPB_PTRADD(e->ptr, have);
8265
8502
  e->overflow += (n - have);
8266
8503
  }
8267
8504
  }
@@ -8365,7 +8602,7 @@ static void jsonenc_bytes(jsonenc *e, upb_strview str) {
8365
8602
  static const char base64[] =
8366
8603
  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
8367
8604
  const unsigned char *ptr = (unsigned char*)str.data;
8368
- const unsigned char *end = ptr + str.size;
8605
+ const unsigned char *end = UPB_PTRADD(ptr, str.size);
8369
8606
  char buf[4];
8370
8607
 
8371
8608
  jsonenc_putstr(e, "\"");
@@ -8401,7 +8638,7 @@ static void jsonenc_bytes(jsonenc *e, upb_strview str) {
8401
8638
 
8402
8639
  static void jsonenc_stringbody(jsonenc *e, upb_strview str) {
8403
8640
  const char *ptr = str.data;
8404
- const char *end = ptr + str.size;
8641
+ const char *end = UPB_PTRADD(ptr, str.size);
8405
8642
 
8406
8643
  while (ptr < end) {
8407
8644
  switch (*ptr) {
@@ -8454,7 +8691,17 @@ static void jsonenc_double(jsonenc *e, const char *fmt, double val) {
8454
8691
  } else if (val != val) {
8455
8692
  jsonenc_putstr(e, "\"NaN\"");
8456
8693
  } else {
8694
+ char *p = e->ptr;
8457
8695
  jsonenc_printf(e, fmt, val);
8696
+
8697
+ /* printf() is dependent on locales; sadly there is no easy and portable way
8698
+ * to avoid this. This little post-processing step will translate 1,2 -> 1.2
8699
+ * since JSON needs the latter. Arguably a hack, but it is simple and the
8700
+ * alternatives are far more complicated, platform-dependent, and/or larger
8701
+ * in code size. */
8702
+ for (char *end = e->ptr; p < end; p++) {
8703
+ if (*p == ',') *p = '.';
8704
+ }
8458
8705
  }
8459
8706
  }
8460
8707
 
@@ -8517,14 +8764,13 @@ static void jsonenc_any(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
8517
8764
 
8518
8765
  jsonenc_putstr(e, "{\"@type\":");
8519
8766
  jsonenc_string(e, type_url);
8520
- jsonenc_putstr(e, ",");
8521
8767
 
8522
8768
  if (upb_msgdef_wellknowntype(any_m) == UPB_WELLKNOWN_UNSPECIFIED) {
8523
8769
  /* Regular messages: {"@type": "...","foo": 1, "bar": 2} */
8524
- jsonenc_msgfields(e, any, any_m);
8770
+ jsonenc_msgfields(e, any, any_m, false);
8525
8771
  } else {
8526
8772
  /* Well-known type: {"@type": "...","value": <well-known encoding>} */
8527
- jsonenc_putstr(e, "\"value\":");
8773
+ jsonenc_putstr(e, ",\"value\":");
8528
8774
  jsonenc_msgfield(e, any, any_m);
8529
8775
  }
8530
8776
 
@@ -8827,10 +9073,9 @@ static void jsonenc_fieldval(jsonenc *e, const upb_fielddef *f,
8827
9073
  }
8828
9074
 
8829
9075
  static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
8830
- const upb_msgdef *m) {
9076
+ const upb_msgdef *m, bool first) {
8831
9077
  upb_msgval val;
8832
9078
  const upb_fielddef *f;
8833
- bool first = true;
8834
9079
 
8835
9080
  if (e->options & UPB_JSONENC_EMITDEFAULTS) {
8836
9081
  /* Iterate over all fields. */
@@ -8853,7 +9098,7 @@ static void jsonenc_msgfields(jsonenc *e, const upb_msg *msg,
8853
9098
 
8854
9099
  static void jsonenc_msg(jsonenc *e, const upb_msg *msg, const upb_msgdef *m) {
8855
9100
  jsonenc_putstr(e, "{");
8856
- jsonenc_msgfields(e, msg, m);
9101
+ jsonenc_msgfields(e, msg, m, true);
8857
9102
  jsonenc_putstr(e, "}");
8858
9103
  }
8859
9104
 
@@ -8875,7 +9120,7 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
8875
9120
 
8876
9121
  e.buf = buf;
8877
9122
  e.ptr = buf;
8878
- e.end = buf + size;
9123
+ e.end = UPB_PTRADD(buf, size);
8879
9124
  e.overflow = 0;
8880
9125
  e.options = options;
8881
9126
  e.ext_pool = ext_pool;
@@ -8888,27 +9133,39 @@ size_t upb_json_encode(const upb_msg *msg, const upb_msgdef *m,
8888
9133
  if (e.arena) upb_arena_free(e.arena);
8889
9134
  return jsonenc_nullz(&e, size);
8890
9135
  }
9136
+
9137
+ /** upb/port_undef.inc ************************************************************/
8891
9138
  /* See port_def.inc. This should #undef all macros #defined there. */
8892
9139
 
8893
- #undef UPB_MAPTYPE_STRING
8894
9140
  #undef UPB_SIZE
8895
9141
  #undef UPB_PTR_AT
8896
9142
  #undef UPB_READ_ONEOF
8897
9143
  #undef UPB_WRITE_ONEOF
9144
+ #undef UPB_MAPTYPE_STRING
8898
9145
  #undef UPB_INLINE
8899
9146
  #undef UPB_ALIGN_UP
8900
9147
  #undef UPB_ALIGN_DOWN
8901
9148
  #undef UPB_ALIGN_MALLOC
8902
9149
  #undef UPB_ALIGN_OF
9150
+ #undef UPB_LIKELY
9151
+ #undef UPB_UNLIKELY
8903
9152
  #undef UPB_FORCEINLINE
8904
9153
  #undef UPB_NOINLINE
8905
9154
  #undef UPB_NORETURN
9155
+ #undef UPB_PRINTF
8906
9156
  #undef UPB_MAX
8907
9157
  #undef UPB_MIN
8908
9158
  #undef UPB_UNUSED
8909
9159
  #undef UPB_ASSUME
8910
9160
  #undef UPB_ASSERT
8911
9161
  #undef UPB_UNREACHABLE
9162
+ #undef UPB_SETJMP
9163
+ #undef UPB_LONGJMP
9164
+ #undef UPB_PTRADD
9165
+ #undef UPB_MUSTTAIL
9166
+ #undef UPB_FASTTABLE_SUPPORTED
9167
+ #undef UPB_FASTTABLE
9168
+ #undef UPB_FASTTABLE_INIT
8912
9169
  #undef UPB_POISON_MEMORY_REGION
8913
9170
  #undef UPB_UNPOISON_MEMORY_REGION
8914
9171
  #undef UPB_ASAN