From 6a850bf9c745fd4b2b620d4c8534edbf7240894a Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Wed, 20 Jul 2022 15:17:19 +0200 Subject: [PATCH 01/11] Automatically enable continuations on JDK 19 with preview features. --- .../com/oracle/svm/core/SubstrateOptions.java | 10 ---------- .../oracle/svm/core/thread/Continuation.java | 2 +- .../svm/core/thread/ContinuationsFeature.java | 19 ++++++++----------- .../oracle/svm/core/thread/LoomSupport.java | 19 +++++++++++++++++-- 4 files changed, 26 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index d125b205cf10..8352a579abea 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -134,16 +134,6 @@ protected void onValueUpdate(EconomicMap, Object> values, Boolean o @Option(help = "Support continuations (without requiring a Project Loom JDK)") // public static final HostedOptionKey SupportContinuations = new HostedOptionKey<>(false); - @Option(help = "Build with Project Loom JDK") // - public static final HostedOptionKey UseLoom = new HostedOptionKey<>(false) { - @Override - protected void onValueUpdate(EconomicMap, Object> values, Boolean oldValue, Boolean newValue) { - if (newValue) { - SupportContinuations.update(values, true); - } - } - }; - public static final int ForceFallback = 10; public static final int Automatic = 5; public static final int NoFallback = 0; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Continuation.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Continuation.java index 996720d8afce..af82e6f662dd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Continuation.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Continuation.java @@ -50,7 +50,7 @@ public final class Continuation { @Fold public static boolean isSupported() { - return SubstrateOptions.SupportContinuations.getValue(); + return SubstrateOptions.SupportContinuations.getValue() || LoomSupport.isEnabled(); } public static final int YIELDING = -2; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java index cf68be30a461..e27e1117473b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/ContinuationsFeature.java @@ -39,6 +39,7 @@ import com.oracle.svm.core.heap.StoredContinuationAccess; import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.UserError; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.util.ReflectionUtil; @AutomaticFeature @@ -49,23 +50,20 @@ public void afterRegistration(AfterRegistrationAccess access) { if (Continuation.isSupported()) { VirtualThreads impl; if (LoomSupport.isEnabled()) { + VMError.guarantee(JavaVersionUtil.JAVA_SPEC >= 19); impl = new LoomVirtualThreads(); - } else { + } else if (JavaVersionUtil.JAVA_SPEC == 17) { /* * GR-37518: ForkJoinPool on 11 syncs on a String which doesn't have its own monitor * field, and unparking a virtual thread in additionalMonitorsLock.unlock causes a * deadlock between carrier thread and virtual thread. 17 uses a ReentrantLock. */ - UserError.guarantee(JavaVersionUtil.JAVA_SPEC >= 17, "Continuations (%s) are currently supported only on JDK 17 and later.", - SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); - impl = new SubstrateVirtualThreads(); + } else { + throw UserError.abort("Continuations are currently supported only on JDK 17 with option %s, or on JDK 19 with preview features enabled.", + SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); } ImageSingletons.add(VirtualThreads.class, impl); - } else { - UserError.guarantee(!SubstrateOptions.UseLoom.getValue(), "%s cannot be enabled without option %s.", - SubstrateOptionsParser.commandArgument(SubstrateOptions.UseLoom, "+"), - SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); } } @@ -89,9 +87,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { static void abortIfUnsupported() { if (!Continuation.isSupported()) { - throw UserError.abort("Continuation support is used, but not enabled. Use options %s or %s.", - SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+"), - SubstrateOptionsParser.commandArgument(SubstrateOptions.UseLoom, "+")); + throw UserError.abort("Continuation support is used, but not available. Use JDK 17 with option %s, or JDK 19 with preview features enabled.", + SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomSupport.java index ebfe9415d870..393886cea8bd 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomSupport.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomSupport.java @@ -24,6 +24,9 @@ */ package com.oracle.svm.core.thread; +import static com.oracle.svm.core.SubstrateOptions.UseEpsilonGC; +import static com.oracle.svm.core.SubstrateOptions.UseSerialGC; + import java.lang.reflect.Field; import org.graalvm.compiler.api.replacements.Fold; @@ -33,7 +36,6 @@ import org.graalvm.nativeimage.IsolateThread; import org.graalvm.word.Pointer; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.stack.JavaFrameAnchor; import com.oracle.svm.core.stack.JavaFrameAnchors; @@ -42,13 +44,26 @@ import jdk.internal.misc.Unsafe; public final class LoomSupport { + private static final boolean isEnabled; + static { + boolean enabled = false; + if (JavaVersionUtil.JAVA_SPEC == 19 && (UseSerialGC.getValue() || UseEpsilonGC.getValue())) { + try { + enabled = (Boolean) Class.forName("jdk.internal.misc.PreviewFeatures") + .getDeclaredMethod("isEnabled").invoke(null); + } catch (ReflectiveOperationException ignored) { + } + } + isEnabled = enabled; + } + public static final int YIELD_SUCCESS = 0; public static final int PINNED_CRITICAL_SECTION = 1; public static final int PINNED_NATIVE = 2; @Fold public static boolean isEnabled() { - return Continuation.isSupported() && SubstrateOptions.UseLoom.getValue(); + return isEnabled; } public static int yield(Target_java_lang_Continuation cont) { From fd9449ceddd5b0a7a2b9ab850c42fda53046faa4 Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Wed, 20 Jul 2022 10:51:53 +0200 Subject: [PATCH 02/11] Support JDK 19 virtual threads (Project Loom) natively. --- .../core/heap/StoredContinuationAccess.java | 6 +- .../image/DisallowedImageHeapObjects.java | 6 +- .../oracle/svm/core/jdk/StackTraceUtils.java | 6 +- .../jdk/Target_java_lang_StackWalker.java | 14 +- .../oracle/svm/core/thread/Continuation.java | 49 ++-- .../svm/core/thread/ContinuationsFeature.java | 47 ++-- .../oracle/svm/core/thread/JavaThreads.java | 7 +- .../oracle/svm/core/thread/LoomSupport.java | 64 +---- .../svm/core/thread/LoomVirtualThreads.java | 10 +- .../core/thread/SubstrateVirtualThread.java | 2 +- .../thread/Target_java_lang_Continuation.java | 248 ------------------ .../core/thread/Target_java_lang_Thread.java | 99 +++---- .../Target_java_lang_VirtualThread.java | 52 +--- .../Target_jdk_internal_vm_Continuation.java | 183 +++++++++++++ ...et_jdk_internal_vm_ContinuationScope.java} | 11 +- .../hosted/jdk/JDKInitializationFeature.java | 3 - 16 files changed, 301 insertions(+), 506 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Continuation.java create mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_jdk_internal_vm_Continuation.java rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/{Target_java_lang_ContinuationScope.java => Target_jdk_internal_vm_ContinuationScope.java} (79%) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java index cecb07f06040..dd3dfb5b3ec9 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java @@ -125,7 +125,7 @@ private static int allocateFromStack(Continuation cont, Pointer baseSp, Pointer if (!yield) { PreemptVisitor visitor = new PreemptVisitor(baseSp); JavaStackWalker.walkThread(targetThread, visitor); - if (visitor.preemptStatus != Continuation.YIELD_SUCCESS) { + if (visitor.preemptStatus != Continuation.FREEZE_OK) { return visitor.preemptStatus; } startSp = visitor.leafSP; @@ -138,7 +138,7 @@ private static int allocateFromStack(Continuation cont, Pointer baseSp, Pointer StoredContinuation instance = allocate(framesSize); fillUninterruptibly(instance, startIp, startSp, framesSize); cont.stored = instance; - return Continuation.YIELD_SUCCESS; + return Continuation.FREEZE_OK; } @Uninterruptible(reason = "Prevent modifications to the stack while initializing instance and copying frames.") @@ -234,7 +234,7 @@ private static final class PreemptVisitor extends StackFrameVisitor { Pointer leafSP; CodePointer leafIP; - int preemptStatus = Continuation.YIELD_SUCCESS; + int preemptStatus = Continuation.FREEZE_OK; PreemptVisitor(Pointer endSP) { this.endSP = endSP; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java index 8f7c0574bb11..70eeac58b77d 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java @@ -33,7 +33,7 @@ import java.util.concurrent.ThreadLocalRandom; import com.oracle.svm.core.thread.LoomSupport; -import com.oracle.svm.core.thread.Target_java_lang_Continuation; +import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.thread.VirtualThreads; import com.oracle.svm.core.util.VMError; import com.oracle.svm.util.ReflectionUtil; @@ -76,8 +76,8 @@ public static void check(Object obj, DisallowedObjectReporter reporter) { asThread, "Try avoiding to initialize the class that caused initialization of the Thread."); } } - if (obj instanceof Target_java_lang_Continuation) { - final Target_java_lang_Continuation asCont = (Target_java_lang_Continuation) obj; + if (obj instanceof Target_jdk_internal_vm_Continuation) { + final Target_jdk_internal_vm_Continuation asCont = (Target_jdk_internal_vm_Continuation) obj; if (LoomSupport.isStarted(asCont)) { throw reporter.raise("Detected a started Continuation in the image heap. " + "Continuations running in the image generator are no longer running at image runtime.", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java index e770d2fab397..8cb03bb4266f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java @@ -30,7 +30,6 @@ import java.util.ArrayList; import org.graalvm.nativeimage.IsolateThread; -import com.oracle.svm.util.DirectAnnotationAccess; import org.graalvm.word.Pointer; import com.oracle.svm.core.SubstrateOptions; @@ -41,7 +40,8 @@ import com.oracle.svm.core.stack.JavaStackFrameVisitor; import com.oracle.svm.core.stack.JavaStackWalker; import com.oracle.svm.core.thread.LoomSupport; -import com.oracle.svm.core.thread.Target_java_lang_Continuation; +import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; +import com.oracle.svm.util.DirectAnnotationAccess; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -137,7 +137,7 @@ public static boolean shouldShowFrame(FrameInfoQueryResult frameInfo, boolean sh return false; } - if (LoomSupport.isEnabled() && clazz == Target_java_lang_Continuation.class) { + if (LoomSupport.isEnabled() && clazz == Target_jdk_internal_vm_Continuation.class) { // Skip intrinsics in JDK if ("enterSpecial".equals(frameInfo.getSourceMethodName())) { return false; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java index f96d4ef2b020..37bb963abbeb 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java @@ -59,9 +59,9 @@ import com.oracle.svm.core.stack.JavaStackWalk; import com.oracle.svm.core.stack.JavaStackWalker; import com.oracle.svm.core.thread.LoomSupport; -import com.oracle.svm.core.thread.Target_java_lang_Continuation; -import com.oracle.svm.core.thread.Target_java_lang_ContinuationScope; import com.oracle.svm.core.thread.Target_java_lang_VirtualThread; +import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; +import com.oracle.svm.core.thread.Target_jdk_internal_vm_ContinuationScope; import com.oracle.svm.core.thread.VirtualThreads; import com.oracle.svm.core.util.VMError; @@ -72,13 +72,13 @@ final class Target_java_lang_StackWalker { * Current continuation that the stack walker is on. */ @Alias @TargetElement(onlyWith = LoomJDK.class)// - Target_java_lang_Continuation continuation; + Target_jdk_internal_vm_Continuation continuation; /** - * Target continuation scope if we're iterating a {@link Target_java_lang_Continuation}. + * Target continuation scope if we're iterating a {@link Target_jdk_internal_vm_Continuation}. */ @Alias @TargetElement(onlyWith = LoomJDK.class)// - Target_java_lang_ContinuationScope contScope; + Target_jdk_internal_vm_ContinuationScope contScope; @Alias Set