Class TruffleContext

java.lang.Object
com.oracle.truffle.api.TruffleContext
All Implemented Interfaces:
AutoCloseable

public final class TruffleContext extends Object implements AutoCloseable
A handle on a context of a set of Truffle languages. This context handle is designed to be used by Truffle guest language implementations. The Truffle context can be used to create inner contexts for isolated execution of guest language code.

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 extends Node {
    void executeInContext(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 static ContextReference<MyContext> REFERENCE
             = ContextReference.create(MyLanguage.class);

private static MyContext getContext(Node node) {
    return REFERENCE.get(node);
}
Since:
0.27
  • Method Details

    • equals

      public boolean equals(Object obj)
      Overrides:
      equals in class Object
      Since:
      20.3
    • hashCode

      public int hashCode()
      Overrides:
      hashCode in class Object
      Since:
      20.3
    • getParent

      public TruffleContext getParent()
      Get a parent context of this context, if any. This provides the hierarchy of inner contexts.
      Returns:
      a parent context, or null if there is no parent
      Since:
      0.30
    • enter

      public Object enter(Node node)
      Enters this context and returns an object representing the previous context. Calls to enter must be followed by a call to 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 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: TruffleContextSnippets.MyNode.executeInContext(com.oracle.truffle.api.TruffleLanguage.Env)

      Since:
      20.3
      See Also:
    • initializeInternal

      public boolean initializeInternal(Node node, String languageId)
      Forces initialization of an internal or public language. If the context is not an inner context and e.g. accessed using 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.

      Parameters:
      node - a partial evaluation constant node context used to optimize this operation. Can be null if not available.
      languageId - the id of the language to initialize
      Returns:
      true if the language was initialized, else false, e.g. if the language as already initialized.
      Throws:
      IllegalStateException - if an invalid context is entered or the context is already closed.
      IllegalArgumentException - if the given language of the source cannot be accessed.
      Since:
      22.3
    • initializePublic

      public boolean initializePublic(Node node, String languageId)
      The same as initializeInternal(Node, String), but only public languages are accessible.
      Parameters:
      node - a partial evaluation constant node context used to optimize this operation. Can be null if not available.
      languageId - the id of the language to initialize
      Returns:
      true if the language was initialized, else false, e.g. if the language as already initialized.
      Throws:
      IllegalStateException - if an invalid context is entered or the context is already closed.
      IllegalArgumentException - if the given language of the source cannot be accessed.
      Since:
      22.3
    • evalInternal

      public Object evalInternal(Node node, Source source)
      Evaluates a source in an inner context and returns the result. If the context is not an inner context and e.g. accessed using 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.

      Parameters:
      node - a partial evaluation constant node context used to optimize this operation. Can be null if not available.
      source - the source to evaluate
      Throws:
      IllegalArgumentException - if the given language of the source cannot be accessed.
      IllegalStateException - if an invalid context is entered or the context is already closed.
      Since:
      21.3
    • evalPublic

      public Object evalPublic(Node node, Source source)
      The same as evalInternal(Node, Source), but only public languages are accessible.
      Parameters:
      node - a partial evaluation constant node context used to optimize this operation. Can be null if not available.
      source - the source to evaluate
      Throws:
      IllegalArgumentException - if the given language of the source cannot be accessed.
      IllegalStateException - if an invalid context is entered or the context is already closed.
      Since:
      21.3
    • isEntered

      public boolean isEntered()
      Checks whether the context is entered on the current thread and the context is the currently active context on this thread. There can be multiple contexts 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.
      Returns:
      true if the context is active, false otherwise
      Since:
      20.0
    • isActive

      public boolean isActive()
      Returns 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 enter(Node) and hasn't been left yet with leave(Node, java.lang.Object) methods. Multiple contexts can be active on a single thread. See isEntered() for checking whether it is the top-most entered context. This method is thread-safe and may be used from multiple threads.
      Since:
      20.3
    • isClosed

      public boolean isClosed()
      Returns true if the context was closed else false. A context may be closed if close(), closeCancelled(Node, String), or closeExited(Node, int) was called previously.
      Since:
      20.3
    • isCancelling

      public boolean isCancelling()
      Returns true if the context is being cancelled else false. A context may be in the process of cancelling if closeCancelled(Node, String) was called previously.
      Since:
      21.1
    • isExiting

      public boolean isExiting()
      Returns true if the context is being hard-exited else false. A context may be in the process of exit if closeExited(Node, int) was called previously.
      Since:
      22.0
    • pause

      public Future<Void> pause()
      Pause execution on all threads for this context. This call does not wait for the threads to be actually paused. Instead, a future is returned that can be used to wait for the execution to be paused. The future is completed when all active threads are paused. New threads entered after this point are paused immediately after entering until resume(Future) is called.
      Returns:
      a future that can be used to wait for the execution to be paused. Also, the future is used to resume execution by passing it to the resume(Future) method.
      Since:
      21.2
    • resume

      public void resume(Future<Void> pauseFuture)
      Resume previously paused execution on all threads for this context. The execution will not resume if pause() was called multiple times and for some of the other calls resume was not called yet.
      Parameters:
      pauseFuture - pause future returned by a previous call to pause().
      Throws:
      IllegalArgumentException - in case the passed pause future was not obtained by a previous call to pause() on this context.
      Since:
      21.2
    • leave

      public void leave(Node node, Object prev)
      Leaves this context and sets the previous context as the new current context.

      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.

      Parameters:
      prev - the previous context returned by enter(Node)
      Since:
      20.3
      See Also:
    • leaveAndEnter

      @Deprecated public <T> T leaveAndEnter(Node node, Supplier<T> runWhileOutsideContext)
      Leaves this context, runs the passed supplier and reenters the context. This is useful when the current thread must wait for another thread (and does not need to access the context to do so) and triggering multithreading is not desired, for instance when implementing coroutines with threads. The supplier cannot access the context and must not run any guest language code or invoke interoperability messages.

      The supplier 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 supplier and reentering the context (again to avoid triggering multithreading).

      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.

      Parameters:
      node - an adopted node or null
      runWhileOutsideContext - the supplier to run while having left this context
      Since:
      21.1
    • leaveAndEnter

      public <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. This is useful when the current thread must wait for another thread (and does not need to access the context to do so) and triggering multithreading is not desired, for instance when implementing coroutines with threads. The function cannot access the context and must not run any guest language code or invoke interoperability messages.

      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.

      Parameters:
      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.
      Returns:
      return value of the interruptible, or null if the interruptibe throws an InterruptedException without the context being cancelled or exited.
      Since:
      23.1
    • close

      public void close()
      Closes this context and disposes its resources. Closes this context and disposes its resources. A context cannot be closed if it is currently 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.
      Specified by:
      close in interface AutoCloseable
      Throws:
      UnsupportedOperationException - if the close operation is not supported on this context
      IllegalStateException - if the context is active.
      Since:
      0.27
      See Also:
    • closeCancelled

      public 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. If this context is not currently entered on the current thread then this method waits until the close operation is complete and 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.

      Parameters:
      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.
      Throws:
      UnsupportedOperationException - if the close operation is not supported on this context
      IllegalStateException - if the context is active but not entered on the current thread.
      Since:
      20.3
      See Also:
    • closeExited

      public void closeExited(Node exitLocation, int exitCode)
      Initiates force close of the context as exited - 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

      • the context is being closed and the finalization stage has already begun (TruffleLanguage.finalizeContext(Object) is being executed for all language contexts).
      • the context is already closed
      • the context threads are being unwound as a part of the cancelling process
      • the context threads are being unwound as a part of the hard exit process that comes after exit notifications
      then calling this method has no effect.
      Parameters:
      exitLocation - the node where the exit occurred.
      exitCode - exitCode provided to the embedder and tools that observe the exit.
      Throws:
      IllegalStateException - if the context is not entered on the current thread.
      Since:
      22.0
      See Also:
    • closeResourceExhausted

      public void closeResourceExhausted(Node location, String message)
      Force closes the context due to resource exhaustion. This method is equivalent to calling closeCancelled(location, message) except in addition the thrown PolyglotException returns true for PolyglotException.isResourceExhausted().
      Since:
      20.3
      See Also: