Class BytecodeDescriptor<R extends RootNode & BytecodeRootNode, L extends TruffleLanguage<?>, B extends BytecodeBuilder>
- Type Parameters:
R- thespecification class, which is both aRootNodeand aBytecodeRootNodeL- the Truffle language typeB- the builder type used to emit bytecode for this interpreter
BytecodeRootNode class and
provides the management API for that interpreter.
A generated bytecode interpreter exposes a public static BYTECODE field of the generated
*Gen.Bytecode class. It is recommended to not refer to the BytecodeDescriptor
directly and instead use the generated *Gen.Bytecode class to avoid the rather verbose
generic type. That field is a concrete subclass of BytecodeDescriptor, and acts as the
central entry point for:
- Creating executable bytecode:
create(TruffleLanguage, BytecodeConfig, BytecodeParser)builds one or moreBytecodeRootNodeinstances by driving aBytecodeBuilder. - Serialization support:
serialize(DataOutput, BytecodeSerializer, BytecodeParser)anddeserialize(L, BytecodeConfig, Supplier, BytecodeDeserializer)define the contract for turning parsed bytecode into a byte stream and restoring it. Generated interpreters that were built withenableSerialization=trueimplement these methods. The default implementation throwsUnsupportedOperationException. - Describing the instruction set:
getInstructionDescriptors()andgetInstructionDescriptor(int)expose all instructions, including normal language operations and injected instrumentation instructions. The descriptor can also produce a human readable dump viadump(). - Per-language runtime configuration:
update(TruffleLanguage, BytecodeConfig)applies configuration (for example enabling instrumentations) to all bytecode roots that were already created for the given language, and to any future roots. - Instruction tracing:
addInstructionTracer(TruffleLanguage, InstructionTracer)andremoveInstructionTracer(TruffleLanguage, InstructionTracer)install and removeInstructionTracers for all roots created for a given language. After a tracer is installed, the interpreter automatically injects tracing instructions (for exampletrace.instruction) and invokes the tracer callback on every executed instruction.
getGeneratedClass()
returns the generated root node class that implements execution, and
getSpecificationClass() identifies the original user-declared @GenerateBytecode
root node (when available). getLanguageClass() identifies the owning
TruffleLanguage.
In short, BytecodeDescriptor is both: (1) a static description of the generated
bytecode interpreter (instruction set, generated classes, language binding), and (2) the
runtime control surface for all bytecode roots created from that interpreter in a given language
context (creation, tracing, instrumentation, serialization).
Usage example
// Assume you have a language MyLanguage and a bytecode root node
// declared as:
//
// @GenerateBytecode(languageClass = MyLanguage.class)
// abstract class MyBytecodeRootNode extends RootNode implements BytecodeRootNode { ... }
//
// The annotation processor generates MyBytecodeRootNodeGen and a nested
// MyBytecodeRootNodeGen.Bytecode class with a public static BYTECODE field:
//
// public static final MyBytecodeRootNodeGen.Bytecode BYTECODE;
//
// The BYTECODE field is a concrete BytecodeDescriptor.
MyLanguage language = ...; // instance of the Truffle language
// Create a new bytecode root node by emitting bytecode through the builder.
// The parser lambda drives the builder to generate the bytecode body.
MyBytecodeRootNode root = MyBytecodeRootNodeGen.BYTECODE
.create(language, BytecodeConfig.DEFAULT, (builder) -> {
builder.beginRoot();
builder.beginReturn();
builder.emitLoadArgument(0); // return the first argument
builder.endReturn();
builder.endRoot();
})
.getNode(0); // obtain the first created root node
// Execute the generated root node through its call target.
Object result = root.getCallTarget().call(42);
- Since:
- 25.1
-
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionvoidaddInstructionTracer(L language, InstructionTracer tracer) Registers anInstructionTracerfor all bytecode root nodes created from this descriptor in the given language.final Rcast(CallTarget target) Casts aCallTargetto the specification root node typeR.abstract RCasts aRootNodeto the specification root node typeR.abstract BytecodeRootNodes<R> create(L language, BytecodeConfig config, BytecodeParser<B> parser) Creates one or more bytecode root nodes.deserialize(L language, BytecodeConfig config, Supplier<DataInput> input, BytecodeDeserializer callback) Deserializes a byte sequence to bytecode nodes.dump()Returns a human readable dump of this bytecode descriptor.Returns the generated root node class that implements the bytecode interpreter.abstract InstructionDescriptorgetInstructionDescriptor(int operationCode) Returns theInstructionDescriptorfor the given operation code, ornullif the code is not defined by this interpreter.abstract List<InstructionDescriptor> Returns an immutable list of all instruction descriptors known to this interpreter.Returns theTruffleLanguageclass that this descriptor is associated with, nevernull.Returns the specification class for this descriptor.abstract BytecodeConfig.BuilderCreates a newBytecodeConfig.Builderinitialized with defaults that are valid for this descriptor.protected final voidonPrepareForLoad(TruffleLanguage<?> language, R rootNode) Internal method called by generated code on root node load.voidremoveInstructionTracer(L language, InstructionTracer tracer) Unregisters a previously installedInstructionTracerfor the given language.voidserialize(DataOutput buffer, BytecodeSerializer callback, BytecodeParser<B> parser) Serializes the bytecode nodes parsed by theparser.toString()Returns a short string representation for debugging.voidupdate(L language, BytecodeConfig config) Updates the bytecode configuration for all bytecode root nodes that were created by this descriptor for the given language instance.protected final longwithGlobalConfig(TruffleLanguage<?> language, long config) Internal method called by generated code whenever the aBytecodeConfigis used.
-
Constructor Details
-
BytecodeDescriptor
-
-
Method Details
-
getSpecificationClass
-
getGeneratedClass
-
getLanguageClass
Returns theTruffleLanguageclass that this descriptor is associated with, nevernull.- Since:
- 25.1
- See Also:
-
getInstructionDescriptor
Returns theInstructionDescriptorfor the given operation code, ornullif the code is not defined by this interpreter.- Parameters:
operationCode- the numeric operation code of the instruction- Since:
- 25.1
- See Also:
-
getInstructionDescriptors
Returns an immutable list of all instruction descriptors known to this interpreter. The list describes every instruction kind that can be executed by nodes generated from this interpreter.- Since:
- 25.1
-
cast
Casts aRootNodeto the specification root node typeR. This also handlesContinuationRootNodeif yield is enabled. Returnsnullif the given root is not compatible with this descriptor.- Parameters:
rootNode- a root node, must not benull- Since:
- 25.1
-
cast
Casts aCallTargetto the specification root node typeR. Returnsnullif the given root is not compatible with this descriptor.- Parameters:
target- a call target, must not benull- Since:
- 25.1
-
newConfigBuilder
Creates a newBytecodeConfig.Builderinitialized with defaults that are valid for this descriptor.- Returns:
- a new mutable configuration builder
- Since:
- 25.1
-
create
public abstract BytecodeRootNodes<R> create(L language, BytecodeConfig config, BytecodeParser<B> parser) Creates one or more bytecode root nodes. This is the entrypoint for creating newRinstances.The
parseris invoked to emit builder calls on aBytecodeBuilderwhich is then materialized into executable bytecode. The returnedBytecodeRootNodescontains the created root nodes, for example entry points and helper nodes.- Parameters:
language- the language instanceconfig- the bytecode configuration, for example whether to include source informationparser- the parser that drives theBytecodeBuilder- Returns:
- the created bytecode root nodes
- Since:
- 25.1
-
serialize
public void serialize(DataOutput buffer, BytecodeSerializer callback, BytecodeParser<B> parser) throws IOException Serializes the bytecode nodes parsed by theparser. All metadata (e.g., source info) is serialized (even if it has not yet been parsed).Unlike the
BytecodeRootNodes.serialize(DataOutput, BytecodeSerializer)instance method, which replays builder calls that were already validated during the original bytecode parse, this method does not validate the builder calls performed by theparser. Validation will happen (as usual) when the bytes are deserialized.Additionally, this method cannot serialize field values that get set outside of the parser, unlike the
BytecodeRootNodes.serialize(DataOutput, BytecodeSerializer)instance method, which has access to the instances being serialized.- Parameters:
buffer- the buffer to write the byte output to.callback- the language-specific serializer for constants in the bytecode.parser- the parser.- Throws:
IOException- Since:
- 25.1
-
deserialize
public BytecodeRootNodes<R> deserialize(L language, BytecodeConfig config, Supplier<DataInput> input, BytecodeDeserializer callback) throws IOException Deserializes a byte sequence to bytecode nodes. The bytes must have been produced by a previous call toserialize(DataOutput, BytecodeSerializer, BytecodeParser).- Parameters:
language- the language instance.config- indicates whether to deserialize metadata (e.g., source information).input- A function that supplies the bytes to deserialize. This supplier must produce a newDataInputeach time, since the bytes may be processed multiple times for reparsing.callback- The language-specific deserializer for constants in the bytecode. This callback must perform the inverse of the callback that was used toserialize(DataOutput, BytecodeSerializer, BytecodeParser)the nodes to bytes.- Throws:
IOException- Since:
- 25.1
-
addInstructionTracer
Registers anInstructionTracerfor all bytecode root nodes created from this descriptor in the given language.After a tracer is installed, all existing and future
BytecodeRootNodeinstances associated with this descriptor andlanguagewill start invoking the tracer's callback before executing each instruction.Installing a tracer is intentionally invasive and may be expensive:
- All affected bytecode roots may need to be invalidated and re-parsed so that tracing
hooks (for example
trace.instruction) can be inserted. - The change applies process-wide to that language instance, not just to a single root node.
If this bytecode interpreter was generated without instruction tracing support (for example using
@GenerateBytecode(enableInstructionTracing = false)), this method throwsUnsupportedOperationException.- Parameters:
language- the language instance whose bytecode roots should start reportingtracer- the tracer to install- Throws:
IllegalArgumentException- iftraceris exclusive to a differentBytecodeDescriptorUnsupportedOperationException- if instruction tracing is not enabled for this descriptor- Since:
- 25.1
- All affected bytecode roots may need to be invalidated and re-parsed so that tracing
hooks (for example
-
removeInstructionTracer
Unregisters a previously installedInstructionTracerfor the given language.After removal, bytecode roots created from this descriptor for
languagewill stop invoking the tracer's callback. Future roots created for the same language will also not attach the tracer. Thetracerargument must be the same tracer instance that was passed toaddInstructionTracer(TruffleLanguage, InstructionTracer).Note that currently when all instruction tracers were removed, the trace instructions remain in the bytecode. This may be improved in the future.
If this bytecode interpreter was generated without instruction tracing support (for example using
@GenerateBytecode(enableInstructionTracing = false)), this method throwsUnsupportedOperationException.- Parameters:
language- the language instance whose bytecode roots should stop reportingtracer- the tracer to remove- Throws:
IllegalArgumentException- iftraceris exclusive to a differentBytecodeDescriptorUnsupportedOperationException- if instruction tracing is not enabled for this descriptor- Since:
- 25.1
-
update
Updates the bytecode configuration for all bytecode root nodes that were created by this descriptor for the given language instance.This can be used to enable features such as source information or instrumentation globally. Options are applied cumulatively and cannot be reverted for that language instance.
- Parameters:
language- the language instanceconfig- the configuration to apply- Since:
- 25.1
-
toString
-
dump
Returns a human readable dump of this bytecode descriptor.The dump includes the instruction set, statistics such as encoded size, and formatted instruction listings. This is intended for diagnostics and test assertions, not for programmatic parsing.
- Returns:
- a multi line string describing the bytecode descriptor
- Since:
- 25.1
-
onPrepareForLoad
Internal method called by generated code on root node load.- Since:
- 25.1
-
withGlobalConfig
Internal method called by generated code whenever the aBytecodeConfigis used.- Since:
- 25.1
-