Package org.codehaus.groovy.classgen.asm

# Class ClosureWriter

java.lang.Object
org.codehaus.groovy.classgen.asm.ClosureWriter

Direct Known Subclasses:
  `LambdaWriter`, `StaticTypesClosureWriter`

public class ClosureWriter extends Object
Generates bytecode for closure expressions.

- ## Nested Class Summary

  Nested Classes
  Modifier and Type
  Class
  Description
  `protected static class`
  `ClosureWriter.CorrectAccessedVariableVisitor`
  Visitor that rewrites `VariableExpression` nodes whose accessed variable is a `FieldNode` in an outer class to instead reference the corresponding field in the generated closure inner class.
  `protected static interface`
  `ClosureWriter.UseExistingReference`
  Marker interface for using existing reference.

- ## Field Summary

  Fields
  Modifier and Type
  Field
  Description
  `protected final WriterController`
  `controller`
  The controller coordinating all bytecode writers for the current class.
  `static final String`
  `GENERATED_CLOSURE_CLASS`
  Node metadata key set on a `ClosureExpression` once it has been compiled to a generated closure class, holding that class's name.
  `static final String`
  `OUTER_INSTANCE`
  Field name for the outer instance reference.
  `static final String`
  `PACKED_METHOD_PREFIX`
  Name prefix of hoisted packed-closure bodies (also consulted by the static call-site writer).
  `static final String`
  `THIS_OBJECT`
  Field name for the this object reference.

- ## Constructor Summary

  Constructors
  Constructor
  Description
  `ClosureWriter(WriterController controller)`
  Creates a closure writer with the given controller.

- ## Method Summary

  Modifier and Type
  Method
  Description
  `protected ConstructorNode`
  `addConstructor(ClosureExpression expression, Parameter[] localVariableParams, InnerClassNode answer, BlockStatement block)`
  Adds a synthetic `public` constructor to the closure inner class that accepts the outer instance, `this` object, and all captured local variable references.
  `protected void`
  `addFieldsForLocalVariables(InnerClassNode closureClass, Parameter[] localVariableParams)`
  Adds synthetic private fields to the closure inner class for each captured local variable parameter, promoting them to `Reference` holders.
  `boolean`
  `addGeneratedClosureConstructorCall(ConstructorCallExpression call)`
  Emits a `super(outerInstance, thisObject)` constructor call for a generated closure class.
  `protected void`
  `addSerialVersionUIDField(ClassNode classNode)`
  Adds a synthetic `serialVersionUID` field to the closure class, derived from a hash of the class name.
  `protected BlockStatement`
  `createBlockStatementForConstructor(ClosureExpression expression, ClassNode outerClass, ClassNode thisClassNode)`
  Creates the block statement for the closure's synthetic constructor, setting up the `super(outerInstance, thisObject)` call and captured variable references.
  `protected ClassNode`
  `createClosureClass(ClosureExpression expression, int modifiers)`
  Creates a new inner class node representing the compiled form of a closure expression.
  `protected Parameter[]`
  `getClosureSharedVariables(ClosureExpression expression)`
  Collects the closure-shared local variables referenced by a closure expression as an array of `Parameter`s, using the type chooser to infer each variable's type.
  `ClassNode`
  `getOrAddClosureClass(ClosureExpression expression, int modifiers)`
  Returns the existing generated class for a closure expression, or creates and registers a new one if none exists yet.
  `protected boolean`
  `isPackTriggered(ClosureExpression expression, boolean annotated)`
  Whether a packable, non-escaping closure literal should actually be packed.
  `static void`
  `loadReference(String name, WriterController controller)`
  Loads a closure-shared variable reference onto the operand stack, looking it up as a field, local variable, or outer closure field as appropriate.
  `protected void`
  `loadThis()`
  Loads the effective `this` reference onto the operand stack — either the actual receiver for a regular method, or the result of `getThisObject()` for a generated closure/lambda.
  `protected void`
  `markHoistedBody(MethodNode hoisted)`
  Marks the hoisted body's compilation mode; the static writer overrides this to compile it statically.
  `protected boolean`
  `packedClosureUsesDelegateGuard()`
  Whether the packed adapter installs the runtime delegate guard.
  `protected ClassNode`
  `readOnlyCaptureType(String name, ClassNode declaredType, Variable variable)`
  The declared type of a read-only (by-value) capture parameter on the hoisted method.
  `protected static void`
  `removeInitialValues(Parameter[] params)`
  Strips initial-value expressions from parameters that are closure-shared, ensuring the closure constructor is not duplicated.
  `protected String`
  `triggerDeclineReason(ClosureExpression expression)`
  A trigger-specific decline reason for `declineReason(org.codehaus.groovy.ast.expr.ClosureExpression)`, or `null` if the trigger did not decline this closure.
  `void`
  `writeClosure(ClosureExpression expression)`
  Generates bytecode for a closure expression.
  `void`
  `writePackedDispatcher()`
  Emits the class's packed-closure dispatch machinery, once per class at the end of class generation (so every hoisted body — including one a hoisted body itself hoisted — has claimed its id): the `$packedDispatch$(int, Object[])` table, whose case `k` casts the packed argument array (`[owner, captured..., args...]`) to target `k`'s declared parameter types and invokes it directly; the array-free per-arity tables (`$packedDispatch1$`/`$packedDispatch2$`) doing the same from plain parameter slots for the hot one/two-value shapes; and the `$getPackedDispatchers$()` accessor, whose single `invokedynamic` site links all three through `IndyInterface.packedDispatchers` (delegating to `GeneratedDispatcher.bootstrap`) into one constant bundle, lazily on first adapter creation.

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

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

- ## Field Details

  - ### OUTER_INSTANCE

    public static final String OUTER_INSTANCE
    Field name for the outer instance reference.
    See Also:
      - Constant Field Values

  - ### THIS_OBJECT

    public static final String THIS_OBJECT
    Field name for the this object reference.
    See Also:
      - Constant Field Values

  - ### controller

    protected final WriterController controller
    The controller coordinating all bytecode writers for the current class.

  - ### PACKED_METHOD_PREFIX

    public static final String PACKED_METHOD_PREFIX
    Name prefix of hoisted packed-closure bodies (also consulted by the static call-site writer).
    See Also:
      - Constant Field Values

  - ### GENERATED_CLOSURE_CLASS

    public static final String GENERATED_CLOSURE_CLASS
    Node metadata key set on a `ClosureExpression` once it has been compiled to a generated closure class, holding that class's name. Tooling such as the AST browser can read it to show which synthetic class a closure literal became; the compiler itself never consults it. The mark only becomes available after the class-generation phase, since that is when the class is made.

- ## Constructor Details

  - ### ClosureWriter

    public ClosureWriter(WriterController controller)
    Creates a closure writer with the given controller.
    Parameters:
      `controller` - the writer controller

- ## Method Details

  - ### writeClosure

    public void writeClosure(ClosureExpression expression)
    Generates bytecode for a closure expression.
    Parameters:
      `expression` - the closure expression

  - ### isPackTriggered

    protected boolean isPackTriggered(ClosureExpression expression, boolean annotated)
    Whether a packable, non-escaping closure literal should actually be packed. Dynamic compilation has no proof of delegate-independence, so the only trigger is the `@PackedClosures` trust assertion; `StaticTypesClosureWriter` overrides this to add the `groovy.target.closure.pack` flag and the delegate-independence proof.
    Parameters:
      `annotated` - whether a non-DISABLED `@PackedClosures` is in scope

  - ### triggerDeclineReason

    protected String triggerDeclineReason(ClosureExpression expression)
    A trigger-specific decline reason for `declineReason(org.codehaus.groovy.ast.expr.ClosureExpression)`, or `null` if the trigger did not decline this closure. Only the static writer has one (a delegate-resolved body); the dynamic path trusts the annotation and never declines on trigger grounds.

  - ### readOnlyCaptureType

    protected ClassNode readOnlyCaptureType(String name, ClassNode declaredType, Variable variable)
    The declared type of a read-only (by-value) capture parameter on the hoisted method. The dynamic writer types it as `Object`; the static writer overrides this to the capture's declared/flow-inferred type so the body compiles with static dispatch. This is the seam that keeps @CompileStatic-specific typing out of the general (dynamic) emitter.

  - ### markHoistedBody

    protected void markHoistedBody(MethodNode hoisted)
    Marks the hoisted body's compilation mode; the static writer overrides this to compile it statically.

  - ### packedClosureUsesDelegateGuard

    protected boolean packedClosureUsesDelegateGuard()
    Whether the packed adapter installs the runtime delegate guard. The dynamic trust path needs it (an unverifiable assertion must fail fast on misuse); the static writer proved independence, so it overrides this to `false` and a caller-set delegate is then stored and ignored.

  - ### writePackedDispatcher

    public void writePackedDispatcher()
    Emits the class's packed-closure dispatch machinery, once per class at the end of class generation (so every hoisted body — including one a hoisted body itself hoisted — has claimed its id): the `$packedDispatch$(int, Object[])` table, whose case `k` casts the packed argument array (`[owner, captured..., args...]`) to target `k`'s declared parameter types and invokes it directly; the array-free per-arity tables (`$packedDispatch1$`/`$packedDispatch2$`) doing the same from plain parameter slots for the hot one/two-value shapes; and the `$getPackedDispatchers$()` accessor, whose single `invokedynamic` site links all three through `IndyInterface.packedDispatchers` (delegating to `GeneratedDispatcher.bootstrap`) into one constant bundle, lazily on first adapter creation. A no-op for classes that packed nothing.

  - ### loadReference

    public static void loadReference(String name, WriterController controller)
    Loads a closure-shared variable reference onto the operand stack, looking it up as a field, local variable, or outer closure field as appropriate.
    Parameters:
      `name` - the variable name to load
      `controller` - the writer controller for the enclosing class

  - ### getOrAddClosureClass

    public ClassNode getOrAddClosureClass(ClosureExpression expression, int modifiers)
    Returns the existing generated class for a closure expression, or creates and registers a new one if none exists yet.
    Parameters:
      `expression` - the closure expression to compile as an inner class
      `modifiers` - the access modifiers for the generated class
    Returns:
      the generated closure class node

  - ### createClosureClass

    protected ClassNode createClosureClass(ClosureExpression expression, int modifiers)
    Creates a new inner class node representing the compiled form of a closure expression.
    Parameters:
      `expression` - the closure expression to compile
      `modifiers` - the access modifiers for the generated class
    Returns:
      the newly created closure class node

  - ### addSerialVersionUIDField

    protected void addSerialVersionUIDField(ClassNode classNode)
    Adds a synthetic `serialVersionUID` field to the closure class, derived from a hash of the class name.
    Parameters:
      `classNode` - the closure class node to add the field to

  - ### addConstructor

    protected ConstructorNode addConstructor(ClosureExpression expression, Parameter[] localVariableParams, InnerClassNode answer, BlockStatement block)
    Adds a synthetic `public` constructor to the closure inner class that accepts the outer instance, `this` object, and all captured local variable references.
    Parameters:
      `expression` - the closure expression
      `localVariableParams` - parameters for closure-shared local variables
      `answer` - the closure inner class node
      `block` - the constructor body
    Returns:
      the created constructor node

  - ### addFieldsForLocalVariables

    protected void addFieldsForLocalVariables(InnerClassNode closureClass, Parameter[] localVariableParams)
    Adds synthetic private fields to the closure inner class for each captured local variable parameter, promoting them to `Reference` holders.
    Parameters:
      `closureClass` - the closure inner class node
      `localVariableParams` - the closure-shared local variable parameters

  - ### createBlockStatementForConstructor

    protected BlockStatement createBlockStatementForConstructor(ClosureExpression expression, ClassNode outerClass, ClassNode thisClassNode)
    Creates the block statement for the closure's synthetic constructor, setting up the `super(outerInstance, thisObject)` call and captured variable references.
    Parameters:
      `expression` - the closure expression
      `outerClass` - the class declaring the closure
      `thisClassNode` - the `this` type in scope at the closure declaration site
    Returns:
      the block statement for the constructor body

  - ### removeInitialValues

    protected static void removeInitialValues(Parameter[] params)
    Strips initial-value expressions from parameters that are closure-shared, ensuring the closure constructor is not duplicated.
    Parameters:
      `params` - the parameters to mutate in-place

  - ### addGeneratedClosureConstructorCall

    public boolean addGeneratedClosureConstructorCall(ConstructorCallExpression call)
    Emits a `super(outerInstance, thisObject)` constructor call for a generated closure class. Returns `false` if the current class is not a generated closure.
    Parameters:
      `call` - the constructor call expression representing `super(...)`
    Returns:
      `true` if the closure constructor call was emitted

  - ### getClosureSharedVariables

    protected Parameter[] getClosureSharedVariables(ClosureExpression expression)
    Collects the closure-shared local variables referenced by a closure expression as an array of `Parameter`s, using the type chooser to infer each variable's type.
    Parameters:
      `expression` - the closure expression
    Returns:
      the array of parameters representing captured shared variables

  - ### loadThis

    protected void loadThis()
    Loads the effective `this` reference onto the operand stack — either the actual receiver for a regular method, or the result of `getThisObject()` for a generated closure/lambda.