Package org.codehaus.groovy.runtime

# Interface GeneratedDispatcher

Functional Interface:
  This is a functional interface and can therefore be used as the assignment target for a lambda expression or method reference.

@FunctionalInterface public interface GeneratedDispatcher
A per-class table of compiler-generated dispatch targets, reached by a compact integer id instead of a `MethodHandle`.

The compiler emits per class: an array-shaped table (`$packedDispatch$(int, Object[])`, covering every target) plus array-free per-arity tables (`$packedDispatch1$`, `$packedDispatch2$`) for the hot shapes taking one or two values beyond the receiver — avoiding the packed argument array, which cannot be scalar-replaced when the dispatch call does not inline. Each table is a switch over the id whose case casts the arguments to the target's declared parameter types and invokes it directly, so the whole chain is ordinary, JIT-friendly bytecode. A single `invokedynamic` accessor per class links all three through `bootstrap(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType)` into one constant `GeneratedDispatcher.Bundle`, created lazily on first use.

Adapters such as `PackedClosure` hold `(dispatchers, id)` and make a plain interface call per invocation. Unlike a `MethodHandle` held in an instance field — which the JIT cannot treat as a constant, so every call runs the (comparatively slow) method-handle invoker — this executes as a cheap indirect call, and inlines fully when the call site is monomorphic. The id space is not limited to packed closure bodies: any statically-known target the compiler wants to reach through a shared adapter (for example a statically-resolved method reference) can claim an id in the same tables.

Since:
  6.0.0

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Interface
  Description
  `static interface`
  `GeneratedDispatcher.Arity1`
  Array-free companion for targets taking exactly one value beyond the receiver.
  `static interface`
  `GeneratedDispatcher.Arity2`
  Array-free companion for targets taking exactly two values beyond the receiver.
  `static final class`
  `GeneratedDispatcher.Bundle`
  The hosting class's three dispatch shapes, linked once by `bootstrap(java.lang.invoke.MethodHandles.Lookup, java.lang.String, java.lang.invoke.MethodType)` and shared by all of that class's adapters.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `static final String`
  `TABLE_METHOD`
  Name of the generated array-shaped dispatch table method.
  `static final String`
  `TABLE1_METHOD`
  Name of the generated one-value dispatch table method.
  `static final String`
  `TABLE2_METHOD`
  Name of the generated two-value dispatch table method.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `static CallSite`
  `bootstrap(MethodHandles.Lookup caller, String name, MethodType type)`
  Legacy invokedynamic bootstrap for the dispatcher accessor, kept for class files emitted by earlier 6.0 pre-releases: adapts the class's three private static dispatch tables to their functional interfaces (one hidden class each, via `LambdaMetafactory` with the caller's full-privilege lookup) and returns them as one constant `GeneratedDispatcher.Bundle`.
  `static CallSite`
  `bootstrap(MethodHandles.Lookup caller, String name, MethodType type, MethodHandle factory)`
  Invokedynamic bootstrap for the dispatcher accessor: the hosting class supplies (as a constant bootstrap argument) a compiler-emitted factory that builds the bundle from its own bytecode-level `LambdaMetafactory` sites, so linking is one call and this method neither looks anything up nor defines any class — fit for any ahead-of-time runtime that restricts run-time reflection or class definition.
  `Object`
  `dispatch(int id, Object[] args)`
  Invokes the dispatch target registered under `id` in the hosting class.
  `static Class<?>[]`
  `paramTypes(MethodHandles.Lookup caller, String name, Class<?> type, String descriptor)`
  Constant-dynamic bootstrap for a closure literal's declared parameter types: decodes a method descriptor (which, unlike `Class` constants, can carry primitive types) with the hosting class's loader into a `Class[]` resolved once per literal site and shared by every adapter created there — closure creation then loads one constant instead of allocating and filling an array.

- ## Field Details

  - ### TABLE_METHOD

    static final String TABLE_METHOD
    Name of the generated array-shaped dispatch table method.
    See Also:
      - Constant Field Values

  - ### TABLE1_METHOD

    static final String TABLE1_METHOD
    Name of the generated one-value dispatch table method.
    See Also:
      - Constant Field Values

  - ### TABLE2_METHOD

    static final String TABLE2_METHOD
    Name of the generated two-value dispatch table method.
    See Also:
      - Constant Field Values

- ## Method Details

  - ### dispatch

    Object dispatch(int id, Object[] args)
    Invokes the dispatch target registered under `id` in the hosting class.
    Parameters:
      `id` - the compile-time-assigned index of the target in the hosting class's table
      `args` - the packed argument array: `args[0]` is the receiver (the adapter's owner — ignored by static targets), followed by any captured values, then the call arguments, all in the target's declared parameter order
    Returns:
      the target's return value (`null` for a void target)

  - ### paramTypes

    static Class<?>[] paramTypes(MethodHandles.Lookup caller, String name, Class<?> type, String descriptor)
    Constant-dynamic bootstrap for a closure literal's declared parameter types: decodes a method descriptor (which, unlike `Class` constants, can carry primitive types) with the hosting class's loader into a `Class[]` resolved once per literal site and shared by every adapter created there — closure creation then loads one constant instead of allocating and filling an array. Sharing matches generated closure classes, whose parameter-type arrays are likewise cached per class. Emitted bytecode reaches this through `org.codehaus.groovy.vmplugin.v8.IndyInterface#packedParamTypes`, which delegates here.
    Parameters:
      `caller` - the hosting class's lookup (supplied by the JVM)
      `name` - the constant's name (unused)
      `type` - the constant's type: `Class[]`
      `descriptor` - a method descriptor whose parameter types are the closure's declared parameter types (the return type is ignored)
    Returns:
      the declared parameter types

  - ### bootstrap

    static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type) throws Throwable
    Legacy invokedynamic bootstrap for the dispatcher accessor, kept for class files emitted by earlier 6.0 pre-releases: adapts the class's three private static dispatch tables to their functional interfaces (one hidden class each, via `LambdaMetafactory` with the caller's full-privilege lookup) and returns them as one constant `GeneratedDispatcher.Bundle`. Current class files link through the one-`MethodHandle` overload instead. Emitted bytecode reaches this through `org.codehaus.groovy.vmplugin.v8.IndyInterface#packedDispatchers` — the central bytecode-facing bootstrap surface — which delegates here.
    Parameters:
      `caller` - the hosting class's lookup (supplied by the JVM)
      `name` - the invoked name (unused)
      `type` - the accessor's type: `() -> Object` as emitted (typed loosely so the `Bundle` type stays off the emitted-bytecode surface); the constant is typed off the requested return type, so `() -> Bundle` also links
    Returns:
      a constant call site producing the bundle
    Throws:
      `Throwable` - if the tables cannot be found or linked (a compiler bug)

  - ### bootstrap

    static CallSite bootstrap(MethodHandles.Lookup caller, String name, MethodType type, MethodHandle factory) throws Throwable
    Invokedynamic bootstrap for the dispatcher accessor: the hosting class supplies (as a constant bootstrap argument) a compiler-emitted factory that builds the bundle from its own bytecode-level `LambdaMetafactory` sites, so linking is one call and this method neither looks anything up nor defines any class — fit for any ahead-of-time runtime that restricts run-time reflection or class definition. Under GraalVM native image, the verified case, those sites are pre-processed at image build time and the factory's method references reach the class's own private tables without reflection metadata (GROOVY-12227). Emitted bytecode reaches this through `org.codehaus.groovy.vmplugin.v8.IndyInterface#packedDispatchers`.
    Parameters:
      `caller` - the hosting class's lookup (supplied by the JVM, unused)
      `name` - the invoked name (unused)
      `type` - the accessor's type (see the three-argument overload)
      `factory` - the hosting class's `$packedDispatchersFactory$`, `() -> Bundle`
    Returns:
      a constant call site producing the bundle
    Throws:
      `Throwable` - if the factory fails (a compiler bug)