Class RootNode
- All Implemented Interfaces:
NodeInterface
,Cloneable
node
that allows to be
executed
using a frame
instance created by
the framework. Please note that the RootNode
should not be executed directly but using
CallTarget.call(Object...)
. The structure of the frame is provided by the
frame descriptor
passed in the constructor. A root node has always a
null
parent
and cannot be replaced
.
Construction
The root node can be constructed with alanguage implementation
if it is
available. The language implementation instance is obtainable while
TruffleLanguage.createContext(Env)
or TruffleLanguage.parse(ParsingRequest)
is
executed. If no language environment is available, then null
can be passed. Please
note that root nodes with null
language are considered not instrumentable and don't
have access to its public language information
.
Execution
In order to execute a root node, its call target is lazily created and can be accessed viagetCallTarget()
. This allows the runtime system to optimize the execution of the
AST. The CallTarget
can either be called
directly from
runtime code or direct
and indirect
call nodes
can be created, inserted in a child field and called
. The
use of direct call nodes allows the framework to automatically inline and further optimize call
sites based on heuristics.
After several calls to a call target or call node, the root node might get compiled using partial evaluation. The details of the compilation heuristic are unspecified, therefore the Truffle runtime system might decide to not compile at all.
Cardinalities
One root node instance refers to other classes using the following cardinalities:- one
language
- one
call target
- many
created
language contexts
Instrumentation
A root node can be instrumented if the following conditions apply:- A non-null
language
is passed in the root node constructor. isInstrumentable()
is overridden and returnstrue
.Node.getSourceSection()
is overridden and returns a non-null value.- The AST contains at least one node that implements
InstrumentableNode
. - It is recommended that children of instrumentable root nodes are tagged with
StandardTags
.
Note: It is recommended to override Node.getSourceSection()
and provide a
source section if available. This allows for better testing/tracing/tooling. If no concrete
source section is available please consider using Source.createUnavailableSection()
.
- Since:
- 0.8 or earlier
-
Nested Class Summary
Nested classes/interfaces inherited from class com.oracle.truffle.api.nodes.Node
Node.Child, Node.Children
-
Constructor Summary
ModifierConstructorDescriptionprotected
RootNode
(TruffleLanguage<?> language) Creates new root node with a given language instance.protected
RootNode
(TruffleLanguage<?> language, FrameDescriptor frameDescriptor) Creates new root node given an language environment and frame descriptor. -
Method Summary
Modifier and TypeMethodDescriptionprotected RootNode
Creates an uninitialized copy of an already initialized/executed root node if it issupported
.protected int
Computes a size estimate of this root node.copy()
Creates a shallow copy of this node.protected boolean
Returnstrue
if this root node should count towardsAbstractTruffleException.getStackTraceElementLimit()
.static RootNode
createConstantNode
(Object constant) Helper method to create a root node that always returns the same value.abstract Object
execute
(VirtualFrame frame) Executes this function using the specified frame and returns the result value.protected List
<TruffleStackTraceElement> findAsynchronousFrames
(Frame frame) Provide a list of stack frames that led to a schedule of asynchronous execution of this root node on the provided frame.protected int
findBytecodeIndex
(Node node, Frame frame) Returns the current byte code index of the root node using a given node location and a frame.final RootCallTarget
final FrameDescriptor
getName()
Returns a simple name of the AST (expected to be a method or procedure name in most languages) that identifies the AST for the benefit of guest language programmers using tools; it might appear, for example in the context of a stack dump or trace and is not expected to be called often.protected FrameDescriptor
If this root node has a lexical scope parent, this method returns its frame descriptor.Returns a qualified name of the AST that in the best case uniquely identifiers the method.boolean
Deprecated.protected boolean
isCaptureFramesForTrace
(boolean compiledFrame) Returnstrue
if an AbstractTruffleException leaving this node should captureFrame
objects in its stack trace in addition to the default information.protected boolean
isCaptureFramesForTrace
(Node compiledFrame) Deprecated.in 24.1, implement and useisCaptureFramesForTrace(boolean)
insteadprotected boolean
Returnstrue
ifcloneUninitialized()
can be used to create uninitialized copies of an already initialized / executed root node.boolean
Returnstrue
if thisRootNode
is allowed to be cloned.protected boolean
Does this contain AST content that it is possible to instrument.boolean
Returnstrue
if this root node should be considered internal and not be shown to a guest language programmer.protected boolean
isSameFrame
(Frame frame1, Frame frame2) Tests if two frames are the same.protected boolean
Is this root node to be considered trivial by the runtime.protected ExecutionSignature
Allows languages to perform actions before a root node is attempted to be compiled without prior call toexecute(VirtualFrame)
.protected Object
Translates theTruffleStackTraceElement
into an interop object supporting thehasExecutableName
and potentiallyhasDeclaringMetaObject
andhasSourceLocation
messages.Methods inherited from class com.oracle.truffle.api.nodes.ExecutableNode
getLanguage, getLanguageInfo
Methods inherited from class com.oracle.truffle.api.nodes.Node
accept, adoptChildren, atomic, atomic, deepCopy, getChildren, getCost, getDebugProperties, getDescription, getEncapsulatingSourceSection, getLock, getParent, getRootNode, getSourceSection, insert, insert, isAdoptable, isSafelyReplaceableBy, notifyInserted, onReplace, replace, replace, reportPolymorphicSpecialize, toString
-
Constructor Details
-
RootNode
Creates new root node with a given language instance. The language instance is obtainable whileTruffleLanguage.createContext(Env)
orTruffleLanguage.parse(ParsingRequest)
is executed. If no language environment is available, thennull
can be passed. Please note that root nodes withnull
language are considered not instrumentable and don't have access to its publiclanguage information
.- Parameters:
language
- the language this root node is associated with- Since:
- 0.25
-
RootNode
Creates new root node given an language environment and frame descriptor. The language instance is obtainable whileTruffleLanguage.createContext(Env)
orTruffleLanguage.parse(ParsingRequest)
is executed. If no language environment is available, thennull
can be passed. Please note that root nodes withnull
language are considered not instrumentable and don't have access to its publiclanguage information
.- Parameters:
language
- the language this root node is associated with- Since:
- 0.25
-
-
Method Details
-
copy
Description copied from class:Node
Creates a shallow copy of this node. -
getQualifiedName
Returns a qualified name of the AST that in the best case uniquely identifiers the method. If the qualified name is not specified by the root, then thename
is used by default. A root node that represents a Java method could consist of the package name, the class name and the method name. E.g.mypackage.MyClass.myMethod
- Since:
- 20.0
-
getName
Returns a simple name of the AST (expected to be a method or procedure name in most languages) that identifies the AST for the benefit of guest language programmers using tools; it might appear, for example in the context of a stack dump or trace and is not expected to be called often. Can be called on any thread and without a language context. The name of a root node that represents a Java method could consist of the method name. E.g.myMethod
In some languages AST "compilation units" may have no intrinsic names. When no information is available, language implementations might simply use the first few characters of the code, followed by "
...
". Language implementations should assign a more helpful name whenever it becomes possible, for example when a functional value is assigned. This means that the name might not be stable over time.Language execution semantics should not depend on either this name or the way that it is formatted. The name should be presented in the way expected to be most useful for programmers.
- Returns:
- a name that helps guest language programmers identify code corresponding to the AST,
possibly
null
if the language implementation is unable to provide any useful information. - Since:
- 0.15
-
isInternal
public boolean isInternal()Returnstrue
if this root node should be considered internal and not be shown to a guest language programmer. This method has effect on tools and guest language stack traces. By default aRootNode
is internal if no language was passed in the constructor or if theroot source section
is set and points to an internal source. This method is intended to be overwritten by guest languages, when the node's source is internal, the implementation should respect that. Can be called on any thread and without a language context.This method may be invoked on compiled code paths. It is recommended to implement this method such that it returns a compilation final constant.
- Since:
- 0.27
-
countsTowardsStackTraceLimit
protected boolean countsTowardsStackTraceLimit()Returnstrue
if this root node should count towardsAbstractTruffleException.getStackTraceElementLimit()
.By default, returns the negation of
isInternal()
.This method may be invoked on compiled code paths. It is recommended to implement this method or #isInternal() such that it returns a partial evaluation constant.
- Since:
- 21.2.0
-
findBytecodeIndex
Returns the current byte code index of the root node using a given node location and a frame. Depending on the strategy (see below) either the node or the frame may be used to find the bytecode index.This method is called by Truffle to determine the bytecode index when constructing
TruffleStackTraceElement
objects. There are two common strategies to implement this method:- If the bytecode index is stored in the frame, then
isCaptureFramesForTrace(boolean)
should be overridden and returntrue
. Next use the frame argument and read the bytecode index from the frame. Note that the provided frame may benull
even ifisCaptureFramesForTrace(boolean)
returnstrue
. - If the bytecode index is stored in the call node, then
parent
nodes should be walked to find the node containing the bytecode index.
This method should return a negative bytecode index if it is unavailable or invalid. A language implementation may assign additional semantics for individual negative byte code indices, other languages will interpret any negative index as if the index is unavailable.
- Parameters:
node
- the top-most node of the activation ornull
frame
- the current frame of the activation ornull
- Since:
- 24.1
- See Also:
- If the bytecode index is stored in the frame, then
-
isCaptureFramesForTrace
Deprecated.in 24.1, implement and useisCaptureFramesForTrace(boolean)
instead- Since:
- 24.1
-
isCaptureFramesForTrace
protected boolean isCaptureFramesForTrace(boolean compiledFrame) Returnstrue
if an AbstractTruffleException leaving this node should captureFrame
objects in its stack trace in addition to the default information. This isfalse
by default to avoid the attached overhead. The captured frames are then accessible throughTruffleStackTraceElement.getFrame()
.Using the compiledFrame argument can be useful to capture the frame only for interpreted frames. This way it is possible to store the
bytecode index
in the frame only in the interpreter, but never in compiled code. This is more efficient, because capturing the frame is a fast operation in the interpreter, but a slow operation for compiled frames.- Parameters:
compiledFrame
- whether the frame would be from a compiled execution.- Since:
- 24.1
-
isCaptureFramesForTrace
Deprecated.in 24.1, implement and useisCaptureFramesForTrace(boolean)
instead- Since:
- 0.31
-
isCloningAllowed
public boolean isCloningAllowed()Returnstrue
if thisRootNode
is allowed to be cloned. The runtime system might decide to create deep copies of theRootNode
in order to gather context sensitive profiling feedback. The default implementation returnsfalse
. Guest language specific implementations may want to returntrue
here to indicate that gathering call site specific profiling information might make sense for thisRootNode
.- Returns:
true
if cloning is allowed elsefalse
.- Since:
- 0.8 or earlier
-
isCloneUninitializedSupported
protected boolean isCloneUninitializedSupported()Returnstrue
ifcloneUninitialized()
can be used to create uninitialized copies of an already initialized / executed root node. By default, or if this method returnsfalse
, an optimizing Truffle runtime might need to copy the AST before it is executed for the first time to ensure it is able to create new uninitialized copies when needed. By returningtrue
and therefore supporting uninitialized copies an optimizing runtime does not need to keep a reference to an uninitialized copy on its own and might therefore be able to save memory. The returned boolean needs to be immutable for aRootNode
instance.- Returns:
true
if calls touninitialized copies
are supported.- Since:
- 0.24
- See Also:
-
cloneUninitialized
Creates an uninitialized copy of an already initialized/executed root node if it issupported
. Throws anUnsupportedOperationException
exception by default. By default, or ifisCloneUninitializedSupported()
returnsfalse
, an optimizing Truffle runtime might need to copy the root node before it is executed for the first time to ensure it is able to create new uninitialized copies when needed. By supporting uninitialized copies an optimizing runtime does not need to keep a reference to an uninitialized copy on its own and might therefore be able to save memory.Two common strategies to implement
cloneUninitialized()
are:- Reparsing: Support it by keeping a reference to the original source code including the lexical scope and create the uninitialized copy of the root node by reparsing the source.
- Resetting: Support it by traversing the
Node
tree and derive an uninitialized copy from each initialized node.
- Returns:
- an uninitialized copy of this root node if supported.
- Throws:
UnsupportedOperationException
- if not supported- Since:
- 0.24
- See Also:
-
execute
Executes this function using the specified frame and returns the result value.- Specified by:
execute
in classExecutableNode
- Parameters:
frame
- the frame of the currently executing guest language method- Returns:
- the value of the execution
- Since:
- 0.8 or earlier
-
getCallTarget
- Since:
- 0.8 or earlier
-
getFrameDescriptor
- Since:
- 0.8 or earlier
-
isInstrumentable
protected boolean isInstrumentable()Does this contain AST content that it is possible to instrument. Can be called on any thread and without a language context.- Since:
- 0.8 or earlier
-
isTrivial
protected boolean isTrivial()Is this root node to be considered trivial by the runtime. A trivial root node is defined as a root node that:- Never increases code size when inlined, i.e. is always less complex then the call.
- Never performs guest language calls.
- Never contains loops.
- Is small (for a language-specific definition of small).
- Returns:
true
if this root node should be considered trivial by the runtime.false
otherwise.- Since:
- 20.3.0
-
findAsynchronousFrames
Provide a list of stack frames that led to a schedule of asynchronous execution of this root node on the provided frame. The asynchronous frames are expected to be found here whenTruffleLanguage.getAsynchronousStackDepth()
is positive. The language is free to provide asynchronous frames or longer list of frames when it's of no performance penalty, or if requested by other options. This method is invoked on slow-paths only and with a context entered.- Parameters:
frame
- A frame, nevernull
- Returns:
- a list of
TruffleStackTraceElement
, ornull
when no asynchronous stack is available. - Since:
- 20.1.0
- See Also:
-
translateStackTraceElement
Translates theTruffleStackTraceElement
into an interop object supporting thehasExecutableName
and potentiallyhasDeclaringMetaObject
andhasSourceLocation
messages. An executable name must be provided, whereas the declaring meta object and source location is optional. Guest languages may typically return their function objects that typically already implement the required contracts.The intention of this method is to provide a guest language object for other languages that they can inspect using interop. An implementation of this method is expected to not fail with a guest error. Implementations are allowed to do
context reference lookups
in the implementation of the method. This may be useful to access the function objects needed to resolve the stack trace element.- Since:
- 20.3
- See Also:
-
prepareForAOT
Allows languages to perform actions before a root node is attempted to be compiled without prior call toexecute(VirtualFrame)
. By default this method returnsnull
to indicate that AOT compilation is not supported. Any non-null value indicates that compilation without execution is supported for this root node. This method is guaranteed to not be invoked prior to any calls toexecute
.Common tasks that need to be performed by this method:
- Initialize local variable types in the
FrameDescriptor
of the root node. Without that any access to the frame will invalidate the code on first execute. - Initialize specializing nodes with profiles that do not invalidate on first execution.
For initialization of Truffle DSL nodes see
AOTSupport
. - Compute the expected execution signature of a root node and return it.
If possible an
execution signature
should be returned for better call efficiency. If the argument and return profile is not available or cannot be derived theExecutionSignature.GENERIC
can be used to indicate that any value needs to be expected for as argument from or as return value of the method. To indicate that a type is unknown anull
return or argument type should be used. The typeObject
type should not be used in that case.This method is invoked when no context is currently
entered
therefore no guest application code must be executed. The execution might happen on any thread, even threads unknown to the guest language implementation. It is allowed to create newcall targets
during preparation of the root node or perform modifications to thelanguage
of this root node.- Since:
- 20.3
- Initialize local variable types in the
-
createConstantNode
Helper method to create a root node that always returns the same value. Certain operations (especiallyinter-operability
API) require return of stableroot nodes
. To simplify creation of such nodes, here is a factory method that can createRootNode
that returns always the same value.- Parameters:
constant
- the constant to return- Returns:
- root node returning the constant
- Since:
- 0.8 or earlier
-
getParentFrameDescriptor
If this root node has a lexical scope parent, this method returns its frame descriptor. As an example, consider the following pseudocode:def m { # For the "m" root node: # getFrameDescriptor returns FrameDescriptor(m) # getParentFrameDescriptor returns null var_method = 0 a = () -> { # For the "a lambda" root node: # getFrameDescriptor returns FrameDescriptor(a) # getParentFrameDescriptor returns FrameDescriptor(m) var_lambda1 = 1 b = () -> { # For the "b lambda" root node: # getFrameDescriptor returns FrameDescriptor(b) # getParentFrameDescriptor returns FrameDescriptor(a) var_method + var_lambda1 } b.call } a.call }
This info is used by the runtime to optimize compilation order by giving more priority to lexical parents which are likely to inline the child thus resulting in better performance sooner rather than waiting for the lexical parent to get hot on its own.- Returns:
- The frame descriptor of the lexical parent scope if it exists.
null
otherwise. - Since:
- 22.3.0
-
isSameFrame
Tests if two frames are the same. This method is mainly used by instruments in case ofyield
of the execution and later resume. Frame comparison is used to match the particular yielded and resumed execution.The default implementation compares the frames identity.
- Since:
- 24.0
-
computeSize
protected int computeSize()Computes a size estimate of this root node. This is intended to be overwritten if the size of the root node cannot be estimated from the natural AST size. For example, in case the root node is represented by a bytecode interpreter. If-1
is returned, the regular AST size estimate is going to be used. By default this method returns-1
.The size estimate is guaranteed to be invoked only once when the
CallTarget
is created. This corresponds to calls togetCallTarget()
for the first time. This method will never be invoked after the root node was already executed.- Since:
- 23.0
-
isCaptureFramesForTrace(boolean)
instead