Class TruffleLanguage<C>
- Type Parameters:
C- internal state of the language associated with every thread that is executing programparsedby the language
TruffleLanguage.Registration in order to be discoverable by the
invalid reference
Polyglot API
TruffleLanguage subclasses must provide a public default constructor.
Lifecycle
A language implementation becomes available for use by an engine when metadata is added using theTruffleLanguage.Registration annotation and the implementation's JAR file placed on the host Java Virtual
Machine's class path.
A newly created engine locates all available language implementations and creates a descriptor for each. The descriptor holds the language's registered metadata, but its execution environment is not initialized until the language is needed for code execution. That execution environment remains initialized for the lifetime of the engine and is isolated from the environment in any other engine instance.
Language global state can be shared between multiple context instances by saving them in a custom
field of the TruffleLanguage subclass. Languages may control sharing between multiple
contexts using its context policy. By default the context
policy is exclusive: each context has its own separate
TruffleLanguage instance.
If the context policy is more permissive then the implementation needs to manually ensure data
isolation between the contexts. This means that state associated with a context must not be
stored in a TruffleLanguage subclass. ASTs and assumptions can be shared across multiple contexts
if modifying them does not affect language semantics. Languages are strongly discouraged from
using static mutable state in their languages. Instead TruffleLanguage instances should
be used instead to store global state and their sharing should be configured using
context policy.
Whenever an engine is disposed then each initialized language context will be
disposed.
Context Policy and Sharing
The number ofTruffleLanguage instances per polyglot context is configured by the context policy. By default an
exclusive language instance is created
for every polyglot context or
inner context. With policy
reuse, language instances will be reused after a language context was
disposed. With policy shared, a language will also be reused if active contexts are not yet disposed. Language
instances will only be shared or reused if they are
compatible. Language
implementations are encouraged to support the most permissive context policy possible. Please see
the individual policies for details on the implications on the language
implementation.
The following illustration shows the cardinalities of the individual components:
N: unbounded
P: N for exclusive, 1 for shared context policy
L: number of installed languages
I: number of installed instruments
- 1 : Host VM Processs
- N : Engine
- N : Context
- L : Language Context
- P * L : TruffleLanguage
- I : Instrument
- 1 : TruffleInstrument
For more information on sharing between multiple contexts please see TruffleLanguage.ContextPolicy.
Parse Caching
The result of theparsing request is cached per language instance,
source, argument
names and environment options. The scope of the caching is influenced
by the context policy. Caching may be
disabled for certain sources. It is enabled for new sources by default.
Language Configuration
Oncontext creation each language context is provided with
information about the environment environment . Language can optionally declare
configurable options in
getOptionDescriptors().
Polyglot Bindings
Language implementations communicate with one another (and with instrumentation-based tools such as debuggers) by reading/writing named values into thepolyglot
bindings. This bindings object is used to implement guest language export/import statements used
for language interoperation.
A language implementation can also import or export a global symbol by name. The scope may be accessed from multiple threads at the same time. Existing keys are overwritten.
Configuration vs. Initialization
To ensure that a Truffle language can be used in a language-agnostic way, the implementation should be designed to decouple its configuration and initialization from language specifics as much as possible. One aspect of this is the initialization and start of execution via theContext, which should be designed in a generic way.
Language-specific entry points, for instance to emulate the command-line interface of an existing
implementation, should be handled externally.
Multi-threading
There are two kinds of threads that access contexts of Truffle guest languages:- Internal threads are
createdand managed by a language for a context. All internally created threads need to be stopped when the context isdisposed. - External threads are created and managed by the host application / language launcher. The
host application is allowed to use language contexts from changing threads, sequentially or at
the same time if the language
allowsit.
By default every context only allows access from one thread at the
same time. Therefore if the context is tried to be accessed from multiple threads at the same
time the access will fail. Languages that want to allow multi-threaded access to a context may
override isThreadAccessAllowed(Thread, boolean) and return true also for
multi-threaded accesses. Initialization actions for multi-threaded access can be performed by
overriding initializeMultiThreading(Object). Threads are
initialized and disposed before and after use with a context. Languages may
create new threads if the environment
allows it.
In addition to the two kinds of threads described above, there are
system threads designed to process language
internal tasks in the background. They do not require the creation permit, but they must not enter any language context.
- Since:
- 0.8 or earlier
- See Also:
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprotected static interfaceContext local factory for Truffle languages.protected static final classProvider for creating context local and context thread local references.static enumDefines the supported policy for reusinglanguagesper context.static classRepresents a reference to the current context.protected static interfaceContext thread local factory for Truffle languages.static final classRepresents execution environment of theTruffleLanguage.static enumMode of exit operation.static final classRequest for inline parsing.static classRepresents a reference to the current language instance.static final classRequest for parsing.static @interfaceThe annotation to use to register your language to the.invalid reference
Polyglot API -
Field Summary
FieldsModifier and TypeFieldDescriptionprotected final TruffleLanguage.ContextLocalProvider<C> Provider for creating context local and context thread local references. -
Constructor Summary
ConstructorsModifierConstructorDescriptionprotectedConstructor to be called by subclasses. -
Method Summary
Modifier and TypeMethodDescriptionprotected booleanareOptionsCompatible(org.graalvm.options.OptionValues firstOptions, org.graalvm.options.OptionValues newOptions) protected abstract CCreates internal representation of the executing context suitable for given environment.protected final <T> ContextLocal<T> createContextLocal(TruffleLanguage.ContextLocalFactory<C, T> factory) Deprecated.protected final <T> ContextThreadLocal<T> Deprecated.protected voiddisposeContext(C context) Disposes the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env).protected voiddisposeThread(C context, Thread thread) Invoked the last time code will be executed for this thread and context.protected voidexitContext(C context, TruffleLanguage.ExitMode exitMode, int exitCode) Performs language exit event actions that are necessary before language contexts arefinalized.protected voidfinalizeContext(C context) Performs language context finalization actions that are necessary before language contexts aredisposed.protected voidfinalizeThread(C context, Thread thread) The behavior of this notification is different forpolyglot threadsand embedder threads.protected final intGet the depth of asynchronous stack.protected static <C, T extends TruffleLanguage<C>>
CgetCurrentContext(Class<T> languageClass) Deprecated.in 21.3, use static final context references instead.protected static <T extends TruffleLanguage<?>>
TgetCurrentLanguage(Class<T> languageClass) Deprecated.in 21.3, use static final context references instead.protected final StringReturns the home location for this language ornullif the language home is not set.protected ObjectgetLanguageView(C context, Object value) Wraps the value to provide language-specific information for primitive and foreign values.protected org.graalvm.options.OptionDescriptorsReturns a set of option descriptors that are supported by this language.protected ObjectGet a top scope of the language, if any.protected voidinitializeContext(C context) Perform any complex initialization.protected voidInitializes this language instance for use with multiple contexts.protected voidinitializeMultiThreading(C context) Invoked before the context is accessed from multiple threads at the same time.protected voidinitializeThread(C context, Thread thread) Invoked before a context is accessed from a new thread.protected booleanisThreadAccessAllowed(Thread thread, boolean singleThreaded) Returnstrueif code of this language is allowed to be executed on this thread.protected booleanDecides whether the result of evaluating an interactive source should be printed to stdout.protected ExecutableNodeParses theprovided source snippetat theprovided locationand generates its appropriate AST representation.protected CallTargetparse(TruffleLanguage.ParsingRequest request) Parses theprovided sourceand generates its appropriate AST representation.protected booleanpatchContext(C context, TruffleLanguage.Env newEnv) Notifies the language with pre-initialized context aboutTruffleLanguage.Envchange.
-
Field Details
-
locals
Provider for creating context local and context thread local references.- Since:
- 23.1
- See Also:
-
-
Constructor Details
-
TruffleLanguage
protected TruffleLanguage()Constructor to be called by subclasses. Language should not create anyRootNodes in its constructor. The RootNodes created in the language constructor are not associated with a Context and they don't respect Context's engine options. The needed RootNodes can be created in thecreateContext(Env).- Since:
- 0.8 or earlier
-
-
Method Details
-
areOptionsCompatible
protected boolean areOptionsCompatible(org.graalvm.options.OptionValues firstOptions, org.graalvm.options.OptionValues newOptions) Returnstrueif the combination of two sets of options allow toshareorreusethe same language instance, elsefalse. If options are incompatible then a new language instance will be created for a new context. The default implementation returnstrue.If the context policy of a language is set to
exclusive(default behavior) thenareOptionsCompatible(OptionValues, OptionValues)will never be invoked asTruffleLanguageinstances will not be shared for multiple contexts. For the other context policiesreuseandsharedthis method can be used to further restrict the reuse of language instances. Compatibility influencesparse cachingbecause it uses thelanguageinstance as a key.Example usage of areOptionsCompatible if sharing of the language instances and parse caching should be restricted by the script version option:
class CompatibleLanguage extends TruffleLanguage<Env> { @Option(help = "", category = OptionCategory.USER) static final OptionKey<String> ScriptVersion = new OptionKey<>("ECMA2017"); @Override protected boolean areOptionsCompatible(OptionValues firstOptions, OptionValues newOptions) { return firstOptions.get(ScriptVersion). equals(newOptions.get(ScriptVersion)); } @Override protected OptionDescriptors getOptionDescriptors() { return new CompatibleLanguageOptionDescriptors(); } }- Parameters:
firstOptions- the options used to create the first context, nevernullnewOptions- the options that will be used for the new context, nevernull- Since:
- 19.0
- See Also:
-
createContext
Creates internal representation of the executing context suitable for given environment. Each time thelanguageis used by a newContext, the system calls this method to let thelanguageprepare for execution. The returned execution context is completely language specific; it is however expected it will contain reference to here-in providedenvand adjust itself according to parameters provided by theenvobject.The context created by this method is accessible using
context references. AnIllegalStateExceptionis thrown if the context is tried to be accessed while the createContext method is executed.This method shouldn't perform any complex operations. The runtime system is just being initialized and for example making
calls into other languagesand assuming your language is already initialized and others can see it would be wrong - until you return from this method, the initialization isn't over. The same is true for instrumentation, the instruments cannot receive any meta data about code executed during context creation. Should there be a need to perform complex initialization, do it by overriding theinitializeContext(java.lang.Object)method.Additional services provided by the language must be
registeredby this method otherwiseIllegalStateExceptionis thrown.May return
nullif the language does not need any per-context state. Otherwise it should return a new object instance every time it is called.- Parameters:
env- the environment the language is supposed to operate in- Returns:
- internal data of the language in given environment or
null - Since:
- 0.8 or earlier
-
initializeContext
Perform any complex initialization. ThecreateContext(com.oracle.truffle.api.TruffleLanguage.Env)factory method shouldn't do any complex operations. Just create the instance of the context, let the runtime system register it properly. Should there be a need to perform complex initialization, override this method and let the runtime call it later to finish any post initialization actions. Example:class PostInitLanguage extends TruffleLanguage<Context> { @Override protected Context createContext(Env env) { // "quickly" create the context return new Context(env); } @Override protected void initializeContext(Context context) throws IOException { // called "later" to finish the initialization // for example call into another language Source source = Source.newBuilder("js", "function(x, y) x * y", "mul.js").build(); context.mul = context.env.parsePublic(source); } }- Parameters:
context- the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env)- Throws:
Exception- if something goes wrong- Since:
- 0.17
-
finalizeContext
Performs language context finalization actions that are necessary before language contexts aredisposed. However, in case the underlying polyglot context is being cancelled or hard-exited,disposeContext(Object)is called even iffinalizeContext(Object)throws anAbstractTruffleExceptionor aThreadDeathcancel or exit exception.For the hard exit a language is supposed to run its finalization actions that require running guest code in
exitContext(Object, ExitMode, int), but please note that afterexitContext(Object, ExitMode, int)runs for a language, the language can still be invoked fromexitContext(Object, ExitMode, int)for a different language. Therefore, for instance, finalization for standard streams should both flush and set them to unbuffered mode at the end of exitContext, so that running guest code is not required to dispose the streams after that point.Context finalization is invoked even if a context was cancelled. In such a case, if guest code would run as part of the finalization, it would be cancelled at the next polled
safepoint. If there is guest code that always needs to run even if cancelled, e.g. to prevent resource leakage, useTruffleSafepoint.setAllowActions(boolean)to temporarily disable safepoints while executing that code.All installed languages must remain usable after finalization. The finalization order can be influenced by specifying
language dependencies. By default internal languages are finalized last, otherwise, the default order is unspecified but deterministic.While the finalization code is run, other language contexts may become initialized. In such a case, the finalization order may be non-deterministic and/or not respect the order specified by language dependencies.
All threads
createdby the language must be stopped and joined during finalizeContext. The languages are responsible for fulfilling that contract, otherwise, anAssertionErroris thrown. It's not safe to use theExecutorService.awaitTermination(long, java.util.concurrent.TimeUnit)to detect Thread termination as the polyglot thread may be cancelled before executing the executor worker.During finalizeContext, all unclosed inner contexts
createdby the language must be left on all threads where the contexts are still active. No active inner context is allowed afterfinalizeContext(Object)returns, otherwise it is an internal error.Non-active inner contexts
createdby the language that are still unclosed afterfinalizeContext(Object)returns are automatically closed by Truffle.Typical implementation looks like:
class AsyncThreadLanguage extends TruffleLanguage<Context> { @Override protected Context createContext(Env env) { return new Context(env); } @Override protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { // allow access from any thread instead of just one return true; } @Override protected void initializeContext(Context context) throws Exception { // create and start a Thread for the asynchronous task // remeber the Thread reference to stop and join it in // the finalizeContext Thread t = context.env.newTruffleThreadBuilder(new Runnable() { @Override public void run() { // asynchronous task } }).build(); context.startedThreads.add(t); t.start(); } @Override protected void finalizeContext(Context context) { // stop and join all the created Threads boolean interrupted = false; for (int i = 0; i < context.startedThreads.size();) { Thread threadToJoin = context.startedThreads.get(i); try { if (threadToJoin != Thread.currentThread()) { threadToJoin.interrupt(); threadToJoin.join(); } i++; } catch (InterruptedException ie) { interrupted = true; } } if (interrupted) { Thread.currentThread().interrupt(); } } }- Parameters:
context- the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env)- Since:
- 0.30
- See Also:
-
exitContext
Performs language exit event actions that are necessary before language contexts arefinalized. However, in case the underlying polyglot context is being cancelled,exit notificationsare not executed. Also, forhard exit,finalizeContext(Object)is called even ifexitContext(Object, ExitMode, int)throws anAbstractTruffleExceptionor aThreadDeathcancel or exit exception. All initialized language contexts must remain usable after exit notifications. In case aAbstractTruffleExceptionor theThreadDeathexit exception is thrown during anhard exit notification, it is just logged and otherwise ignored and the notification process continues with the next language in order. In case theThreadDeathcancel exception is thrown, it means the context is being cancelled in which case the exit notification process immediately stops. The exit notification order can be influenced by specifyinglanguage dependencies- The exit notification for language A that depends on language B is executed before the exit notification for language B. By default, notifications for internal languages are executed last, otherwise, the default order is unspecified but deterministic.During
hard exitnotification, a language is supposed to run its finalization actions that require running guest code instead of running them infinalizeContext(Object).While the exit notification code is run, all languages remain fully functional. Also, other language contexts may become initialized. In such a case, the notification order may be non-deterministic and/or not respect the order specified by language dependencies.
In case
TruffleContext.closeExited(Node, int)is called during anatural exitnotification, natural exit notifications for remaining language contexts are not executed and thehard exitprocess starts by executinghard exitnotifications. In caseTruffleContext.closeExited(Node, int)is called during ahard exitnotification, it just throws the specialThreadDeathexit exception, which is then just logged as described above.In case the underlying polyglot context is cancelled by e.g.
TruffleContext.closeCancelled(Node, String)during exit notifications, guest code executed during exit notification is regularly cancelled, i.e., throws theThreadDeathcancel exception, and the notification process does not continue as described above.In the case of
hard exit, if the current context has inner contexts that are still active, the execution for them will be stopped as well after all language exit notifications are executed for the outer context, but the exit notifications for the inner contexts are not automatically executed. The language needs to take appropriate action to make sure inner contexts are exited properly.- Parameters:
context- language context.exitMode- mode of exit.exitCode- exit code that was specified for exit.- Since:
- 22.0
- See Also:
-
initializeMultipleContexts
protected void initializeMultipleContexts()Initializes this language instance for use with multiple contexts. Whether a language instance supports being used for multiple contexts depends on itscontext policy.For any sharing of a language instance for multiple language contexts to take place a context must be created with sharing enabled. By default sharing is disabled for polyglot contexts. Sharing can be enabled by specifying an
explicit engineor using an option. Before any language is used for sharinginitializeMultipleContexts()is invoked. It is guaranteed that sharing between multiple contexts isinitializedbefore any language context iscreated.A language may use this method to configure itself to use context independent speculations only. Since Truffle nodes are never shared between multiple language instances it is sufficient to keep track of whether sharing is enabled using a non-volatile boolean field instead of an assumption. They field may also be annotated with
CompilerDirectives.CompilationFinalas it is guaranteed that this method is called prior to any compilation. The following criteria should be satisfied when supporting context independent code:- All speculation on runtime value identity must be disabled with multiple contexts initialized, as they will lead to a guaranteed deoptimization when used with a second context.
- Function inline caches should be modified and implemented as a two-level inline cache. The first level speculates on the function instance's identity and the second level on the underlying CallTarget instance. The first level cache must be disabled if multiple contexts are initialized, as this would unnecessarily cause deoptimization.
- The DynamicObject root Shape instance should be stored in the language instance instead of the language context. Otherwise, any inline cache on shapes will not stabilize and ultimately end up in the generic state.
- All Node implementations must not store context-dependent data structures or context-dependent runtime values.
- All assumption instances should be stored in the language instance instead of the context. With multiple contexts initialized, the context instance read using context references may no longer be a constant. In this case any assumption read from the context would not be folded and they would cause significant runtime performance overhead. Assumptions from the language can always be folded by the compiler in both single and multiple context mode.
- Since:
- 19.0
- See Also:
-
disposeContext
Disposes the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env). A dispose cleans up all resources associated with a context. The context may become unusable after it was disposed. It is not allowed to run guest language code while disposing a context. Finalization code should be run infinalizeContext(Object)instead. Finalization will be performed prior to contextdisposal. However, in case the underlying polyglot context is being cancelled,disposeContext(Object)is called even iffinalizeContext(Object)throwsAbstractTruffleExceptionorThreadDeathexception..The disposal order can be influenced by specifying
language dependencies. By default internal languages are disposed last, otherwise the default order is unspecified but deterministic. During disposal no other language must be accessed using thelanguage environment.- Parameters:
context- the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env)- Since:
- 0.8 or earlier
- See Also:
-
parse
Parses theprovided sourceand generates its appropriate AST representation. The parsing should execute no user code, it should only create theNodetree to represent the source. If theprovided sourcedoes not correspond naturally to acall target, the returned call target should create and if necessary initialize the corresponding language entity and return it.The result of the parsing request is cached per language instance,
sourceandargument names. It is safe to assume that currentlanguageinstance andargument nameswill remain unchanged for a parsedCallTarget. The scope of the caching is influenced by thecontext policyand optioncompatibility. Caching may bedisabledfor sources. It is enabled for new sources by default.The
argumentNamesmay contain symbolic names for actual parameters of the call to the returned value. The result should be a call target with methodCallTarget.call(java.lang.Object...)that accepts as many arguments as were provided via theTruffleLanguage.ParsingRequest.getArgumentNames()method.Implement
parse(com.oracle.truffle.api.TruffleLanguage.InlineParsingRequest)to parse source in a specific context location.- Parameters:
request- request for parsing- Returns:
- a call target to invoke which also keeps in memory the
Nodetree representing just parsedcode - Throws:
Exception- exception can be thrown when parsing goes wrong. Here-in thrown exception is propagated to the user who called one ofevalmethods ofContext- Since:
- 0.22
- See Also:
-
parse
Parses theprovided source snippetat theprovided locationand generates its appropriate AST representation. The parsing should execute no user code, it should only create theNodetree to represent the source.The parsing should be performed in a context (specified by
TruffleLanguage.InlineParsingRequest.getLocation()). The result should be an AST fragment with methodExecutableNode.execute(com.oracle.truffle.api.frame.VirtualFrame)that accepts frames valid at theprovided location.When not implemented,
nullis returned by default. -
getOptionDescriptors
protected org.graalvm.options.OptionDescriptors getOptionDescriptors()Returns a set of option descriptors that are supported by this language. Option values are accessible using theenvironmentwhen the context iscreated. To construct option descriptors from a list thenOptionDescriptors.create(List)can be used. Languages must always return the same option descriptors independent of the language instance or side-effects.- Since:
- 0.27
- See Also:
-
patchContext
Notifies the language with pre-initialized context aboutTruffleLanguage.Envchange. SeeContextfor information how to enable the Context pre-initialization.During the pre-initialization (in the native compilation time) the
createContext(com.oracle.truffle.api.TruffleLanguage.Env)andinitializeContext(java.lang.Object)methods are called. In the image execution time, thepatchContext(java.lang.Object, com.oracle.truffle.api.TruffleLanguage.Env)is called on all languages whose contexts were created during the pre-initialization a consequence ofContext.create(java.lang.String...)invocation. The contexts are patched in a topological order starting from dependent languages. If thepatchContext(java.lang.Object, com.oracle.truffle.api.TruffleLanguage.Env)is successful for all pre-initialized languages the pre-initialized context is used, otherwise a new context is created.Typical implementation looks like:
@Override protected boolean patchContext(Context context, Env newEnv) { if (!optionsAllowPreInitializedContext(context, newEnv)) { // Incompatible options - cannot use pre-initialized context return false; } context.env = newEnv; context.args = newEnv.getApplicationArguments(); context.in = newEnv.in(); context.out = newEnv.out(); context.err = newEnv.err(); return true; } private boolean optionsAllowPreInitializedContext(Context context, Env newEnv) { // Verify that values of important options in the new Env do not differ // from values in the pre-initialized context final String newVersionValue = newEnv.getOptions().get(version); return Objects.equals(context.languageVersion, newVersionValue); }- Parameters:
context- the context created bycreateContext(com.oracle.truffle.api.TruffleLanguage.Env)during pre-initializationnewEnv- the new environment replacing the environment used in pre-initialization phase- Returns:
- true in case of successful environment update. When the context cannot be updated to
a new environment return false to create a new context. By default it returns
falseto prevent an usage of pre-initialized context by a language which is not aware of context pre-initialization. - Since:
- 0.31
-
isThreadAccessAllowed
Returnstrueif code of this language is allowed to be executed on this thread. The method returnsfalseto deny execution on this thread. The default implementation denies access to more than one thread at the same time. Thecurrent threadmay differ from the passed thread. If this method throws anAbstractTruffleExceptionthe exception interop messages may be executed without a context being entered.Example multi-threaded language implementation:
class MultiThreadedLanguage extends TruffleLanguage<Context> { @Override protected Context createContext(Env env) { return new Context(env); } @Override protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { // allow access from any thread instead of just one return true; } @Override protected void initializeMultiThreading(Context context) { // perform actions when the context is switched to multi-threading context.singleThreaded.invalidate(); } @Override protected void initializeThread(Context context, Thread thread) { // perform initialization actions for threads } @Override protected void disposeThread(Context context, Thread thread) { // perform disposal actions for threads } }- Parameters:
thread- the thread that accesses the context for the first time.singleThreaded-trueif the access is considered single-threaded,falseif more than one thread is active at the same time.- Since:
- 0.28
-
initializeMultiThreading
Invoked before the context is accessed from multiple threads at the same time. This allows languages to perform actions that are required to support multi-threading. It will never be invoked ifisThreadAccessAllowed(Thread, boolean)is implemented to deny access from multiple threads at the same time. All initialized languages must allow multi-threading for this method to be invoked. If this method throws anAbstractTruffleExceptionthe exception interop messages may be executed without a context being entered.Example multi-threaded language implementation:
class MultiThreadedLanguage extends TruffleLanguage<Context> { @Override protected Context createContext(Env env) { return new Context(env); } @Override protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { // allow access from any thread instead of just one return true; } @Override protected void initializeMultiThreading(Context context) { // perform actions when the context is switched to multi-threading context.singleThreaded.invalidate(); } @Override protected void initializeThread(Context context, Thread thread) { // perform initialization actions for threads } @Override protected void disposeThread(Context context, Thread thread) { // perform disposal actions for threads } }- Parameters:
context- the context that should be prepared for multi-threading.- Since:
- 0.28
-
initializeThread
Invoked before a context is accessed from a new thread. This allows the language to perform initialization actions for each thread before guest language code is executed. Also for languages that deny access from multiple threads at the same time, multiple threads may be initialized if they are used sequentially. This method will be invoked before the context isinitializedfor the thread the context will be initialized with. If the thread is stored in the context it must be referenced usingWeakReferenceto avoid leaking thread objects.The
current threadis equal to the initialized thread.If this method throws an
AbstractTruffleExceptionthe exception interop messages may be executed without a context being entered.Example multi-threaded language implementation:
class MultiThreadedLanguage extends TruffleLanguage<Context> { @Override protected Context createContext(Env env) { return new Context(env); } @Override protected boolean isThreadAccessAllowed(Thread thread, boolean singleThreaded) { // allow access from any thread instead of just one return true; } @Override protected void initializeMultiThreading(Context context) { // perform actions when the context is switched to multi-threading context.singleThreaded.invalidate(); } @Override protected void initializeThread(Context context, Thread thread) { // perform initialization actions for threads } @Override protected void disposeThread(Context context, Thread thread) { // perform disposal actions for threads } }- Parameters:
context- the context that is enteredthread- the thread that accesses the context for the first time.- Since:
- 0.28
-
finalizeThread
The behavior of this notification is different forpolyglot threadsand embedder threads.For
polyglot threadsthefinalizeThreadnotification is invoked just before the context is left for the last time in the thread, and it is still safe to run guest code unless the context is cancelled or hard-exited. This allows the language to perform finalization actions for each thread and context. Polyglot threads are finalized before or while the context is finalized and it always holds thatthread == Thread.currentThread().Embedder threads are finalized after the context is finalized, but before it is disposed.
thread == Thread.currentThread()holds only for the embedder thread that performed the context finalization. Finalization of other embedder threads is invoked in the context finalization thread as well, and sothread != Thread.currentThread(). It is still safe to run guest code infinalizeThreadfor an embedder thread unless the context is cancelled or hard-exited, but it is not allowed to initialize new language contexts or create polyglot threads. A language context initialization or creation of a polyglot thread infinalizeThreadfor an embedder thread results inIllegalStateException. Please note that embedder threads may be collected by the garbage collector before they can be finalized and may therefore not be finalized.Thread finalization is invoked before
thread disposal.- Since:
- 23.1
- See Also:
-
disposeThread
Invoked the last time code will be executed for this thread and context. This allows the language to perform cleanup actions for each thread and context. Threads might be disposed before after or while a context is disposed. Thecurrent threadmay differ from the disposed thread. Disposal of threads is only guaranteed for threads that were created by guest languages, so calledpolyglot threads. Other threads, created by the embedder, may be collected by the garbage collector before they can be disposed and may therefore not be disposed.- Since:
- 0.28
- See Also:
-
getScope
Get a top scope of the language, if any. The returned object must be aninterop scope objectand may haveparent scopes. The scope object exposes all top scopes variables as flattenedmembers. Top scopes are independent of aFrame. SeeInteropLibrary.isScope(Object)for details.The returned scope objects may be cached by the caller per language context. Therefore the method should always return equivalent top-scopes and variables objects for a given language context. Changes to the top scope by executing guest language code should be reflected by cached scope instances. It is recommended to store the top-scope directly in the language context for efficient access.
Interpretation
In most languages, just evaluating an expression likeMathis equivalent of a lookup with the identifier 'Math' in the top-most scopes of the language. Looking up the identifier 'Math' should have equivalent semantics as reading with the key 'Math' from the variables object of one of the top-most scopes of the language. In addition languages may optionally allow modification and insertion with the variables object of the returned top-scopes.Languages may want to specify multiple parent top-scopes. It is recommended to stay as close as possible to the set of top-scopes that as is described in the guest language specification, if available. For example, in JavaScript, there is a 'global environment' and a 'global object' scope. While the global environment scope contains class declarations and is not insertable, the global object scope is used to insert new global variable values and is therefore insertable.
Use Cases
- Top scopes are accessible to instruments with
TruffleInstrument.Env.getScope(LanguageInfo). They are used by debuggers to access the top-most scopes of the language. - Top scopes available in the
as context
invalid reference
polyglot APIbindingsobject. Access to members of the bindings object is applied to the returned scope object via interop. - Languages may expose other language scopes using a polyglot bindings builtin. E.g with
TruffleLanguage.Env.getScopePublic(LanguageInfo).
- Parameters:
context- the context to find the language top scope in- Returns:
- the scope object or
nullif the language does not support such concept - Since:
- 20.3
- Top scopes are accessible to instruments with
-
isVisible
Decides whether the result of evaluating an interactive source should be printed to stdout. By default this methods returnstrueclaiming all values are visible.This method affects behavior of
Context.eval(org.graalvm.polyglot.Source)- when evaluating aninteractive sourcethe result of the evaluation is tested forvisibilityand if the value is found visible, it gets converted to string and printed tostandard output.A language can control whether a value is or isn't printed by overriding this method and returning
falsefor some or all values. In such case it is up to the language itself to use theTruffleLanguage.Env.out(),TruffleLanguage.Env.err()andTruffleLanguage.Env.in()streams of the environment. When evaluation is called with aninteractive sourceof a language that controls its interactive behavior, it is the responsibility of the language itself to print the result to use theTruffleLanguage.Env.out(),TruffleLanguage.Env.err()andTruffleLanguage.Env.in()streams of the environment.- Parameters:
context- the execution context for doing the conversionvalue- the value to check. Either primitive type orTruffleObject- Returns:
trueif the language implements an interactive response to evaluation of interactive sources.- Since:
- 0.22
-
getLanguageView
Wraps the value to provide language-specific information for primitive and foreign values. Foreign values should be enhanced to look like the most generic object type of the language. The wrapper needs to introduce any "virtual" methods and properties that are commonly used in language constructs and in algorithms that are written to work on this generic object type. The wrapper may add or remove existing interop traits, but it is not allowed to change theinterop type. For example, it is not allowed to change the type from number to string. If the behavior of an existing trait is modified then all writes on the mapper need to be forwarded to the underlying object, apart from the virtual members. Writes to the virtual members should be persisted in the wrapper if this is the behavior of the object type that is being mapped to.Every language view wrapper must return the current language as their associated
language. AnAssertionErroris thrown when a language view is requested if this contract is violated.Example modifications language view wrappers may perform:
- Provide a language specific
display stringfor primitive and foreign values. - Return a language specific
metaobjectfor primitive or foreign values. - Add virtual members to the object for the view. For example, any JavaScript object is expected to have an implicit __proto__ member. Foreign objects, even if they do not have such a member, are interpreted as if they have.
- There are languages where all scalar values are also vectors. In such a case the array element trait may be added using the language wrapper to such values.
The default implementation returns
null. Ifnullis returned then the default language view will be used. The default language view wraps the value and returns the current language as their associated language. With the default view wrapper all interop library messages will be forwarded to the delegate value.This following example shows a simplified language view. For a full implementation including an example of metaobjects can be found in the Truffle examples language "SimpleLanguage".
@ExportLibrary(value = InteropLibrary.class, delegateTo = "delegate") final class ExampleLanguageView implements TruffleObject { protected final Object delegate; ExampleLanguageView(Object delegate) { this.delegate = delegate; } @ExportMessage boolean hasLanguage() { return true; } @ExportMessage Class<? extends TruffleLanguage<?>> getLanguage() { return MyLanguage.class; } @ExportMessage Object toDisplayString(boolean allowSideEffects, @CachedLibrary("this.delegate") InteropLibrary dLib) { try { if (dLib.isString(this.delegate)) { return dLib.asString(this.delegate); } else if (dLib.isBoolean(this.delegate)) { return dLib.asBoolean(this.delegate) ? "TRUE" : "FALSE"; } else if (dLib.fitsInLong(this.delegate)) { return longToString(dLib.asLong(this.delegate)); } else { // full list truncated for this language return "Unsupported value"; } } catch (UnsupportedMessageException e) { CompilerDirectives.transferToInterpreter(); throw new AssertionError(e); } } @TruffleBoundary private static String longToString(long value) { return String.valueOf(value); } @ExportMessage boolean hasMetaObject(@CachedLibrary("this.delegate") InteropLibrary dLib) { return dLib.isString(this.delegate)// || dLib.fitsInLong(this.delegate)// || dLib.isBoolean(this.delegate); } @ExportMessage Object getMetaObject(@CachedLibrary("this.delegate") InteropLibrary dLib) throws UnsupportedMessageException { if (dLib.isString(this.delegate)) { return MyMetaObject.PRIMITIVE_STRING; } else if (dLib.isBoolean(this.delegate)) { return MyMetaObject.PRIMITIVE_LONG; } else if (dLib.fitsInLong(this.delegate)) { return MyMetaObject.PRIMITIVE_BOOLEAN; } else { // no associable metaobject throw UnsupportedMessageException.create(); } } }- Parameters:
context- the current context.value- the value- Since:
- 20.1
- Provide a language specific
-
getCurrentLanguage
@Deprecated(since="21.3") protected static <T extends TruffleLanguage<?>> T getCurrentLanguage(Class<T> languageClass) Deprecated.in 21.3, use static final context references instead. SeeTruffleLanguage.ContextReferencefor the new intended usage.- Since:
- 0.27
-
getCurrentContext
@Deprecated(since="21.3") protected static <C, T extends TruffleLanguage<C>> C getCurrentContext(Class<T> languageClass) Deprecated.in 21.3, use static final context references instead. SeeTruffleLanguage.LanguageReferencefor the new intended usage.- Since:
- 0.27
-
createContextLocal
@Deprecated protected final <T> ContextLocal<T> createContextLocal(TruffleLanguage.ContextLocalFactory<C, T> factory) Deprecated.Creates a new context local reference for this Truffle language. Starting with JDK 21, using this method leads to a this-escape warning. UseTruffleLanguage.ContextLocalProvider.createContextLocal(TruffleLanguage.ContextLocalFactory)instead.- Since:
- 20.3
-
createContextThreadLocal
@Deprecated protected final <T> ContextThreadLocal<T> createContextThreadLocal(TruffleLanguage.ContextThreadLocalFactory<C, T> factory) Deprecated.Creates a new context thread local reference for this Truffle language. Starting with JDK 21, using this method leads to a this-escape warning. UseTruffleLanguage.ContextLocalProvider.createContextThreadLocal(TruffleLanguage.ContextThreadLocalFactory)instead.- Since:
- 20.3
-
getLanguageHome
Returns the home location for this language ornullif the language home is not set. Languages consumed from the Maven repository typically don't have a language home. For legacy graalvm or standalone builds the language home corresponds to the directory in which the Jar file is located, if run from a Jar file. For an AOT compiled binary, this corresponds to the location of the language files in the default GraalVM distribution layout.- Since:
- 19.0
-
getAsynchronousStackDepth
protected final int getAsynchronousStackDepth()Get the depth of asynchronous stack. When zero, the language should not sacrifice performance to be able to provide asynchronous stack. When the depth is non-zero, the language should provide asynchronous stack up to that depth. The language may provide more asynchronous frames than this depth if it's of no performance penalty, or if requested by other (e.g. language-specific) options. The returned depth may change at any time.Override
RootNode.findAsynchronousFrames(Frame)to provide the asynchronous stack frames.- Since:
- 20.1.0
- See Also:
-
TruffleLanguage.ContextLocalProvider.createContextLocal(TruffleLanguage.ContextLocalFactory)instead