google-protobuf 4.34.2-aarch64-linux-gnu → 4.35.0-aarch64-linux-gnu

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.
@@ -1970,7 +1970,7 @@ const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = {
1970
1970
 
1971
1971
  const upb_MiniTableEnum google__protobuf__Edition_enum_init = {
1972
1972
  64,
1973
- 10,
1973
+ 11,
1974
1974
  {
1975
1975
  0x7,
1976
1976
  0x0,
@@ -1979,6 +1979,7 @@ const upb_MiniTableEnum google__protobuf__Edition_enum_init = {
1979
1979
  0x3e7,
1980
1980
  0x3e8,
1981
1981
  0x3e9,
1982
+ 0x3ea,
1982
1983
  0x270f,
1983
1984
  0x1869d,
1984
1985
  0x1869e,
@@ -2000,7 +2001,7 @@ const upb_MiniTableEnum google__protobuf__FeatureSet__EnforceNamingStyle_enum_in
2000
2001
  64,
2001
2002
  0,
2002
2003
  {
2003
- 0x7,
2004
+ 0xf,
2004
2005
  0x0,
2005
2006
  },
2006
2007
  };
@@ -2346,10 +2347,15 @@ static int log2ceil(uint64_t v) {
2346
2347
  return UPB_MIN(UPB_MAXARRSIZE, ret);
2347
2348
  }
2348
2349
 
2349
- /* A type to represent the lookup key of either a strtable or an inttable. */
2350
+ /* A type to represent the lookup key of either a strtable, inttable or
2351
+ * exttable. */
2350
2352
  typedef union {
2351
2353
  uintptr_t num;
2352
2354
  upb_StringView str;
2355
+ struct {
2356
+ const void* ptr;
2357
+ uint32_t ext_num;
2358
+ } ext;
2353
2359
  } lookupkey_t;
2354
2360
 
2355
2361
  static lookupkey_t strkey2(const char* str, size_t len) {
@@ -2358,16 +2364,24 @@ static lookupkey_t strkey2(const char* str, size_t len) {
2358
2364
 
2359
2365
  static lookupkey_t intkey(uintptr_t key) { return (lookupkey_t){.num = key}; }
2360
2366
 
2361
- typedef uint32_t hashfunc_t(upb_key key);
2362
- typedef bool eqlfunc_t(upb_key k1, lookupkey_t k2);
2367
+ static lookupkey_t extkey(const void* ptr, uint32_t ext_num) {
2368
+ return (lookupkey_t){.ext = {ptr, ext_num}};
2369
+ }
2370
+
2371
+ // Conceptually the hash and equal functions should only take the key, not the
2372
+ // value, but the extension table stores part of its logical key in the value
2373
+ // slot. This is a sign that we have outgrown the original architecture.
2374
+ typedef uint32_t hashfunc_t(upb_key key, upb_value val);
2375
+ typedef bool eqlfunc_t(upb_key k1, upb_value v1, lookupkey_t k2);
2363
2376
 
2364
2377
  /* Base table (shared code) ***************************************************/
2365
2378
 
2366
2379
  static uint32_t upb_inthash(uintptr_t key) {
2380
+ UPB_STATIC_ASSERT(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
2381
+ "Pointers don't fit");
2367
2382
  if (sizeof(uintptr_t) == 8) {
2368
2383
  return (uint32_t)key ^ (uint32_t)(key >> 32);
2369
2384
  } else {
2370
- UPB_ASSERT(sizeof(uintptr_t) == 4);
2371
2385
  return (uint32_t)key;
2372
2386
  }
2373
2387
  }
@@ -2428,7 +2442,7 @@ static const upb_tabent* findentry(const upb_table* t, lookupkey_t key,
2428
2442
  e = upb_getentry(t, hash);
2429
2443
  if (upb_tabent_isempty(e)) return NULL;
2430
2444
  while (1) {
2431
- if (eql(e->key, key)) return e;
2445
+ if (eql(e->key, e->val, key)) return e;
2432
2446
  if ((e = e->next) == NULL) return NULL;
2433
2447
  }
2434
2448
  }
@@ -2468,7 +2482,8 @@ static void insert(upb_table* t, lookupkey_t key, upb_key tabkey, upb_value val,
2468
2482
  /* Collision. */
2469
2483
  upb_tabent* new_e = emptyent(t, mainpos_e);
2470
2484
  /* Head of collider's chain. */
2471
- upb_tabent* chain = getentry_mutable(t, hashfunc(mainpos_e->key));
2485
+ upb_tabent* chain =
2486
+ getentry_mutable(t, hashfunc(mainpos_e->key, mainpos_e->val));
2472
2487
  if (chain == mainpos_e) {
2473
2488
  /* Existing ent is in its main position (it has the same hash as us, and
2474
2489
  * is the head of our chain). Insert to new ent and append to this chain.
@@ -2499,7 +2514,7 @@ static bool rm(upb_table* t, lookupkey_t key, upb_value* val, uint32_t hash,
2499
2514
  eqlfunc_t* eql) {
2500
2515
  upb_tabent* chain = getentry_mutable(t, hash);
2501
2516
  if (upb_tabent_isempty(chain)) return false;
2502
- if (eql(chain->key, key)) {
2517
+ if (eql(chain->key, chain->val, key)) {
2503
2518
  /* Element to remove is at the head of its chain. */
2504
2519
  t->count--;
2505
2520
  if (val) *val = chain->val;
@@ -2514,7 +2529,7 @@ static bool rm(upb_table* t, lookupkey_t key, upb_value* val, uint32_t hash,
2514
2529
  } else {
2515
2530
  /* Element to remove is either in a non-head position or not in the
2516
2531
  * table. */
2517
- while (chain->next && !eql(chain->next->key, key)) {
2532
+ while (chain->next && !eql(chain->next->key, chain->next->val, key)) {
2518
2533
  chain = (upb_tabent*)chain->next;
2519
2534
  }
2520
2535
  if (chain->next) {
@@ -2713,11 +2728,13 @@ static uint32_t _upb_Hash_NoSeed(const char* p, size_t n) {
2713
2728
  return _upb_Hash(p, n, _upb_Seed());
2714
2729
  }
2715
2730
 
2716
- static uint32_t strhash(upb_key key) {
2731
+ static uint32_t strhash(upb_key key, upb_value val) {
2732
+ UPB_UNUSED(val);
2717
2733
  return _upb_Hash_NoSeed(key.str->data, key.str->size);
2718
2734
  }
2719
2735
 
2720
- static bool streql(upb_key k1, lookupkey_t k2) {
2736
+ static bool streql(upb_key k1, upb_value v1, lookupkey_t k2) {
2737
+ UPB_UNUSED(v1);
2721
2738
  const upb_SizePrefixString* k1s = k1.str;
2722
2739
  const upb_StringView k2s = k2.str;
2723
2740
  return k1s->size == k2s.size &&
@@ -2881,6 +2898,98 @@ void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) {
2881
2898
  t->t.entries[iter].val = v;
2882
2899
  }
2883
2900
 
2901
+ /* upb_exttable ***************************************************************/
2902
+
2903
+ static uint32_t _upb_exttable_hash(const void* ptr, uint32_t ext_num) {
2904
+ uint64_t a = (uintptr_t)ptr;
2905
+ uint64_t b = ext_num;
2906
+ return (uint32_t)WyhashMix(a ^ kWyhashSalt[1], b ^ _upb_Seed());
2907
+ }
2908
+
2909
+ static uint32_t exthash(upb_key key, upb_value val) {
2910
+ const void* ptr = (const void*)key.num;
2911
+ uint32_t ext_num = *(const uint32_t*)upb_value_getconstptr(val);
2912
+ return _upb_exttable_hash(ptr, ext_num);
2913
+ }
2914
+
2915
+ static bool exteql(upb_key k1, upb_value v1, lookupkey_t k2) {
2916
+ if ((const void*)k1.num == k2.ext.ptr) {
2917
+ uint32_t ext_num1 = *(const uint32_t*)upb_value_getconstptr(v1);
2918
+ return ext_num1 == k2.ext.ext_num;
2919
+ }
2920
+ return false;
2921
+ }
2922
+
2923
+ bool upb_exttable_init(upb_exttable* t, size_t expected_size, upb_Arena* a) {
2924
+ int size_lg2 = upb_Log2Ceiling(_upb_entries_needed_for(expected_size));
2925
+ return init(&t->t, size_lg2, a);
2926
+ }
2927
+
2928
+ void upb_exttable_clear(upb_exttable* t) {
2929
+ size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
2930
+ t->t.count = 0;
2931
+ memset((char*)t->t.entries, 0, bytes);
2932
+ }
2933
+
2934
+ bool upb_exttable_resize(upb_exttable* t, size_t size_lg2, upb_Arena* a) {
2935
+ upb_exttable new_table;
2936
+ if (!init(&new_table.t, size_lg2, a)) return false;
2937
+
2938
+ size_t i;
2939
+ for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
2940
+ const upb_tabent* e = &t->t.entries[i];
2941
+ uint32_t hash = exthash(e->key, e->val);
2942
+ uint32_t ext_num = *(const uint32_t*)upb_value_getconstptr(e->val);
2943
+ lookupkey_t lookupkey = extkey((const void*)e->key.num, ext_num);
2944
+ insert(&new_table.t, lookupkey, e->key, e->val, hash, &exthash, &exteql);
2945
+ }
2946
+
2947
+ *t = new_table;
2948
+ return true;
2949
+ }
2950
+
2951
+ bool upb_exttable_insert(upb_exttable* t, const void* k, const uint32_t* v,
2952
+ upb_Arena* a) {
2953
+ UPB_ASSERT(k != NULL);
2954
+ UPB_ASSERT(v != NULL);
2955
+ UPB_ASSERT(*v != 0);
2956
+
2957
+ if (isfull(&t->t)) {
2958
+ if (!upb_exttable_resize(t, _upb_log2_table_size(&t->t) + 1, a)) {
2959
+ return false;
2960
+ }
2961
+ }
2962
+
2963
+ lookupkey_t lookupkey = extkey(k, *v);
2964
+ upb_key key = {.num = (uintptr_t)k};
2965
+ upb_value val = upb_value_constptr(v);
2966
+ uint32_t hash = _upb_exttable_hash(k, *v);
2967
+ insert(&t->t, lookupkey, key, val, hash, &exthash, &exteql);
2968
+ return true;
2969
+ }
2970
+
2971
+ const uint32_t* upb_exttable_lookup(const upb_exttable* t, const void* k,
2972
+ uint32_t ext_number) {
2973
+ uint32_t hash = _upb_exttable_hash(k, ext_number);
2974
+ upb_value val;
2975
+ if (lookup(&t->t, extkey(k, ext_number), &val, hash, &exteql)) {
2976
+ return (const uint32_t*)upb_value_getconstptr(val);
2977
+ }
2978
+ return NULL;
2979
+ }
2980
+
2981
+ const uint32_t* upb_exttable_remove(upb_exttable* t, const void* k,
2982
+ uint32_t ext_number) {
2983
+ uint32_t hash = _upb_exttable_hash(k, ext_number);
2984
+ upb_value val;
2985
+ if (rm(&t->t, extkey(k, ext_number), &val, hash, &exteql)) {
2986
+ return (const uint32_t*)upb_value_getconstptr(val);
2987
+ }
2988
+ return NULL;
2989
+ }
2990
+
2991
+ size_t upb_exttable_size(const upb_exttable* t) { return t->t.count; }
2992
+
2884
2993
  /* upb_inttable ***************************************************************/
2885
2994
 
2886
2995
  /* For inttables we use a hybrid structure where small keys are kept in an
@@ -2895,9 +3004,15 @@ static uint32_t presence_mask_arr_size(uint32_t array_size) {
2895
3004
  return (array_size + 7) / 8; // sizeof(uint8_t) is always 1.
2896
3005
  }
2897
3006
 
2898
- static uint32_t inthash(upb_key key) { return upb_inthash(key.num); }
3007
+ static uint32_t inthash(upb_key key, upb_value val) {
3008
+ UPB_UNUSED(val);
3009
+ return upb_inthash(key.num);
3010
+ }
2899
3011
 
2900
- static bool inteql(upb_key k1, lookupkey_t k2) { return k1.num == k2.num; }
3012
+ static bool inteql(upb_key k1, upb_value v1, lookupkey_t k2) {
3013
+ UPB_UNUSED(v1);
3014
+ return k1.num == k2.num;
3015
+ }
2901
3016
 
2902
3017
  static upb_value* mutable_array(upb_inttable* t) {
2903
3018
  return (upb_value*)t->array;
@@ -3003,8 +3118,8 @@ bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
3003
3118
 
3004
3119
  for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
3005
3120
  const upb_tabent* e = &t->t.entries[i];
3006
- insert(&new_table, intkey(e->key.num), e->key, e->val, inthash(e->key),
3007
- &inthash, &inteql);
3121
+ insert(&new_table, intkey(e->key.num), e->key, e->val,
3122
+ inthash(e->key, e->val), &inthash, &inteql);
3008
3123
  }
3009
3124
 
3010
3125
  UPB_ASSERT(t->t.count == new_table.count);
@@ -5663,24 +5778,33 @@ static int GetLocaleRadix(char *data, size_t capacity) {
5663
5778
  const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
5664
5779
  UPB_ASSERT(temp[0] == '1');
5665
5780
  UPB_ASSERT(temp[size - 1] == '5');
5666
- UPB_ASSERT(size < capacity);
5781
+ if (size < capacity) {
5782
+ return 0;
5783
+ }
5667
5784
  temp[size - 1] = '\0';
5668
- strcpy(data, temp + 1);
5785
+ strncpy(data, temp + 1, size);
5669
5786
  return size - 2;
5670
5787
  }
5671
5788
 
5672
5789
  // Populates a string identical to *input except that the character pointed to
5673
5790
  // by pos (which should be '.') is replaced with the locale-specific radix.
5674
5791
 
5675
- static void LocalizeRadix(const char *input, const char *pos, char *output) {
5792
+ static void LocalizeRadix(const char *input, const char *pos, char *output,
5793
+ int output_size) {
5676
5794
  const int len1 = pos - input;
5677
5795
 
5678
5796
  char radix[8];
5679
5797
  const int len2 = GetLocaleRadix(radix, sizeof(radix));
5680
5798
 
5799
+ const int n = output_size - len1 - len2 - 1;
5800
+ if (n < 0) {
5801
+ return;
5802
+ }
5803
+
5681
5804
  memcpy(output, input, len1);
5682
5805
  memcpy(output + len1, radix, len2);
5683
- strcpy(output + len1 + len2, input + len1 + 1);
5806
+ strncpy(output + len1 + len2, input + len1 + 1, n);
5807
+ output[output_size - 1] = '\0';
5684
5808
  }
5685
5809
 
5686
5810
  double _upb_NoLocaleStrtod(const char *str, char **endptr) {
@@ -5700,7 +5824,7 @@ double _upb_NoLocaleStrtod(const char *str, char **endptr) {
5700
5824
  // try again.
5701
5825
 
5702
5826
  char localized[80];
5703
- LocalizeRadix(str, temp_endptr, localized);
5827
+ LocalizeRadix(str, temp_endptr, localized, sizeof localized);
5704
5828
  char *localized_endptr;
5705
5829
  result = strtod(localized, &localized_endptr);
5706
5830
  if ((localized_endptr - &localized[0]) > (temp_endptr - str)) {
@@ -5782,6 +5906,7 @@ upb_alloc upb_alloc_global = {&upb_global_allocfunc};
5782
5906
  static UPB_ATOMIC(size_t) g_max_block_size = UPB_DEFAULT_MAX_BLOCK_SIZE;
5783
5907
 
5784
5908
  void upb_Arena_SetMaxBlockSize(size_t max) {
5909
+ UPB_ASSERT(max <= UINT32_MAX);
5785
5910
  upb_Atomic_Store(&g_max_block_size, max, memory_order_relaxed);
5786
5911
  }
5787
5912
 
@@ -5818,8 +5943,14 @@ typedef struct upb_ArenaInternal {
5818
5943
  UPB_ATOMIC(const upb_ArenaRef*) refs;
5819
5944
  #endif
5820
5945
 
5821
- // A growing hint of what the *next* block should be sized
5822
- size_t size_hint;
5946
+ // Size of the last block we allocated in the normal exponential scheme.
5947
+ uint32_t last_block_size;
5948
+
5949
+ // A hint that grows whenever we perform a "one-off" allocation into a a
5950
+ // dedicated block. This helps us determine if these outlier blocks are
5951
+ // actually common enough that we should switch back to the normal exponential
5952
+ // scheme at the larger size.
5953
+ uint32_t size_hint;
5823
5954
 
5824
5955
  // All non atomic members used during allocation must be above this point, and
5825
5956
  // are used by _SwapIn/_SwapOut
@@ -6115,23 +6246,60 @@ bool upb_Arena_HasRefChain(const upb_Arena* from, const upb_Arena* to) {
6115
6246
 
6116
6247
  #endif
6117
6248
 
6118
- // Adds an allocated block to the head of the list.
6119
- static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t offset,
6120
- size_t block_size) {
6249
+ static upb_MemBlock* _upb_Arena_AllocBlockInternal(upb_alloc* alloc,
6250
+ size_t size) {
6251
+ UPB_ASSERT(size >= kUpb_MemblockReserve);
6252
+ upb_SizedPtr alloc_result = upb_SizeReturningMalloc(alloc, size);
6253
+ if (!alloc_result.p) return NULL;
6254
+ upb_MemBlock* block = alloc_result.p;
6255
+ block->size = alloc_result.n;
6256
+ return block;
6257
+ }
6258
+
6259
+ static upb_MemBlock* _upb_Arena_AllocBlock(upb_Arena* a, size_t size) {
6260
+ upb_ArenaInternal* ai = upb_Arena_Internal(a);
6261
+ return _upb_Arena_AllocBlockInternal(_upb_ArenaInternal_BlockAlloc(ai), size);
6262
+ }
6263
+
6264
+ static void _upb_Arena_AddBlock(upb_Arena* a, upb_MemBlock* block) {
6121
6265
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6122
- upb_MemBlock* block = ptr;
6123
6266
 
6124
- block->size = block_size;
6125
- UPB_ASSERT(offset >= kUpb_MemblockReserve);
6126
- char* start = UPB_PTR_AT(block, offset, char);
6127
- upb_MemBlock* head = ai->blocks;
6128
- block->next = head;
6267
+ // Atomic add not required here, as threads won't race allocating blocks, plus
6268
+ // atomic fetch-add is slower than load/add/store on arm devices compiled
6269
+ // targeting pre-v8.1. Relaxed order is safe as nothing depends on order of
6270
+ // size allocated.
6271
+ uintptr_t old_space_allocated =
6272
+ upb_Atomic_Load(&ai->space_allocated, memory_order_relaxed);
6273
+ upb_Atomic_Store(&ai->space_allocated, old_space_allocated + block->size,
6274
+ memory_order_relaxed);
6275
+
6276
+ block->next = ai->blocks;
6129
6277
  ai->blocks = block;
6130
- UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(a));
6278
+ }
6279
+
6280
+ static void _upb_Arena_UseBlockInternal(upb_Arena* a, upb_MemBlock* block,
6281
+ size_t offset) {
6282
+ size_t block_size = block->size;
6283
+ char* start = UPB_PTR_AT(block, kUpb_MemblockReserve + offset, char);
6131
6284
  a->UPB_PRIVATE(ptr) = start;
6132
6285
  a->UPB_PRIVATE(end) = UPB_PTR_AT(block, block_size, char);
6133
6286
  UPB_PRIVATE(upb_Xsan_PoisonRegion)(start, a->UPB_PRIVATE(end) - start);
6134
- UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= block_size - offset);
6287
+ UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(a));
6288
+ UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >=
6289
+ block_size - kUpb_MemblockReserve - offset);
6290
+ }
6291
+
6292
+ static void _upb_Arena_UseBlock(upb_Arena* a, upb_MemBlock* block) {
6293
+ _upb_Arena_UseBlockInternal(a, block, 0);
6294
+ }
6295
+
6296
+ static bool _upb_Arena_WouldReduceFreeSpace(upb_Arena* a, size_t size,
6297
+ size_t block_size) {
6298
+ upb_ArenaInternal* ai = upb_Arena_Internal(a);
6299
+ size_t current_free =
6300
+ ai->blocks ? a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr) : 0;
6301
+ size_t future_free = block_size - kUpb_MemblockReserve - size;
6302
+ return current_free >= future_free;
6135
6303
  }
6136
6304
 
6137
6305
  // Fulfills the allocation request by allocating a new block. Returns NULL on
@@ -6139,84 +6307,60 @@ static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t offset,
6139
6307
  void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) {
6140
6308
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6141
6309
  if (!ai->block_alloc) return NULL;
6142
- size_t last_size = 128;
6143
- size_t current_free = 0;
6144
- upb_MemBlock* last_block = ai->blocks;
6145
- if (last_block) {
6146
- last_size = last_block->size;
6147
- current_free = a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr);
6148
- }
6310
+
6311
+ // Whether to satisfy the allocation from a one-off block which is right-sized
6312
+ // for the current allocation. We do this if we suspect that the current
6313
+ // allocation is an outlier that does not represent the typical size of
6314
+ // allocations from this arena, or if we would reduce free space by
6315
+ // using exponential growth.
6316
+ bool one_off = false;
6149
6317
 
6150
6318
  // Relaxed order is safe here as we don't need any ordering with the setter.
6151
6319
  size_t max_block_size =
6152
6320
  upb_Atomic_Load(&g_max_block_size, memory_order_relaxed);
6153
-
6154
- // Don't naturally grow beyond the max block size.
6155
- size_t target_size = UPB_MIN(last_size * 2, max_block_size);
6156
- size_t future_free = UPB_MAX(size, target_size - kUpb_MemblockReserve) - size;
6157
- // We want to preserve exponential growth in block size without wasting too
6158
- // much unused space at the end of blocks. Once the head of our blocks list is
6159
- // large enough to always trigger a max-sized block for all subsequent
6160
- // allocations, allocate blocks that would net reduce free space behind it.
6161
- if (last_block && current_free > future_free &&
6162
- target_size < max_block_size) {
6163
- last_size = ai->size_hint;
6164
- // Recalculate sizes with possibly larger last_size
6165
- target_size = UPB_MIN(last_size * 2, max_block_size);
6166
- future_free = UPB_MAX(size, target_size - kUpb_MemblockReserve) - size;
6167
- }
6168
- bool insert_after_head = false;
6169
- // Only insert after head if an allocated block is present; we don't want to
6170
- // continue allocating out of the initial block because we'll have no way of
6171
- // restoring the size of our allocated block if we add another.
6172
- if (last_block && current_free >= future_free) {
6173
- // If we're still going to net reduce free space with this new block, then
6174
- // only allocate the precise size requested and keep the current last block
6175
- // as the active block for future allocations.
6176
- insert_after_head = true;
6177
- target_size = size + kUpb_MemblockReserve;
6178
- // Add something to our previous size each time, so that eventually we
6179
- // will reach the max block size. Allocations larger than the max block size
6180
- // will always get their own backing allocation, so don't include them.
6181
- if (target_size <= max_block_size) {
6182
- ai->size_hint = UPB_MIN(ai->size_hint + (size >> 1), max_block_size >> 1);
6321
+ size_t block_size = UPB_MIN(ai->last_block_size * 2, max_block_size);
6322
+
6323
+ if (size + kUpb_MemblockReserve > block_size) {
6324
+ // A regular doubling would not yield a large enough block. Does size_hint
6325
+ // indicate that we have consistently needed large blocks?
6326
+ block_size = UPB_MIN(ai->size_hint * 2, max_block_size);
6327
+ if (size + kUpb_MemblockReserve > block_size) {
6328
+ // Even size_hint is not large enough, we will have to do a one-off.
6329
+ one_off = true;
6183
6330
  }
6184
6331
  }
6185
- // We may need to exceed the max block size if the user requested a large
6186
- // allocation.
6187
- size_t block_size = UPB_MAX(kUpb_MemblockReserve + size, target_size);
6188
- upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai);
6189
- upb_SizedPtr alloc_result = upb_SizeReturningMalloc(block_alloc, block_size);
6190
6332
 
6191
- if (!alloc_result.p) return NULL;
6333
+ // If switching to a block of this size would *reduce* available free space,
6334
+ // we might as well make a one-off block instead.
6335
+ one_off = one_off || _upb_Arena_WouldReduceFreeSpace(a, size, block_size);
6192
6336
 
6193
- upb_MemBlock* block = alloc_result.p;
6194
- size_t actual_block_size = alloc_result.n;
6337
+ if (one_off) {
6338
+ // Note: this may exceed the max block size, but that's okay.
6339
+ block_size = size + kUpb_MemblockReserve;
6340
+ }
6195
6341
 
6196
- // Atomic add not required here, as threads won't race allocating blocks, plus
6197
- // atomic fetch-add is slower than load/add/store on arm devices compiled
6198
- // targetting pre-v8.1. Relaxed order is safe as nothing depends on order of
6199
- // size allocated.
6342
+ upb_MemBlock* block = _upb_Arena_AllocBlock(a, block_size);
6343
+ if (!block) return NULL;
6200
6344
 
6201
- uintptr_t old_space_allocated =
6202
- upb_Atomic_Load(&ai->space_allocated, memory_order_relaxed);
6203
- upb_Atomic_Store(&ai->space_allocated,
6204
- old_space_allocated + actual_block_size,
6205
- memory_order_relaxed);
6206
- if (UPB_UNLIKELY(insert_after_head)) {
6207
- upb_ArenaInternal* ai = upb_Arena_Internal(a);
6208
- block->size = actual_block_size;
6209
- upb_MemBlock* head = ai->blocks;
6210
- block->next = head->next;
6211
- head->next = block;
6345
+ _upb_Arena_AddBlock(a, block);
6212
6346
 
6347
+ // Recheck size, in case the allocator gave us a much larger block than we
6348
+ // requested and we want to make it the new allocating region.
6349
+ if (UPB_UNLIKELY(one_off) &&
6350
+ _upb_Arena_WouldReduceFreeSpace(a, size, block->size)) {
6351
+ // Increase size_hint, so that a series of one-off allocations will
6352
+ // eventually convince us to switch to exponential growth at the larger
6353
+ // size.
6354
+ ai->size_hint = UPB_MIN(ai->size_hint + (size >> 1), max_block_size >> 1);
6213
6355
  char* allocated = UPB_PTR_AT(block, kUpb_MemblockReserve, char);
6214
- UPB_PRIVATE(upb_Xsan_PoisonRegion)(allocated + size,
6215
- UPB_PRIVATE(kUpb_Asan_GuardSize));
6356
+ char* poison_start = allocated + size - UPB_PRIVATE(kUpb_Asan_GuardSize);
6357
+ UPB_PRIVATE(upb_Xsan_PoisonRegion)(
6358
+ poison_start, UPB_PTR_AT(block, block->size, char) - poison_start);
6216
6359
  return allocated;
6217
6360
  } else {
6218
- ai->size_hint = actual_block_size;
6219
- _upb_Arena_AddBlock(a, block, kUpb_MemblockReserve, actual_block_size);
6361
+ ai->last_block_size = UPB_MIN(block->size, UINT32_MAX);
6362
+ ai->size_hint = ai->last_block_size;
6363
+ _upb_Arena_UseBlock(a, block);
6220
6364
  UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size);
6221
6365
  return upb_Arena_Malloc(a, size - UPB_PRIVATE(kUpb_Asan_GuardSize));
6222
6366
  }
@@ -6227,27 +6371,26 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6227
6371
  UPB_ALIGN_MALLOC(kUpb_MemblockReserve + sizeof(upb_ArenaState));
6228
6372
  upb_ArenaState* a;
6229
6373
 
6230
- // We need to malloc the initial block.
6374
+ if (!alloc) return NULL;
6231
6375
 
6376
+ // We need to malloc the initial block.
6232
6377
  size_t block_size =
6233
6378
  first_block_overhead + UPB_MAX(256, UPB_ALIGN_MALLOC(first_size) +
6234
6379
  UPB_PRIVATE(kUpb_Asan_GuardSize));
6235
- upb_SizedPtr alloc_result;
6236
- if (!alloc ||
6237
- !(alloc_result = upb_SizeReturningMalloc(alloc, block_size)).p) {
6238
- return NULL;
6239
- }
6240
- char* mem = alloc_result.p;
6241
- size_t actual_block_size = alloc_result.n;
6380
+ upb_MemBlock* block = _upb_Arena_AllocBlockInternal(alloc, block_size);
6381
+ if (!block) return NULL;
6242
6382
 
6243
- a = UPB_PTR_AT(mem, kUpb_MemblockReserve, upb_ArenaState);
6383
+ // Initialize the arena state in the first block. We "borrow" the memory from
6384
+ // the block, because we can't yet call upb_Arena_Malloc.
6385
+ a = UPB_PTR_AT(block, kUpb_MemblockReserve, upb_ArenaState);
6244
6386
  a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0);
6245
- a->body.size_hint = actual_block_size;
6387
+ a->body.last_block_size = UPB_MIN(block->size, UINT32_MAX);
6388
+ a->body.size_hint = UPB_MIN(block->size, UINT32_MAX);
6246
6389
  upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1));
6247
6390
  upb_Atomic_Init(&a->body.next, NULL);
6248
6391
  upb_Atomic_Init(&a->body.previous_or_tail,
6249
6392
  _upb_Arena_TaggedFromTail(&a->body));
6250
- upb_Atomic_Init(&a->body.space_allocated, actual_block_size);
6393
+ upb_Atomic_Init(&a->body.space_allocated, 0);
6251
6394
  a->body.blocks = NULL;
6252
6395
  #ifndef NDEBUG
6253
6396
  a->body.refs = NULL;
@@ -6255,15 +6398,16 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6255
6398
  a->body.upb_alloc_cleanup = NULL;
6256
6399
  UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(&a->body));
6257
6400
 
6258
- _upb_Arena_AddBlock(&a->head, mem, first_block_overhead, actual_block_size);
6401
+ _upb_Arena_AddBlock(&a->head, block);
6402
+ _upb_Arena_UseBlockInternal(&a->head, block,
6403
+ UPB_ALIGN_MALLOC(sizeof(upb_ArenaState)));
6259
6404
 
6260
6405
  return &a->head;
6261
6406
  }
6262
6407
 
6263
6408
  upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
6264
- UPB_STATIC_ASSERT(
6265
- sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState),
6266
- "Need to update UPB_ARENA_SIZE_HACK");
6409
+ UPB_STATIC_ASSERT(UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState),
6410
+ "Need to update UPB_ARENA_SIZE_HACK");
6267
6411
  upb_ArenaState* a;
6268
6412
 
6269
6413
  if (mem) {
@@ -6293,6 +6437,7 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
6293
6437
  a->body.refs = NULL;
6294
6438
  #endif
6295
6439
  a->body.size_hint = 128;
6440
+ a->body.last_block_size = 128;
6296
6441
  a->body.upb_alloc_cleanup = NULL;
6297
6442
  a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1);
6298
6443
  a->head.UPB_PRIVATE(ptr) = (void*)UPB_ALIGN_MALLOC((uintptr_t)(a + 1));
@@ -6739,14 +6884,11 @@ void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) {
6739
6884
  bool _upb_Arena_WasLastAlloc(struct upb_Arena* a, void* ptr, size_t oldsize) {
6740
6885
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6741
6886
  upb_MemBlock* block = ai->blocks;
6742
- if (block == NULL) return false;
6743
6887
  // Skip any arena refs.
6744
6888
  while (block != NULL && block->size == 0) {
6745
6889
  block = block->next;
6746
6890
  }
6747
6891
  if (block == NULL) return false;
6748
- block = block->next;
6749
- if (block == NULL) return false;
6750
6892
  char* start = UPB_PTR_AT(block, kUpb_MemblockReserve, char);
6751
6893
  return UPB_PRIVATE(upb_Xsan_PtrEq)(ptr, start) &&
6752
6894
  UPB_PRIVATE(_upb_Arena_AllocSpan)(oldsize) ==
@@ -6828,6 +6970,46 @@ bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
6828
6970
  return true;
6829
6971
  }
6830
6972
 
6973
+ bool upb_Array_Copy(upb_Array* dst, const upb_Array* src, upb_Arena* arena) {
6974
+ UPB_ASSERT(dst);
6975
+ UPB_ASSERT(src);
6976
+ UPB_ASSERT(!upb_Array_IsFrozen(dst));
6977
+ if (dst == src) return true;
6978
+ size_t len = upb_Array_Size(src);
6979
+ if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(dst, len, arena)) {
6980
+ return false;
6981
+ }
6982
+ if (len == 0) return true;
6983
+ const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(dst);
6984
+ const int src_lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(src);
6985
+ UPB_ASSERT(lg2 == src_lg2);
6986
+ char* dst_data = upb_Array_MutableDataPtr(dst);
6987
+ const char* src_data = upb_Array_DataPtr(src);
6988
+ memcpy(dst_data, src_data, len << lg2);
6989
+ return true;
6990
+ }
6991
+
6992
+ bool upb_Array_AppendAll(upb_Array* dst, const upb_Array* src,
6993
+ upb_Arena* arena) {
6994
+ UPB_ASSERT(!upb_Array_IsFrozen(dst));
6995
+ UPB_ASSERT(src);
6996
+ size_t src_len = upb_Array_Size(src);
6997
+ if (src_len == 0) return true;
6998
+ size_t dst_len = upb_Array_Size(dst);
6999
+ size_t len = dst_len + src_len;
7000
+ if (UPB_UNLIKELY(len < dst_len)) return false;
7001
+ if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(dst, len, arena)) {
7002
+ return false;
7003
+ }
7004
+ const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(dst);
7005
+ const int src_lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(src);
7006
+ UPB_ASSERT(lg2 == src_lg2);
7007
+ char* dst_data = upb_Array_MutableDataPtr(dst);
7008
+ const char* src_data = upb_Array_DataPtr(src);
7009
+ memcpy(dst_data + (dst_len << lg2), src_data, src_len << lg2);
7010
+ return true;
7011
+ }
7012
+
6831
7013
  void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
6832
7014
  size_t count) {
6833
7015
  UPB_ASSERT(!upb_Array_IsFrozen(arr));
@@ -6888,9 +7070,17 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity,
6888
7070
  void* ptr = upb_Array_MutableDataPtr(array);
6889
7071
 
6890
7072
  // Log2 ceiling of size.
6891
- while (new_capacity < min_capacity) new_capacity *= 2;
7073
+ while (new_capacity < min_capacity) {
7074
+ if (upb_ShlOverflow(&new_capacity, 1)) {
7075
+ new_capacity = SIZE_MAX;
7076
+ break;
7077
+ }
7078
+ }
6892
7079
 
6893
- const size_t new_bytes = new_capacity << lg2;
7080
+ size_t new_bytes = new_capacity;
7081
+ if (upb_ShlOverflow(&new_bytes, lg2)) {
7082
+ return false;
7083
+ }
6894
7084
  ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes);
6895
7085
  if (!ptr) return false;
6896
7086
 
@@ -7348,6 +7538,7 @@ UPB_NOINLINE bool UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(upb_Message* msg,
7348
7538
  if (!view) return false;
7349
7539
  view->data = data;
7350
7540
  } else {
7541
+ if (SIZE_MAX - sizeof(upb_StringView) < len) return false;
7351
7542
  view = upb_Arena_Malloc(arena, sizeof(upb_StringView) + len);
7352
7543
  if (!view) return false;
7353
7544
  char* copy = UPB_PTR_AT(view, sizeof(upb_StringView), char);
@@ -8124,7 +8315,7 @@ static bool upb_Clone_MessageValue(void* value, upb_CType value_type,
8124
8315
  case kUpb_CType_String:
8125
8316
  case kUpb_CType_Bytes: {
8126
8317
  upb_StringView source = *(upb_StringView*)value;
8127
- int size = source.size;
8318
+ size_t size = source.size;
8128
8319
  void* cloned_data = upb_Arena_Malloc(arena, size);
8129
8320
  if (cloned_data == NULL) {
8130
8321
  return false;
@@ -8504,8 +8695,15 @@ bool UPB_PRIVATE(_upb_Message_ReserveSlot)(struct upb_Message* msg,
8504
8695
  in->capacity = capacity;
8505
8696
  UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
8506
8697
  } else if (in->capacity == in->size) {
8698
+ if (in->size == UINT32_MAX) return false;
8507
8699
  // Internal data is too small, reallocate.
8508
- uint32_t new_capacity = upb_RoundUpToPowerOfTwo(in->size + 1);
8700
+ size_t needed_pow2 = upb_RoundUpToPowerOfTwo(in->size + 1);
8701
+ if (needed_pow2 > UINT32_MAX) return false;
8702
+ uint32_t new_capacity = needed_pow2;
8703
+ if (UPB_SIZEOF_FLEX_WOULD_OVERFLOW(upb_Message_Internal, aux_data,
8704
+ new_capacity)) {
8705
+ return false;
8706
+ }
8509
8707
  in = upb_Arena_Realloc(a, in, _upb_Message_SizeOfInternal(in->capacity),
8510
8708
  _upb_Message_SizeOfInternal(new_capacity));
8511
8709
  if (!in) return false;
@@ -8710,7 +8908,6 @@ upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
8710
8908
 
8711
8909
 
8712
8910
  #include <inttypes.h>
8713
- #include <stdalign.h>
8714
8911
  #include <stddef.h>
8715
8912
  #include <stdint.h>
8716
8913
  #include <stdlib.h>
@@ -10117,28 +10314,25 @@ char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) {
10117
10314
 
10118
10315
  // Must be last.
10119
10316
 
10120
- #define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
10121
-
10122
10317
  struct upb_ExtensionRegistry {
10318
+ upb_exttable exts;
10123
10319
  upb_Arena* arena;
10124
- upb_strtable exts; // Key is upb_MiniTable* concatenated with fieldnum.
10125
10320
  };
10126
10321
 
10127
- static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
10128
- memcpy(buf, &l, sizeof(l));
10129
- memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
10130
- }
10131
-
10132
10322
  upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
10133
10323
  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
10134
10324
  if (!r) return NULL;
10135
10325
  r->arena = arena;
10136
- if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
10326
+ if (!upb_exttable_init(&r->exts, 8, arena)) return NULL;
10137
10327
  return r;
10138
10328
  }
10139
10329
 
10140
10330
  UPB_API upb_ExtensionRegistryStatus upb_ExtensionRegistry_Add(
10141
10331
  upb_ExtensionRegistry* r, const upb_MiniTableExtension* e) {
10332
+ UPB_STATIC_ASSERT(
10333
+ offsetof(upb_MiniTableExtension,
10334
+ UPB_PRIVATE(field).UPB_PRIVATE(number)) == 0,
10335
+ "Extension must be first-member-of-struct convertable with uint32_t");
10142
10336
  uint32_t fieldnum = upb_MiniTableExtension_Number(e);
10143
10337
  const upb_MiniTable* extendee = upb_MiniTableExtension_Extendee(e);
10144
10338
 
@@ -10148,15 +10342,11 @@ UPB_API upb_ExtensionRegistryStatus upb_ExtensionRegistry_Add(
10148
10342
  return kUpb_ExtensionRegistryStatus_InvalidExtension;
10149
10343
  }
10150
10344
 
10151
- char buf[EXTREG_KEY_SIZE];
10152
- extreg_key(buf, extendee, fieldnum);
10153
-
10154
- if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, NULL)) {
10345
+ if (upb_exttable_lookup(&r->exts, extendee, fieldnum) != NULL) {
10155
10346
  return kUpb_ExtensionRegistryStatus_DuplicateEntry;
10156
10347
  }
10157
10348
 
10158
- if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
10159
- upb_value_constptr(e), r->arena)) {
10349
+ if (!upb_exttable_insert(&r->exts, extendee, (const uint32_t*)e, r->arena)) {
10160
10350
  return kUpb_ExtensionRegistryStatus_OutOfMemory;
10161
10351
  }
10162
10352
  return kUpb_ExtensionRegistryStatus_Ok;
@@ -10177,10 +10367,8 @@ failure:
10177
10367
  // Back out the entries previously added.
10178
10368
  for (end = e, e = start; e < end; e++) {
10179
10369
  const upb_MiniTableExtension* ext = *e;
10180
- char buf[EXTREG_KEY_SIZE];
10181
- extreg_key(buf, ext->UPB_PRIVATE(extendee),
10182
- upb_MiniTableExtension_Number(ext));
10183
- upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
10370
+ upb_exttable_remove(&r->exts, upb_MiniTableExtension_Extendee(ext),
10371
+ upb_MiniTableExtension_Number(ext));
10184
10372
  }
10185
10373
  UPB_ASSERT(status != kUpb_ExtensionRegistryStatus_Ok);
10186
10374
  return status;
@@ -10188,18 +10376,12 @@ failure:
10188
10376
 
10189
10377
  const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
10190
10378
  const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) {
10191
- char buf[EXTREG_KEY_SIZE];
10192
- upb_value v;
10193
- extreg_key(buf, t, num);
10194
- if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
10195
- return upb_value_getconstptr(v);
10196
- } else {
10197
- return NULL;
10198
- }
10379
+ const uint32_t* v = upb_exttable_lookup(&r->exts, t, num);
10380
+ return (const upb_MiniTableExtension*)v;
10199
10381
  }
10200
10382
 
10201
10383
  size_t upb_ExtensionRegistry_Size(const upb_ExtensionRegistry* r) {
10202
- return upb_strtable_count(&r->exts);
10384
+ return upb_exttable_size(&r->exts);
10203
10385
  }
10204
10386
 
10205
10387
 
@@ -10448,6 +10630,7 @@ struct upb_DefPool {
10448
10630
  size_t scratch_size;
10449
10631
  size_t bytes_loaded;
10450
10632
  bool disable_closed_enum_checking;
10633
+ bool disable_implicit_field_presence;
10451
10634
  };
10452
10635
 
10453
10636
  void upb_DefPool_Free(upb_DefPool* s) {
@@ -10466,6 +10649,7 @@ upb_DefPool* upb_DefPool_New(void) {
10466
10649
  s->arena = upb_Arena_New();
10467
10650
  s->bytes_loaded = 0;
10468
10651
  s->disable_closed_enum_checking = false;
10652
+ s->disable_implicit_field_presence = false;
10469
10653
 
10470
10654
  s->scratch_size = 240;
10471
10655
  s->scratch_data = upb_gmalloc(s->scratch_size);
@@ -10507,6 +10691,15 @@ bool upb_DefPool_ClosedEnumCheckingDisabled(const upb_DefPool* s) {
10507
10691
  return s->disable_closed_enum_checking;
10508
10692
  }
10509
10693
 
10694
+ void upb_DefPool_DisableImplicitFieldPresence(upb_DefPool* s) {
10695
+ UPB_ASSERT(upb_strtable_count(&s->files) == 0);
10696
+ s->disable_implicit_field_presence = true;
10697
+ }
10698
+
10699
+ bool upb_DefPool_ImplicitFieldPresenceDisabled(const upb_DefPool* s) {
10700
+ return s->disable_implicit_field_presence;
10701
+ }
10702
+
10510
10703
  const google_protobuf_FeatureSetDefaults* upb_DefPool_FeatureSetDefaults(
10511
10704
  const upb_DefPool* s) {
10512
10705
  return s->feature_set_defaults;
@@ -10616,7 +10809,7 @@ void _upb_DefPool_SetPlatform(upb_DefPool* s, upb_MiniTablePlatform platform) {
10616
10809
 
10617
10810
  const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
10618
10811
  const char* sym) {
10619
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_MSG);
10812
+ return upb_DefPool_FindMessageByNameWithSize(s, sym, strlen(sym));
10620
10813
  }
10621
10814
 
10622
10815
  const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
@@ -10626,12 +10819,23 @@ const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
10626
10819
 
10627
10820
  const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
10628
10821
  const char* sym) {
10629
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUM);
10822
+ return upb_DefPool_FindEnumByNameWithSize(s, sym, strlen(sym));
10823
+ }
10824
+
10825
+ const upb_EnumDef* upb_DefPool_FindEnumByNameWithSize(const upb_DefPool* s,
10826
+ const char* sym,
10827
+ size_t len) {
10828
+ return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_ENUM);
10630
10829
  }
10631
10830
 
10632
- const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
10633
- const char* sym) {
10634
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUMVAL);
10831
+ const upb_EnumValueDef* upb_DefPool_FindEnumValueByName(const upb_DefPool* s,
10832
+ const char* sym) {
10833
+ return upb_DefPool_FindEnumValueByNameWithSize(s, sym, strlen(sym));
10834
+ }
10835
+
10836
+ const upb_EnumValueDef* upb_DefPool_FindEnumValueByNameWithSize(
10837
+ const upb_DefPool* s, const char* sym, size_t len) {
10838
+ return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_ENUMVAL);
10635
10839
  }
10636
10840
 
10637
10841
  const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
@@ -12248,7 +12452,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix,
12248
12452
 
12249
12453
  f->has_presence =
12250
12454
  (!upb_FieldDef_IsRepeated(f)) &&
12251
- (f->is_extension ||
12455
+ (f->is_extension || _upb_FileDef_ImplicitFieldPresenceDisabled(f->file) ||
12252
12456
  (f->type_ == kUpb_FieldType_Message ||
12253
12457
  f->type_ == kUpb_FieldType_Group || upb_FieldDef_ContainingOneof(f) ||
12254
12458
  google_protobuf_FeatureSet_field_presence(f->resolved_features) !=
@@ -12652,6 +12856,10 @@ bool _upb_FileDef_ClosedEnumCheckingDisabled(const upb_FileDef* f) {
12652
12856
  return upb_DefPool_ClosedEnumCheckingDisabled(f->symtab);
12653
12857
  }
12654
12858
 
12859
+ bool _upb_FileDef_ImplicitFieldPresenceDisabled(const upb_FileDef* f) {
12860
+ return upb_DefPool_ImplicitFieldPresenceDisabled(f->symtab);
12861
+ }
12862
+
12655
12863
  int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
12656
12864
  return f->top_lvl_enum_count;
12657
12865
  }
@@ -14540,6 +14748,7 @@ static void create_method(upb_DefBuilder* ctx,
14540
14748
  m->output_type = _upb_DefBuilder_Resolve(
14541
14749
  ctx, m->full_name, m->full_name,
14542
14750
  google_protobuf_MethodDescriptorProto_output_type(method_proto), UPB_DEFTYPE_MSG);
14751
+ _upb_ServiceDef_InsertMethod(ctx, s, m);
14543
14752
  }
14544
14753
 
14545
14754
  // Allocate and initialize an array of |n| method defs belonging to |s|.
@@ -14771,6 +14980,7 @@ struct upb_ServiceDef {
14771
14980
  upb_MethodDef* methods;
14772
14981
  int method_count;
14773
14982
  int index;
14983
+ upb_strtable ntom;
14774
14984
  };
14775
14985
 
14776
14986
  upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int index) {
@@ -14815,13 +15025,18 @@ const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
14815
15025
 
14816
15026
  const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
14817
15027
  const char* name) {
14818
- for (int i = 0; i < s->method_count; i++) {
14819
- const upb_MethodDef* m = _upb_MethodDef_At(s->methods, i);
14820
- if (strcmp(name, upb_MethodDef_Name(m)) == 0) {
14821
- return m;
14822
- }
15028
+ return upb_ServiceDef_FindMethodByNameWithSize(s, name, strlen(name));
15029
+ }
15030
+
15031
+ const upb_MethodDef* upb_ServiceDef_FindMethodByNameWithSize(
15032
+ const upb_ServiceDef* s, const char* name, size_t len) {
15033
+ upb_value val;
15034
+
15035
+ if (!upb_strtable_lookup2(&s->ntom, name, len, &val)) {
15036
+ return NULL;
14823
15037
  }
14824
- return NULL;
15038
+
15039
+ return _upb_DefType_Unpack(val, UPB_DEFTYPE_METHOD);
14825
15040
  }
14826
15041
 
14827
15042
  static void create_service(upb_DefBuilder* ctx,
@@ -14846,6 +15061,8 @@ static void create_service(upb_DefBuilder* ctx,
14846
15061
  const google_protobuf_MethodDescriptorProto* const* methods =
14847
15062
  google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
14848
15063
  s->method_count = n;
15064
+ bool ok = upb_strtable_init(&s->ntom, n, ctx->arena);
15065
+ if (!ok) _upb_DefBuilder_OomErr(ctx);
14849
15066
  s->methods = _upb_MethodDefs_New(ctx, n, methods, s->resolved_features, s);
14850
15067
  }
14851
15068
 
@@ -14863,6 +15080,20 @@ upb_ServiceDef* _upb_ServiceDefs_New(
14863
15080
  return s;
14864
15081
  }
14865
15082
 
15083
+ void _upb_ServiceDef_InsertMethod(upb_DefBuilder* ctx, upb_ServiceDef* s,
15084
+ const upb_MethodDef* m) {
15085
+ const char* shortname = upb_MethodDef_Name(m);
15086
+ const size_t shortnamelen = strlen(shortname);
15087
+ upb_value existing_v;
15088
+ if (upb_strtable_lookup(&s->ntom, shortname, &existing_v)) {
15089
+ _upb_DefBuilder_Errf(ctx, "duplicate method name (%s)", shortname);
15090
+ }
15091
+ const upb_value method_v = _upb_DefType_Pack(m, UPB_DEFTYPE_METHOD);
15092
+ bool ok = upb_strtable_insert(&s->ntom, shortname, shortnamelen, method_v,
15093
+ ctx->arena);
15094
+ if (!ok) _upb_DefBuilder_OomErr(ctx);
15095
+ }
15096
+
14866
15097
 
14867
15098
  #include <inttypes.h>
14868
15099
  #include <math.h>
@@ -16470,6 +16701,7 @@ const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
16470
16701
  *op = kUpb_DecodeOp_UnknownField;
16471
16702
  return ptr;
16472
16703
  }
16704
+ _upb_Decoder_MungeInt32(val);
16473
16705
  } else {
16474
16706
  _upb_Decoder_Munge(field, val);
16475
16707
  }
@@ -16512,7 +16744,6 @@ const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
16512
16744
  UPB_FORCEINLINE
16513
16745
  const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr,
16514
16746
  upb_Message* msg,
16515
- const upb_MiniTable* layout,
16516
16747
  const upb_MiniTableField* field,
16517
16748
  int op, wireval* val) {
16518
16749
  uint8_t mode = field->UPB_PRIVATE(mode);
@@ -16541,67 +16772,13 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr,
16541
16772
  }
16542
16773
  }
16543
16774
 
16544
- static const char* _upb_Decoder_FindFieldStart(upb_Decoder* d, const char* ptr,
16545
- uint32_t field_number,
16546
- uint32_t wire_type) {
16547
- // Since unknown fields are the uncommon case, we do a little extra work here
16548
- // to walk backwards through the buffer to find the field start. This frees
16549
- // up a register in the fast paths (when the field is known), which leads to
16550
- // significant speedups in benchmarks. Note that ptr may point into the slop
16551
- // space, beyond the normal end of the input buffer.
16552
- const char* start = ptr;
16553
-
16554
- switch (wire_type) {
16555
- case kUpb_WireType_Varint:
16556
- case kUpb_WireType_Delimited:
16557
- // Skip the last byte
16558
- start--;
16559
- // Skip bytes until we encounter the final byte of the tag varint.
16560
- while (start[-1] & 0x80) start--;
16561
- break;
16562
- case kUpb_WireType_32Bit:
16563
- start -= 4;
16564
- break;
16565
- case kUpb_WireType_64Bit:
16566
- start -= 8;
16567
- break;
16568
- default:
16569
- break;
16570
- }
16571
- assert(start == d->debug_valstart);
16572
-
16573
- {
16574
- // The varint parser does not enforce that integers are encoded with their
16575
- // minimum size; for example the value 1 could be encoded with three
16576
- // bytes: 0x81, 0x80, 0x00. These unnecessary trailing zeroes mean that we
16577
- // cannot skip backwards by the minimum encoded size of the tag; and
16578
- // unlike the loop for delimited or varint fields, we can't stop at a
16579
- // sentinel value because anything can precede a tag. Instead, parse back
16580
- // one byte at a time until we read the same tag value that was parsed
16581
- // earlier.
16582
- uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
16583
- uint32_t seen = 0;
16584
- do {
16585
- start--;
16586
- seen <<= 7;
16587
- seen |= *start & 0x7f;
16588
- } while (seen != tag);
16589
- }
16590
- assert(start == d->debug_tagstart);
16591
-
16592
- return start;
16593
- }
16594
-
16595
16775
  static const char* _upb_Decoder_DecodeUnknownField(
16596
16776
  upb_Decoder* d, const char* ptr, upb_Message* msg, uint32_t field_number,
16597
- uint32_t wire_type, wireval val) {
16777
+ uint32_t wire_type, wireval val, const char* start) {
16598
16778
  if (field_number == 0) {
16599
16779
  upb_ErrorHandler_ThrowError(&d->err, kUpb_DecodeStatus_Malformed);
16600
16780
  }
16601
16781
 
16602
- const char* start =
16603
- _upb_Decoder_FindFieldStart(d, ptr, field_number, wire_type);
16604
-
16605
16782
  upb_EpsCopyInputStream_StartCapture(&d->input, start);
16606
16783
 
16607
16784
  if (wire_type == kUpb_WireType_Delimited) {
@@ -16640,10 +16817,6 @@ UPB_FORCEINLINE
16640
16817
  const char* _upb_Decoder_DecodeFieldTag(upb_Decoder* d, const char* ptr,
16641
16818
  uint32_t* field_number,
16642
16819
  uint32_t* wire_type) {
16643
- #ifndef NDEBUG
16644
- d->debug_tagstart = ptr;
16645
- #endif
16646
-
16647
16820
  uint32_t tag;
16648
16821
  UPB_ASSERT(ptr < d->input.limit_ptr);
16649
16822
  ptr = upb_WireReader_ReadTag(ptr, &tag, EPS(d));
@@ -16653,15 +16826,9 @@ const char* _upb_Decoder_DecodeFieldTag(upb_Decoder* d, const char* ptr,
16653
16826
  }
16654
16827
 
16655
16828
  UPB_FORCEINLINE
16656
- const char* _upb_Decoder_DecodeFieldData(upb_Decoder* d, const char* ptr,
16657
- upb_Message* msg,
16658
- const upb_MiniTable* mt,
16659
- uint32_t field_number,
16660
- uint32_t wire_type) {
16661
- #ifndef NDEBUG
16662
- d->debug_valstart = ptr;
16663
- #endif
16664
-
16829
+ const char* _upb_Decoder_DecodeFieldData(
16830
+ upb_Decoder* d, const char* ptr, upb_Message* msg, const upb_MiniTable* mt,
16831
+ uint32_t field_number, uint32_t wire_type, const char* start) {
16665
16832
  int op;
16666
16833
  wireval val;
16667
16834
 
@@ -16670,12 +16837,12 @@ const char* _upb_Decoder_DecodeFieldData(upb_Decoder* d, const char* ptr,
16670
16837
  ptr = _upb_Decoder_DecodeWireValue(d, ptr, mt, field, wire_type, &val, &op);
16671
16838
 
16672
16839
  if (op >= 0) {
16673
- return _upb_Decoder_DecodeKnownField(d, ptr, msg, mt, field, op, &val);
16840
+ return _upb_Decoder_DecodeKnownField(d, ptr, msg, field, op, &val);
16674
16841
  } else {
16675
16842
  switch (op) {
16676
16843
  case kUpb_DecodeOp_UnknownField:
16677
16844
  return _upb_Decoder_DecodeUnknownField(d, ptr, msg, field_number,
16678
- wire_type, val);
16845
+ wire_type, val, start);
16679
16846
  case kUpb_DecodeOp_MessageSetItem:
16680
16847
  return upb_Decoder_DecodeMessageSetItem(d, ptr, msg, mt);
16681
16848
  default:
@@ -16696,6 +16863,7 @@ const char* _upb_Decoder_DecodeFieldNoFast(upb_Decoder* d, const char* ptr,
16696
16863
  uint32_t field_number;
16697
16864
  uint32_t wire_type;
16698
16865
 
16866
+ const char* start = ptr;
16699
16867
  ptr = _upb_Decoder_DecodeFieldTag(d, ptr, &field_number, &wire_type);
16700
16868
 
16701
16869
  if (wire_type == kUpb_WireType_EndGroup) {
@@ -16703,7 +16871,8 @@ const char* _upb_Decoder_DecodeFieldNoFast(upb_Decoder* d, const char* ptr,
16703
16871
  return _upb_Decoder_EndMessage(d, ptr);
16704
16872
  }
16705
16873
 
16706
- ptr = _upb_Decoder_DecodeFieldData(d, ptr, msg, mt, field_number, wire_type);
16874
+ ptr = _upb_Decoder_DecodeFieldData(d, ptr, msg, mt, field_number, wire_type,
16875
+ start);
16707
16876
  _upb_Decoder_Trace(d, 'M');
16708
16877
  return ptr;
16709
16878
  }
@@ -16922,14 +17091,6 @@ typedef struct {
16922
17091
  _upb_mapsorter sorter;
16923
17092
  } upb_encstate;
16924
17093
 
16925
- static size_t upb_roundup_pow2(size_t bytes) {
16926
- size_t ret = 128;
16927
- while (ret < bytes) {
16928
- ret *= 2;
16929
- }
16930
- return ret;
16931
- }
16932
-
16933
17094
  UPB_NORETURN static void encode_err(upb_encstate* e, upb_EncodeStatus s) {
16934
17095
  UPB_ASSERT(s != kUpb_EncodeStatus_Ok);
16935
17096
  e->status = s;
@@ -16945,7 +17106,9 @@ UPB_NOINLINE static char* encode_growbuffer(char* ptr, upb_encstate* e,
16945
17106
  size_t bytes) {
16946
17107
  size_t old_size = e->limit - e->buf;
16947
17108
  size_t needed_size = bytes + (e->limit - ptr);
16948
- size_t new_size = upb_roundup_pow2(needed_size);
17109
+ if (needed_size < bytes) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
17110
+ size_t new_size = upb_RoundUpToPowerOfTwo(UPB_MAX(128, needed_size));
17111
+ if (new_size == old_size) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
16949
17112
  void* old_buf = e->buf == &initial_buf_sentinel ? NULL : (void*)e->buf;
16950
17113
  char* new_buf = upb_Arena_Realloc(e->arena, old_buf, old_size, new_size);
16951
17114