T - the type of the block element nodepublic abstract class BlockNode<T extends Node> extends Node
Elements are executed using the BlockNode.ElementExecutor provided when
creating the block node. When a block is executed then
all elements are executed using executeVoid except the last element which will be executed using the typed execute method also
used to execute the block node. This allows to implement boxing elimination of the return value
of blocks in the interpreter. For example, if executeInt
is invoked on the block , then all elements except the last one is executed using
executeVoid, but the last one
with executeInt.
The optimizing runtime may decide to group elements of a block into multiple block compilation units. This may happen if the block is too big to be compiled with a single compilation unit. If the compilation final state of an element is changed, or a node is replaced only the compilation unit of the current block is invalidated and not all compilations units of a block. Therefore, no compilation final assumptions must be taken between elements of a block.
// language base node abstract class LanguageNode extendsNode{ public abstractObjectexecute(VirtualFrameframe); } final class LanguageBlockNode extends LanguageNode implementsBlockNode.ElementExecutor<LanguageNode> { @Child privateBlockNode<LanguageNode> block; LanguageBlockNode(LanguageNode[] elements) { this.block =BlockNode.create(elements, this); } @Overridepublic void executeVoid(VirtualFrameframe, LanguageNode node, int index, int arg) { node.execute(frame); } @OverridepublicObjectexecuteGeneric(VirtualFrameframe, LanguageNode node, int index, int arg) { return node.execute(frame); } @OverridepublicObjectexecute(VirtualFrameframe) { return block.executeGeneric(frame, 0); } }
final class YieldException extendsControlFlowException{ finalObjectresult; YieldException(Objectresult) { this.result = result; } } final class ResumableBlockNode extends LanguageNode implementsBlockNode.ElementExecutor<LanguageNode> { @CompilerDirectives.CompilationFinalprivateIntegerindexSlot; @Child privateBlockNode<LanguageNode> block; ResumableBlockNode(LanguageNode[] elements) { this.block =BlockNode.create(elements, this); } @OverridepublicObjectexecute(VirtualFrameframe) { frame.setAuxiliarySlot(getIndexSlot(), 0); return block.executeGeneric(frame, 0); } // Called if the resumable block needs to be // resumed later on after a yield. public void resume(VirtualFrameframe) { getIndexSlot(); int startIndex = frame.getInt(getIndexSlot()); block.executeGeneric(frame, startIndex); } @Overridepublic void executeVoid(VirtualFrameframe, LanguageNode node, int elementIndex, int startIndex) { executeGeneric(frame, node, elementIndex, startIndex); } @OverridepublicObjectexecuteGeneric(VirtualFrameframe, LanguageNode node, int elementIndex, int startIndex) { if (elementIndex >= startIndex) { try { return node.execute(frame); } catch (YieldException e) { // store index to be able to resume later frame.setInt(getIndexSlot(), elementIndex); return e.result; } } else {CompilerDirectives.transferToInterpreterAndInvalidate(); throw newAssertionError("Invalid start index"); } } private int getIndexSlot() {Integerslot = this.indexSlot; if (slot == null) {CompilerDirectives.transferToInterpreterAndInvalidate();FrameDescriptorfd = getRootNode().getFrameDescriptor(); this.indexSlot = slot = fd.findOrAddAuxiliarySlot(this); } return slot; } }
| Modifier and Type | Class and Description |
|---|---|
static interface |
BlockNode.ElementExecutor<T extends Node>
Represents a contract how block element nodes can be executed.
|
Node.Child, Node.Children| Modifier and Type | Field and Description |
|---|---|
static int |
NO_ARGUMENT
Use when no argument is needed for the block node.
|
| Modifier | Constructor and Description |
|---|---|
protected |
BlockNode(T[] elements)
Internal constructor for implementations.
|
| Modifier and Type | Method and Description |
|---|---|
static <T extends Node> |
create(T[] elements,
BlockNode.ElementExecutor<T> executor)
Creates a new block node.
|
abstract boolean |
executeBoolean(VirtualFrame frame,
int argument)
Executes the block and returns a boolean value.
|
abstract byte |
executeByte(VirtualFrame frame,
int argument)
Executes the block and returns a byte value.
|
abstract char |
executeChar(VirtualFrame frame,
int argument)
Executes the block and returns a char value.
|
abstract double |
executeDouble(VirtualFrame frame,
int argument)
Executes the block and returns a double value.
|
abstract float |
executeFloat(VirtualFrame frame,
int argument)
Executes the block and returns a float value.
|
abstract Object |
executeGeneric(VirtualFrame frame,
int argument)
Executes the block and returns a generic value.
|
abstract int |
executeInt(VirtualFrame frame,
int argument)
Executes the block and returns an int value.
|
abstract long |
executeLong(VirtualFrame frame,
int argument)
Executes the block and returns a long value.
|
abstract short |
executeShort(VirtualFrame frame,
int argument)
Executes the block and returns a short value.
|
abstract void |
executeVoid(VirtualFrame frame,
int argument)
Executes the block and returns no value.
|
NodeCost |
getCost()
Block nodes always have
NodeCost.NONE. |
T[] |
getElements()
Returns the elements of the block node.
|
accept, adoptChildren, atomic, atomic, copy, deepCopy, getChildren, getDebugProperties, getDescription, getEncapsulatingSourceSection, getLock, getParent, getRootNode, getSourceSection, insert, insert, isAdoptable, isSafelyReplaceableBy, notifyInserted, onReplace, replace, replace, reportPolymorphicSpecialize, toStringpublic static final int NO_ARGUMENT
protected BlockNode(T[] elements)
public abstract void executeVoid(VirtualFrame frame, int argument)
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block.frame - the frame to execute the block in.argument - a custom argument that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.public abstract Object executeGeneric(VirtualFrame frame, int argument)
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeGeneric(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.public abstract byte executeByte(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeByte(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract short executeShort(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeShort(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract int executeInt(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeInt(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract char executeChar(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeChar(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract float executeFloat(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeFloat(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract double executeDouble(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeDouble(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract long executeLong(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeLong(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic abstract boolean executeBoolean(VirtualFrame frame, int argument) throws UnexpectedResultException
BlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int) for all elements of the
block except the last element. The last element is executed using
BlockNode.ElementExecutor.executeBoolean(VirtualFrame, Node, int, int).frame - the frame to execute the block in.argument - a custom value that is forwarded to the executor as is. If no argument is
needed then BlockNode.NO_ARGUMENT should be used.UnexpectedResultExceptionpublic final T[] getElements()
BlockNode.create(Node[], ElementExecutor).public final NodeCost getCost()
NodeCost.NONE.
Returns a rough estimate for the cost of this Node. This estimate can be used by
runtime systems or guest languages to implement heuristics based on Truffle ASTs. This method
is intended to be overridden by subclasses. The default implementation returns the value of
NodeInfo.cost() of the NodeInfo annotation declared at the subclass. If no
NodeInfo annotation is declared the method returns NodeCost.MONOMORPHIC as a
default value.public static <T extends Node> BlockNode<T> create(T[] elements, BlockNode.ElementExecutor<T> executor)
IllegalArgumentException is thrown. Elements of a block must at least extend
Node. An executor must be provided that allows the block node implementation to
execute the block elements. The executor must not be null.