Class LoopNode
- All Implemented Interfaces:
NodeInterface
,Cloneable
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 intended to be implemented by Truffle runtime implementations
and not by guest language implementations.
Note: The loop condition is automatically profiled by the loop node, so the repeating node
should not use a loop condition profile.
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
{}
- Since:
- 0.8 or earlier
- See Also:
-
Nested Class Summary
Nested classes/interfaces inherited from class com.oracle.truffle.api.nodes.Node
Node.Child, Node.Children
-
Constructor Summary
-
Method Summary
Modifier and TypeMethodDescriptionexecute
(VirtualFrame frame) Invokes one loop invocation by repeatedly callingexecute)
on the repeating node the loop was initialized with.abstract RepeatingNode
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 noLoopNode
was used.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, reportReplace, toString
-
Constructor Details
-
LoopNode
protected LoopNode()Constructor for subclasses.- Since:
- 0.8 or earlier
-
-
Method Details
-
execute
Invokes one loop invocation by repeatedly callingexecute)
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.- Parameters:
frame
- the current execution frame or null if the repeating node does not require a frame- Returns:
- a value
v
returned byexecute
satisfyingshouldContinue(v)
== false
, which can be used in a language-specific way (for example, to encode structured jumps) - Since:
- 19.3
-
getRepeatingNode
Returns the repeating node the loop node was created with.- Since:
- 0.8 or earlier
-
reportLoopCount
Reports the execution count of a loop for which no
LoopNode
was used. The optimization heuristics can use the loop count from non Truffle loops to guide compilation and inlining better. Do not useLoopNode
andreportLoopCount(Node, int)
at the same time for one loop. If the number of iterations needs to be counted and can overflow, only count ifCompilerDirectives.hasNextTier()
istrue
(reporting will have no effect in the last tier) and consider reportingInteger.MAX_VALUE
in case of overflows. If the number is often zero andreportLoopCount(Node, int)
is called frequently (e.g. in a loop), consider adding a check to avoid the overhead of redundant calls with aniterations
argument of zero in the interpreter.Example usage for a custom loop iterating over an array:
public int executeCustomLoopSum(int[] data) { int sum = 0; for (int i = 0; i < data.length; i++) { sum += data[i]; } LoopNode.reportLoopCount(this, data.length); return sum; }
int
overflow:public Object executeCustomLoopWithUnknownIterations(int[] data) { Object result; int counter = 0; while(true) { if (isResultAvailable()) { result = getResult(); break; } // do some work to calculate result if (CompilerDirectives.hasNextTier()) { counter++; } } if (counter != 0) { LoopNode.reportLoopCount(this, counter > 0 ? counter : Integer.MAX_VALUE); } return result; }
- Parameters:
source
- the Node which invoked the loop.iterations
- the number iterations to report to the runtime system, must be >= 0- Since:
- 0.12
-