public abstract class LoopNode extends Node
A loop node calls repeating nodes
as long as
it returns true
. Using the loop node in a guest language implementation allows the
Truffle runtime to optimize loops in a better way. For example a Truffle runtime implementation
might decide to optimize loop already during its first execution (also called on stack
replacement OSR). Loop nodes are not intended to be implemented by Truffle runtime
implementations and not by guest language implementations.
Full usage example for guest language while node:
public class WhileNode extends GuestLanguageNode {
@Node.Child
private LoopNode
loop;
public WhileNode(GuestLanguageNode conditionNode, GuestLanguageNode bodyNode) {
loop = Truffle.getRuntime().createLoopNode(new WhileRepeatingNode(conditionNode, bodyNode));
}
@Override
public Object execute(VirtualFrame
frame) {
loop.executeLoop(frame);
return null;
}
private static class WhileRepeatingNode extends Node
implements RepeatingNode
{
@Node.Child
private GuestLanguageNode conditionNode;
@Node.Child
private GuestLanguageNode bodyNode;
public WhileRepeatingNode(GuestLanguageNode conditionNode, GuestLanguageNode bodyNode) {
this.conditionNode = conditionNode;
this.bodyNode = bodyNode;
}
public boolean executeRepeating(VirtualFrame
frame) {
if ((boolean) conditionNode.execute(frame)) {
try {
bodyNode.execute(frame);
} catch (ContinueException ex) {
// the body might throw a continue control-flow exception
// continue loop invocation
} catch (BreakException ex) {
// the body might throw a break control-flow exception
// break loop invocation by returning false
return false;
}
return true;
} else {
return false;
}
}
}
}
// substitute with a guest language node type
public abstract class GuestLanguageNode extends Node
{
public abstract Object execute(VirtualFrame
frame);
}
// thrown by guest language continue statements
public final class ContinueException extends ControlFlowException
{}
// thrown by guest language break statements
public final class BreakException extends ControlFlowException
{}
RepeatingNode
,
TruffleRuntime.createLoopNode(RepeatingNode)
Node.Child, Node.Children
Modifier | Constructor and Description |
---|---|
protected |
LoopNode()
Constructor for subclasses.
|
Modifier and Type | Method and Description |
---|---|
Object |
execute(VirtualFrame frame)
Invokes one loop invocation by repeatedly calling
execute) on the repeating node the loop
was initialized with. |
abstract RepeatingNode |
getRepeatingNode()
Returns the repeating node the loop node was created with.
|
static void |
reportLoopCount(Node source,
int iterations)
Reports the execution count of a loop for which a no
LoopNode was used. |
accept, adoptChildren, atomic, atomic, copy, deepCopy, getChildren, getCost, getDebugProperties, getDescription, getEncapsulatingSourceSection, getLock, getParent, getRootNode, getSourceSection, insert, insert, isAdoptable, isSafelyReplaceableBy, lookupContextReference, lookupLanguageReference, notifyInserted, onReplace, replace, replace, reportPolymorphicSpecialize, toString
public Object execute(VirtualFrame frame)
execute)
on the repeating node the loop
was initialized with. Any exceptions that occur in the execution of the repeating node will
just be forwarded to this method and will cancel the current loop invocation.frame
- the current execution frame or null if the repeating node does not require a
framev
returned by
execute
satisfying
shouldContinue(v)
== false
, which
can be used in a language-specific way (for example, to encode structured jumps)public abstract RepeatingNode getRepeatingNode()
public static void reportLoopCount(Node source, int iterations)
Reports the execution count of a loop for which a no LoopNode
was used. The
optimization heuristics can use the loop count from non Truffle loops to guide compilation
and inlining better. Do not use LoopNode
and LoopNode.reportLoopCount(Node, int)
at
the same time for one loop.
Example usage with a custom loop:
public int executeCustomLoopSum(int[] data) {
try {
int sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i];
}
return sum;
} finally {
LoopNode.reportLoopCount(this, data.length);
}
}
source
- the Node which invoked the loop.iterations
- the number iterations to report to the runtime system, must be >= 0