[
https://issues.apache.org/jira/browse/GROOVY-12185?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
]
Daniel Sun updated GROOVY-12185:
--------------------------------
Fix Version/s: 6.0.0-beta-1
> Move classic call-site caching into optional groovy-callsite module
> -------------------------------------------------------------------
>
> Key: GROOVY-12185
> URL: https://issues.apache.org/jira/browse/GROOVY-12185
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Priority: Major
> Fix For: 6.0.0-beta-1
>
>
> h2. Background
> Since Groovy 4, invokedynamic is the default call-dispatch path. The classic
> (pre-indy) call-site cache under {{org.codehaus.groovy.runtime.callsite}}
> still lived in groovy-core, so every runtime paid for types that default
> compilation no longer needs.
> The *primary purpose* of extracting this code is *runtime binary
> compatibility* for classes compiled by *Groovy 4 and Groovy 5* (and earlier
> releases that always used classic call sites). Those classes embed
> {{$getCallSiteArray}} / {{CallSiteArray}} / {{CallSite}} linkage. On Groovy 6
> they must still *load and execute* when {{org.apache.groovy:groovy-callsite}}
> is on the classpath.
> Secondary use: compiling with {{indy}} disabled
> ({{{}groovy.target.indy=false{}}} or optimization option {{{}indy: false{}}}).
> This implements the direction from the PR #1934 / GROOVY-11158: isolate
> classic call-site caching into an optional, deprecated module.
> h2. Goal
> * *Compatibility first:* preserve the public linkage surface of {{CallSite}}
> and {{CallSiteArray}} so Groovy 4/5 classic bytecode runs on Groovy 6 +
> {{{}groovy-callsite{}}}.
> * Move classic call-site runtime into optional module
> {{org.apache.groovy:groovy-callsite}} (not part of {{{}groovy-all{}}}).
> * Keep groovy-core free of a dependency on that module; default path stays
> invokedynamic-only.
> * Expose enough public MetaClass selection API so the optional module can
> build sites without package-private coupling into core.
> * When {{indy}} is off and the classic runtime is missing, *fail at compile
> time* with a clear error instead of emitting unloadable bytecode.
> h2. Design
> h3. Module boundary
> * New subproject: {{subprojects/groovy-callsite}}
> * Depends on groovy-core ({{{}api{}}}); core never depends on
> {{groovy-callsite}}
> * {{optionalModule()}} — not shipped in {{groovy-all}}
> * Entire package {{org.codehaus.groovy.runtime.callsite}} is {{@Deprecated}}
> (removal planned in a later major)
> h3. What moves where
> ||Former location (core)||New location ({{{}groovy-callsite{}}})||
> |{{MetaClassImpl}} / {{ExpandoMetaClass}} / {{ClosureMetaClass}}
> {{create…CallSite}} factories|{{MetaClassCallSites}}|
> |{{CachedMethod}} {{create…MetaMethodSite}} (+ SoftReference compile
> cache)|{{CachedMethodCallSites}} (side map of per-method state)|
> |{{CallSiteArray}} hooks into those MetaClass factories|{{CallSiteArray}} →
> {{MetaClassCallSites}}|
> |{{{}CallSite{}}}, {{{}AbstractCallSite{}}}, specialized sites,
> {{{}CallSiteGenerator{}}}, …|same package names under the module|
> h3. Core API kept for optional consumers (since 6.0.0)
> * {{MetaClassImpl#getMethodWithCaching(Class, String, Class[])}}
> * {{MetaClassImpl#chooseConstructor(Class[])}}
> * {{MetaClassImpl#chooseNamedArgCompatibleConstructor(Class[], Object[])}}
> * {{ExpandoMetaClass#hasCustomInvokeMethod()}}
> h3. Core clean-up (major-version break)
> Removed from groovy-core:
> * {{create…CallSite}} methods on {{MetaClassImpl}} / {{ExpandoMetaClass}} /
> {{ClosureMetaClass}}
> * {{CachedMethod}} {{create…MetaMethodSite}} and related SoftReference fields
> * {{CachedClass#getCallSiteLoader()}}
> * {{CallSiteAwareMetaMethod}} and DGM/array call-site specializations
> Retained in core:
> * DGM {{invoke()}} paths (numbers, arrays) for MOP / indy
> * Helpers under {{org.codehaus.groovy.runtime}} (e.g.
> {{{}BooleanClosureWrapper{}}})
> * Classic *bytecode emission* ({{{}CallSiteWriter{}}}) only when {{indy}} is
> disabled
> h3. Compiler guard
> When {{indy}} is off, {{WriterController}} requires {{CallSiteArray}} on the
> compilation class loader before emitting classic call-site bytecode. Missing
> module → clear error pointing at {{groovy-callsite}} / GROOVY-11158.
> h2. Migration
> h4. Default users (indy on — default since Groovy 4)
> No action. Core jar no longer ships classic call-site classes.
> h4. Run classes compiled by Groovy 4/5 classic mode (or older)
> Add the optional module to the *runtime* classpath:
> {code:xml}
> <dependency>
> <groupId>org.apache.groovy</groupId>
> <artifactId>groovy-callsite</artifactId>
> <version>${groovy.version}</version>
> </dependency>
> {code}
> {code:groovy}
> // Gradle
> runtimeOnly "org.apache.groovy:groovy-callsite:${groovyVersion}"
> {code}
> Use the published (jarjar) artifact together with groovy-core so shaded ASM
> ({{{}groovyjarjarasm{}}}) resolves for {{{}CallSiteGenerator{}}}.
> h4. Compile with indy disabled
> Same module on the *compile* classpath. Without it, compilation fails fast
> rather than producing unloadable classes.
> h4. Code that called removed core factory APIs
> * Prefer invokedynamic (default), or
> * Depend on {{groovy-callsite}} and use {{MetaClassCallSites}} /
> {{CachedMethodCallSites}} instead of removed {{MetaClassImpl}} /
> {{CachedMethod}} factories.
> h2. Compatibility contract
> Stable for precompiled classic bytecode:
> * Package: {{org.codehaus.groovy.runtime.callsite}}
> * {{{}CallSiteArray(Class, String[]){}}}, public fields {{array}} /
> {{{}owner{}}}, {{NOPARAM}}
> * Full {{CallSite}} method set ({{{}call{}}}, {{{}callCurrent{}}},
> {{{}callStatic{}}}, {{{}callConstructor{}}}, {{{}callGetProperty{}}},
> {{{}callSafe{}}}, …)
> Binary break in core is intentional for a major version. japicmp against 5.x
> is disabled for the new module ({{{}withoutBinaryCompatibilityChecks(){}}}).
--
This message was sent by Atlassian Jira
(v8.20.10#820010)