Class CompileStack
Some Notes:
- every push method will require a later pop call
- method parameters may define a category 2 variable, so don't ignore the type stored in the variable object
- the index of the variable may not be as assumed when the variable is a parameter of a method because the parameter may be used in a closure, so don't ignore the stored variable index
- the names of temporary variables can be ignored. The names are only used for debugging and do not conflict with each other or normal variables. For accessing, the index of the variable must be used.
- never mix temporary and normal variables by changes to this class. While the name is very important for a normal variable, it is only a helper construct for temporary variables. That means for example a name for a temporary variable can be used multiple times without conflict. So mixing them both may lead to the problem that a normal or temporary variable is hidden or even removed. That must not happen!
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic classRecords a block for finally or other special handling.protected static classRepresents a label range for exception handling or other scoping. -
Constructor Summary
ConstructorsConstructorDescriptionCompileStack(WriterController controller) Creates a CompileStack managed by the given controller. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddExceptionBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, org.objectweb.asm.Label goal, String sig) Adds a typed or untyped exception handler to the exception table for the current method.voidApplies all currently active finally blocks for a normal (non-jump) fall-through.voidapplyFinallyBlocks(org.objectweb.asm.Label label, boolean isBreakLabel) Applies any pending finally blocks on the path tolabel.voidclear()Clears the state of the class.booleancontainsVariable(String name) org.objectweb.asm.LabelcreateLocalLabel(String name) Creates or returns the label for the given name.intdefineTemporaryVariable(String name, boolean store) Creates a temporary variable.intdefineTemporaryVariable(String name, ClassNode type, boolean store) Creates a temporary variable.intdefineTemporaryVariable(Variable var, boolean store) Creates a temporary variable.defineVariable(Variable v, boolean initFromStack) Defines a new Variable using an AST variable.defineVariable(Variable v, ClassNode variableType, boolean initFromStack) Defines a variable for the given AST variable using an explicitly specified bytecode type (which may differ from the declared type, e.g.org.objectweb.asm.LabelReturns the current break label, ornullif not inside a breakable construct.org.objectweb.asm.LabelReturns the current continue label, ornullif not inside a loop.org.objectweb.asm.LabelReturns the label for the given name.org.objectweb.asm.LabelgetNamedBreakLabel(String name) org.objectweb.asm.LabelgetNamedContinueLabel(String name) getScope()Returns the current variable scope.getVariable(String variableName) Returns a variable by name, throwing aGroovyBugErrorif it does not exist.getVariable(String variableName, boolean mustExist) Returns a normal variable.booleanReturnstrueif there are any active finally/synchronized blocks on the stack.voidinit(VariableScope scope, Parameter[] parameters) initializes this class for a MethodNode.booleanReturnstrueif the currentthisreference is implicit (no explicit qualifier).booleanReturnstrueif the current context is inside a special constructor call (super(...)orthis(...)).booleanisLHS()Returnstrueif the current expression is being compiled as a left-hand side.voidpop()Restores the compilation state that was saved by the matchingpush*call, and emits end-labels for all local variables declared within the scope that is being popped.voidpopBlockRecorderVisit(CompileStack.BlockRecorder finallyBlock) RemovesfinallyBlockfrom the visited-block set after its inline emission is complete.voidPops the top implicit-this flag, restoring the previous state.voidpopLHS()Pops the top left-hand-side flag, restoring the previous LHS state.voidpushBlockRecorder(CompileStack.BlockRecorder recorder) Pushes a newCompileStack.BlockRecorder(finally or synchronized guard) onto the block-recorder stack and saves state so thatpop()will remove it.voidpushBlockRecorderVisit(CompileStack.BlockRecorder finallyBlock) MarksfinallyBlockas currently being visited so that recursive finally-block application does not re-enter it.voidDeprecated.org.objectweb.asm.LabelpushBreakable(List<String> labelNames) Creates a new break label and an element for the state stack so pop has to be called later.voidpushImplicitThis(boolean implicitThis) Pushes a new implicit-this flag onto the stack.voidEnters a special constructor call context (super(...)orthis(...)).voidpushLHS(boolean lhs) Pushes a new left-hand-side flag onto the LHS stack.voidDeprecated.voidShould be called when descending into a loop that does not define a scope Creates a element for the state stack so pop has to be called later.voidpushLoop(VariableScope scope, String labelName) Deprecated.voidpushLoop(VariableScope scope, List<String> labelNames) Should be called when descending into a loop that defines also a scope.voidSaves the current compilation state onto an internal stack so that it can be restored by a later call topop().org.objectweb.asm.LabelCreates a new break label and an element for the state stack so pop has to be called later.org.objectweb.asm.LabelpushSwitch(List<String> labelNames) Creates a new break label, registers it as the named break target for each label name, and pushes an element onto the state stack so that a later call topop()restores the previous state.voidpushVariableScope(VariableScope scope) Causes the state-stack to add an element and sets the given scope as new current variable scope.voidremoveVar(int variableIndex) Indicates that the specified temporary variable is no longer used.voidvisitExcludedFinally(CompileStack.BlockRecorder recorder, Runnable visit) Inlines an excluded finally block viavisitwhile hiding the variables of the current (try) scope, then fully restores that scope — including its variables.voidwriteExceptionTable(CompileStack.BlockRecorder block, org.objectweb.asm.Label goal, String sig) Writes the exception-table entries for all label ranges recorded inblock.
-
Constructor Details
-
CompileStack
Creates a CompileStack managed by the given controller.- Parameters:
controller- the writer controller for the current compilation
-
-
Method Details
-
getBreakLabel
public org.objectweb.asm.Label getBreakLabel()Returns the current break label, ornullif not inside a breakable construct. -
getContinueLabel
public org.objectweb.asm.Label getContinueLabel()Returns the current continue label, ornullif not inside a loop. -
getScope
Returns the current variable scope. -
pushState
public void pushState()Saves the current compilation state onto an internal stack so that it can be restored by a later call topop(). Everypush*method calls this internally; it is also exposed for callers that need a bare state snapshot without additional label setup. -
removeVar
public void removeVar(int variableIndex) Indicates that the specified temporary variable is no longer used. -
pop
public void pop()Restores the compilation state that was saved by the matchingpush*call, and emits end-labels for all local variables declared within the scope that is being popped. -
defineTemporaryVariable
Creates a temporary variable.- Parameters:
var- specifies name and typestore- defines if the toplevel argument of the stack should be stored- Returns:
- the index used for this temporary variable
-
getVariable
Returns a variable by name, throwing aGroovyBugErrorif it does not exist. Convenience overload ofgetVariable(String, boolean)withmustExist = true.- Parameters:
variableName- the name to look up- Returns:
- the corresponding
BytecodeVariable
-
getVariable
Returns a normal variable.If
mustExistis true and the normal variable doesn't exist, then this method will throw a GroovyBugError. It is not the intention of this method to let this happen! And the exception should not be used for flow control - it is just acting as an assertion. If the exception is thrown then it indicates a bug in the class using CompileStack. This method can also not be used to return a temporary variable. Temporary variables are not normal variables.- Parameters:
variableName- name of the variablemustExist- throw exception if variable does not exist- Returns:
- the normal variable or null if not found (and
mustExistnot true)
-
defineTemporaryVariable
Creates a temporary variable.- Parameters:
name- defines type and namestore- defines if the top-level argument of the stack should be stored- Returns:
- the index used for this temporary variable
-
defineTemporaryVariable
Creates a temporary variable.- Parameters:
name- the variable nametype- the variable typestore- indicates if the top-level argument of the stack should be stored- Returns:
- the index used for this temporary variable
-
clear
public void clear()Clears the state of the class. This method should be called after a MethodNode is visited. Note that a call to init will fail if clear is not called before -
addExceptionBlock
public void addExceptionBlock(org.objectweb.asm.Label start, org.objectweb.asm.Label end, org.objectweb.asm.Label goal, String sig) Adds a typed or untyped exception handler to the exception table for the current method. Typed entries (non-nullsig) are emitted before untyped ones to ensure correct handler ordering in the bytecode.- Parameters:
start- the start label of the guarded rangeend- the end label of the guarded rangegoal- the label of the handler blocksig- the internal name of the caught exception type, ornullfor a catch-all handler
-
init
initializes this class for a MethodNode. This method will automatically define variables for the method parameters and will create references if needed. The created variables can be accessed by calling getVariable(). -
pushVariableScope
Causes the state-stack to add an element and sets the given scope as new current variable scope. Creates an element for the state stack so pop has to be called later -
pushLoop
Should be called when descending into a loop that defines also a scope. Calls pushVariableScope and prepares labels for a loop structure. Creates an element for the state stack so pop has to be called later -
pushLoop
Deprecated.Should be called when descending into a loop that defines also a scope. Calls pushVariableScope and prepares labels for a loop structure. Creates a element for the state stack so pop has to be called later. -
pushLoop
Should be called when descending into a loop that does not define a scope Creates a element for the state stack so pop has to be called later. -
pushLoop
Deprecated.Should be called when descending into a loop that does not define a scope. Creates a element for the state stack so pop has to be called later. -
pushSwitch
public org.objectweb.asm.Label pushSwitch()Creates a new break label and an element for the state stack so pop has to be called later.- Returns:
- the break label
-
pushSwitch
Creates a new break label, registers it as the named break target for each label name, and pushes an element onto the state stack so that a later call topop()restores the previous state.- Parameters:
labelNames- the statement labels on the switch (may benull)- Returns:
- the break label
- Since:
- 6.0.0
-
pushBreakable
Creates a new break label and an element for the state stack so pop has to be called later.- Returns:
- the break label
- Since:
- 6.0.0
-
getNamedBreakLabel
- Returns:
- the
breaklabel for name
-
getNamedContinueLabel
- Returns:
- the
continuelabel for name
-
getLabel
Returns the label for the given name. -
createLocalLabel
Creates or returns the label for the given name. -
pushBooleanExpression
Deprecated.UsepushState()directly.Because a boolean Expression may not be evaluated completely it is important to keep the registers clean. -
defineVariable
Defines a new Variable using an AST variable.- Parameters:
initFromStack- if true the last element of the stack will be used to initialize the new variable. If false null will be used.
-
defineVariable
Defines a variable for the given AST variable using an explicitly specified bytecode type (which may differ from the declared type, e.g. when widening for closure-shared variables).- Parameters:
v- the AST variable to definevariableType- the bytecode type to assign to the slotinitFromStack- iftruethe top of the operand stack is stored into the new slot; otherwise a default/null value is used- Returns:
- the created
BytecodeVariable
-
containsVariable
- Parameters:
name- the name of the variable of interest- Returns:
- true if a variable is already defined
-
applyFinallyBlocks
public void applyFinallyBlocks(org.objectweb.asm.Label label, boolean isBreakLabel) Applies any pending finally blocks on the path tolabel. Walks the state stack to determine which finally blocks are between the current position and the target label and inlines their bytecode.- Parameters:
label- the target label (break or continue destination)isBreakLabel-truefor a break label,falsefor continue
-
applyBlockRecorder
public void applyBlockRecorder()Applies all currently active finally blocks for a normal (non-jump) fall-through. -
hasBlockRecorder
public boolean hasBlockRecorder()Returnstrueif there are any active finally/synchronized blocks on the stack. -
pushBlockRecorder
Pushes a newCompileStack.BlockRecorder(finally or synchronized guard) onto the block-recorder stack and saves state so thatpop()will remove it.- Parameters:
recorder- the recorder to push
-
pushBlockRecorderVisit
MarksfinallyBlockas currently being visited so that recursive finally-block application does not re-enter it.- Parameters:
finallyBlock- the block being visited
-
popBlockRecorderVisit
RemovesfinallyBlockfrom the visited-block set after its inline emission is complete.- Parameters:
finallyBlock- the block that finished being visited
-
visitExcludedFinally
Inlines an excluded finally block viavisitwhile hiding the variables of the current (try) scope, then fully restores that scope — including its variables.Popping the current scope keeps try-block locals out of scope in the finally body (GROOVY-4721); restoring the saved variables afterwards ensures any subsequent re-emission of the same statement (e.g. the
OptimizingStatementWriterfast/slow fork) still resolves those locals rather than falling back to property access (GROOVY-12062).- Parameters:
recorder- the block recorder being visitedvisit- emits the finally body
-
writeExceptionTable
public void writeExceptionTable(CompileStack.BlockRecorder block, org.objectweb.asm.Label goal, String sig) Writes the exception-table entries for all label ranges recorded inblock.- Parameters:
block- the block recorder containing the try-range labelsgoal- the handler labelsig- the internal name of the caught type, ornullfor catch-all
-
isLHS
public boolean isLHS()Returnstrueif the current expression is being compiled as a left-hand side. -
pushLHS
public void pushLHS(boolean lhs) Pushes a new left-hand-side flag onto the LHS stack.- Parameters:
lhs-trueif the next expression is compiled as an assignment target
-
popLHS
public void popLHS()Pops the top left-hand-side flag, restoring the previous LHS state. -
isImplicitThis
public boolean isImplicitThis()Returnstrueif the currentthisreference is implicit (no explicit qualifier). -
pushImplicitThis
public void pushImplicitThis(boolean implicitThis) Pushes a new implicit-this flag onto the stack.- Parameters:
implicitThis-trueifthisis used implicitly in the current context
-
popImplicitThis
public void popImplicitThis()Pops the top implicit-this flag, restoring the previous state. -
isInSpecialConstructorCall
public boolean isInSpecialConstructorCall()Returnstrueif the current context is inside a special constructor call (super(...)orthis(...)). -
pushInSpecialConstructorCall
public void pushInSpecialConstructorCall()Enters a special constructor call context (super(...)orthis(...)). Pushes state so thatpop()will restore the previous context.
-
pushState()directly.