public abstract class TruffleSafepoint extends Object
Safepoints are explicitly polled by invoking the TruffleSafepoint.poll(Node)
method. Safepoints are
polled
with relaxed location or with exact location
.
A poll with a relaxed location is significantly more efficient than a poll with a precise
location as the compiler is able to move and combine the poll requests during compilation. A
Truffle guest language implementation must ensure that a safepoint is polled repeatedly within a
constant time interval. For example, a single arithmetic expression completes within a constant
number of CPU cycles. However, a loop that summarizes values over an array uses a non-constant
time dependent on the array size. This typically means that safepoints are best polled at the end
of loops and at the end of function or method calls to cover recursion. In addition, any guest
language code that blocks the execution, like guest language locks, need to use the
blocking API
to
allow polling of safepoints while the thread is waiting.
Truffle's loop node
and root node
support safepoint polling
automatically. No further calls to TruffleSafepoint.poll(Node)
are therefore necessary. Custom loops or
loops behind boundary
annotated method calls are expected to be notified
by the guest language implementation manually.
Thread local actions optionally incur side-effects. By default side-effects are enabled. A
language implementation may disable side-effects temporarily for the current thread using
TruffleSafepoint.setAllowSideEffects(boolean)
method.
See ThreadLocalAction
for details on how to submit actions.
Further information can be found in the safepoint tutorial.
ThreadLocalAction
,
Context.safepoint()
Modifier and Type | Class and Description |
---|---|
static interface |
TruffleSafepoint.CompiledInterruptible<T>
Just like
TruffleSafepoint.Interruptible but allows partial evaluation. |
static interface |
TruffleSafepoint.CompiledInterruptibleFunction<T,R>
Just like
TruffleSafepoint.InterruptibleFunction but allows partial evaluation. |
static interface |
TruffleSafepoint.Interrupter
An interrupter allows a foreign thread to interrupt the execution on a separate thread.
|
static interface |
TruffleSafepoint.Interruptible<T>
Function interface that represent interruptable Java methods.
|
static interface |
TruffleSafepoint.InterruptibleFunction<T,R>
Function interface that represent interruptable Java methods.
|
Modifier | Constructor and Description |
---|---|
protected |
TruffleSafepoint(com.oracle.truffle.api.impl.Accessor.EngineSupport support)
Do not extend this class.
|
Modifier and Type | Method and Description |
---|---|
static TruffleSafepoint |
getCurrent()
Returns the current safepoint configuration for the current thread.
|
abstract boolean |
hasPendingSideEffectingActions()
Returns whether there is any pending side-effecting thread local action on this thread, due
to being in a critical section using
TruffleSafepoint.setAllowSideEffects(boolean) . |
static void |
poll(Node location)
Polls a safepoint at the provided location.
|
static void |
pollHere(Node location)
Similar to
TruffleSafepoint.poll(Node) but with exact location. |
abstract boolean |
setAllowActions(boolean enabled)
Allows to temporarily delay all thread local actions on the current thread.
|
abstract boolean |
setAllowSideEffects(boolean enabled)
Allows to temporarily delay side-effecting thread local actions on the current thread.
|
abstract <T> void |
setBlocked(Node location,
TruffleSafepoint.Interrupter interrupter,
TruffleSafepoint.Interruptible<T> interruptible,
T object,
Runnable beforeInterrupt,
Consumer<Throwable> afterInterrupt)
|
abstract <T,R> R |
setBlockedFunction(Node location,
TruffleSafepoint.Interrupter interrupter,
TruffleSafepoint.InterruptibleFunction<T,R> interruptible,
T object,
Runnable beforeInterrupt,
Consumer<Throwable> afterInterrupt)
Transitions the current thread into a blocked state and calls an interruptible functional
method.
|
static <T> void |
setBlockedThreadInterruptible(Node location,
TruffleSafepoint.Interruptible<T> interruptible,
T object)
Short-cut method to allow setting the blocked status for methods that throw
InterruptedException and support interrupting using Thread.interrupt() . |
static <T,R> R |
setBlockedThreadInterruptibleFunction(Node location,
TruffleSafepoint.InterruptibleFunction<T,R> interruptible,
T object)
Short-cut method to allow setting the blocked status for methods that throw
InterruptedException and support interrupting using Thread.interrupt() . |
protected TruffleSafepoint(com.oracle.truffle.api.impl.Accessor.EngineSupport support)
public static void poll(Node location)
TruffleSafepoint
for further details.
In compiled code calls to this method are removed. Instead the compiler inserts safepoints automatically at loop ends and method exits. In this case the node location is approximated by frame state of method ends and loop exits in the compiler IR. For method ends the parent root node and for loop exits the loop node is passed as location.
Guest language exceptions may be thrown by this method. If
side-effects
are allowed then also guest language
exceptions may be thrown. Otherwise only internal or thread-death
exceptions may be thrown. This method is safe to be used on compiled code paths.
Example usage with an unbounded loop sum behind a CompilerDirectives.TruffleBoundary
.
@TruffleBoundary int sum(int[] array) { int sum = 0; for (int i = 0; i < array.length; i++) { sum += array[i]; TruffleSafepoint.poll(); } return sum; }
location
- the location of the poll. Must not be null
.TruffleSafepoint
,
TruffleSafepoint.pollHere(Node)
public static void pollHere(Node location)
TruffleSafepoint.poll(Node)
but with exact location. A poll with relaxed location
is significantly more efficient than a poll with precise location as the
compiler is able to move and combine the poll requests during compilation. This method is
safe to be used on compiled code paths.
Usage example:
TruffleSafepoint safepoint = TruffleSafepoint.getCurrent(); boolean prev = safepoint.setAllowSideEffects(false); try { // criticial section } finally { safepoint.setAllowSideEffects(prev); TruffleSafepoint.pollHere(this); }
location
- the location of the poll. Must not be null
.TruffleSafepoint.poll(Node)
public abstract <T,R> R setBlockedFunction(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.InterruptibleFunction<T,R> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt)
The location>
parameter is used poll
all pending thread
local actions before transition to blocked state.
The interrupter
parameter specifies how the blocked state can be interrupted
from another thread. The interrupter allows to interrupt the blocked state from other
threads. For most blocking java.util.concurrent primitives the
thread interrupter
can be used. If the thread will be
blocked in native code, other ways of interrupting, like signals may be used by implementing
the TruffleSafepoint.Interrupter
interface.
The interruptible
parameter provides the method that calls the blocking method
which throws InterruptedException
on interrupt. In order to avoid allocations of the
functional interface a single argument can be provided that is passed to the interface. This
is typically the lock
or semaphore
instance. The
implementation of this method is expected to throw an InterruptedException
if the
TruffleSafepoint.Interrupter.interrupt(Thread)
method is invoked for this thread. For most
java.util.concurrent primitives this is supported by using the interruptible blocking method
variant, for example Lock.lockInterruptibly()
.
boundary
is applied for the entire interruptible method call by
default. If the interruptible is called from a compiled code path and the interruptible
should get partial evaluated, then TruffleSafepoint.CompiledInterruptibleFunction
should be used
instead of TruffleSafepoint.InterruptibleFunction
. In this case the parameter must be a
partial evaluation constant
.
The beforeInterrupt
runnable
and afterInterrupt
consumer
optional parameters allow to run code before and after a thread got
interrupted and safepoint events are processed. If null
is provided then no
action will be performed. Arbitrary code may be executed in this runnable. Note that the
blocked state is temporarily reset to its previous state while the afterInterrupt is called.
If an exception is thrown during the processing of the safepoint, afterInterrupt
will receive the throwable as argument, or null
if the safepoint successfully
completed. This exception will still be thrown after completion of
afterInterrupt
, unless afterInterrupt
throws an exception of its
own.
Multiple recursive invocations of this method is supported. The previous blocked state will be restored when the method completes or fails.
Example usage:
Note there is a short-cut method to achieve the same behavior as in this example
TruffleSafepoint.setBlockedThreadInterruptibleFunction(Node, InterruptibleFunction, Object)
.
Queue
TruffleSafepoint
public abstract <T> void setBlocked(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Consumer<Throwable> afterInterrupt)
TruffleSafepoint.setBlockedFunction(Node, Interrupter, InterruptibleFunction, Object, Runnable, Consumer)
.
The only difference is that the interruptible functional method does not return anything.public static <T> void setBlockedThreadInterruptible(Node location, TruffleSafepoint.Interruptible<T> interruptible, T object)
InterruptedException
and support interrupting using Thread.interrupt()
.location
- the location with which the safepoint should be polled.interruptible
- the thread interruptable method to use for locking the objectobject
- the instance to use the interruptable method with.public static <T,R> R setBlockedThreadInterruptibleFunction(Node location, TruffleSafepoint.InterruptibleFunction<T,R> interruptible, T object)
InterruptedException
and support interrupting using Thread.interrupt()
.location
- the location with which the safepoint should be polled.interruptible
- the thread interruptable method to use for locking the objectobject
- the instance to use the interruptable method with.public abstract boolean setAllowActions(boolean enabled) throws IllegalStateException
TruffleSafepoint.setAllowSideEffects(boolean)
before using this
method. While actions are disabled the value of TruffleSafepoint.setAllowSideEffects(boolean)
has no
effect. When actions
are enabled again the value of
TruffleSafepoint.setAllowSideEffects(boolean)
will be interpreted again.
Currently this method may only be used during context finalization
. This could be necessary to free up native resources through guest code
when a context is cancelled to avoid resource leakage. Any usage of this method should be
subject to a detailed security review to ensure only internal and well-known guest code is
executed. Disabling thread local actions may delay thread local actions like exit,
cancellation and interruption.
Example usage:
TruffleSafepoint sp = TruffleSafepoint.getCurrent(); boolean prev = sp.setAllowActions(false); try { // critical section } finally { sp.setAllowActions(prev); }
IllegalStateException
- if allow actions can currently not be set, for example outside
the scope of a context
finalization
.TruffleLanguage.finalizeContext(Object)
public abstract boolean setAllowSideEffects(boolean enabled)
While side-effecting thread local actions are delayed on this thread, only non-side-effecting thread local actions will be scheduled in this thread. Non-side-effecting thread local actions do not mutate guest objects, run guest code or throw guest exceptions, but they might still throw internal errors.
Example usage:
TruffleSafepoint sp = TruffleSafepoint.getCurrent(); boolean prev = sp.setAllowSideEffects(false); try { // critical section } finally { sp.setAllowSideEffects(prev); }
public abstract boolean hasPendingSideEffectingActions()
TruffleSafepoint.setAllowSideEffects(boolean)
. When
side-effecting actions are allowed, this method always returns false
.
This is useful if the language exposes a way to know if there are any pending side-effecting
thread local action due to using TruffleSafepoint.setAllowSideEffects(boolean)
.
public static TruffleSafepoint getCurrent()
TruffleSafepoint.setBlocked(Node, Interrupter, Interruptible, Object, Runnable, Consumer)
or
TruffleSafepoint.setAllowSideEffects(boolean)
.
Important: The result of this method must not be stored or used on a different thread than the current thread.