Package org.apache.groovy.runtime.indy

# Class AotDispatch

java.lang.Object
org.apache.groovy.runtime.indy.AotDispatch

public final class AotDispatch extends Object
Ahead-of-time link mode for indy dispatch (incubating).

GraalVM native image supports every `java.lang.invoke` building block Groovy's indy runtime uses except retargeting an existing call site: both `MutableCallSite.setTarget` and `SwitchPoint.invalidateAll` fail with `Unsupported method java.lang.invoke.MethodHandleNatives.setCallSiteTargetNormal`. In Groovy's design those two primitives only ever install or invalidate caches — the dispatch semantics live entirely in method selection — so under AOT the runtime links every site once to its cache-consulting default path (`ConstantCallSite`) and carries freshness in data instead:

- a global invalidation stamp, bumped wherever the JVM path would invalidate SwitchPoints;
- a stamp captured per cached `MethodHandleWrapper` at selection time and compared on every PIC hit — a mismatch is treated as a cache miss and re-selects;
- a pre-selection sample guarding the PIC write itself: when the stamp moves while a selection runs, the sentinel is cached instead of the wrapper, since the wrapper's construction-time stamp would postdate an invalidation its selection may have missed (SwitchPoint guards are immune to this window — their token is acquired during selection and mutated by the invalidation itself).

The JVM path is untouched: sites link mutable exactly as before, and the stamp is written but never read. Coarser than the scoped SwitchPoint invalidation of GROOVY-12191 (any invalidation flushes every AOT PIC entry on next hit), which is safe — staleness is impossible, over-invalidation just re-selects.

The retargeting restriction is particular to GraalVM native image — other ahead-of-time or checkpointed runtimes (ART, CRaC, HotSpot AOT caches) retarget call sites normally and never need this mode — so auto-detection probes only GraalVM's image-code property. The mode itself relies on nothing GraalVM-specific; `FORCE_PROPERTY` is the opt-in for any runtime that turns out to share the restriction.

Since:
  6.0.0

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final String`
  `FORCE_PROPERTY`
  Diagnostic knob: forces AOT link mode on a regular JVM so the whole mode can be exercised by ordinary tests without a native build.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static void`
  `invalidateAll(SwitchPoint[] switchPoints)`
  Invalidates the given switch points, AOT-safely: the global stamp is always advanced (so AOT-linked sites observe the change on their next PIC hit), and the actual `SwitchPoint.invalidateAll(java.lang.invoke.SwitchPoint[])` — which native image cannot execute — runs only outside AOT mode.
  `static boolean`
  `isAotLinkRequested()`
  Whether sites should link in AOT mode.
  `static long`
  `stamp()`
  The current global invalidation stamp.

  ### Methods inherited from class java.lang.Object

  `clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- ## Field Details

  - ### FORCE_PROPERTY

    public static final String FORCE_PROPERTY
    Diagnostic knob: forces AOT link mode on a regular JVM so the whole mode can be exercised by ordinary tests without a native build.

    Set it at JVM startup (or before any Groovy code runs) and leave it alone. Because `isAotLinkRequested()` is re-evaluated per link and per invalidation, flipping the property on mid-run suppresses the real `SwitchPoint.invalidateAll(java.lang.invoke.SwitchPoint[])` that sites already linked in mutable mode depend on — their guards never fire and they dispatch stale. (Flipping it off is merely wasteful: sites linked while it was on keep consulting the stamp, which keeps advancing, so they stay correct but never regain the retargeting fast path.)

    See Also:
      - Constant Field Values

- ## Method Details

  - ### isAotLinkRequested

    public static boolean isAotLinkRequested()
    Whether sites should link in AOT mode. Evaluated per call and never cached in a static: under native image this class may be initialized at image build time, where `org.graalvm.nativeimage.imagecode` reports `buildtime` — caching would bake the wrong answer into the image heap. Callers are all link-time or invalidation-time (cold); per-invocation code reads the site-local flag captured at link time instead.

  - ### stamp

    public static long stamp()
    The current global invalidation stamp.

  - ### invalidateAll

    public static void invalidateAll(SwitchPoint[] switchPoints)
    Invalidates the given switch points, AOT-safely: the global stamp is always advanced (so AOT-linked sites observe the change on their next PIC hit), and the actual `SwitchPoint.invalidateAll(java.lang.invoke.SwitchPoint[])` — which native image cannot execute — runs only outside AOT mode. All indy invalidation funnels through here.
    Parameters:
      `switchPoints` - the points to invalidate; may be empty