Commit graph

73 commits

Author SHA1 Message Date
Ada Zhang
bbe2f9a5e0 Move internal encoding functions to the internal encoder files.
PiperOrigin-RevId: 914421139
2026-05-12 12:33:14 -07:00
Ada Zhang
5fdcfac9eb Pass the starting buffer pointer for the backalloc to _upb_Encode_Field and _upb_Encode_Extension.
PiperOrigin-RevId: 914346686
2026-05-12 10:20:55 -07:00
Protobuf Team Bot
a7864c77bc Backwards allocation for encode.
* Allocates slightly less than a power-of-two buffer size when encoding, which avoids pathological sizes when combined with arena overhead.
* Takes the whole available block, minimizing intermediate allocations and copying
* Frees intermediate block allocations, which results in retaining about 45% less memory on average
* Returns unused memory from the last block back to the arena for future use
* Does not align the arena `end` pointer, so repeatedly serializing small protos or proto fields does not pay an up-to-7-byte overhead each

PiperOrigin-RevId: 912234452
2026-05-07 17:19:17 -07:00
Protobuf Team Bot
7b650943ad Delete array part of inttable, reducing complexity
PiperOrigin-RevId: 911624420
2026-05-06 17:00:23 -07:00
Protobuf Team Bot
0e81bccec6 Fasttable: Dispatch to fast unknown handler on slot collision when eligible.
Claims a new bit on ExtMode to track eligibility.

PiperOrigin-RevId: 908348263
2026-04-30 13:36:26 -07:00
Ada Zhang
b59ca2e627 - Update the upb_ErrorHandler err member in the upb_Decoder struct to be a pointer (upb_ErrorHandler* err).
- Add new _upb_Encode_Field and _upb_Encode_Extension internal APIs.

PiperOrigin-RevId: 903268174
2026-04-21 09:20:32 -07:00
Protobuf Team Bot
c8703b9fde Fixed missed LICM, found via -Rpass-missed=licm
PiperOrigin-RevId: 900882576
2026-04-16 13:31:47 -07:00
Protobuf Team Bot
6a3bcdaca2 overflow checks in unknown field realloc
PiperOrigin-RevId: 882240287
2026-03-11 15:59:19 -07:00
Mikita Belahlazau
4f076d951f Add metadata annotations for generated Python protobuf symbols.
The pyi generator now includes Kythe annotations for:
*   Extension field constants (e.g., `EXTENSION_FIELD`).
*   Field number constants (e.g., `STRING_FIELD_FIELD_NUMBER`).
*   `Create` methods in generated Stubby client classes.

These annotations allow the Python indexer to link these generated symbols back to their definitions in the `.proto` files.

PiperOrigin-RevId: 852971617
2026-01-06 16:05:56 -08:00
Protobuf Team Bot
ae67a4c195 Internal version update.
PiperOrigin-RevId: 852733884
2026-01-06 05:27:44 -08:00
Protobuf Team Bot
0e84323cd6 Fixes a compiler crash when building the Windows arm64 Ruby/Python extension
This works around llvm/llvm-project#47432 which is causing crashes during compilation for some users, by not aligning the indirect branch target when SEH is enabled.

Fixes #24758

PiperOrigin-RevId: 845310735
2025-12-16 09:39:44 -08:00
Protobuf Team Bot
1df3f674d2 Automated rollback of commit d8a1f8cf79.
PiperOrigin-RevId: 834496697
2025-11-19 16:51:00 -08:00
Joshua Haberman
d8a1f8cf79 Optimized and refined bounds checking for delimited fields.
Prior to this CL, whenever we parsed a size we would immediately verify that size against the current EpsCopyInputStream limit.  This was correct but was unnecessarily expensive, especially since it was redundant with other checks we perform when parsing sub-messages or strings.

In this CL, we remove the eager check when parsing a size, and we perform more targeted and optimized bounds checks at the points where these checks are actually needed.  This brings us more into line with how EpsCopyInputStream works in C++.

In particular:

- We never need to check against the pushed limit, because `IsDone()` is already checking to make sure we ended at the correct limit.
- When reading a string (either to alias or to copy), we only need to check against the buffer end, not the limit.  This could result in us reading a string that extends beyond the current limit, but the parse will then fail, and the string fields will still be safe to read (even if nonsense).

PiperOrigin-RevId: 834415733
2025-11-19 13:15:32 -08:00
Protobuf Team Bot
a3ca522fc5 Add BTI to branch targets when branch protection is enabled. This resolves
https://github.com/protocolbuffers/protobuf/issues/23306

Since there's a measurable performance cost (~12% for a long varint heavy message) on little and mid size cores, these instructions aren't unconditionally emitted even though they're compatible (CPUs lacking FEAT_BTI interpret them as HINT/NOP). Even with these extra instructions, the assembly path is still much faster than the generic one.

PiperOrigin-RevId: 834093313
2025-11-18 20:44:01 -08:00
Joshua Haberman
2ad03aa1d0 Pack the field array and the subs array into one block of contiguous memory.
Instead of giving every MiniTable two parallel arrays (fields and subs), we now have one block of memory that contains both lists.

For sub-message or enum fields, the `upb_MiniTableField` now contains a byte offset to where the `upb_MiniTable*` or `upb_MiniTableEnum*` can be found.

The new design offers several benefits:

1. The sub-table requires fewer pointer-chasing indirections to find.
2. We no longer need the `upb_MiniTable*` to find the sub-MiniTable -- the `upb_MiniTableField*` is enough now.  So APIs like `upb_MiniTable_GetSubMessageTable()` now require fewer parameters.
3. This unifies fields and extensions -- both can now find a sub-table using exactly the same code, with no need to distinguish between them.

We still benefit from having two lists.  If we tried to put the sub-table pointer directly into `upb_MiniTableField`, it would double the size of `upb_MiniTableField` from 12 to 24 bytes, due to alignment.  Using the current design, sub-message fields only take 20 bytes, while others take 12, so this design is an improvement even if 100% of fields are sub-message fields.

PiperOrigin-RevId: 833329706
2025-11-17 07:29:38 -08:00
Joshua Haberman
af91d2a2fc Rolling forward after fixing the weak symbol linking for optimized iOS builds.
The previous CL's approach of using `__attribute__((weakref()))` was not actually behaving as expected, and the unit tests were not sufficient to catch this.

We now use inline assembly to achieve the functionality that we thought we were getting with `__attribute__((weakref()))`.  From assembly, we can create a weak symbol whose value is the same as another "stub" symbol in the same file.

Unfortunately we cannot have all of our weak symbols reference a single placeholder "empty" message, due to a bug I discovered in the LLVM linker and reported in https://github.com/llvm/llvm-project/issues/167262

If and when that bug is fixed, we should be able to get optimal tree shaking behavior, even on iOS.

PiperOrigin-RevId: 831396179
2025-11-12 08:21:20 -08:00
Joshua Haberman
f79742a2dc Automated jj rollback of changelist 829022414
*** Reason for rollback ***

Breaking tests.

PiperOrigin-RevId: 829158111
2025-11-06 16:46:00 -08:00
Joshua Haberman
1a54fdb2c3 Removed indirection for sub-messages.
To do this, we use `__attribute__((weakref()))` to weakly reference a placeholder definition for tree shaken sub-messages.  This provides the same tree shaking behavior we had before, but without needing an extra indirection.  If we had discovered this technique before, we would have had no reason to add the indirection in cl/640369522.

This will reduce the code size and memory overhead of any MiniTables with sub-messages in them, because we no longer need an extra `void*` per sub-message field to store the extra indirect pointer.

It also should improve efficiency a bit since there is one fewer indirection when recursing into a sub-message field.

PiperOrigin-RevId: 829022414
2025-11-06 10:55:15 -08:00
Protobuf Team Bot
e028049e79 Merge bounds checks for scalar encode.
PiperOrigin-RevId: 823692538
2025-10-24 15:52:18 -07:00
Joshua Haberman
83d1db468b Removed obsolete experimental code for tagged-ptr field promotion.
PiperOrigin-RevId: 823526718
2025-10-24 07:50:19 -07:00
Protobuf Team Bot
3ef585a8db Extract arm64 asm check
PiperOrigin-RevId: 823185820
2025-10-23 14:23:17 -07:00
Protobuf Team Bot
2293d51b42 Return an error if asked to serialize a proto larger than 2gb
PiperOrigin-RevId: 821777650
2025-10-20 13:25:27 -07:00
Protobuf Team Bot
ab7ec28873 Avoid NULL - NULL UB on the first bounds check of encoding a proto
PiperOrigin-RevId: 820751947
2025-10-17 10:51:54 -07:00
Protobuf Team Bot
9664a6bd64 Enable the optimized arm encoder with msan on by telling msan which bytes it initializes
PiperOrigin-RevId: 819353317
2025-10-14 12:45:46 -07:00
Protobuf Team Bot
389da83b1c Don't use the inline assembly encoder when msan is on.
Msan relies on instrumenting stores, which it can't do for inline asm.

PiperOrigin-RevId: 768131870
2025-06-06 10:38:59 -07:00
Protobuf Team Bot
b039dfe265 Optimize encoding long varints on arm64
I couldn't get the compiler to emit the jump table I wanted so it's written as inline asm. This benchmarked as 1% faster in the overall encode benchmarks than doing the same size calculation and a normal loop.

PiperOrigin-RevId: 767814597
2025-06-05 16:41:51 -07:00
Protobuf Team Bot
974884ecc9 Prevent dereference and add const to bounds pointers during encode
PiperOrigin-RevId: 762591913
2025-05-23 15:38:02 -07:00
Protobuf Team Bot
7ddb510d47 Pass current buffer position as argument and return during encode
This shows a 7% improvement to encode speed in benchmarks on arm little cores.

PiperOrigin-RevId: 762542993
2025-05-23 13:20:27 -07:00
Protobuf Team Bot
fe86814abf Fix noinline function called unconditionally from noinline function.
1.3% encoding improvement on arm little cores

PiperOrigin-RevId: 762472874
2025-05-23 10:14:04 -07:00
Joshua Haberman
95af41ec9c Fixed a few edge cases around depth limits in encode, decode, and compare.
1. The unknown field depth comparison had an off by one error compared with the logic in decode/encode.
2. The functions to limit encode/decode depth were not working properly when the max depth was unset, because the "default" depth was represented as 0 which did not trigger the min operation.
3. The regular (non-"effective") functions `upb_DecodeOptions_GetMaxDepth()` and `upb_EncodeOptions_GetMaxDepth()` are footguns that do not belong in the header (as illustrated by the bug in (2).  So moved them to the source file.

PiperOrigin-RevId: 760911128
2025-05-19 22:04:43 -07:00
Ada Zhang
6f095cfbf9 upb: Support UINT64_MAX in the array part of inttable, so that we can remove the constraint that inttable table can only be used for 32-bit values for primitive keys in upb_Map.
PiperOrigin-RevId: 737811835
2025-03-17 17:49:54 -07:00
Protobuf Team Bot
70beaef54e Cleanup on upb/hash/common
- Remove the unnecessary distinct types of upb_value vs upb_tabvalue (notably contrasted with upb_MessageValue which is widely used and very different). Presumably there was legacy where it was expected we might evolve these separately, but in practice we just have noise converting between the two structs which have identical definitions.

- Rename upb_tabkey to "upb_key" as a clear parallel to "upb_value"

- Just do normal assignment for one upb_value to another upb_value (I think some of these were C89 remnants, others cleaned up from the unnecessary type duality).

- Make the sentinel value handling in inttable more explicit, including rename upb_arrhas() with is_inttable_sentinel() since we eg check it in an assert of something before we were going to insert it into the table where we're checking for sentinel of a thing thats not in an array, so arrhas didn't really make sense.

PiperOrigin-RevId: 734933132
2025-03-08 11:52:12 -08:00
Ada Zhang
fce32cf458 Add support in inttable to support upb_Map of primitive keys.
When the kUpb_EncodeOption_Deterministic option is set, inttable entries will be encoded in a deterministic order but not necessarily in a sorted order by its key.

PiperOrigin-RevId: 734614535
2025-03-07 10:52:57 -08:00
Protobuf Team Bot
584340d3d9 Poison and unpoison on realloc
Prior to this change, the asan guard size meant that the fast path for realloc never triggered in asan mode, masking the fact that the realloc fast path did not unpoison the newly extended memory region. This change also poisons the "previous" memory area if an alloc+copy is performed, to match the C realloc behavior of freeing the previous memory.

PiperOrigin-RevId: 734278556
2025-03-06 14:06:22 -08:00
Ada Zhang
e6c6bf1827 upb: Working with inttable in most of the upb_Map functions.
This change is still a no-op until we actually initialize an inttable for primitive keys in _upb_Map_New.

PiperOrigin-RevId: 733786380
2025-03-05 10:35:18 -08:00
Protobuf Team Bot
d8c0681b0d upb: introduce a union to upb_Map to support both string and int table.
This is a no-op change, but would prepare us to add the int table as an alternative data structure for primitive map keys.

PiperOrigin-RevId: 726536300
2025-02-13 10:17:56 -08:00
Protobuf Team Bot
cec097b9b5 Implement merged unknowns/extensions storage.
Previously, extensions and unknown fields were stored on opposite ends of a growing buffer:
```
|------unknown fields-------|---------unallocated space------|--extensions---|
```
Unknown fields were appended and extensions were prepended during parse. When either side ran into the other, the buffer was reallocated to fit, rounding up to the nearest power of 2. This meant that for a proto with 70,000 bytes of unknown fields, the total memory consumed could be up to 128+256+512+1024+2048+4096+8192+16384+32768+65536+131072=262016 bytes allocated in the arena. In the more common case of a large, length-delimited field it'd be just 131072 bytes; but as a 3.74x increase or a 1.87x increase, that's a lot of extra memory.

The new representation still does exponential reallocation, but only for pointers to normal arena allocations. We exploit the fact that arena allocations are aligned to store data about whether the pointer is to an extension or a `upb_StringView` of unknown fields in the low bits of the pointer itself. This costs three pointers of overhead per unknown field and one pointer of overhead per extension, but that's a fixed overhead - we won't over-allocate large buffers for large unknown fields. If this overhead proves to be a problem, more compact representations could be implemented.

In addition, because unknown field bytes are now in their own allocations, they are pointer stable - in the future, this will allow us to exploit aliasing (when enabled during parse) for both unknown fields and lazy extensions (parsed from unknown fields), which can greatly reduce memory use for messages with a lot of unknown, string, or bytes fields.

PiperOrigin-RevId: 708058272
2024-12-19 15:39:41 -08:00
Protobuf Team Bot
c78129dba2 Fix bug in deterministic extension encoding when empty extensions are present
PiperOrigin-RevId: 707943424
2024-12-19 09:55:50 -08:00
Joshua Haberman
3d065d1ced Fixed depth limit check by comparing effective depth limits.
Before we were trying to work around the fact that we don't know the default depth limit. The logic is simpler and more robust if we take the default into account.

PiperOrigin-RevId: 698856552
2024-11-21 11:41:00 -08:00
Protobuf Team Bot
db71344633 Move iteration APIs to headers, so they're inlined in loop calls
PiperOrigin-RevId: 698497070
2024-11-20 13:29:38 -08:00
Protobuf Team Bot
35dbd5cfd6 Use an explicit union with commented explanation rather than casting
PiperOrigin-RevId: 698437576
2024-11-20 10:29:24 -08:00
Protobuf Team Bot
32afcb9cf8 Update callers to use noncontiguous APIs
PiperOrigin-RevId: 696922501
2024-11-15 10:09:25 -08:00
Joshua Haberman
85c7cc24e0 Add an indirection to sub-messages pointers to allow for static tree shaking.
PiperOrigin-RevId: 640369522
2024-06-04 20:09:22 -07:00
Hong Shin
0645439efa Introduce upb_EncodeStatus_String and upb_DecodeStatus_String
Wrapper languages can now use these helpers to get human-friendly
error codes as opposed to manually re-mapping.

PiperOrigin-RevId: 634112262
2024-05-15 16:30:37 -07:00
Protobuf Team Bot
d5a435fb4b Rename 'length delimited' to 'length prefixed'
PiperOrigin-RevId: 621597812
2024-04-03 12:13:54 -07:00
Protobuf Team Bot
c6f6a3291e Add Length-Delimited Encode and Decode functions to upb.
PiperOrigin-RevId: 621510731
2024-04-03 07:08:18 -07:00
Eric Salo
f212cc23d7 upb: use upb_MessageValue in upb_Extension
PiperOrigin-RevId: 602785269
2024-01-30 11:17:15 -08:00
Eric Salo
98843d15ac upb: attempt to reduce the direct use of UPB_PRIVATE() fields
PiperOrigin-RevId: 602270576
2024-01-28 21:43:08 -08:00
Eric Salo
5bded04d28 upb: add 'static' to UPB_FORCEINLINE()
PiperOrigin-RevId: 601525709
2024-01-25 12:19:18 -08:00
Eric Salo
9d625a1df7 upb: fix the map encoder to stop dying under ubsan
PiperOrigin-RevId: 601004095
2024-01-23 21:54:30 -08:00