GROOVY-12227: GeneratedDispatcher: avoid runtime class definition so … - #2765
Open
paulk-asert wants to merge 1 commit into
Open
GROOVY-12227: GeneratedDispatcher: avoid runtime class definition so …#2765paulk-asert wants to merge 1 commit into
paulk-asert wants to merge 1 commit into
Conversation
…packed closures work in native images Two layered changes to the GROOVY-12151 packed-closure machinery (GEP-27): 1. ClosureWriter now passes the three dispatch tables as constant bootstrap arguments (CONSTANT_MethodHandle), resolved by the VM's constant pool rather than a runtime Lookup.findStatic -- which under GraalVM native image demanded per-class reflection metadata. Verified: the tracing agent records zero packedDispatch entries for the new bytecode. 2. GeneratedDispatcher.bootstrap keeps the LambdaMetafactory hidden-class adapters on a regular JVM (the JIT-inlining rationale in the class javadoc), but where classes cannot be defined at run time -- native image, detected per link so build-time class init cannot bake in the wrong answer -- it adapts the tables with method-handle-invoking wrappers instead: ordinary bytecode of this class, AOT-compiled into the image. A catch-based fallback covers AOT runtimes the property probe misses. -Dgroovy.packed.dispatch.handles=true forces the wrapper path on a JVM, for parity testing. Permanent behaviour, no user-facing flag: JVM semantics are unchanged and the fallback engages only where the hidden-class path cannot work. The old 3-arg bootstrap remains for class files from earlier 6.0 snapshots. Before/after on GraalVM 25.2.4 (native-image 25.0.4): the packed repro previously failed with 'Classes cannot be defined at runtime ... M$$Lambda...'; it now runs correctly (single emitted class, 30MB image, ~12ms total run time). Parity + undeclared-checked-exception propagation covered by PackedDispatcherHandleBundleTest; all existing packed-closure suites green.
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## master #2765 +/- ##
==================================================
+ Coverage 69.9738% 69.9778% +0.0040%
- Complexity 35505 35528 +23
==================================================
Files 1557 1557
Lines 131675 131706 +31
Branches 24169 24174 +5
==================================================
+ Hits 92138 92165 +27
- Misses 31193 31205 +12
+ Partials 8344 8336 -8
🚀 New features to boost your workflow:
|
✅ All tests passed ✅🏷️ Commit: b5b5692 Learn more about TestLens at testlens.app. |
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.
…packed closures work in native images
Two layered changes to the GROOVY-12151 packed-closure machinery (GEP-27):
ClosureWriter now passes the three dispatch tables as constant bootstrap arguments (CONSTANT_MethodHandle), resolved by the VM's constant pool rather than a runtime Lookup.findStatic -- which under GraalVM native image demanded per-class reflection metadata. Verified: the tracing agent records zero packedDispatch entries for the new bytecode.
GeneratedDispatcher.bootstrap keeps the LambdaMetafactory hidden-class adapters on a regular JVM (the JIT-inlining rationale in the class javadoc), but where classes cannot be defined at run time -- native image, detected per link so build-time class init cannot bake in the wrong answer -- it adapts the tables with method-handle-invoking wrappers instead: ordinary bytecode of this class, AOT-compiled into the image. A catch-based fallback covers AOT runtimes the property probe misses. -Dgroovy.packed.dispatch.handles=true forces the wrapper path on a JVM, for parity testing.
Permanent behaviour, no user-facing flag: JVM semantics are unchanged and the fallback engages only where the hidden-class path cannot work. The old 3-arg bootstrap remains for class files from earlier 6.0 snapshots.
Before/after on GraalVM 25.2.4 (native-image 25.0.4): the packed repro previously failed with 'Classes cannot be defined at runtime ... M$$Lambda...'; it now runs correctly (single emitted class, 30MB image, ~12ms total run time). Parity + undeclared-checked-exception propagation covered by PackedDispatcherHandleBundleTest; all existing packed-closure suites green.