mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 23:04:50 +02:00
8286666: JEP 429: Implementation of Scoped Values (Incubator)
Reviewed-by: psandoz, dlong, alanb, mcimadamore
This commit is contained in:
parent
ccc69af966
commit
221e1a4260
61 changed files with 2889 additions and 230 deletions
|
@ -86,6 +86,7 @@ import jdk.internal.vm.Continuation;
|
|||
import jdk.internal.vm.ContinuationScope;
|
||||
import jdk.internal.vm.StackableScope;
|
||||
import jdk.internal.vm.ThreadContainer;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
import jdk.internal.vm.annotation.Stable;
|
||||
import jdk.internal.vm.annotation.ChangesCurrentThread;
|
||||
|
@ -2578,20 +2579,29 @@ public final class System {
|
|||
return ((ThreadLocal<?>)local).isCarrierThreadLocalPresent();
|
||||
}
|
||||
|
||||
public Object[] extentLocalCache() {
|
||||
return Thread.extentLocalCache();
|
||||
public Object[] scopedValueCache() {
|
||||
return Thread.scopedValueCache();
|
||||
}
|
||||
|
||||
public void setExtentLocalCache(Object[] cache) {
|
||||
Thread.setExtentLocalCache(cache);
|
||||
public void setScopedValueCache(Object[] cache) {
|
||||
Thread.setScopedValueCache(cache);
|
||||
}
|
||||
|
||||
public Object extentLocalBindings() {
|
||||
return Thread.extentLocalBindings();
|
||||
public Object scopedValueBindings() {
|
||||
return Thread.scopedValueBindings();
|
||||
}
|
||||
|
||||
public void setExtentLocalBindings(Object bindings) {
|
||||
Thread.setExtentLocalBindings(bindings);
|
||||
public Object findScopedValueBindings() {
|
||||
return Thread.findScopedValueBindings();
|
||||
}
|
||||
|
||||
public void setScopedValueBindings(Object bindings) {
|
||||
Thread.setScopedValueBindings(bindings);
|
||||
}
|
||||
|
||||
@ForceInline
|
||||
public void ensureMaterializedForStackWalk(Object value) {
|
||||
Thread.ensureMaterializedForStackWalk(value);
|
||||
}
|
||||
|
||||
public Continuation getContinuation(Thread thread) {
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
package java.lang;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.lang.reflect.Field;
|
||||
import java.security.AccessController;
|
||||
import java.security.AccessControlContext;
|
||||
|
@ -49,9 +50,11 @@ import jdk.internal.misc.VM;
|
|||
import jdk.internal.reflect.CallerSensitive;
|
||||
import jdk.internal.reflect.Reflection;
|
||||
import jdk.internal.vm.Continuation;
|
||||
import jdk.internal.vm.ExtentLocalContainer;
|
||||
import jdk.internal.vm.ScopedValueContainer;
|
||||
import jdk.internal.vm.StackableScope;
|
||||
import jdk.internal.vm.ThreadContainer;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Hidden;
|
||||
import jdk.internal.vm.annotation.IntrinsicCandidate;
|
||||
import sun.nio.ch.Interruptible;
|
||||
import sun.security.util.SecurityConstants;
|
||||
|
@ -279,34 +282,44 @@ public class Thread implements Runnable {
|
|||
ThreadLocal.ThreadLocalMap inheritableThreadLocals;
|
||||
|
||||
/*
|
||||
* Extent locals binding are maintained by the ExtentLocal class.
|
||||
* Scoped value bindings are maintained by the ScopedValue class.
|
||||
*/
|
||||
private Object extentLocalBindings;
|
||||
private Object scopedValueBindings;
|
||||
|
||||
static Object extentLocalBindings() {
|
||||
return currentThread().extentLocalBindings;
|
||||
// Special value to indicate this is a newly-created Thread
|
||||
// Note that his must match the declaration in ScopedValue.
|
||||
private static final Object NEW_THREAD_BINDINGS = Thread.class;
|
||||
|
||||
static Object scopedValueBindings() {
|
||||
return currentThread().scopedValueBindings;
|
||||
}
|
||||
|
||||
static void setExtentLocalBindings(Object bindings) {
|
||||
currentThread().extentLocalBindings = bindings;
|
||||
static void setScopedValueBindings(Object bindings) {
|
||||
currentThread().scopedValueBindings = bindings;
|
||||
}
|
||||
|
||||
/**
|
||||
* Inherit the extent-local bindings from the given container.
|
||||
* Search the stack for the most recent scoped-value bindings.
|
||||
*/
|
||||
@IntrinsicCandidate
|
||||
static native Object findScopedValueBindings();
|
||||
|
||||
/**
|
||||
* Inherit the scoped-value bindings from the given container.
|
||||
* Invoked when starting a thread.
|
||||
*/
|
||||
void inheritExtentLocalBindings(ThreadContainer container) {
|
||||
ExtentLocalContainer.BindingsSnapshot snapshot;
|
||||
void inheritScopedValueBindings(ThreadContainer container) {
|
||||
ScopedValueContainer.BindingsSnapshot snapshot;
|
||||
if (container.owner() != null
|
||||
&& (snapshot = container.extentLocalBindings()) != null) {
|
||||
&& (snapshot = container.scopedValueBindings()) != null) {
|
||||
|
||||
// bindings established for running/calling an operation
|
||||
Object bindings = snapshot.extentLocalBindings();
|
||||
if (currentThread().extentLocalBindings != bindings) {
|
||||
StructureViolationExceptions.throwException("Extent local bindings have changed");
|
||||
Object bindings = snapshot.scopedValueBindings();
|
||||
if (currentThread().scopedValueBindings != bindings) {
|
||||
StructureViolationExceptions.throwException("Scoped value bindings have changed");
|
||||
}
|
||||
|
||||
this.extentLocalBindings = bindings;
|
||||
this.scopedValueBindings = bindings;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -393,13 +406,16 @@ public class Thread implements Runnable {
|
|||
@IntrinsicCandidate
|
||||
native void setCurrentThread(Thread thread);
|
||||
|
||||
// ExtentLocal support:
|
||||
// ScopedValue support:
|
||||
|
||||
@IntrinsicCandidate
|
||||
static native Object[] extentLocalCache();
|
||||
static native Object[] scopedValueCache();
|
||||
|
||||
@IntrinsicCandidate
|
||||
static native void setExtentLocalCache(Object[] cache);
|
||||
static native void setScopedValueCache(Object[] cache);
|
||||
|
||||
@IntrinsicCandidate
|
||||
static native void ensureMaterializedForStackWalk(Object o);
|
||||
|
||||
/**
|
||||
* A hint to the scheduler that the current thread is willing to yield
|
||||
|
@ -728,6 +744,10 @@ public class Thread implements Runnable {
|
|||
this.contextClassLoader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
}
|
||||
|
||||
// Special value to indicate this is a newly-created Thread
|
||||
// Note that his must match the declaration in ScopedValue.
|
||||
this.scopedValueBindings = NEW_THREAD_BINDINGS;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -767,6 +787,9 @@ public class Thread implements Runnable {
|
|||
this.contextClassLoader = ClassLoader.getSystemClassLoader();
|
||||
}
|
||||
|
||||
// Special value to indicate this is a newly-created Thread
|
||||
this.scopedValueBindings = NEW_THREAD_BINDINGS;
|
||||
|
||||
// create a FieldHolder object, needed when bound to an OS thread
|
||||
if (bound) {
|
||||
ThreadGroup g = Constants.VTHREAD_GROUP;
|
||||
|
@ -1564,8 +1587,8 @@ public class Thread implements Runnable {
|
|||
boolean started = false;
|
||||
container.onStart(this); // may throw
|
||||
try {
|
||||
// extent locals may be inherited
|
||||
inheritExtentLocalBindings(container);
|
||||
// scoped values may be inherited
|
||||
inheritScopedValueBindings(container);
|
||||
|
||||
start0();
|
||||
started = true;
|
||||
|
@ -1596,10 +1619,24 @@ public class Thread implements Runnable {
|
|||
public void run() {
|
||||
Runnable task = holder.task;
|
||||
if (task != null) {
|
||||
task.run();
|
||||
Object bindings = scopedValueBindings();
|
||||
runWith(bindings, task);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The VM recognizes this method as special, so any changes to the
|
||||
* name or signature require corresponding changes in
|
||||
* JVM_FindScopedValueBindings().
|
||||
*/
|
||||
@Hidden
|
||||
@ForceInline
|
||||
private void runWith(Object bindings, Runnable op) {
|
||||
ensureMaterializedForStackWalk(bindings);
|
||||
op.run();
|
||||
Reference.reachabilityFence(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Null out reference after Thread termination.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
*/
|
||||
package java.lang;
|
||||
|
||||
import java.lang.ref.Reference;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
import java.util.Locale;
|
||||
|
@ -53,6 +54,8 @@ import jdk.internal.vm.StackableScope;
|
|||
import jdk.internal.vm.ThreadContainer;
|
||||
import jdk.internal.vm.ThreadContainers;
|
||||
import jdk.internal.vm.annotation.ChangesCurrentThread;
|
||||
import jdk.internal.vm.annotation.ForceInline;
|
||||
import jdk.internal.vm.annotation.Hidden;
|
||||
import jdk.internal.vm.annotation.JvmtiMountTransition;
|
||||
import sun.nio.ch.Interruptible;
|
||||
import sun.security.action.GetPropertyAction;
|
||||
|
@ -283,13 +286,13 @@ final class VirtualThread extends BaseVirtualThread {
|
|||
event.commit();
|
||||
}
|
||||
|
||||
Object bindings = scopedValueBindings();
|
||||
try {
|
||||
task.run();
|
||||
runWith(bindings, task);
|
||||
} catch (Throwable exc) {
|
||||
dispatchUncaughtException(exc);
|
||||
} finally {
|
||||
try {
|
||||
|
||||
// pop any remaining scopes from the stack, this may block
|
||||
StackableScope.popAll();
|
||||
|
||||
|
@ -311,6 +314,14 @@ final class VirtualThread extends BaseVirtualThread {
|
|||
}
|
||||
}
|
||||
|
||||
@Hidden
|
||||
@ForceInline
|
||||
private void runWith(Object bindings, Runnable op) {
|
||||
ensureMaterializedForStackWalk(bindings);
|
||||
op.run();
|
||||
Reference.reachabilityFence(bindings);
|
||||
}
|
||||
|
||||
/**
|
||||
* Mounts this virtual thread onto the current platform thread. On
|
||||
* return, the current thread is the virtual thread.
|
||||
|
@ -488,8 +499,8 @@ final class VirtualThread extends BaseVirtualThread {
|
|||
boolean started = false;
|
||||
container.onStart(this); // may throw
|
||||
try {
|
||||
// extent locals may be inherited
|
||||
inheritExtentLocalBindings(container);
|
||||
// scoped values may be inherited
|
||||
inheritScopedValueBindings(container);
|
||||
|
||||
// submit task to run thread
|
||||
submitRunContinuation();
|
||||
|
|
|
@ -401,7 +401,7 @@ public final class ThreadLocalRandom extends Random {
|
|||
= new AtomicLong(RandomSupport.mixMurmur64(System.currentTimeMillis()) ^
|
||||
RandomSupport.mixMurmur64(System.nanoTime()));
|
||||
|
||||
// used by ExtentLocal
|
||||
// used by ScopedValue
|
||||
private static class Access {
|
||||
static {
|
||||
SharedSecrets.setJavaUtilConcurrentTLRAccess(
|
||||
|
|
|
@ -476,24 +476,28 @@ public interface JavaLangAccess {
|
|||
boolean isCarrierThreadLocalPresent(CarrierThreadLocal<?> local);
|
||||
|
||||
/**
|
||||
* Returns the current thread's extent locals cache
|
||||
* Returns the current thread's scoped values cache
|
||||
*/
|
||||
Object[] extentLocalCache();
|
||||
Object[] scopedValueCache();
|
||||
|
||||
/**
|
||||
* Sets the current thread's extent locals cache
|
||||
* Sets the current thread's scoped values cache
|
||||
*/
|
||||
void setExtentLocalCache(Object[] cache);
|
||||
void setScopedValueCache(Object[] cache);
|
||||
|
||||
/**
|
||||
* Return the current thread's extent local bindings.
|
||||
* Return the current thread's scoped value bindings.
|
||||
*/
|
||||
Object extentLocalBindings();
|
||||
Object scopedValueBindings();
|
||||
|
||||
/**
|
||||
* Set the current thread's extent local bindings.
|
||||
* Set the current thread's scoped value bindings.
|
||||
*/
|
||||
void setExtentLocalBindings(Object bindings);
|
||||
void setScopedValueBindings(Object bindings);
|
||||
|
||||
Object findScopedValueBindings();
|
||||
|
||||
void ensureMaterializedForStackWalk(Object value);
|
||||
|
||||
/**
|
||||
* Returns the innermost mounted continuation
|
||||
|
|
|
@ -35,7 +35,7 @@ import java.util.concurrent.locks.LockSupport;
|
|||
import java.util.stream.Stream;
|
||||
import jdk.internal.access.JavaLangAccess;
|
||||
import jdk.internal.access.SharedSecrets;
|
||||
import jdk.internal.vm.ExtentLocalContainer;
|
||||
import jdk.internal.vm.ScopedValueContainer;
|
||||
import jdk.internal.vm.ThreadContainer;
|
||||
import jdk.internal.vm.ThreadContainers;
|
||||
import static java.util.concurrent.TimeUnit.NANOSECONDS;
|
||||
|
@ -99,7 +99,7 @@ public class ThreadFlock implements AutoCloseable {
|
|||
private volatile int threadCount;
|
||||
|
||||
private final String name;
|
||||
private final ExtentLocalContainer.BindingsSnapshot extentLocalBindings;
|
||||
private final ScopedValueContainer.BindingsSnapshot scopedValueBindings;
|
||||
private final ThreadContainerImpl container; // encapsulate for now
|
||||
|
||||
// state
|
||||
|
@ -111,7 +111,7 @@ public class ThreadFlock implements AutoCloseable {
|
|||
|
||||
ThreadFlock(String name) {
|
||||
this.name = name;
|
||||
this.extentLocalBindings = ExtentLocalContainer.captureBindings();
|
||||
this.scopedValueBindings = ScopedValueContainer.captureBindings();
|
||||
this.container = new ThreadContainerImpl(this);
|
||||
}
|
||||
|
||||
|
@ -119,8 +119,8 @@ public class ThreadFlock implements AutoCloseable {
|
|||
return threadCount;
|
||||
}
|
||||
|
||||
private ExtentLocalContainer.BindingsSnapshot extentLocalBindings() {
|
||||
return extentLocalBindings;
|
||||
private ScopedValueContainer.BindingsSnapshot scopedValueBindings() {
|
||||
return scopedValueBindings;
|
||||
}
|
||||
|
||||
private void incrementThreadCount() {
|
||||
|
@ -210,7 +210,7 @@ public class ThreadFlock implements AutoCloseable {
|
|||
* Opens a new thread flock. The flock is owned by the current thread. It can be
|
||||
* named to aid debugging.
|
||||
*
|
||||
* <p> This method captures the current thread's {@linkplain ExtentLocal extent-local}
|
||||
* <p> This method captures the current thread's {@linkplain ScopedValue scoped value}
|
||||
* bindings for inheritance by threads created in the flock.
|
||||
*
|
||||
* <p> For the purposes of containment, monitoring, and debugging, the parent
|
||||
|
@ -250,7 +250,7 @@ public class ThreadFlock implements AutoCloseable {
|
|||
/**
|
||||
* Starts the given unstarted thread in this flock.
|
||||
*
|
||||
* <p> The thread is started with the extent-local bindings that were captured
|
||||
* <p> The thread is started with the scoped value bindings that were captured
|
||||
* when opening the flock. The bindings must match the current thread's bindings.
|
||||
*
|
||||
* <p> This method may only be invoked by the flock owner or threads {@linkplain
|
||||
|
@ -263,7 +263,7 @@ public class ThreadFlock implements AutoCloseable {
|
|||
* @throws WrongThreadException if the current thread is not the owner or a thread
|
||||
* contained in the flock
|
||||
* @throws jdk.incubator.concurrent.StructureViolationException if the current
|
||||
* extent-local bindings are not the same as when the flock was created
|
||||
* scoped value bindings are not the same as when the flock was created
|
||||
*/
|
||||
public Thread start(Thread thread) {
|
||||
ensureOwnerOrContainsThread();
|
||||
|
@ -398,12 +398,11 @@ public class ThreadFlock implements AutoCloseable {
|
|||
* <p> A ThreadFlock is intended to be used in a <em>structured manner</em>. If
|
||||
* this method is called to close a flock before nested flocks are closed then it
|
||||
* closes the nested flocks (in the reverse order that they were created in),
|
||||
* closes this flock, and then throws {@link
|
||||
* jdk.incubator.concurrent.StructureViolationException}.
|
||||
* Similarly, if called to close a flock that <em>encloses</em> {@linkplain
|
||||
* jdk.incubator.concurrent.ExtentLocal.Carrier#run(Runnable) operations} with
|
||||
* extent-local bindings then it also throws {@code StructureViolationException}
|
||||
* after closing the flock.
|
||||
* closes this flock, and then throws {@code StructureViolationException}.
|
||||
* Similarly, if this method is called to close a thread flock while executing with
|
||||
* scoped value bindings, and the thread flock was created before the scoped values
|
||||
* were bound, then {@code StructureViolationException} is thrown after closing the
|
||||
* thread flock.
|
||||
*
|
||||
* @throws WrongThreadException if invoked by a thread that is not the owner
|
||||
* @throws jdk.incubator.concurrent.StructureViolationException if a structure
|
||||
|
@ -585,8 +584,8 @@ public class ThreadFlock implements AutoCloseable {
|
|||
return flock.toString();
|
||||
}
|
||||
@Override
|
||||
public ExtentLocalContainer.BindingsSnapshot extentLocalBindings() {
|
||||
return flock.extentLocalBindings();
|
||||
public ScopedValueContainer.BindingsSnapshot scopedValueBindings() {
|
||||
return flock.scopedValueBindings();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,7 +46,7 @@ import jdk.internal.access.SharedSecrets;
|
|||
*/
|
||||
public class Continuation {
|
||||
private static final Unsafe U = Unsafe.getUnsafe();
|
||||
private static final boolean PRESERVE_EXTENT_LOCAL_CACHE;
|
||||
private static final boolean PRESERVE_SCOPED_VALUE_CACHE;
|
||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||
static {
|
||||
ContinuationSupport.ensureSupported();
|
||||
|
@ -54,8 +54,8 @@ public class Continuation {
|
|||
|
||||
StackChunk.init(); // ensure StackChunk class is initialized
|
||||
|
||||
String value = GetPropertyAction.privilegedGetProperty("jdk.preserveExtentLocalCache");
|
||||
PRESERVE_EXTENT_LOCAL_CACHE = (value == null) || Boolean.parseBoolean(value);
|
||||
String value = GetPropertyAction.privilegedGetProperty("jdk.preserveScopedValueCache");
|
||||
PRESERVE_SCOPED_VALUE_CACHE = (value == null) || Boolean.parseBoolean(value);
|
||||
}
|
||||
|
||||
private static final VarHandle MOUNTED;
|
||||
|
@ -129,7 +129,7 @@ public class Continuation {
|
|||
private Object yieldInfo;
|
||||
private boolean preempted;
|
||||
|
||||
private Object[] extentLocalCache;
|
||||
private Object[] scopedValueCache;
|
||||
|
||||
/**
|
||||
* Constructs a continuation
|
||||
|
@ -238,7 +238,7 @@ public class Continuation {
|
|||
public final void run() {
|
||||
while (true) {
|
||||
mount();
|
||||
JLA.setExtentLocalCache(extentLocalCache);
|
||||
JLA.setScopedValueCache(scopedValueCache);
|
||||
|
||||
if (done)
|
||||
throw new IllegalStateException("Continuation terminated");
|
||||
|
@ -270,12 +270,12 @@ public class Continuation {
|
|||
postYieldCleanup();
|
||||
|
||||
unmount();
|
||||
if (PRESERVE_EXTENT_LOCAL_CACHE) {
|
||||
extentLocalCache = JLA.extentLocalCache();
|
||||
if (PRESERVE_SCOPED_VALUE_CACHE) {
|
||||
scopedValueCache = JLA.scopedValueCache();
|
||||
} else {
|
||||
extentLocalCache = null;
|
||||
scopedValueCache = null;
|
||||
}
|
||||
JLA.setExtentLocalCache(null);
|
||||
JLA.setScopedValueCache(null);
|
||||
} catch (Throwable e) { e.printStackTrace(); System.exit(1); }
|
||||
}
|
||||
// we're now in the parent continuation
|
||||
|
|
|
@ -33,26 +33,26 @@ import jdk.internal.vm.annotation.DontInline;
|
|||
import jdk.internal.vm.annotation.ReservedStackAccess;
|
||||
|
||||
/**
|
||||
* A StackableScope to represent extent-local bindings.
|
||||
* A StackableScope to represent scoped-value bindings.
|
||||
*
|
||||
* This class defines static methods to run an operation with a ExtentLocalContainer
|
||||
* on the scope stack. It also defines a method to get the latest ExtentLocalContainer
|
||||
* and a method to return a snapshot of the extent local bindings.
|
||||
* This class defines static methods to run an operation with a ScopedValueContainer
|
||||
* on the scope stack. It also defines a method to get the latest ScopedValueContainer
|
||||
* and a method to return a snapshot of the scoped value bindings.
|
||||
*/
|
||||
public class ExtentLocalContainer extends StackableScope {
|
||||
public class ScopedValueContainer extends StackableScope {
|
||||
private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess();
|
||||
static {
|
||||
Unsafe.getUnsafe().ensureClassInitialized(StructureViolationExceptions.class);
|
||||
}
|
||||
|
||||
private ExtentLocalContainer() {
|
||||
private ScopedValueContainer() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the "latest" ExtentLocalContainer for the current Thread. This may be on
|
||||
* the current thread's scope task or ma require walking up the tree to find it.
|
||||
* Returns the "latest" ScopedValueContainer for the current Thread. This may be on
|
||||
* the current thread's scope task or may require walking up the tree to find it.
|
||||
*/
|
||||
public static <T extends ExtentLocalContainer> T latest(Class<T> containerClass) {
|
||||
public static <T extends ScopedValueContainer> T latest(Class<T> containerClass) {
|
||||
StackableScope scope = head();
|
||||
if (scope == null) {
|
||||
scope = JLA.threadContainer(Thread.currentThread());
|
||||
|
@ -69,37 +69,37 @@ public class ExtentLocalContainer extends StackableScope {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the "latest" ExtentLocalContainer for the current Thread. This
|
||||
* Returns the "latest" ScopedValueContainer for the current Thread. This
|
||||
* may be on the current thread's scope task or may require walking up the
|
||||
* tree to find it.
|
||||
*/
|
||||
public static ExtentLocalContainer latest() {
|
||||
return latest(ExtentLocalContainer.class);
|
||||
public static ScopedValueContainer latest() {
|
||||
return latest(ScopedValueContainer.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* A snapshot of the extent local bindings. The snapshot includes the bindings
|
||||
* established for the current thread and extent local container.
|
||||
* A snapshot of the scoped value bindings. The snapshot includes the bindings
|
||||
* established for the current thread and scoped value container.
|
||||
*/
|
||||
public record BindingsSnapshot(Object extentLocalBindings,
|
||||
ExtentLocalContainer container) { }
|
||||
public record BindingsSnapshot(Object scopedValueBindings,
|
||||
ScopedValueContainer container) { }
|
||||
|
||||
/**
|
||||
* Returns the extent local bindings for the current thread.
|
||||
* Returns the scoped value bindings for the current thread.
|
||||
*/
|
||||
public static BindingsSnapshot captureBindings() {
|
||||
return new BindingsSnapshot(JLA.extentLocalBindings(), latest());
|
||||
return new BindingsSnapshot(JLA.scopedValueBindings(), latest());
|
||||
}
|
||||
|
||||
/**
|
||||
* For use by ExtentLocal to run an operation in a structured context.
|
||||
* For use by ScopedValue to run an operation in a structured context.
|
||||
*/
|
||||
public static void run(Runnable op) {
|
||||
if (head() == null) {
|
||||
// no need to push scope when stack is empty
|
||||
runWithoutScope(op);
|
||||
} else {
|
||||
new ExtentLocalContainer().doRun(op);
|
||||
new ScopedValueContainer().doRun(op);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,14 +141,14 @@ public class ExtentLocalContainer extends StackableScope {
|
|||
}
|
||||
|
||||
/**
|
||||
* For use by ExtentLocal to call a value returning operation in a structured context.
|
||||
* For use by ScopedValue to call a value returning operation in a structured context.
|
||||
*/
|
||||
public static <V> V call(Callable<V> op) throws Exception {
|
||||
if (head() == null) {
|
||||
// no need to push scope when stack is empty
|
||||
return callWithoutScope(op);
|
||||
} else {
|
||||
return new ExtentLocalContainer().doCall(op);
|
||||
return new ScopedValueContainer().doCall(op);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +199,6 @@ public class ExtentLocalContainer extends StackableScope {
|
|||
* Throws {@code ex} if not null. StructureViolationException is thrown or added
|
||||
* as a suppressed exception when {@code atTop} is false.
|
||||
*/
|
||||
@DontInline @ReservedStackAccess
|
||||
private static void throwIfFailed(Throwable ex, boolean atTop) {
|
||||
if (ex != null || !atTop) {
|
||||
if (!atTop) {
|
|
@ -89,9 +89,9 @@ public abstract class ThreadContainer extends StackableScope {
|
|||
}
|
||||
|
||||
/**
|
||||
* The extent locals captured when the thread container was created.
|
||||
* The scoped values captured when the thread container was created.
|
||||
*/
|
||||
public ExtentLocalContainer.BindingsSnapshot extentLocalBindings() {
|
||||
public ScopedValueContainer.BindingsSnapshot scopedValueBindings() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -167,6 +167,7 @@ module java.base {
|
|||
jdk.jlink,
|
||||
jdk.jfr,
|
||||
jdk.net,
|
||||
jdk.incubator.concurrent,
|
||||
jdk.sctp,
|
||||
jdk.crypto.cryptoki;
|
||||
exports jdk.internal.foreign to
|
||||
|
@ -247,12 +248,14 @@ module java.base {
|
|||
jdk.unsupported;
|
||||
exports jdk.internal.vm to
|
||||
java.management,
|
||||
jdk.incubator.concurrent,
|
||||
jdk.internal.jvmstat,
|
||||
jdk.management,
|
||||
jdk.management.agent;
|
||||
exports jdk.internal.vm.annotation to
|
||||
java.instrument,
|
||||
jdk.internal.vm.ci,
|
||||
jdk.incubator.concurrent,
|
||||
jdk.incubator.vector,
|
||||
jdk.jfr,
|
||||
jdk.unsupported;
|
||||
|
@ -307,7 +310,8 @@ module java.base {
|
|||
exports sun.security.action to
|
||||
java.desktop,
|
||||
java.security.jgss,
|
||||
jdk.crypto.ec;
|
||||
jdk.crypto.ec,
|
||||
jdk.incubator.concurrent;
|
||||
exports sun.security.internal.interfaces to
|
||||
jdk.crypto.cryptoki;
|
||||
exports sun.security.internal.spec to
|
||||
|
|
|
@ -50,9 +50,12 @@ static JNINativeMethod methods[] = {
|
|||
{"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads},
|
||||
{"getStackTrace0", "()" OBJ, (void *)&JVM_GetStackTrace},
|
||||
{"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName},
|
||||
{"extentLocalCache", "()[" OBJ, (void *)&JVM_ExtentLocalCache},
|
||||
{"setExtentLocalCache", "([" OBJ ")V",(void *)&JVM_SetExtentLocalCache},
|
||||
{"getNextThreadIdOffset", "()J", (void *)&JVM_GetNextThreadIdOffset}
|
||||
{"scopedValueCache", "()[" OBJ, (void *)&JVM_ScopedValueCache},
|
||||
{"setScopedValueCache", "([" OBJ ")V",(void *)&JVM_SetScopedValueCache},
|
||||
{"getNextThreadIdOffset", "()J", (void *)&JVM_GetNextThreadIdOffset},
|
||||
{"findScopedValueBindings", "()" OBJ, (void *)&JVM_FindScopedValueBindings},
|
||||
{"ensureMaterializedForStackWalk",
|
||||
"(" OBJ ")V", (void*)&JVM_EnsureMaterializedForStackWalk_func},
|
||||
};
|
||||
|
||||
#undef THD
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue