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
createdlanguage contexts
Instrumentation
A root node can be instrumented if the following conditions apply:- A non-null
languageis 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
ConstructorsModifierConstructorDescriptionprotectedRootNode(TruffleLanguage<?> language) Creates new root node with a given language instance.protectedRootNode(TruffleLanguage<?> language, FrameDescriptor frameDescriptor) Creates new root node given an language environment and frame descriptor. -
Method Summary
Modifier and TypeMethodDescriptionprotected RootNodeCreates an uninitialized copy of an already initialized/executed root node if it issupported.protected intComputes a size estimate of this root node.copy()Creates a shallow copy of this node.protected booleanReturnstrueif this root node should count towardsAbstractTruffleException.getStackTraceElementLimit().static RootNodecreateConstantNode(Object constant) Helper method to create a root node that always returns the same value.abstract Objectexecute(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 intfindBytecodeIndex(Node node, Frame frame) Returns the current byte code index of the root node using a given node location and a frame.final RootCallTargetfinal FrameDescriptorgetName()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 FrameDescriptorIf 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.booleanDeprecated.protected booleanisCaptureFramesForTrace(boolean compiledFrame) Returnstrueif an AbstractTruffleException leaving this node should captureFrameobjects in its stack trace in addition to the default information.protected booleanisCaptureFramesForTrace(Node compiledFrame) Deprecated.in 24.1, implement and useisCaptureFramesForTrace(boolean)insteadprotected booleanReturnstrueifcloneUninitialized()can be used to create uninitialized copies of an already initialized / executed root node.booleanReturnstrueif thisRootNodeis allowed to be cloned.protected booleanDoes this contain AST content that it is possible to instrument.booleanReturnstrueif this root node should be considered internal and not be shown to a guest language programmer.protected booleanisSameFrame(Frame frame1, Frame frame2) Tests if two frames are the same.protected booleanIs this root node to be considered trivial by the runtime.protected ExecutionSignatureAllows languages to perform actions before a root node is attempted to be compiled without prior call toexecute(VirtualFrame).protected ObjectTranslates theTruffleStackTraceElementinto an interop object supporting thehasExecutableNameand potentiallyhasDeclaringMetaObjectandhasSourceLocationmessages.Methods inherited from class com.oracle.truffle.api.nodes.ExecutableNode
getLanguage, getLanguageInfoMethods 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, thennullcan be passed. Please note that root nodes withnulllanguage 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, thennullcan be passed. Please note that root nodes withnulllanguage 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
-
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 thenameis 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.myMethodIn 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
nullif the language implementation is unable to provide any useful information. - Since:
- 0.15
-
isInternal
public boolean isInternal()Returnstrueif 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 aRootNodeis internal if no language was passed in the constructor or if theroot source sectionis 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()Returnstrueif 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
TruffleStackTraceElementobjects. 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 benulleven ifisCaptureFramesForTrace(boolean)returnstrue. - If the bytecode index is stored in the call node, then
parentnodes 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 ornullframe- 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) Returnstrueif an AbstractTruffleException leaving this node should captureFrameobjects in its stack trace in addition to the default information. This isfalseby 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 indexin 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()Returnstrueif thisRootNodeis allowed to be cloned. The runtime system might decide to create deep copies of theRootNodein order to gather context sensitive profiling feedback. The default implementation returnsfalse. Guest language specific implementations may want to returntruehere to indicate that gathering call site specific profiling information might make sense for thisRootNode.- Returns:
trueif cloning is allowed elsefalse.- Since:
- 0.8 or earlier
-
isCloneUninitializedSupported
protected boolean isCloneUninitializedSupported()ReturnstrueifcloneUninitialized()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 returningtrueand 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 aRootNodeinstance.- Returns:
trueif calls touninitialized copiesare supported.- Since:
- 0.24
- See Also:
-
cloneUninitialized
Creates an uninitialized copy of an already initialized/executed root node if it issupported. Throws anUnsupportedOperationExceptionexception 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
Nodetree 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:
executein 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:
trueif this root node should be considered trivial by the runtime.falseotherwise.- 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 whenis 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.invalid reference
Env#getAsynchronousStackDepth()- Parameters:
frame- A frame, nevernull- Returns:
- a list of
TruffleStackTraceElement, ornullwhen no asynchronous stack is available. - Since:
- 20.1.0
- See Also:
-
translateStackTraceElement
Translates theTruffleStackTraceElementinto an interop object supporting thehasExecutableNameand potentiallyhasDeclaringMetaObjectandhasSourceLocationmessages. 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 lookupsin 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 returnsnullto 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
FrameDescriptorof 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 signatureshould be returned for better call efficiency. If the argument and return profile is not available or cannot be derived theExecutionSignature.GENERICcan 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 anullreturn or argument type should be used. The typeObjecttype should not be used in that case.This method is invoked when no context is currently
enteredtherefore 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 targetsduring preparation of the root node or perform modifications to thelanguageof 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-operabilityAPI) require return of stableroot nodes. To simplify creation of such nodes, here is a factory method that can createRootNodethat 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.
nullotherwise. - Since:
- 22.3.0
-
isSameFrame
Tests if two frames are the same. This method is mainly used by instruments in case ofyieldof 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-1is 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
CallTargetis 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