[
https://issues.apache.org/jira/browse/GROOVY-12191?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18100539#comment-18100539
]
ASF GitHub Bot commented on GROOVY-12191:
-----------------------------------------
blackdrag commented on PR #2736:
URL: https://github.com/apache/groovy/pull/2736#issuecomment-5135065448
> ### Short answer
>
> Hierarchy SwitchPoint fan-out is needed in **one** live-selection
situation only:
>
> > The **receiver’s MetaClass is unchanged**, selection previously linked a
result that depended on an **ancestor** modified `MutableMetaClass` (almost
always EMC) via the **missing-method** walk
(`MetaClassImpl.findMethodInClassHierarchy`), and that ancestor later **gains
or loses** methods that change the walk’s result.
[...]
> 4. **The case that _does_ need hierarchy SP** (what the machinery is
for):
>
> ```groovy
> class Parent {}
> class Child extends Parent {}
> def call(x) {
> try { x.onlyOnParent(); 'hit' }
> catch (MissingMethodException e) { 'miss' }
> }
> def c = new Child()
> assert call(c) == 'miss' // monomorphic miss linked on Child
> Parent.metaClass.onlyOnParent = { -> 'now-visible' }
> assert call(c) == 'hit' // must re-select; Child MetaClass
unchanged
> ```
Does this single MissingMethodException case really justify the SwitchPoint
usage? Are we even caching in that case? If we are then caching that would be
new in this pull request I assume. And in that case I would question that
decision.
[...]
> The _feature_ is small in description (missing-method hierarchy + EMC),
not quite, it is: missing-method hierarchy + EMC + MissingMethodException +
Method exists later. That is a lot smaller. How often does this appear in a
typical code base in for example Grails? @paulk-asert maybe you can help here
in answering that? I simply think that the hierarchy is overkill for this and a
simple uncached path through the metaclass would be sufficient. If I oversee
something here, I would love for you to correct me. Switchpoints add overhead
too.
> Scope indy SwitchPoint invalidation
> -----------------------------------
>
> Key: GROOVY-12191
> URL: https://issues.apache.org/jira/browse/GROOVY-12191
> Project: Groovy
> Issue Type: Improvement
> Reporter: Daniel Sun
> Priority: Major
> Fix For: 6.0.0-beta-1
>
>
> h3. Problem
> With invokedynamic enabled (default since Groovy 4), linked MOP call sites
> were guarded by a *single process-wide* {{SwitchPoint}}
> ({{{}IndyInterface.switchPoint{}}}).
> Any MetaClass registry change or category enter/leave invalidated that switch
> point, so *every* linked site fell back and re-linked — including sites whose
> receiver type was unrelated.
> That global invalidation is expensive when MetaClass churn is common (e.g.
> ExpandoMetaClass / mixins on startup or per-request paths, Grails-like
> patterns). Unrelated hot monomorphic sites pay re-link and JIT deopt cost
> they should not.
> h3. Goal
> Keep linked call sites optimized unless the *relevant* MetaClass state for
> that site actually changed.
> h3. Approach
> One SwitchPoint domain {*}per class{*}, stored on {{{}ClassInfo{}}}:
> * MetaClass change for type {{T}} retires {{{}T{}}}'s SwitchPoint *and*
> those of loaded subtypes / implementors (hierarchy fan-out).
> * Unrelated types keep their SwitchPoints; their call sites stay optimized.
> * Category enter/leave (and {{{}VMPlugin.invalidateCallSites(){}}})
> bulk-retire *all* loaded class SwitchPoints so sites re-link under the new
> category state. There is *no* second category SwitchPoint on the hot path.
> * Linked handles always install a *single* class-domain guard via
> {{IndyInvalidation.guardWithMopSwitchPoints(...)}} — same monomorphic guard
> shape as before, without global deopt on unrelated MetaClass churn.
> Final classes short-circuit hierarchy fan-out (no full {{ClassInfo}} scan).
> Non-final types batch retirements with {{{}SwitchPoint.invalidateAll{}}}.
> h3. Invalidation map
> ||Event||What is retired||
> |MetaClass change for type {{T}} (registry /
> {{{}ClassInfo.incVersion{}}})|{{T}} + loaded subtypes / implementors|
> |Category enter/leave, {{invalidateCallSites()}}|All loaded class
> SwitchPoints (bulk)|
> |Unattributed MetaClass registry event|All loaded class SwitchPoints (bulk)|
> |First MetaClass *install* on a class|Version bump only (no linked sites
> yet); replacement / clear retires that class's SwitchPoint|
>
--
This message was sent by Atlassian Jira
(v8.20.10#820010)