mirror of
https://github.com/openjdk/jdk.git
synced 2025-08-27 14:54:52 +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(
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue