Class IndyInvalidation
SwitchPoint invalidation for the Groovy MOP
(GROOVY-12191).
Domain: one SwitchPoint domain per Class, owned by its
ClassInfo and covering every MetaClass generation of that class
(pre-MetaClass link included). The domain outlives the MetaClass
object, so exact-class invalidation still reaches installed guards
after a soft/weak MetaClass has been collected. Monomorphic indy sites
install a single guardWithTest on the class-level domain observed
at link time.
Width policy (two axes only)
- Exact class —
invalidateClass(Class): stockMetaClassImpl/ EMC changes (includingClassInfo.incVersion(), registry replace, per-instance MetaClass). - All loaded — process-wide retire used for category enter/leave
(
invalidateCategory()), unattributed registry events (invalidateUnscoped()), and non-stock custom MetaClass kinds (invalidateBulk()).
MetaClass.invokeMethod / property miss and walks the hierarchy live
from the registry each call. Construction-time snapshots of ancestor expando
methods are pre-existing MOP behaviour and are not refreshed by SwitchPoint
retirement. See also MetaClassImpl.findMethodInClassHierarchy(java.lang.Class, java.lang.String, java.lang.Class[], groovy.lang.MetaClass).
Optional stats: -Dgroovy.indy.invalidation.stats=true.
Production guards: IndyInterface.applyMopSwitchPoints; tests may use
guardWithMopSwitchPoints(java.lang.invoke.MethodHandle, java.lang.invoke.MethodHandle, java.lang.Object).
- Since:
- 6.0.0
-
Method Summary
Modifier and TypeMethodDescriptionstatic voidanchorClassDomain(ClassInfo owner, SwitchPointInvalidator domain) Anchors a reclaim reference for a ClassInfo-owned class domain: when the ClassInfo (and with it the class) becomes unreachable while the domain still has a live registered SwitchPoint, the reference is delivered by the sharedweak-bundlemanager and the domain is retired — installed guards keep only the SwitchPoint's internal invoker reachable, so retiring the orphan forces straggler sites to re-link, which is always safe.static longNon-category process-wide bulk event count (invalidateBulk()/invalidateUnscoped()).static longCategory-style bulk invalidation count (invalidateCategory()).static longExact-class invalidation event count (invalidateClass(Class)).static SwitchPointclassSwitchPointFor(Class<?> type) Returns the SwitchPoint for the given class at link time: the current generation of the ClassInfo-owned class domain (defineClass-safe — does not create or consult a MetaClass).static SwitchPointclassSwitchPointFor(Object receiver) Returns the class-level MetaClass SwitchPoint for the given receiver.static voidcollectLiveForClass(Class<?> type, List<SwitchPoint> out) Collects the live SwitchPoint (if any) oftype's class domain.static MethodHandleguardWithMopSwitchPoints(MethodHandle handle, MethodHandle fallback, Class<?> receiverClass) Installs a MetaClass SwitchPoint guard onhandle.static MethodHandleguardWithMopSwitchPoints(MethodHandle handle, MethodHandle fallback, Object receiver) Installs a MetaClass SwitchPoint guard onhandle.static voidProcess-wide bulk retirement for non-stock (custom) MetaClass registry events — correctness-first when selection may consult state outside the stock miss walk.static voidCategory enter/leave andVMPlugin.invalidateCallSites().static voidinvalidateClass(Class<?> type) Retires onlytype's MetaClass SwitchPoint domain (exact class; no subtype fan-out).static voidRegistry-driven invalidation: exact class for stock MetaClass kinds and per-instance changes; process-wide bulk for custom MetaClass kinds or unattributed events.static voidRetires the class domain ofmc's class (if a generation was allocated).static voidProcess-wide bulk retirement when a MetaClass registry event carries noClassattribution.static booleanWhethermcis a stock MOP MetaClass for which exact-class invalidation is sufficient:null, or unwrappedMetaClassImpl(includes EMC and subclasses).static booleanneedsBulkInvalidation(MetaClass oldMc, MetaClass newMc) Whether a class-level MetaClass change involvingoldMc/newMcrequires process-wide bulk invalidation.static voidResets process-wide counters (tests only).static Class<?>switchPointClassFor(Object receiver) Resolves the class used for the MetaClass SwitchPoint domain of a receiver.static SwitchPointReturns the class-domain SwitchPoint for a MetaClass.
-
Method Details
-
anchorClassDomain
Anchors a reclaim reference for a ClassInfo-owned class domain: when the ClassInfo (and with it the class) becomes unreachable while the domain still has a live registered SwitchPoint, the reference is delivered by the sharedweak-bundlemanager and the domain is retired — installed guards keep only the SwitchPoint's internal invoker reachable, so retiring the orphan forces straggler sites to re-link, which is always safe.Reachability: the live-SwitchPoint registry holds the invalidator strongly, and the invalidator holds the reclaim reference, so cleanup stays reachable exactly as long as there is something to clean; once the domain is retired the whole chain becomes collectable.
- Parameters:
owner- the ClassInfo owning the domain (must not benull)domain- the class-level domain (must not benull)
-
invalidateClass
Retires onlytype's MetaClass SwitchPoint domain (exact class; no subtype fan-out). No-op whentypeisnull. Does not bumpClassInfo.getVersion().Used by
ClassInfo.incVersion(), stock registry MetaClass changes, and per-instance MetaClass changes. Non-stock MetaClass kinds useinvalidateBulk()instead.- Parameters:
type- the class whose MetaClass changed
-
invalidateCategory
public static void invalidateCategory()Category enter/leave andVMPlugin.invalidateCallSites(). Retires every loaded class-level domain so sites re-link under the new category state. No separate category SwitchPoint on the hot path. -
invalidateBulk
public static void invalidateBulk()Process-wide bulk retirement for non-stock (custom) MetaClass registry events — correctness-first when selection may consult state outside the stock miss walk. Rare. -
invalidateUnscoped
public static void invalidateUnscoped()Process-wide bulk retirement when a MetaClass registry event carries noClassattribution. -
invalidateForMetaClassChange
Registry-driven invalidation: exact class for stock MetaClass kinds and per-instance changes; process-wide bulk for custom MetaClass kinds or unattributed events. See class javadoc.- Parameters:
event- the registry change event (must not benull)
-
needsBulkInvalidation
Whether a class-level MetaClass change involvingoldMc/newMcrequires process-wide bulk invalidation.Bulk is reserved for non-stock MetaClass kinds: not
MetaClassImplafter adapter unwrap. Stock pairs stay exact-class.- Parameters:
oldMc- previous MetaClass (may benull)newMc- new MetaClass (may benullon remove)- Returns:
trueif bulk invalidation is required
-
isStockMetaClass
Whethermcis a stock MOP MetaClass for which exact-class invalidation is sufficient:null, or unwrappedMetaClassImpl(includes EMC and subclasses). Any other kind is non-stock and triggers bulk invalidation on registry replace.- Parameters:
mc- MetaClass to classify (may benull)- Returns:
trueif exact-class invalidation is sufficient
-
collectLiveForClass
Collects the live SwitchPoint (if any) oftype's class domain. Does not create a MetaClass and does not allocate a domain generation.- Parameters:
type- class to inspect (must not benull)out- destination list
-
switchPointClassFor
Resolves the class used for the MetaClass SwitchPoint domain of a receiver.nullmaps toNullObject; aClassreceiver uses itself.- Parameters:
receiver- the call receiver (may benull)- Returns:
- the class whose class-level MetaClass SwitchPoint guards this site
-
switchPointForMetaClass
Returns the class-domain SwitchPoint for a MetaClass. The domain belongs tothe class, not the MetaClass instance, so every generation (and every adapter wrapping) of a class's MetaClass shares one domain.- Parameters:
mc- MetaClass (must not benull)- Returns:
- the class-domain SwitchPoint
-
invalidateMetaClass
Retires the class domain ofmc's class (if a generation was allocated). Does not bump counters (local domain retire; width policy is separate).- Parameters:
mc- MetaClass (may benull)
-
classSwitchPointFor
Returns the class-level MetaClass SwitchPoint for the given receiver.- Parameters:
receiver- the call receiver (may benull)- Returns:
- the MetaClass-domain switch point
-
classSwitchPointFor
Returns the SwitchPoint for the given class at link time: the current generation of the ClassInfo-owned class domain (defineClass-safe — does not create or consult a MetaClass).- Parameters:
type- the class (must not benull)- Returns:
- the SwitchPoint for monomorphic MOP guards
-
guardWithMopSwitchPoints
public static MethodHandle guardWithMopSwitchPoints(MethodHandle handle, MethodHandle fallback, Object receiver) Installs a MetaClass SwitchPoint guard onhandle. Public entry for tests; production usesIndyInterface.applyMopSwitchPoints.- Parameters:
handle- the fast-path handlefallback- the re-link / fallback handlereceiver- the receiver used to select the MetaClass-domain switch point- Returns:
- the guarded handle
-
guardWithMopSwitchPoints
public static MethodHandle guardWithMopSwitchPoints(MethodHandle handle, MethodHandle fallback, Class<?> receiverClass) Installs a MetaClass SwitchPoint guard onhandle.- Parameters:
handle- the fast-path handlefallback- the re-link / fallback handlereceiverClass- the class whose class-level MetaClass domain guards this site- Returns:
- the guarded handle
-
classInvalidationCount
public static long classInvalidationCount()Exact-class invalidation event count (invalidateClass(Class)).- Returns:
- class invalidation count
-
bulkInvalidationCount
public static long bulkInvalidationCount()Non-category process-wide bulk event count (invalidateBulk()/invalidateUnscoped()).- Returns:
- bulk invalidation count
-
categoryInvalidationCount
public static long categoryInvalidationCount()Category-style bulk invalidation count (invalidateCategory()).- Returns:
- category invalidation count
-
resetCountersForTesting
public static void resetCountersForTesting()Resets process-wide counters (tests only). Does not reset live switch points.
-