Class BlockNode<T extends Node>
- Type Parameters:
T
- the type of the block element node
- All Implemented Interfaces:
NodeInterface
,Cloneable
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.
Simple Usage:
The following example shows how a language with untyped execute methods, but with blocks that return values would use the block node.// language base node
abstract class LanguageNode extends Node {
public abstract Object execute(VirtualFrame frame);
}
final class LanguageBlockNode extends LanguageNode
implements ElementExecutor<LanguageNode> {
@Child private BlockNode<LanguageNode> block;
LanguageBlockNode(LanguageNode[] elements) {
this.block = BlockNode.create(elements, this);
}
@Override
public void executeVoid(VirtualFrame frame, LanguageNode node,
int index, int arg) {
node.execute(frame);
}
@Override
public Object executeGeneric(VirtualFrame frame, LanguageNode node,
int index, int arg) {
return node.execute(frame);
}
@Override
public Object execute(VirtualFrame frame) {
return block.executeGeneric(frame, 0);
}
}
Resumable Usage:
The following example shows how the block node can be used to implement resumable blocks, e.g. for generator implementations:final class YieldException extends ControlFlowException {
final Object result;
YieldException(Object result) {
this.result = result;
}
}
final class ResumableBlockNode extends LanguageNode
implements ElementExecutor<LanguageNode> {
@CompilationFinal private Integer indexSlot;
@Child private BlockNode<LanguageNode> block;
ResumableBlockNode(LanguageNode[] elements) {
this.block = BlockNode.create(elements, this);
}
@Override
public Object execute(VirtualFrame frame) {
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(VirtualFrame frame) {
getIndexSlot();
int startIndex = frame.getInt(getIndexSlot());
block.executeGeneric(frame, startIndex);
}
@Override
public void executeVoid(VirtualFrame frame, LanguageNode node,
int elementIndex, int startIndex) {
executeGeneric(frame, node, elementIndex, startIndex);
}
@Override
public Object executeGeneric(VirtualFrame frame, 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 new AssertionError("Invalid start index");
}
}
private int getIndexSlot() {
Integer slot = this.indexSlot;
if (slot == null) {
CompilerDirectives.transferToInterpreterAndInvalidate();
FrameDescriptor fd = getRootNode().getFrameDescriptor();
this.indexSlot = slot = fd.findOrAddAuxiliarySlot(this);
}
return slot;
}
}
- Since:
- 19.3
-
Nested Class Summary
Modifier and TypeClassDescriptionstatic interface
BlockNode.ElementExecutor<T extends Node>
Represents a contract how block element nodes can be executed.Nested classes/interfaces inherited from class com.oracle.truffle.api.nodes.Node
Node.Child, Node.Children
-
Field Summary
Modifier and TypeFieldDescriptionstatic final int
Use when no argument is needed for the block node. -
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptioncreate
(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.final T[]
Returns the elements of the block node.Methods inherited from class com.oracle.truffle.api.nodes.Node
accept, adoptChildren, atomic, atomic, copy, deepCopy, getChildren, getCost, getDebugProperties, getDescription, getEncapsulatingSourceSection, getLock, getParent, getRootNode, getSourceSection, insert, insert, isAdoptable, isSafelyReplaceableBy, notifyInserted, onReplace, replace, replace, reportPolymorphicSpecialize, toString
-
Field Details
-
NO_ARGUMENT
public static final int NO_ARGUMENTUse when no argument is needed for the block node.- Since:
- 19.3
- See Also:
-
-
Constructor Details
-
BlockNode
-
-
Method Details
-
executeVoid
Executes the block and returns no value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block.- Parameters:
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 thenNO_ARGUMENT
should be used.- Since:
- 19.3
-
executeGeneric
Executes the block and returns a generic value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeGeneric(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Since:
- 19.3
-
executeByte
Executes the block and returns a byte value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeByte(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeShort
public abstract short executeShort(VirtualFrame frame, int argument) throws UnexpectedResultException Executes the block and returns a short value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeShort(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeInt
Executes the block and returns an int value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeInt(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeChar
Executes the block and returns a char value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeChar(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeFloat
public abstract float executeFloat(VirtualFrame frame, int argument) throws UnexpectedResultException Executes the block and returns a float value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeFloat(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeDouble
public abstract double executeDouble(VirtualFrame frame, int argument) throws UnexpectedResultException Executes the block and returns a double value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeDouble(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeLong
Executes the block and returns a long value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeLong(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
executeBoolean
public abstract boolean executeBoolean(VirtualFrame frame, int argument) throws UnexpectedResultException Executes the block and returns a boolean value. The block implementation callsBlockNode.ElementExecutor.executeVoid(VirtualFrame, Node, int, int)
for all elements of the block except the last element. The last element is executed usingBlockNode.ElementExecutor.executeBoolean(VirtualFrame, Node, int, int)
.- Parameters:
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 thenNO_ARGUMENT
should be used.- Throws:
UnexpectedResultException
- Since:
- 19.3
-
getElements
Returns the elements of the block node. Elements of block nodes are provided usingcreate(Node[], ElementExecutor)
.- Since:
- 19.3
-
create
public static <T extends Node> BlockNode<T> create(T[] elements, BlockNode.ElementExecutor<T> executor) Creates a new block node. The elements array of the block node must not be empty or anIllegalArgumentException
is thrown. Elements of a block must at least extendNode
. An executor must be provided that allows the block node implementation to execute the block elements. The executor must not benull
.- Since:
- 19.3
-