fix(Bytecode DSL): deduplicate constants by identity instead of equals - #14537
Open
The-Alchemist wants to merge 1 commit into
Open
The-Alchemist wants to merge 1 commit into
The-Alchemist wants to merge 1 commit into
Conversation
ConstantsBuffer deduplicated constants using equals, so two distinct but equal objects passed to separate LoadConstant calls or constant operands were collapsed into one pool slot. Operations could observe the substitution through ==, getClass(), or state not covered by equals. Serialization had the same problem because SerializationState.objects was a HashMap. Constants are now deduplicated by reference identity. Boxed primitives and the Bytecode DSL accessor types keep value-based deduplication since their identity is unspecified; floating-point values compare by raw bits. Serialization now uses an IdentityHashMap. Because finally generators are serialized once but deserialized once per emitted handler, objects first seen inside a finally generator are now created in the outermost serialization context whose root nodes they reference, and inner contexts refer to them with a new CODE_$CREATE_OUTER_OBJECT record. This keeps repeated references shared across handler replays and with the enclosing code after a round trip, which equals-based merging used to hide. Signed-off-by: The-Alchemist <kap4020@gmail.com>
The-Alchemist
marked this pull request as ready for review
September 26, 2026 22:46
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
BytecodeSupport.ConstantsBuffer.adddeduplicated constants with==orequals, so two distinct but equal objects passed to separateemitLoadConstantcalls or constant operands collapsed into one pool slot. Operations could observe the substitution through==,getClass(), or state not covered byequals. Serialization had the same problem independently, because the generatedSerializationState.objectswas aHashMap.==andSystem.identityHashCode). Boxed primitives and the Bytecode DSL accessor types (LocalAccessor,MaterializedLocalAccessor,LocalRangeAccessor) are still deduplicated by value, because their identity is already unspecified (boxing caches andconstantOfcaches) and pure identity would only grow the pool.Double/Floatnow compare by raw bits, so0.0/-0.0and different NaN payloads are no longer merged.IdentityHashMap. That exposed an issueequalsmerging used to hide: a finally generator is serialized once but deserialized once per emitted handler, so a reference in afinallybody came back as a separate instance per replay. Objects first seen inside a finally generator are now created in the outermost serialization context whose root nodes they reference, and the generator refers to them with a newCODE_$CREATE_OUTER_OBJECTrecord. Objects that reference root nodes built inside the generator are still re-created per replay. Old serialized data still deserializes, since only a record type was added.ConstantsBufferTestcovers equal-but-distinct objects below and aboveHASH_THRESHOLD, same-reference sharing, value-based boxed types, and raw-bit floats. The newConstantIdentityTestcoversLoadConstant, constant operands, and sharing across finally-generator replays, each both directly and through a serialization round trip. Thecom.oracle.truffle.api.bytecode.testpackage passes.Questions
@GenerateBytecode-level policy controlling both paths would be another option.Feedback welcome!