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 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:
  • 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