8286666: JEP 429: Implementation of Scoped Values (Incubator)

Reviewed-by: psandoz, dlong, alanb, mcimadamore
This commit is contained in:
Andrew Haley 2022-12-07 10:14:06 +00:00 committed by Alan Bateman
parent ccc69af966
commit 221e1a4260
61 changed files with 2889 additions and 230 deletions

View file

@ -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) {

View file

@ -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.
*/

View file

@ -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();