Package: org.apache.groovy.runtime.indy

## [Java] Class AotDispatch

- 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
    Modifiers | Name | Description
    --- | --- | ---
    `static 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.

  - ### Methods Summary

    Methods
    Type Params | Return Type | Name and description
    --- | --- | ---
    `` | `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 — which native image cannot execute — runs only outside AOT mode.
    `` | `public static boolean` | `isAotLinkRequested()` Whether sites should link in AOT mode.
    `` | `public static long` | `stamp()` The current global invalidation stamp.

  - ### Inherited Methods Summary

    Inherited Methods
    Methods inherited from class | Name
    --- | ---
    `class Object` | `equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

- - ### Field Detail

    - #### 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 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.)

  - ### Method Detail

    - #### 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 — 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

    - #### 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.

    - #### public static long stamp()

      The current global invalidation stamp.