public abstract class TruffleSafepoint extends Object
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.
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.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.
|
| 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 |
setAllowSideEffects(boolean enabled)
Allows to temporarily delay side-effecting thread local actions on this thread.
|
abstract <T> void |
setBlocked(Node location,
TruffleSafepoint.Interrupter interrupter,
TruffleSafepoint.Interruptible<T> interruptible,
T object,
Runnable beforeInterrupt,
Runnable 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(). |
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> void setBlocked(Node location, TruffleSafepoint.Interrupter interrupter, TruffleSafepoint.Interruptible<T> interruptible, T object, Runnable beforeInterrupt, Runnable 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().
Since it is common to use this method with method reference syntax e.g.
Lock::lockInterruptibly for the interruptible parameter, we implicitlely apply a
boundary for the entire method call by default. If the interruptible
is called from a compiled code path and the interruptible should get partial evaluated, then
TruffleSafepoint.CompiledInterruptible should be used instead of TruffleSafepoint.Interruptible. In this case
the parameter must be a partial
evaluation constant.
The beforeInterrupt and afterInterrupt runnable
optional parameter 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.
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.setBlockedThreadInterruptible(Node, Interruptible, Object).
Lock lock = new ReentrantLock(); TruffleSafepoint sp = TruffleSafepoint.getCurrent(); sp.setBlocked(location, Interrupter.THREAD_INTERRUPT, ReentrantLock::lockInterruptibly, lock, null, null);
TruffleSafepointpublic 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 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, Runnable) or
TruffleSafepoint.setAllowSideEffects(boolean).
Important: The result of this method must not be stored or used on a different thread than the current thread.