public final class TruffleContext extends Object implements AutoCloseable
A context
consists of a language
context
instance for each installed language
. The current
language context is created
eagerly and can be
accessed using a context reference
after the context was
entered
.
The configuration for each language context is inherited from its parent/creator context. In
addition to that config
parameters can be passed to new
language context instance of the current language. The configuration of other installed languages
cannot be modified. To run guest language code in a context, the context needs to be first
entered
and then left
. The context should be
closed
when it is no longer needed. If the context is not closed explicitly,
then it is automatically closed together with the parent context.
Example usage:
final class MyNode extendsNode
{ void executeInContext(TruffleLanguage.Env
env) { MyContext outerLangContext = getContext(this);TruffleContext
innerContext = env.newInnerContextBuilder(). initializeCreatorContext(true).build();Object
p = innerContext.enter(this); try { /* * Here the this node cannot be passed otherwise an * invalid sharing error would occur. */ MyContext innerLangContext = getContext(null); assert outerLangContext != innerLangContext; } finally { innerContext.leave(this, p); } assert outerLangContext == getContext(this); innerContext.close(); } } private staticTruffleLanguage.ContextReference
<MyContext> REFERENCE =TruffleLanguage.ContextReference
.create(MyLanguage.class); private static MyContext getContext(Node
node) { return REFERENCE.get(node); }
Modifier and Type | Class and Description |
---|---|
class |
TruffleContext.Builder
Builder class to create new
TruffleContext instances. |
Modifier and Type | Method and Description |
---|---|
void |
close()
Closes this context and disposes its resources.
|
void |
closeCancelled(Node closeLocation,
String message)
Force closes the context as cancelled and stops all the execution on all active threads using
a special
ThreadDeath cancel exception. |
void |
closeExited(Node exitLocation,
int exitCode)
Initiates force close of the context as exited -
hard exit . |
void |
closeResourceExhausted(Node location,
String message)
Force closes the context due to resource exhaustion.
|
Object |
enter(Node node)
Enters this context and returns an object representing the previous context.
|
boolean |
equals(Object obj) |
Object |
evalInternal(Node node,
Source source)
Evaluates a source in an inner context and returns the result.
|
Object |
evalPublic(Node node,
Source source)
The same as
TruffleContext.evalInternal(Node, Source) , but only public languages are accessible. |
TruffleContext |
getParent()
Get a parent context of this context, if any.
|
int |
hashCode() |
boolean |
initializeInternal(Node node,
String languageId)
Forces initialization of an internal or public language.
|
boolean |
initializePublic(Node node,
String languageId)
The same as
TruffleContext.initializeInternal(Node, String) , but only public languages are
accessible. |
boolean |
isActive()
Returns
true if the context is currently active on the current thread, else
false . |
boolean |
isCancelling()
Returns
true if the context is being cancelled else false . |
boolean |
isClosed()
Returns
true if the context was closed else false . |
boolean |
isEntered()
Checks whether the context is entered on the current thread and the context is the currently
active context on this thread.
|
boolean |
isExiting()
Returns
true if the context is being hard-exited else false . |
void |
leave(Node node,
Object prev)
Leaves this context and sets the previous context as the new current context.
|
<T,R> R |
leaveAndEnter(Node node,
TruffleSafepoint.Interrupter interrupter,
TruffleSafepoint.InterruptibleFunction<T,R> interruptible,
T object)
Leaves this context, runs the passed interruptible function and reenters the context.
|
Future<Void> |
pause()
Pause execution on all threads for this context.
|
void |
resume(Future<Void> pauseFuture)
Resume previously paused execution on all threads for this context.
|
public TruffleContext getParent()
null
if there is no parentpublic Object enter(Node node)
TruffleContext.leave(Node, Object)
in a finally block and the
previous context must be passed as an argument. It is allowed to enter a context multiple
times from the same thread. If the context is currently not entered by any thread then it is
allowed be entered by an arbitrary thread. Entering the context from two or more different
threads at the same time is possible, unless one of the loaded languages denies access to the
thread, in which case an IllegalStateException
is thrown.
If the current thread was not previously entered in any context, the enter function returns
null
. If the return value is not null
, the result of the enter function is
unspecified and must only be passed to TruffleContext.leave(Node, Object)
. The result value must
not be stored permanently.
An adopted node may be passed to allow perform optimizations on the fast-path. If a
null
node is passed then entering a context will result in a
boundary
call in compiled code. If the provided node is not adopted
an IllegalArgumentException
is thrown.
Entering a language context is designed for compilation and is most efficient if the
context
instance is compilation final.
Example usage:
final class MyNode extendsNode
{ void executeInContext(TruffleLanguage.Env
env) { MyContext outerLangContext = getContext(this);TruffleContext
innerContext = env.newInnerContextBuilder(). initializeCreatorContext(true).build();Object
p = innerContext.enter(this); try { /* * Here the this node cannot be passed otherwise an * invalid sharing error would occur. */ MyContext innerLangContext = getContext(null); assert outerLangContext != innerLangContext; } finally { innerContext.leave(this, p); } assert outerLangContext == getContext(this); innerContext.close(); } } private staticTruffleLanguage.ContextReference
<MyContext> REFERENCE =TruffleLanguage.ContextReference
.create(MyLanguage.class); private static MyContext getContext(Node
node) { return REFERENCE.get(node); }
TruffleContext.leave(Node, Object)
public boolean initializeInternal(Node node, String languageId)
TruffleLanguage.Env.getContext()
an IllegalStateException
is
thrown. In such a case TruffleLanguage.Env.initializeLanguage(LanguageInfo)
should be used instead to
initialize contexts.
No context or the parent creator context must be entered to initialize languages in a
TruffleContext
otherwise an IllegalStateException
will be thrown.
languageId
- the id of the language to initializenode
- a partial evaluation constant node context used to optimize this operation. Can
be null
if not available.true
if the language was initialized, else false
, e.g. if
the language as already initialized.IllegalStateException
- if an invalid context is entered or the context is already
closed.IllegalArgumentException
- if the given language of the source cannot be accessed.public boolean initializePublic(Node node, String languageId)
TruffleContext.initializeInternal(Node, String)
, but only public languages are
accessible.languageId
- the id of the language to initializenode
- a partial evaluation constant node context used to optimize this operation. Can
be null
if not available.true
if the language was initialized, else false
, e.g. if
the language as already initialized.IllegalStateException
- if an invalid context is entered or the context is already
closed.IllegalArgumentException
- if the given language of the source cannot be accessed.public Object evalInternal(Node node, Source source)
TruffleLanguage.Env.getContext()
an IllegalStateException
is
thrown. In such a case TruffleLanguage.Env.parseInternal(Source, String...)
should be used instead to
evaluate sources.
No context or the parent creator context must be entered to evaluate sources in a
TruffleContext
otherwise an IllegalStateException
will be thrown. In order to
ensure that all values are accessed from their respective contexts only, any non-primitive
value returned by the evaluation will be wrapped and enter this context for each interop
message sent. Parameters to interop messages will enter and leave the parent context when
they are accessed. If the result is a primitive value, then the value is directly returned.
This method has access to all public and internal languages the creator context has access
to. This corresponds to the set of languages returned by TruffleLanguage.Env.getInternalLanguages()
.
If a language cannot be accessed then an IllegalArgumentException
is thrown. If a
language is not yet initialized in the inner context, it will get automatically initialized.
This method is designed to be used in compiled code paths. This method may be used from
multiple threads at the same time. The result of this method must not be cached, instead the
Source
object should be cached.
node
- a partial evaluation constant node context used to optimize this operation. Can
be null
if not available.source
- the source to evaluateIllegalArgumentException
- if the given language of the source cannot be accessed.IllegalStateException
- if an invalid context is entered or the context is already
closed.public Object evalPublic(Node node, Source source)
TruffleContext.evalInternal(Node, Source)
, but only public languages are accessible.node
- a partial evaluation constant node context used to optimize this operation. Can
be null
if not available.source
- the source to evaluateIllegalArgumentException
- if the given language of the source cannot be accessed.IllegalStateException
- if an invalid context is entered or the context is already
closed.public boolean isEntered()
active
on a
single thread, but this method only returns true
if it is the top-most context.
This method is thread-safe and may be used from multiple threads.true
if the context is active, false
otherwisepublic boolean isActive()
true
if the context is currently active on the current thread, else
false
. Checks whether the context has been previously entered by this thread
with TruffleContext.enter(Node)
and hasn't been left yet with
TruffleContext.leave(Node, java.lang.Object)
methods. Multiple contexts can be active on a single
thread. See TruffleContext.isEntered()
for checking whether it is the top-most entered context.
This method is thread-safe and may be used from multiple threads.public boolean isClosed()
true
if the context was closed else false
. A context may be
closed if TruffleContext.close()
, TruffleContext.closeCancelled(Node, String)
, or
TruffleContext.closeExited(Node, int)
was called previously.public boolean isCancelling()
true
if the context is being cancelled else false
. A
context may be in the process of cancelling if TruffleContext.closeCancelled(Node, String)
was
called previously.public boolean isExiting()
true
if the context is being hard-exited else false
. A
context may be in the process of exit if TruffleContext.closeExited(Node, int)
was called
previously.public Future<Void> pause()
TruffleContext.resume(Future)
is called.TruffleContext.resume(Future)
method.public void resume(Future<Void> pauseFuture)
TruffleContext.pause()
was called multiple times and for some of the other
calls resume was not called yet.pauseFuture
- pause future returned by a previous call to
TruffleContext.pause()
.IllegalArgumentException
- in case the passed pause future was not obtained by a
previous call to TruffleContext.pause()
on this context.public void leave(Node node, Object prev)
An adopted node may be passed to allow perform optimizations on the fast-path. If a
null
node is passed then entering a context will result in a
boundary
call in compiled code. If the node is not adopted an
IllegalArgumentException
is thrown.
Leaving a language context is designed for compilation and is most efficient if the
context
instance is compilation final.
prev
- the previous context returned by TruffleContext.enter(Node)
TruffleContext.enter(Node)
public <T,R> R leaveAndEnter(Node node, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.InterruptibleFunction<T,R> interruptible, T object)
The function will typically notify another thread that it can now enter the context without triggering multithreading and then wait for some thread to leave the context before exiting the function and reentering the context (again to avoid triggering multithreading).
An adopted node may be passed to allow performing optimizations on the fast-path.
node
- an adopted node or null
interrupter
- an interrupter used to interrupt the interruptible function when, e.g.,
the context is cancelled. The interrupter is also used to
reset
the interrupted state when the
context is reentered.interruptible
- the interruptible function to run while having left this context. This
function is run at most once.null
if the interruptibe throws an
InterruptedException
without the context being cancelled or exited.public void close()
entered
or
active by any thread. If a closed context is attempted to be accessed or entered, then an
IllegalStateException
is thrown. If the context is not closed explicitly, then it is
automatically closed together with the parent context. If an attempt to close a context was
successful then consecutive calls to close have no effect.close
in interface AutoCloseable
UnsupportedOperationException
- if the close operation is not supported on this contextIllegalStateException
- if the context is active
.TruffleContext.closeCancelled(Node, String)
,
TruffleContext.closeResourceExhausted(Node, String)
public void closeCancelled(Node closeLocation, String message)
ThreadDeath
cancel exception. If this context is not currently
entered
on the current thread then this method waits until the close
operation is complete and TruffleContext.isClosed()
returns true
, else it throws the
cancelled exception upon its completion of this method. If an attempt to close a context was
successful then consecutive calls to close have no effect.
The throwing of the special ThreadDeath
cancel exception also applies to any guest
code run during TruffleLanguage.finalizeContext(Object)
which means that
TruffleLanguage.finalizeContext(Object)
cannot run guest code during the cancel
operation.
If forced and this context currently entered
on the current thread and
no other context is entered on the current thread then this method directly throws a
ThreadDeath
error instead of completing to indicate that the current thread should be
stopped. The thrown ThreadDeath
must not be caught by the guest language and freely
propagated to the guest application to cancel the execution on the current thread. Please
note that this means that the guest language's finally blocks must not be executed.
If a context is active
on the current thread, but not entered
, then an IllegalStateException
is thrown, as parent contexts that are active
on the current thread cannot be cancelled.
closeLocation
- the node where the close occurred. If the context is currently entered
on the thread, then this node will be used as location, for the exception thrown.
If the context is not entered, then the closeLocation parameter will be ignored.message
- exception text for humans provided to the embedder and tools that observe the
cancellation.UnsupportedOperationException
- if the close operation is not supported on this contextIllegalStateException
- if the context is active
but not
entered
on the current thread.TruffleContext.close()
,
TruffleContext.closeResourceExhausted(Node, String)
public void closeExited(Node exitLocation, int exitCode)
hard exit
. Requires the context
to be entered on the current thread. Languages are first notified by calling
TruffleLanguage.exitContext(Object, TruffleLanguage.ExitMode, int)
and then the
closing of the context is initiated. Execution on all active threads including the current
thread is stopped by throwing a special ThreadDeath
exit exception. This method does
not wait for the execution on other threads to be stopped, it throws the ThreadDeath
exception as soon as possible. To exit threads reliably, guest languages need to ensure that
the ThreadDeath
is always immediately rethrown and guest language exception handlers
and finally blocks are not run.
The throwing of the special ThreadDeath
exit exception also applies to any guest code
run during TruffleLanguage.finalizeContext(Object)
which means that
TruffleLanguage.finalizeContext(Object)
cannot run guest code during hard exit.
The exit code can be specified only once and the first call to this method also executes the
exit notifications
on the same thread. Further calls to this method will ensure that the following guest code on
the calling thread is not executed by throwing the ThreadDeath
exit exception, and
the exit location is used as the stopping point of the thread, but the passed exit code is
ignored and exit notifications are not run.
In case the context is in one of the following states
TruffleLanguage.finalizeContext(Object)
is being executed for all language
contexts).
exitLocation
- the node where the exit occurred.exitCode
- exitCode provided to the embedder and tools that observe the exit.IllegalStateException
- if the context is not entered
on the
current thread.public void closeResourceExhausted(Node location, String message)
closeCancelled(location, message)
except in addition
the thrown PolyglotException
returns true
for
PolyglotException.isResourceExhausted()
.PolyglotException.isResourceExhausted()
,
TruffleContext.close()
,
TruffleContext.closeCancelled(Node, String)