google-protobuf 4.34.1-java → 4.35.0.rc.1-java

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.
@@ -1962,7 +1962,7 @@ const upb_MiniTable google__protobuf__GeneratedCodeInfo__Annotation_msg_init = {
1962
1962
 
1963
1963
  const upb_MiniTableEnum google__protobuf__Edition_enum_init = {
1964
1964
  64,
1965
- 10,
1965
+ 11,
1966
1966
  {
1967
1967
  0x7,
1968
1968
  0x0,
@@ -1971,6 +1971,7 @@ const upb_MiniTableEnum google__protobuf__Edition_enum_init = {
1971
1971
  0x3e7,
1972
1972
  0x3e8,
1973
1973
  0x3e9,
1974
+ 0x3ea,
1974
1975
  0x270f,
1975
1976
  0x1869d,
1976
1977
  0x1869e,
@@ -1992,7 +1993,7 @@ const upb_MiniTableEnum google__protobuf__FeatureSet__EnforceNamingStyle_enum_in
1992
1993
  64,
1993
1994
  0,
1994
1995
  {
1995
- 0x7,
1996
+ 0xf,
1996
1997
  0x0,
1997
1998
  },
1998
1999
  };
@@ -2338,10 +2339,15 @@ static int log2ceil(uint64_t v) {
2338
2339
  return UPB_MIN(UPB_MAXARRSIZE, ret);
2339
2340
  }
2340
2341
 
2341
- /* A type to represent the lookup key of either a strtable or an inttable. */
2342
+ /* A type to represent the lookup key of either a strtable, inttable or
2343
+ * exttable. */
2342
2344
  typedef union {
2343
2345
  uintptr_t num;
2344
2346
  upb_StringView str;
2347
+ struct {
2348
+ const void* ptr;
2349
+ uint32_t ext_num;
2350
+ } ext;
2345
2351
  } lookupkey_t;
2346
2352
 
2347
2353
  static lookupkey_t strkey2(const char* str, size_t len) {
@@ -2350,16 +2356,24 @@ static lookupkey_t strkey2(const char* str, size_t len) {
2350
2356
 
2351
2357
  static lookupkey_t intkey(uintptr_t key) { return (lookupkey_t){.num = key}; }
2352
2358
 
2353
- typedef uint32_t hashfunc_t(upb_key key);
2354
- typedef bool eqlfunc_t(upb_key k1, lookupkey_t k2);
2359
+ static lookupkey_t extkey(const void* ptr, uint32_t ext_num) {
2360
+ return (lookupkey_t){.ext = {ptr, ext_num}};
2361
+ }
2362
+
2363
+ // Conceptually the hash and equal functions should only take the key, not the
2364
+ // value, but the extension table stores part of its logical key in the value
2365
+ // slot. This is a sign that we have outgrown the original architecture.
2366
+ typedef uint32_t hashfunc_t(upb_key key, upb_value val);
2367
+ typedef bool eqlfunc_t(upb_key k1, upb_value v1, lookupkey_t k2);
2355
2368
 
2356
2369
  /* Base table (shared code) ***************************************************/
2357
2370
 
2358
2371
  static uint32_t upb_inthash(uintptr_t key) {
2372
+ UPB_STATIC_ASSERT(sizeof(uintptr_t) == 4 || sizeof(uintptr_t) == 8,
2373
+ "Pointers don't fit");
2359
2374
  if (sizeof(uintptr_t) == 8) {
2360
2375
  return (uint32_t)key ^ (uint32_t)(key >> 32);
2361
2376
  } else {
2362
- UPB_ASSERT(sizeof(uintptr_t) == 4);
2363
2377
  return (uint32_t)key;
2364
2378
  }
2365
2379
  }
@@ -2420,7 +2434,7 @@ static const upb_tabent* findentry(const upb_table* t, lookupkey_t key,
2420
2434
  e = upb_getentry(t, hash);
2421
2435
  if (upb_tabent_isempty(e)) return NULL;
2422
2436
  while (1) {
2423
- if (eql(e->key, key)) return e;
2437
+ if (eql(e->key, e->val, key)) return e;
2424
2438
  if ((e = e->next) == NULL) return NULL;
2425
2439
  }
2426
2440
  }
@@ -2460,7 +2474,8 @@ static void insert(upb_table* t, lookupkey_t key, upb_key tabkey, upb_value val,
2460
2474
  /* Collision. */
2461
2475
  upb_tabent* new_e = emptyent(t, mainpos_e);
2462
2476
  /* Head of collider's chain. */
2463
- upb_tabent* chain = getentry_mutable(t, hashfunc(mainpos_e->key));
2477
+ upb_tabent* chain =
2478
+ getentry_mutable(t, hashfunc(mainpos_e->key, mainpos_e->val));
2464
2479
  if (chain == mainpos_e) {
2465
2480
  /* Existing ent is in its main position (it has the same hash as us, and
2466
2481
  * is the head of our chain). Insert to new ent and append to this chain.
@@ -2491,7 +2506,7 @@ static bool rm(upb_table* t, lookupkey_t key, upb_value* val, uint32_t hash,
2491
2506
  eqlfunc_t* eql) {
2492
2507
  upb_tabent* chain = getentry_mutable(t, hash);
2493
2508
  if (upb_tabent_isempty(chain)) return false;
2494
- if (eql(chain->key, key)) {
2509
+ if (eql(chain->key, chain->val, key)) {
2495
2510
  /* Element to remove is at the head of its chain. */
2496
2511
  t->count--;
2497
2512
  if (val) *val = chain->val;
@@ -2506,7 +2521,7 @@ static bool rm(upb_table* t, lookupkey_t key, upb_value* val, uint32_t hash,
2506
2521
  } else {
2507
2522
  /* Element to remove is either in a non-head position or not in the
2508
2523
  * table. */
2509
- while (chain->next && !eql(chain->next->key, key)) {
2524
+ while (chain->next && !eql(chain->next->key, chain->next->val, key)) {
2510
2525
  chain = (upb_tabent*)chain->next;
2511
2526
  }
2512
2527
  if (chain->next) {
@@ -2705,11 +2720,13 @@ static uint32_t _upb_Hash_NoSeed(const char* p, size_t n) {
2705
2720
  return _upb_Hash(p, n, _upb_Seed());
2706
2721
  }
2707
2722
 
2708
- static uint32_t strhash(upb_key key) {
2723
+ static uint32_t strhash(upb_key key, upb_value val) {
2724
+ UPB_UNUSED(val);
2709
2725
  return _upb_Hash_NoSeed(key.str->data, key.str->size);
2710
2726
  }
2711
2727
 
2712
- static bool streql(upb_key k1, lookupkey_t k2) {
2728
+ static bool streql(upb_key k1, upb_value v1, lookupkey_t k2) {
2729
+ UPB_UNUSED(v1);
2713
2730
  const upb_SizePrefixString* k1s = k1.str;
2714
2731
  const upb_StringView k2s = k2.str;
2715
2732
  return k1s->size == k2s.size &&
@@ -2873,6 +2890,96 @@ void upb_strtable_setentryvalue(upb_strtable* t, intptr_t iter, upb_value v) {
2873
2890
  t->t.entries[iter].val = v;
2874
2891
  }
2875
2892
 
2893
+ /* upb_exttable ***************************************************************/
2894
+
2895
+ static uint32_t _upb_exttable_hash(const void* ptr, uint32_t ext_num) {
2896
+ uint64_t a = (uintptr_t)ptr;
2897
+ uint64_t b = ext_num;
2898
+ return (uint32_t)WyhashMix(a ^ kWyhashSalt[1], b ^ _upb_Seed());
2899
+ }
2900
+
2901
+ static uint32_t exthash(upb_key key, upb_value val) {
2902
+ const void* ptr = (const void*)key.num;
2903
+ uint32_t ext_num = *(const uint32_t*)upb_value_getconstptr(val);
2904
+ return _upb_exttable_hash(ptr, ext_num);
2905
+ }
2906
+
2907
+ static bool exteql(upb_key k1, upb_value v1, lookupkey_t k2) {
2908
+ if ((const void*)k1.num == k2.ext.ptr) {
2909
+ uint32_t ext_num1 = *(const uint32_t*)upb_value_getconstptr(v1);
2910
+ return ext_num1 == k2.ext.ext_num;
2911
+ }
2912
+ return false;
2913
+ }
2914
+
2915
+ bool upb_exttable_init(upb_exttable* t, size_t expected_size, upb_Arena* a) {
2916
+ int size_lg2 = upb_Log2Ceiling(_upb_entries_needed_for(expected_size));
2917
+ return init(&t->t, size_lg2, a);
2918
+ }
2919
+
2920
+ void upb_exttable_clear(upb_exttable* t) {
2921
+ size_t bytes = upb_table_size(&t->t) * sizeof(upb_tabent);
2922
+ t->t.count = 0;
2923
+ memset((char*)t->t.entries, 0, bytes);
2924
+ }
2925
+
2926
+ bool upb_exttable_resize(upb_exttable* t, size_t size_lg2, upb_Arena* a) {
2927
+ upb_exttable new_table;
2928
+ if (!init(&new_table.t, size_lg2, a)) return false;
2929
+
2930
+ size_t i;
2931
+ for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
2932
+ const upb_tabent* e = &t->t.entries[i];
2933
+ uint32_t hash = exthash(e->key, e->val);
2934
+ uint32_t ext_num = *(const uint32_t*)upb_value_getconstptr(e->val);
2935
+ lookupkey_t lookupkey = extkey((const void*)e->key.num, ext_num);
2936
+ insert(&new_table.t, lookupkey, e->key, e->val, hash, &exthash, &exteql);
2937
+ }
2938
+
2939
+ *t = new_table;
2940
+ return true;
2941
+ }
2942
+
2943
+ bool upb_exttable_insert(upb_exttable* t, const void* k, const uint32_t* v,
2944
+ upb_Arena* a) {
2945
+ UPB_ASSERT(k != NULL);
2946
+ UPB_ASSERT(v != NULL);
2947
+ UPB_ASSERT(*v != 0);
2948
+
2949
+ if (isfull(&t->t)) {
2950
+ if (!upb_exttable_resize(t, _upb_log2_table_size(&t->t) + 1, a)) {
2951
+ return false;
2952
+ }
2953
+ }
2954
+
2955
+ lookupkey_t lookupkey = extkey(k, *v);
2956
+ upb_key key = {.num = (uintptr_t)k};
2957
+ upb_value val = upb_value_constptr(v);
2958
+ uint32_t hash = _upb_exttable_hash(k, *v);
2959
+ insert(&t->t, lookupkey, key, val, hash, &exthash, &exteql);
2960
+ return true;
2961
+ }
2962
+
2963
+ const uint32_t* upb_exttable_lookup(const upb_exttable* t, const void* k,
2964
+ uint32_t ext_number) {
2965
+ uint32_t hash = _upb_exttable_hash(k, ext_number);
2966
+ upb_value val;
2967
+ if (lookup(&t->t, extkey(k, ext_number), &val, hash, &exteql)) {
2968
+ return (const uint32_t*)upb_value_getconstptr(val);
2969
+ }
2970
+ return NULL;
2971
+ }
2972
+
2973
+ const uint32_t* upb_exttable_remove(upb_exttable* t, const void* k,
2974
+ uint32_t ext_number) {
2975
+ uint32_t hash = _upb_exttable_hash(k, ext_number);
2976
+ upb_value val;
2977
+ if (rm(&t->t, extkey(k, ext_number), &val, hash, &exteql)) {
2978
+ return (const uint32_t*)upb_value_getconstptr(val);
2979
+ }
2980
+ return NULL;
2981
+ }
2982
+
2876
2983
  /* upb_inttable ***************************************************************/
2877
2984
 
2878
2985
  /* For inttables we use a hybrid structure where small keys are kept in an
@@ -2887,9 +2994,15 @@ static uint32_t presence_mask_arr_size(uint32_t array_size) {
2887
2994
  return (array_size + 7) / 8; // sizeof(uint8_t) is always 1.
2888
2995
  }
2889
2996
 
2890
- static uint32_t inthash(upb_key key) { return upb_inthash(key.num); }
2997
+ static uint32_t inthash(upb_key key, upb_value val) {
2998
+ UPB_UNUSED(val);
2999
+ return upb_inthash(key.num);
3000
+ }
2891
3001
 
2892
- static bool inteql(upb_key k1, lookupkey_t k2) { return k1.num == k2.num; }
3002
+ static bool inteql(upb_key k1, upb_value v1, lookupkey_t k2) {
3003
+ UPB_UNUSED(v1);
3004
+ return k1.num == k2.num;
3005
+ }
2893
3006
 
2894
3007
  static upb_value* mutable_array(upb_inttable* t) {
2895
3008
  return (upb_value*)t->array;
@@ -2995,8 +3108,8 @@ bool upb_inttable_insert(upb_inttable* t, uintptr_t key, upb_value val,
2995
3108
 
2996
3109
  for (i = begin(&t->t); i < upb_table_size(&t->t); i = next(&t->t, i)) {
2997
3110
  const upb_tabent* e = &t->t.entries[i];
2998
- insert(&new_table, intkey(e->key.num), e->key, e->val, inthash(e->key),
2999
- &inthash, &inteql);
3111
+ insert(&new_table, intkey(e->key.num), e->key, e->val,
3112
+ inthash(e->key, e->val), &inthash, &inteql);
3000
3113
  }
3001
3114
 
3002
3115
  UPB_ASSERT(t->t.count == new_table.count);
@@ -5655,24 +5768,33 @@ static int GetLocaleRadix(char *data, size_t capacity) {
5655
5768
  const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
5656
5769
  UPB_ASSERT(temp[0] == '1');
5657
5770
  UPB_ASSERT(temp[size - 1] == '5');
5658
- UPB_ASSERT(size < capacity);
5771
+ if (size < capacity) {
5772
+ return 0;
5773
+ }
5659
5774
  temp[size - 1] = '\0';
5660
- strcpy(data, temp + 1);
5775
+ strncpy(data, temp + 1, size);
5661
5776
  return size - 2;
5662
5777
  }
5663
5778
 
5664
5779
  // Populates a string identical to *input except that the character pointed to
5665
5780
  // by pos (which should be '.') is replaced with the locale-specific radix.
5666
5781
 
5667
- static void LocalizeRadix(const char *input, const char *pos, char *output) {
5782
+ static void LocalizeRadix(const char *input, const char *pos, char *output,
5783
+ int output_size) {
5668
5784
  const int len1 = pos - input;
5669
5785
 
5670
5786
  char radix[8];
5671
5787
  const int len2 = GetLocaleRadix(radix, sizeof(radix));
5672
5788
 
5789
+ const int n = output_size - len1 - len2 - 1;
5790
+ if (n < 0) {
5791
+ return;
5792
+ }
5793
+
5673
5794
  memcpy(output, input, len1);
5674
5795
  memcpy(output + len1, radix, len2);
5675
- strcpy(output + len1 + len2, input + len1 + 1);
5796
+ strncpy(output + len1 + len2, input + len1 + 1, n);
5797
+ output[output_size - 1] = '\0';
5676
5798
  }
5677
5799
 
5678
5800
  double _upb_NoLocaleStrtod(const char *str, char **endptr) {
@@ -5692,7 +5814,7 @@ double _upb_NoLocaleStrtod(const char *str, char **endptr) {
5692
5814
  // try again.
5693
5815
 
5694
5816
  char localized[80];
5695
- LocalizeRadix(str, temp_endptr, localized);
5817
+ LocalizeRadix(str, temp_endptr, localized, sizeof localized);
5696
5818
  char *localized_endptr;
5697
5819
  result = strtod(localized, &localized_endptr);
5698
5820
  if ((localized_endptr - &localized[0]) > (temp_endptr - str)) {
@@ -5774,6 +5896,7 @@ upb_alloc upb_alloc_global = {&upb_global_allocfunc};
5774
5896
  static UPB_ATOMIC(size_t) g_max_block_size = UPB_DEFAULT_MAX_BLOCK_SIZE;
5775
5897
 
5776
5898
  void upb_Arena_SetMaxBlockSize(size_t max) {
5899
+ UPB_ASSERT(max <= UINT32_MAX);
5777
5900
  upb_Atomic_Store(&g_max_block_size, max, memory_order_relaxed);
5778
5901
  }
5779
5902
 
@@ -5810,8 +5933,14 @@ typedef struct upb_ArenaInternal {
5810
5933
  UPB_ATOMIC(const upb_ArenaRef*) refs;
5811
5934
  #endif
5812
5935
 
5813
- // A growing hint of what the *next* block should be sized
5814
- size_t size_hint;
5936
+ // Size of the last block we allocated in the normal exponential scheme.
5937
+ uint32_t last_block_size;
5938
+
5939
+ // A hint that grows whenever we perform a "one-off" allocation into a a
5940
+ // dedicated block. This helps us determine if these outlier blocks are
5941
+ // actually common enough that we should switch back to the normal exponential
5942
+ // scheme at the larger size.
5943
+ uint32_t size_hint;
5815
5944
 
5816
5945
  // All non atomic members used during allocation must be above this point, and
5817
5946
  // are used by _SwapIn/_SwapOut
@@ -6107,23 +6236,60 @@ bool upb_Arena_HasRefChain(const upb_Arena* from, const upb_Arena* to) {
6107
6236
 
6108
6237
  #endif
6109
6238
 
6110
- // Adds an allocated block to the head of the list.
6111
- static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t offset,
6112
- size_t block_size) {
6239
+ static upb_MemBlock* _upb_Arena_AllocBlockInternal(upb_alloc* alloc,
6240
+ size_t size) {
6241
+ UPB_ASSERT(size >= kUpb_MemblockReserve);
6242
+ upb_SizedPtr alloc_result = upb_SizeReturningMalloc(alloc, size);
6243
+ if (!alloc_result.p) return NULL;
6244
+ upb_MemBlock* block = alloc_result.p;
6245
+ block->size = alloc_result.n;
6246
+ return block;
6247
+ }
6248
+
6249
+ static upb_MemBlock* _upb_Arena_AllocBlock(upb_Arena* a, size_t size) {
6250
+ upb_ArenaInternal* ai = upb_Arena_Internal(a);
6251
+ return _upb_Arena_AllocBlockInternal(_upb_ArenaInternal_BlockAlloc(ai), size);
6252
+ }
6253
+
6254
+ static void _upb_Arena_AddBlock(upb_Arena* a, upb_MemBlock* block) {
6113
6255
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6114
- upb_MemBlock* block = ptr;
6115
6256
 
6116
- block->size = block_size;
6117
- UPB_ASSERT(offset >= kUpb_MemblockReserve);
6118
- char* start = UPB_PTR_AT(block, offset, char);
6119
- upb_MemBlock* head = ai->blocks;
6120
- block->next = head;
6257
+ // Atomic add not required here, as threads won't race allocating blocks, plus
6258
+ // atomic fetch-add is slower than load/add/store on arm devices compiled
6259
+ // targeting pre-v8.1. Relaxed order is safe as nothing depends on order of
6260
+ // size allocated.
6261
+ uintptr_t old_space_allocated =
6262
+ upb_Atomic_Load(&ai->space_allocated, memory_order_relaxed);
6263
+ upb_Atomic_Store(&ai->space_allocated, old_space_allocated + block->size,
6264
+ memory_order_relaxed);
6265
+
6266
+ block->next = ai->blocks;
6121
6267
  ai->blocks = block;
6122
- UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(a));
6268
+ }
6269
+
6270
+ static void _upb_Arena_UseBlockInternal(upb_Arena* a, upb_MemBlock* block,
6271
+ size_t offset) {
6272
+ size_t block_size = block->size;
6273
+ char* start = UPB_PTR_AT(block, kUpb_MemblockReserve + offset, char);
6123
6274
  a->UPB_PRIVATE(ptr) = start;
6124
6275
  a->UPB_PRIVATE(end) = UPB_PTR_AT(block, block_size, char);
6125
6276
  UPB_PRIVATE(upb_Xsan_PoisonRegion)(start, a->UPB_PRIVATE(end) - start);
6126
- UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= block_size - offset);
6277
+ UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(a));
6278
+ UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >=
6279
+ block_size - kUpb_MemblockReserve - offset);
6280
+ }
6281
+
6282
+ static void _upb_Arena_UseBlock(upb_Arena* a, upb_MemBlock* block) {
6283
+ _upb_Arena_UseBlockInternal(a, block, 0);
6284
+ }
6285
+
6286
+ static bool _upb_Arena_WouldReduceFreeSpace(upb_Arena* a, size_t size,
6287
+ size_t block_size) {
6288
+ upb_ArenaInternal* ai = upb_Arena_Internal(a);
6289
+ size_t current_free =
6290
+ ai->blocks ? a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr) : 0;
6291
+ size_t future_free = block_size - kUpb_MemblockReserve - size;
6292
+ return current_free >= future_free;
6127
6293
  }
6128
6294
 
6129
6295
  // Fulfills the allocation request by allocating a new block. Returns NULL on
@@ -6131,84 +6297,60 @@ static void _upb_Arena_AddBlock(upb_Arena* a, void* ptr, size_t offset,
6131
6297
  void* UPB_PRIVATE(_upb_Arena_SlowMalloc)(upb_Arena* a, size_t size) {
6132
6298
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6133
6299
  if (!ai->block_alloc) return NULL;
6134
- size_t last_size = 128;
6135
- size_t current_free = 0;
6136
- upb_MemBlock* last_block = ai->blocks;
6137
- if (last_block) {
6138
- last_size = last_block->size;
6139
- current_free = a->UPB_PRIVATE(end) - a->UPB_PRIVATE(ptr);
6140
- }
6300
+
6301
+ // Whether to satisfy the allocation from a one-off block which is right-sized
6302
+ // for the current allocation. We do this if we suspect that the current
6303
+ // allocation is an outlier that does not represent the typical size of
6304
+ // allocations from this arena, or if we would reduce free space by
6305
+ // using exponential growth.
6306
+ bool one_off = false;
6141
6307
 
6142
6308
  // Relaxed order is safe here as we don't need any ordering with the setter.
6143
6309
  size_t max_block_size =
6144
6310
  upb_Atomic_Load(&g_max_block_size, memory_order_relaxed);
6145
-
6146
- // Don't naturally grow beyond the max block size.
6147
- size_t target_size = UPB_MIN(last_size * 2, max_block_size);
6148
- size_t future_free = UPB_MAX(size, target_size - kUpb_MemblockReserve) - size;
6149
- // We want to preserve exponential growth in block size without wasting too
6150
- // much unused space at the end of blocks. Once the head of our blocks list is
6151
- // large enough to always trigger a max-sized block for all subsequent
6152
- // allocations, allocate blocks that would net reduce free space behind it.
6153
- if (last_block && current_free > future_free &&
6154
- target_size < max_block_size) {
6155
- last_size = ai->size_hint;
6156
- // Recalculate sizes with possibly larger last_size
6157
- target_size = UPB_MIN(last_size * 2, max_block_size);
6158
- future_free = UPB_MAX(size, target_size - kUpb_MemblockReserve) - size;
6159
- }
6160
- bool insert_after_head = false;
6161
- // Only insert after head if an allocated block is present; we don't want to
6162
- // continue allocating out of the initial block because we'll have no way of
6163
- // restoring the size of our allocated block if we add another.
6164
- if (last_block && current_free >= future_free) {
6165
- // If we're still going to net reduce free space with this new block, then
6166
- // only allocate the precise size requested and keep the current last block
6167
- // as the active block for future allocations.
6168
- insert_after_head = true;
6169
- target_size = size + kUpb_MemblockReserve;
6170
- // Add something to our previous size each time, so that eventually we
6171
- // will reach the max block size. Allocations larger than the max block size
6172
- // will always get their own backing allocation, so don't include them.
6173
- if (target_size <= max_block_size) {
6174
- ai->size_hint = UPB_MIN(ai->size_hint + (size >> 1), max_block_size >> 1);
6311
+ size_t block_size = UPB_MIN(ai->last_block_size * 2, max_block_size);
6312
+
6313
+ if (size + kUpb_MemblockReserve > block_size) {
6314
+ // A regular doubling would not yield a large enough block. Does size_hint
6315
+ // indicate that we have consistently needed large blocks?
6316
+ block_size = UPB_MIN(ai->size_hint * 2, max_block_size);
6317
+ if (size + kUpb_MemblockReserve > block_size) {
6318
+ // Even size_hint is not large enough, we will have to do a one-off.
6319
+ one_off = true;
6175
6320
  }
6176
6321
  }
6177
- // We may need to exceed the max block size if the user requested a large
6178
- // allocation.
6179
- size_t block_size = UPB_MAX(kUpb_MemblockReserve + size, target_size);
6180
- upb_alloc* block_alloc = _upb_ArenaInternal_BlockAlloc(ai);
6181
- upb_SizedPtr alloc_result = upb_SizeReturningMalloc(block_alloc, block_size);
6182
6322
 
6183
- if (!alloc_result.p) return NULL;
6323
+ // If switching to a block of this size would *reduce* available free space,
6324
+ // we might as well make a one-off block instead.
6325
+ one_off = one_off || _upb_Arena_WouldReduceFreeSpace(a, size, block_size);
6184
6326
 
6185
- upb_MemBlock* block = alloc_result.p;
6186
- size_t actual_block_size = alloc_result.n;
6327
+ if (one_off) {
6328
+ // Note: this may exceed the max block size, but that's okay.
6329
+ block_size = size + kUpb_MemblockReserve;
6330
+ }
6187
6331
 
6188
- // Atomic add not required here, as threads won't race allocating blocks, plus
6189
- // atomic fetch-add is slower than load/add/store on arm devices compiled
6190
- // targetting pre-v8.1. Relaxed order is safe as nothing depends on order of
6191
- // size allocated.
6332
+ upb_MemBlock* block = _upb_Arena_AllocBlock(a, block_size);
6333
+ if (!block) return NULL;
6192
6334
 
6193
- uintptr_t old_space_allocated =
6194
- upb_Atomic_Load(&ai->space_allocated, memory_order_relaxed);
6195
- upb_Atomic_Store(&ai->space_allocated,
6196
- old_space_allocated + actual_block_size,
6197
- memory_order_relaxed);
6198
- if (UPB_UNLIKELY(insert_after_head)) {
6199
- upb_ArenaInternal* ai = upb_Arena_Internal(a);
6200
- block->size = actual_block_size;
6201
- upb_MemBlock* head = ai->blocks;
6202
- block->next = head->next;
6203
- head->next = block;
6335
+ _upb_Arena_AddBlock(a, block);
6204
6336
 
6337
+ // Recheck size, in case the allocator gave us a much larger block than we
6338
+ // requested and we want to make it the new allocating region.
6339
+ if (UPB_UNLIKELY(one_off) &&
6340
+ _upb_Arena_WouldReduceFreeSpace(a, size, block->size)) {
6341
+ // Increase size_hint, so that a series of one-off allocations will
6342
+ // eventually convince us to switch to exponential growth at the larger
6343
+ // size.
6344
+ ai->size_hint = UPB_MIN(ai->size_hint + (size >> 1), max_block_size >> 1);
6205
6345
  char* allocated = UPB_PTR_AT(block, kUpb_MemblockReserve, char);
6206
- UPB_PRIVATE(upb_Xsan_PoisonRegion)(allocated + size,
6207
- UPB_PRIVATE(kUpb_Asan_GuardSize));
6346
+ char* poison_start = allocated + size - UPB_PRIVATE(kUpb_Asan_GuardSize);
6347
+ UPB_PRIVATE(upb_Xsan_PoisonRegion)(
6348
+ poison_start, UPB_PTR_AT(block, block->size, char) - poison_start);
6208
6349
  return allocated;
6209
6350
  } else {
6210
- ai->size_hint = actual_block_size;
6211
- _upb_Arena_AddBlock(a, block, kUpb_MemblockReserve, actual_block_size);
6351
+ ai->last_block_size = UPB_MIN(block->size, UINT32_MAX);
6352
+ ai->size_hint = ai->last_block_size;
6353
+ _upb_Arena_UseBlock(a, block);
6212
6354
  UPB_ASSERT(UPB_PRIVATE(_upb_ArenaHas)(a) >= size);
6213
6355
  return upb_Arena_Malloc(a, size - UPB_PRIVATE(kUpb_Asan_GuardSize));
6214
6356
  }
@@ -6219,27 +6361,26 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6219
6361
  UPB_ALIGN_MALLOC(kUpb_MemblockReserve + sizeof(upb_ArenaState));
6220
6362
  upb_ArenaState* a;
6221
6363
 
6222
- // We need to malloc the initial block.
6364
+ if (!alloc) return NULL;
6223
6365
 
6366
+ // We need to malloc the initial block.
6224
6367
  size_t block_size =
6225
6368
  first_block_overhead + UPB_MAX(256, UPB_ALIGN_MALLOC(first_size) +
6226
6369
  UPB_PRIVATE(kUpb_Asan_GuardSize));
6227
- upb_SizedPtr alloc_result;
6228
- if (!alloc ||
6229
- !(alloc_result = upb_SizeReturningMalloc(alloc, block_size)).p) {
6230
- return NULL;
6231
- }
6232
- char* mem = alloc_result.p;
6233
- size_t actual_block_size = alloc_result.n;
6370
+ upb_MemBlock* block = _upb_Arena_AllocBlockInternal(alloc, block_size);
6371
+ if (!block) return NULL;
6234
6372
 
6235
- a = UPB_PTR_AT(mem, kUpb_MemblockReserve, upb_ArenaState);
6373
+ // Initialize the arena state in the first block. We "borrow" the memory from
6374
+ // the block, because we can't yet call upb_Arena_Malloc.
6375
+ a = UPB_PTR_AT(block, kUpb_MemblockReserve, upb_ArenaState);
6236
6376
  a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 0);
6237
- a->body.size_hint = actual_block_size;
6377
+ a->body.last_block_size = UPB_MIN(block->size, UINT32_MAX);
6378
+ a->body.size_hint = UPB_MIN(block->size, UINT32_MAX);
6238
6379
  upb_Atomic_Init(&a->body.parent_or_count, _upb_Arena_TaggedFromRefcount(1));
6239
6380
  upb_Atomic_Init(&a->body.next, NULL);
6240
6381
  upb_Atomic_Init(&a->body.previous_or_tail,
6241
6382
  _upb_Arena_TaggedFromTail(&a->body));
6242
- upb_Atomic_Init(&a->body.space_allocated, actual_block_size);
6383
+ upb_Atomic_Init(&a->body.space_allocated, 0);
6243
6384
  a->body.blocks = NULL;
6244
6385
  #ifndef NDEBUG
6245
6386
  a->body.refs = NULL;
@@ -6247,15 +6388,16 @@ static upb_Arena* _upb_Arena_InitSlow(upb_alloc* alloc, size_t first_size) {
6247
6388
  a->body.upb_alloc_cleanup = NULL;
6248
6389
  UPB_PRIVATE(upb_Xsan_Init)(UPB_XSAN(&a->body));
6249
6390
 
6250
- _upb_Arena_AddBlock(&a->head, mem, first_block_overhead, actual_block_size);
6391
+ _upb_Arena_AddBlock(&a->head, block);
6392
+ _upb_Arena_UseBlockInternal(&a->head, block,
6393
+ UPB_ALIGN_MALLOC(sizeof(upb_ArenaState)));
6251
6394
 
6252
6395
  return &a->head;
6253
6396
  }
6254
6397
 
6255
6398
  upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
6256
- UPB_STATIC_ASSERT(
6257
- sizeof(void*) * UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState),
6258
- "Need to update UPB_ARENA_SIZE_HACK");
6399
+ UPB_STATIC_ASSERT(UPB_ARENA_SIZE_HACK >= sizeof(upb_ArenaState),
6400
+ "Need to update UPB_ARENA_SIZE_HACK");
6259
6401
  upb_ArenaState* a;
6260
6402
 
6261
6403
  if (mem) {
@@ -6285,6 +6427,7 @@ upb_Arena* upb_Arena_Init(void* mem, size_t n, upb_alloc* alloc) {
6285
6427
  a->body.refs = NULL;
6286
6428
  #endif
6287
6429
  a->body.size_hint = 128;
6430
+ a->body.last_block_size = 128;
6288
6431
  a->body.upb_alloc_cleanup = NULL;
6289
6432
  a->body.block_alloc = _upb_Arena_MakeBlockAlloc(alloc, 1);
6290
6433
  a->head.UPB_PRIVATE(ptr) = (void*)UPB_ALIGN_MALLOC((uintptr_t)(a + 1));
@@ -6731,14 +6874,11 @@ void UPB_PRIVATE(_upb_Arena_SwapOut)(upb_Arena* des, const upb_Arena* src) {
6731
6874
  bool _upb_Arena_WasLastAlloc(struct upb_Arena* a, void* ptr, size_t oldsize) {
6732
6875
  upb_ArenaInternal* ai = upb_Arena_Internal(a);
6733
6876
  upb_MemBlock* block = ai->blocks;
6734
- if (block == NULL) return false;
6735
6877
  // Skip any arena refs.
6736
6878
  while (block != NULL && block->size == 0) {
6737
6879
  block = block->next;
6738
6880
  }
6739
6881
  if (block == NULL) return false;
6740
- block = block->next;
6741
- if (block == NULL) return false;
6742
6882
  char* start = UPB_PTR_AT(block, kUpb_MemblockReserve, char);
6743
6883
  return UPB_PRIVATE(upb_Xsan_PtrEq)(ptr, start) &&
6744
6884
  UPB_PRIVATE(_upb_Arena_AllocSpan)(oldsize) ==
@@ -6820,6 +6960,46 @@ bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
6820
6960
  return true;
6821
6961
  }
6822
6962
 
6963
+ bool upb_Array_Copy(upb_Array* dst, const upb_Array* src, upb_Arena* arena) {
6964
+ UPB_ASSERT(dst);
6965
+ UPB_ASSERT(src);
6966
+ UPB_ASSERT(!upb_Array_IsFrozen(dst));
6967
+ if (dst == src) return true;
6968
+ size_t len = upb_Array_Size(src);
6969
+ if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(dst, len, arena)) {
6970
+ return false;
6971
+ }
6972
+ if (len == 0) return true;
6973
+ const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(dst);
6974
+ const int src_lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(src);
6975
+ UPB_ASSERT(lg2 == src_lg2);
6976
+ char* dst_data = upb_Array_MutableDataPtr(dst);
6977
+ const char* src_data = upb_Array_DataPtr(src);
6978
+ memcpy(dst_data, src_data, len << lg2);
6979
+ return true;
6980
+ }
6981
+
6982
+ bool upb_Array_AppendAll(upb_Array* dst, const upb_Array* src,
6983
+ upb_Arena* arena) {
6984
+ UPB_ASSERT(!upb_Array_IsFrozen(dst));
6985
+ UPB_ASSERT(src);
6986
+ size_t src_len = upb_Array_Size(src);
6987
+ if (src_len == 0) return true;
6988
+ size_t dst_len = upb_Array_Size(dst);
6989
+ size_t len = dst_len + src_len;
6990
+ if (UPB_UNLIKELY(len < dst_len)) return false;
6991
+ if (!UPB_PRIVATE(_upb_Array_ResizeUninitialized)(dst, len, arena)) {
6992
+ return false;
6993
+ }
6994
+ const int lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(dst);
6995
+ const int src_lg2 = UPB_PRIVATE(_upb_Array_ElemSizeLg2)(src);
6996
+ UPB_ASSERT(lg2 == src_lg2);
6997
+ char* dst_data = upb_Array_MutableDataPtr(dst);
6998
+ const char* src_data = upb_Array_DataPtr(src);
6999
+ memcpy(dst_data + (dst_len << lg2), src_data, src_len << lg2);
7000
+ return true;
7001
+ }
7002
+
6823
7003
  void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
6824
7004
  size_t count) {
6825
7005
  UPB_ASSERT(!upb_Array_IsFrozen(arr));
@@ -6880,9 +7060,17 @@ bool UPB_PRIVATE(_upb_Array_Realloc)(upb_Array* array, size_t min_capacity,
6880
7060
  void* ptr = upb_Array_MutableDataPtr(array);
6881
7061
 
6882
7062
  // Log2 ceiling of size.
6883
- while (new_capacity < min_capacity) new_capacity *= 2;
7063
+ while (new_capacity < min_capacity) {
7064
+ if (upb_ShlOverflow(&new_capacity, 1)) {
7065
+ new_capacity = SIZE_MAX;
7066
+ break;
7067
+ }
7068
+ }
6884
7069
 
6885
- const size_t new_bytes = new_capacity << lg2;
7070
+ size_t new_bytes = new_capacity;
7071
+ if (upb_ShlOverflow(&new_bytes, lg2)) {
7072
+ return false;
7073
+ }
6886
7074
  ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes);
6887
7075
  if (!ptr) return false;
6888
7076
 
@@ -7340,6 +7528,7 @@ UPB_NOINLINE bool UPB_PRIVATE(_upb_Message_AddUnknownSlowPath)(upb_Message* msg,
7340
7528
  if (!view) return false;
7341
7529
  view->data = data;
7342
7530
  } else {
7531
+ if (SIZE_MAX - sizeof(upb_StringView) < len) return false;
7343
7532
  view = upb_Arena_Malloc(arena, sizeof(upb_StringView) + len);
7344
7533
  if (!view) return false;
7345
7534
  char* copy = UPB_PTR_AT(view, sizeof(upb_StringView), char);
@@ -8116,7 +8305,7 @@ static bool upb_Clone_MessageValue(void* value, upb_CType value_type,
8116
8305
  case kUpb_CType_String:
8117
8306
  case kUpb_CType_Bytes: {
8118
8307
  upb_StringView source = *(upb_StringView*)value;
8119
- int size = source.size;
8308
+ size_t size = source.size;
8120
8309
  void* cloned_data = upb_Arena_Malloc(arena, size);
8121
8310
  if (cloned_data == NULL) {
8122
8311
  return false;
@@ -8496,8 +8685,15 @@ bool UPB_PRIVATE(_upb_Message_ReserveSlot)(struct upb_Message* msg,
8496
8685
  in->capacity = capacity;
8497
8686
  UPB_PRIVATE(_upb_Message_SetInternal)(msg, in);
8498
8687
  } else if (in->capacity == in->size) {
8688
+ if (in->size == UINT32_MAX) return false;
8499
8689
  // Internal data is too small, reallocate.
8500
- uint32_t new_capacity = upb_RoundUpToPowerOfTwo(in->size + 1);
8690
+ size_t needed_pow2 = upb_RoundUpToPowerOfTwo(in->size + 1);
8691
+ if (needed_pow2 > UINT32_MAX) return false;
8692
+ uint32_t new_capacity = needed_pow2;
8693
+ if (UPB_SIZEOF_FLEX_WOULD_OVERFLOW(upb_Message_Internal, aux_data,
8694
+ new_capacity)) {
8695
+ return false;
8696
+ }
8501
8697
  in = upb_Arena_Realloc(a, in, _upb_Message_SizeOfInternal(in->capacity),
8502
8698
  _upb_Message_SizeOfInternal(new_capacity));
8503
8699
  if (!in) return false;
@@ -8702,7 +8898,6 @@ upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
8702
8898
 
8703
8899
 
8704
8900
  #include <inttypes.h>
8705
- #include <stdalign.h>
8706
8901
  #include <stddef.h>
8707
8902
  #include <stdint.h>
8708
8903
  #include <stdlib.h>
@@ -10109,28 +10304,25 @@ char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) {
10109
10304
 
10110
10305
  // Must be last.
10111
10306
 
10112
- #define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
10113
-
10114
10307
  struct upb_ExtensionRegistry {
10308
+ upb_exttable exts;
10115
10309
  upb_Arena* arena;
10116
- upb_strtable exts; // Key is upb_MiniTable* concatenated with fieldnum.
10117
10310
  };
10118
10311
 
10119
- static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
10120
- memcpy(buf, &l, sizeof(l));
10121
- memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
10122
- }
10123
-
10124
10312
  upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
10125
10313
  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
10126
10314
  if (!r) return NULL;
10127
10315
  r->arena = arena;
10128
- if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
10316
+ if (!upb_exttable_init(&r->exts, 8, arena)) return NULL;
10129
10317
  return r;
10130
10318
  }
10131
10319
 
10132
10320
  UPB_API upb_ExtensionRegistryStatus upb_ExtensionRegistry_Add(
10133
10321
  upb_ExtensionRegistry* r, const upb_MiniTableExtension* e) {
10322
+ UPB_STATIC_ASSERT(
10323
+ offsetof(upb_MiniTableExtension,
10324
+ UPB_PRIVATE(field).UPB_PRIVATE(number)) == 0,
10325
+ "Extension must be first-member-of-struct convertable with uint32_t");
10134
10326
  uint32_t fieldnum = upb_MiniTableExtension_Number(e);
10135
10327
  const upb_MiniTable* extendee = upb_MiniTableExtension_Extendee(e);
10136
10328
 
@@ -10140,15 +10332,11 @@ UPB_API upb_ExtensionRegistryStatus upb_ExtensionRegistry_Add(
10140
10332
  return kUpb_ExtensionRegistryStatus_InvalidExtension;
10141
10333
  }
10142
10334
 
10143
- char buf[EXTREG_KEY_SIZE];
10144
- extreg_key(buf, extendee, fieldnum);
10145
-
10146
- if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, NULL)) {
10335
+ if (upb_exttable_lookup(&r->exts, extendee, fieldnum) != NULL) {
10147
10336
  return kUpb_ExtensionRegistryStatus_DuplicateEntry;
10148
10337
  }
10149
10338
 
10150
- if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
10151
- upb_value_constptr(e), r->arena)) {
10339
+ if (!upb_exttable_insert(&r->exts, extendee, (const uint32_t*)e, r->arena)) {
10152
10340
  return kUpb_ExtensionRegistryStatus_OutOfMemory;
10153
10341
  }
10154
10342
  return kUpb_ExtensionRegistryStatus_Ok;
@@ -10169,10 +10357,8 @@ failure:
10169
10357
  // Back out the entries previously added.
10170
10358
  for (end = e, e = start; e < end; e++) {
10171
10359
  const upb_MiniTableExtension* ext = *e;
10172
- char buf[EXTREG_KEY_SIZE];
10173
- extreg_key(buf, ext->UPB_PRIVATE(extendee),
10174
- upb_MiniTableExtension_Number(ext));
10175
- upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
10360
+ upb_exttable_remove(&r->exts, upb_MiniTableExtension_Extendee(ext),
10361
+ upb_MiniTableExtension_Number(ext));
10176
10362
  }
10177
10363
  UPB_ASSERT(status != kUpb_ExtensionRegistryStatus_Ok);
10178
10364
  return status;
@@ -10180,14 +10366,8 @@ failure:
10180
10366
 
10181
10367
  const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
10182
10368
  const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) {
10183
- char buf[EXTREG_KEY_SIZE];
10184
- upb_value v;
10185
- extreg_key(buf, t, num);
10186
- if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
10187
- return upb_value_getconstptr(v);
10188
- } else {
10189
- return NULL;
10190
- }
10369
+ const uint32_t* v = upb_exttable_lookup(&r->exts, t, num);
10370
+ return (const upb_MiniTableExtension*)v;
10191
10371
  }
10192
10372
 
10193
10373
 
@@ -10440,6 +10620,7 @@ struct upb_DefPool {
10440
10620
  size_t scratch_size;
10441
10621
  size_t bytes_loaded;
10442
10622
  bool disable_closed_enum_checking;
10623
+ bool disable_implicit_field_presence;
10443
10624
  };
10444
10625
 
10445
10626
  void upb_DefPool_Free(upb_DefPool* s) {
@@ -10458,6 +10639,7 @@ upb_DefPool* upb_DefPool_New(void) {
10458
10639
  s->arena = upb_Arena_New();
10459
10640
  s->bytes_loaded = 0;
10460
10641
  s->disable_closed_enum_checking = false;
10642
+ s->disable_implicit_field_presence = false;
10461
10643
 
10462
10644
  s->scratch_size = 240;
10463
10645
  s->scratch_data = upb_gmalloc(s->scratch_size);
@@ -10499,6 +10681,15 @@ bool upb_DefPool_ClosedEnumCheckingDisabled(const upb_DefPool* s) {
10499
10681
  return s->disable_closed_enum_checking;
10500
10682
  }
10501
10683
 
10684
+ void upb_DefPool_DisableImplicitFieldPresence(upb_DefPool* s) {
10685
+ UPB_ASSERT(upb_strtable_count(&s->files) == 0);
10686
+ s->disable_implicit_field_presence = true;
10687
+ }
10688
+
10689
+ bool upb_DefPool_ImplicitFieldPresenceDisabled(const upb_DefPool* s) {
10690
+ return s->disable_implicit_field_presence;
10691
+ }
10692
+
10502
10693
  const google_protobuf_FeatureSetDefaults* upb_DefPool_FeatureSetDefaults(
10503
10694
  const upb_DefPool* s) {
10504
10695
  return s->feature_set_defaults;
@@ -10608,7 +10799,7 @@ void _upb_DefPool_SetPlatform(upb_DefPool* s, upb_MiniTablePlatform platform) {
10608
10799
 
10609
10800
  const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
10610
10801
  const char* sym) {
10611
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_MSG);
10802
+ return upb_DefPool_FindMessageByNameWithSize(s, sym, strlen(sym));
10612
10803
  }
10613
10804
 
10614
10805
  const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
@@ -10618,12 +10809,23 @@ const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
10618
10809
 
10619
10810
  const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
10620
10811
  const char* sym) {
10621
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUM);
10812
+ return upb_DefPool_FindEnumByNameWithSize(s, sym, strlen(sym));
10813
+ }
10814
+
10815
+ const upb_EnumDef* upb_DefPool_FindEnumByNameWithSize(const upb_DefPool* s,
10816
+ const char* sym,
10817
+ size_t len) {
10818
+ return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_ENUM);
10819
+ }
10820
+
10821
+ const upb_EnumValueDef* upb_DefPool_FindEnumValueByName(const upb_DefPool* s,
10822
+ const char* sym) {
10823
+ return upb_DefPool_FindEnumValueByNameWithSize(s, sym, strlen(sym));
10622
10824
  }
10623
10825
 
10624
- const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
10625
- const char* sym) {
10626
- return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUMVAL);
10826
+ const upb_EnumValueDef* upb_DefPool_FindEnumValueByNameWithSize(
10827
+ const upb_DefPool* s, const char* sym, size_t len) {
10828
+ return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_ENUMVAL);
10627
10829
  }
10628
10830
 
10629
10831
  const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
@@ -12240,7 +12442,7 @@ static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix,
12240
12442
 
12241
12443
  f->has_presence =
12242
12444
  (!upb_FieldDef_IsRepeated(f)) &&
12243
- (f->is_extension ||
12445
+ (f->is_extension || _upb_FileDef_ImplicitFieldPresenceDisabled(f->file) ||
12244
12446
  (f->type_ == kUpb_FieldType_Message ||
12245
12447
  f->type_ == kUpb_FieldType_Group || upb_FieldDef_ContainingOneof(f) ||
12246
12448
  google_protobuf_FeatureSet_field_presence(f->resolved_features) !=
@@ -12644,6 +12846,10 @@ bool _upb_FileDef_ClosedEnumCheckingDisabled(const upb_FileDef* f) {
12644
12846
  return upb_DefPool_ClosedEnumCheckingDisabled(f->symtab);
12645
12847
  }
12646
12848
 
12849
+ bool _upb_FileDef_ImplicitFieldPresenceDisabled(const upb_FileDef* f) {
12850
+ return upb_DefPool_ImplicitFieldPresenceDisabled(f->symtab);
12851
+ }
12852
+
12647
12853
  int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
12648
12854
  return f->top_lvl_enum_count;
12649
12855
  }
@@ -14532,6 +14738,7 @@ static void create_method(upb_DefBuilder* ctx,
14532
14738
  m->output_type = _upb_DefBuilder_Resolve(
14533
14739
  ctx, m->full_name, m->full_name,
14534
14740
  google_protobuf_MethodDescriptorProto_output_type(method_proto), UPB_DEFTYPE_MSG);
14741
+ _upb_ServiceDef_InsertMethod(ctx, s, m);
14535
14742
  }
14536
14743
 
14537
14744
  // Allocate and initialize an array of |n| method defs belonging to |s|.
@@ -14763,6 +14970,7 @@ struct upb_ServiceDef {
14763
14970
  upb_MethodDef* methods;
14764
14971
  int method_count;
14765
14972
  int index;
14973
+ upb_strtable ntom;
14766
14974
  };
14767
14975
 
14768
14976
  upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int index) {
@@ -14807,13 +15015,18 @@ const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
14807
15015
 
14808
15016
  const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
14809
15017
  const char* name) {
14810
- for (int i = 0; i < s->method_count; i++) {
14811
- const upb_MethodDef* m = _upb_MethodDef_At(s->methods, i);
14812
- if (strcmp(name, upb_MethodDef_Name(m)) == 0) {
14813
- return m;
14814
- }
15018
+ return upb_ServiceDef_FindMethodByNameWithSize(s, name, strlen(name));
15019
+ }
15020
+
15021
+ const upb_MethodDef* upb_ServiceDef_FindMethodByNameWithSize(
15022
+ const upb_ServiceDef* s, const char* name, size_t len) {
15023
+ upb_value val;
15024
+
15025
+ if (!upb_strtable_lookup2(&s->ntom, name, len, &val)) {
15026
+ return NULL;
14815
15027
  }
14816
- return NULL;
15028
+
15029
+ return _upb_DefType_Unpack(val, UPB_DEFTYPE_METHOD);
14817
15030
  }
14818
15031
 
14819
15032
  static void create_service(upb_DefBuilder* ctx,
@@ -14838,6 +15051,8 @@ static void create_service(upb_DefBuilder* ctx,
14838
15051
  const google_protobuf_MethodDescriptorProto* const* methods =
14839
15052
  google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
14840
15053
  s->method_count = n;
15054
+ bool ok = upb_strtable_init(&s->ntom, n, ctx->arena);
15055
+ if (!ok) _upb_DefBuilder_OomErr(ctx);
14841
15056
  s->methods = _upb_MethodDefs_New(ctx, n, methods, s->resolved_features, s);
14842
15057
  }
14843
15058
 
@@ -14855,6 +15070,20 @@ upb_ServiceDef* _upb_ServiceDefs_New(
14855
15070
  return s;
14856
15071
  }
14857
15072
 
15073
+ void _upb_ServiceDef_InsertMethod(upb_DefBuilder* ctx, upb_ServiceDef* s,
15074
+ const upb_MethodDef* m) {
15075
+ const char* shortname = upb_MethodDef_Name(m);
15076
+ const size_t shortnamelen = strlen(shortname);
15077
+ upb_value existing_v;
15078
+ if (upb_strtable_lookup(&s->ntom, shortname, &existing_v)) {
15079
+ _upb_DefBuilder_Errf(ctx, "duplicate method name (%s)", shortname);
15080
+ }
15081
+ const upb_value method_v = _upb_DefType_Pack(m, UPB_DEFTYPE_METHOD);
15082
+ bool ok = upb_strtable_insert(&s->ntom, shortname, shortnamelen, method_v,
15083
+ ctx->arena);
15084
+ if (!ok) _upb_DefBuilder_OomErr(ctx);
15085
+ }
15086
+
14858
15087
 
14859
15088
  #include <inttypes.h>
14860
15089
  #include <math.h>
@@ -16462,6 +16691,7 @@ const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
16462
16691
  *op = kUpb_DecodeOp_UnknownField;
16463
16692
  return ptr;
16464
16693
  }
16694
+ _upb_Decoder_MungeInt32(val);
16465
16695
  } else {
16466
16696
  _upb_Decoder_Munge(field, val);
16467
16697
  }
@@ -16504,7 +16734,6 @@ const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
16504
16734
  UPB_FORCEINLINE
16505
16735
  const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr,
16506
16736
  upb_Message* msg,
16507
- const upb_MiniTable* layout,
16508
16737
  const upb_MiniTableField* field,
16509
16738
  int op, wireval* val) {
16510
16739
  uint8_t mode = field->UPB_PRIVATE(mode);
@@ -16533,67 +16762,13 @@ const char* _upb_Decoder_DecodeKnownField(upb_Decoder* d, const char* ptr,
16533
16762
  }
16534
16763
  }
16535
16764
 
16536
- static const char* _upb_Decoder_FindFieldStart(upb_Decoder* d, const char* ptr,
16537
- uint32_t field_number,
16538
- uint32_t wire_type) {
16539
- // Since unknown fields are the uncommon case, we do a little extra work here
16540
- // to walk backwards through the buffer to find the field start. This frees
16541
- // up a register in the fast paths (when the field is known), which leads to
16542
- // significant speedups in benchmarks. Note that ptr may point into the slop
16543
- // space, beyond the normal end of the input buffer.
16544
- const char* start = ptr;
16545
-
16546
- switch (wire_type) {
16547
- case kUpb_WireType_Varint:
16548
- case kUpb_WireType_Delimited:
16549
- // Skip the last byte
16550
- start--;
16551
- // Skip bytes until we encounter the final byte of the tag varint.
16552
- while (start[-1] & 0x80) start--;
16553
- break;
16554
- case kUpb_WireType_32Bit:
16555
- start -= 4;
16556
- break;
16557
- case kUpb_WireType_64Bit:
16558
- start -= 8;
16559
- break;
16560
- default:
16561
- break;
16562
- }
16563
- assert(start == d->debug_valstart);
16564
-
16565
- {
16566
- // The varint parser does not enforce that integers are encoded with their
16567
- // minimum size; for example the value 1 could be encoded with three
16568
- // bytes: 0x81, 0x80, 0x00. These unnecessary trailing zeroes mean that we
16569
- // cannot skip backwards by the minimum encoded size of the tag; and
16570
- // unlike the loop for delimited or varint fields, we can't stop at a
16571
- // sentinel value because anything can precede a tag. Instead, parse back
16572
- // one byte at a time until we read the same tag value that was parsed
16573
- // earlier.
16574
- uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
16575
- uint32_t seen = 0;
16576
- do {
16577
- start--;
16578
- seen <<= 7;
16579
- seen |= *start & 0x7f;
16580
- } while (seen != tag);
16581
- }
16582
- assert(start == d->debug_tagstart);
16583
-
16584
- return start;
16585
- }
16586
-
16587
16765
  static const char* _upb_Decoder_DecodeUnknownField(
16588
16766
  upb_Decoder* d, const char* ptr, upb_Message* msg, uint32_t field_number,
16589
- uint32_t wire_type, wireval val) {
16767
+ uint32_t wire_type, wireval val, const char* start) {
16590
16768
  if (field_number == 0) {
16591
16769
  upb_ErrorHandler_ThrowError(&d->err, kUpb_DecodeStatus_Malformed);
16592
16770
  }
16593
16771
 
16594
- const char* start =
16595
- _upb_Decoder_FindFieldStart(d, ptr, field_number, wire_type);
16596
-
16597
16772
  upb_EpsCopyInputStream_StartCapture(&d->input, start);
16598
16773
 
16599
16774
  if (wire_type == kUpb_WireType_Delimited) {
@@ -16632,10 +16807,6 @@ UPB_FORCEINLINE
16632
16807
  const char* _upb_Decoder_DecodeFieldTag(upb_Decoder* d, const char* ptr,
16633
16808
  uint32_t* field_number,
16634
16809
  uint32_t* wire_type) {
16635
- #ifndef NDEBUG
16636
- d->debug_tagstart = ptr;
16637
- #endif
16638
-
16639
16810
  uint32_t tag;
16640
16811
  UPB_ASSERT(ptr < d->input.limit_ptr);
16641
16812
  ptr = upb_WireReader_ReadTag(ptr, &tag, EPS(d));
@@ -16645,15 +16816,9 @@ const char* _upb_Decoder_DecodeFieldTag(upb_Decoder* d, const char* ptr,
16645
16816
  }
16646
16817
 
16647
16818
  UPB_FORCEINLINE
16648
- const char* _upb_Decoder_DecodeFieldData(upb_Decoder* d, const char* ptr,
16649
- upb_Message* msg,
16650
- const upb_MiniTable* mt,
16651
- uint32_t field_number,
16652
- uint32_t wire_type) {
16653
- #ifndef NDEBUG
16654
- d->debug_valstart = ptr;
16655
- #endif
16656
-
16819
+ const char* _upb_Decoder_DecodeFieldData(
16820
+ upb_Decoder* d, const char* ptr, upb_Message* msg, const upb_MiniTable* mt,
16821
+ uint32_t field_number, uint32_t wire_type, const char* start) {
16657
16822
  int op;
16658
16823
  wireval val;
16659
16824
 
@@ -16662,12 +16827,12 @@ const char* _upb_Decoder_DecodeFieldData(upb_Decoder* d, const char* ptr,
16662
16827
  ptr = _upb_Decoder_DecodeWireValue(d, ptr, mt, field, wire_type, &val, &op);
16663
16828
 
16664
16829
  if (op >= 0) {
16665
- return _upb_Decoder_DecodeKnownField(d, ptr, msg, mt, field, op, &val);
16830
+ return _upb_Decoder_DecodeKnownField(d, ptr, msg, field, op, &val);
16666
16831
  } else {
16667
16832
  switch (op) {
16668
16833
  case kUpb_DecodeOp_UnknownField:
16669
16834
  return _upb_Decoder_DecodeUnknownField(d, ptr, msg, field_number,
16670
- wire_type, val);
16835
+ wire_type, val, start);
16671
16836
  case kUpb_DecodeOp_MessageSetItem:
16672
16837
  return upb_Decoder_DecodeMessageSetItem(d, ptr, msg, mt);
16673
16838
  default:
@@ -16688,6 +16853,7 @@ const char* _upb_Decoder_DecodeFieldNoFast(upb_Decoder* d, const char* ptr,
16688
16853
  uint32_t field_number;
16689
16854
  uint32_t wire_type;
16690
16855
 
16856
+ const char* start = ptr;
16691
16857
  ptr = _upb_Decoder_DecodeFieldTag(d, ptr, &field_number, &wire_type);
16692
16858
 
16693
16859
  if (wire_type == kUpb_WireType_EndGroup) {
@@ -16695,7 +16861,8 @@ const char* _upb_Decoder_DecodeFieldNoFast(upb_Decoder* d, const char* ptr,
16695
16861
  return _upb_Decoder_EndMessage(d, ptr);
16696
16862
  }
16697
16863
 
16698
- ptr = _upb_Decoder_DecodeFieldData(d, ptr, msg, mt, field_number, wire_type);
16864
+ ptr = _upb_Decoder_DecodeFieldData(d, ptr, msg, mt, field_number, wire_type,
16865
+ start);
16699
16866
  _upb_Decoder_Trace(d, 'M');
16700
16867
  return ptr;
16701
16868
  }
@@ -16914,14 +17081,6 @@ typedef struct {
16914
17081
  _upb_mapsorter sorter;
16915
17082
  } upb_encstate;
16916
17083
 
16917
- static size_t upb_roundup_pow2(size_t bytes) {
16918
- size_t ret = 128;
16919
- while (ret < bytes) {
16920
- ret *= 2;
16921
- }
16922
- return ret;
16923
- }
16924
-
16925
17084
  UPB_NORETURN static void encode_err(upb_encstate* e, upb_EncodeStatus s) {
16926
17085
  UPB_ASSERT(s != kUpb_EncodeStatus_Ok);
16927
17086
  e->status = s;
@@ -16937,7 +17096,9 @@ UPB_NOINLINE static char* encode_growbuffer(char* ptr, upb_encstate* e,
16937
17096
  size_t bytes) {
16938
17097
  size_t old_size = e->limit - e->buf;
16939
17098
  size_t needed_size = bytes + (e->limit - ptr);
16940
- size_t new_size = upb_roundup_pow2(needed_size);
17099
+ if (needed_size < bytes) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
17100
+ size_t new_size = upb_RoundUpToPowerOfTwo(UPB_MAX(128, needed_size));
17101
+ if (new_size == old_size) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
16941
17102
  void* old_buf = e->buf == &initial_buf_sentinel ? NULL : (void*)e->buf;
16942
17103
  char* new_buf = upb_Arena_Realloc(e->arena, old_buf, old_size, new_size);
16943
17104