From cef378b71a7186e9aaaba29c86fb158bf31b0180 Mon Sep 17 00:00:00 2001 From: Yichen Yan Date: Sat, 2 Jul 2022 22:50:16 +0800 Subject: [PATCH 1/3] Some thread updates in JDK 19. --- .../oracle/svm/core/thread/JavaThreads.java | 10 ++++ .../core/thread/SubstrateVirtualThread.java | 9 +-- .../core/thread/Target_java_lang_Thread.java | 59 +++++++------------ 3 files changed, 37 insertions(+), 41 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java index 02d8e48d0e55..774ab6541eed 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/JavaThreads.java @@ -72,6 +72,8 @@ public final class JavaThreads { static final AtomicLong threadSeqNumber = new AtomicLong(); /** For Thread.nextThreadNum(). */ static final AtomicInteger threadInitNumber = new AtomicInteger(); + /** For Thread.ThreadNumbering.next() after JDK 19. */ + static final AtomicInteger threadNumber = new AtomicInteger(); private JavaThreads() { } @@ -95,6 +97,14 @@ public static void setThreadStatus(Thread thread, int threadStatus) { LoomSupport.CompatibilityUtil.setThreadStatus(toTarget(thread), threadStatus); } + public static Target_sun_nio_ch_Interruptible getBlocker(Thread thread) { + if (JavaVersionUtil.JAVA_SPEC >= 19) { + return toTarget(thread).nioBlocker; + } else { + return toTarget(thread).blocker; + } + } + /** Safe method to get a thread's internal state since {@link Thread#getState} is not final. */ static Thread.State getThreadState(Thread thread) { return Target_jdk_internal_misc_VM.toThreadState(getThreadStatus(thread)); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/SubstrateVirtualThread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/SubstrateVirtualThread.java index 0eaddd8fa40c..5d99edad13c2 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/SubstrateVirtualThread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/SubstrateVirtualThread.java @@ -433,10 +433,11 @@ boolean joinNanos(long nanos) throws InterruptedException { } private Object interruptLock() { - if (JavaVersionUtil.JAVA_SPEC >= 19) { - throw VMError.unsupportedFeature("Loom is not yet supported on JDK 19"); + if (JavaVersionUtil.JAVA_SPEC < 19) { + return JavaThreads.toTarget(this).blockerLock; + } else { + return JavaThreads.toTarget(this).interruptLock; } - return JavaThreads.toTarget(this).blockerLock; } /** @see #releaseInterruptLockAndSwitchBack */ @@ -478,7 +479,7 @@ public void interrupt() { Object token = switchToCarrierAndAcquireInterruptLock(); try { JavaThreads.writeInterruptedFlag(this, true); - Target_sun_nio_ch_Interruptible b = JavaThreads.toTarget(this).blocker; + Target_sun_nio_ch_Interruptible b = JavaThreads.getBlocker(this); if (b != null) { b.interrupt(this); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java index aee511c32f06..024aa4685f96 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/Target_java_lang_Thread.java @@ -153,6 +153,8 @@ public final class Target_java_lang_Thread { @Alias @TargetElement(onlyWith = JDK17OrEarlier.class) // volatile Target_sun_nio_ch_Interruptible blocker; + @Alias @TargetElement(onlyWith = JDK19OrLater.class) // + volatile Target_sun_nio_ch_Interruptible nioBlocker; /** @see JavaThreads#setCurrentThreadLockHelper */ @Inject @TargetElement(onlyWith = ContinuationsSupported.class) // @@ -206,10 +208,10 @@ private static int nextThreadNum() { null, 0, Thread.NORM_PRIORITY, asDaemon, ThreadStatus.RUNNABLE); - if (LoomSupport.isEnabled() || JavaVersionUtil.JAVA_SPEC >= 19) { - tid = Target_java_lang_Thread_ThreadIdentifiers.next(); + tid = nextThreadID(); + if (JavaVersionUtil.JAVA_SPEC >= 19) { + interruptLock = new Object(); } else { - tid = nextThreadID(); blockerLock = new Object(); } name = (withName != null) ? withName : ("System-" + nextThreadNum()); @@ -258,15 +260,6 @@ static Thread currentThread() { return thread; } - @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) - @Substitute - @TargetElement(onlyWith = LoomJDK.class) - private static Thread currentThread0() { - Thread thread = PlatformThreads.currentThread.get(); - assert thread != null : "Thread has not been set yet"; - return thread; - } - @Substitute @TargetElement(onlyWith = JDK19OrLater.class) static Thread currentCarrierThread() { @@ -346,22 +339,7 @@ static String genThreadName() { return "Thread-" + JavaThreads.threadInitNumber.incrementAndGet(); } - /** - * This constructor is only called by `VirtualThread#VirtualThread(Executor, String, int, - * Runnable)`. - */ - @Substitute - @TargetElement(onlyWith = LoomJDK.class) - private Target_java_lang_Thread(String name, int characteristics) { - /* Non-0 instance field initialization. */ - this.interruptLock = new Object(); - - this.name = (name != null) ? name : ""; - this.tid = Target_java_lang_Thread_ThreadIdentifiers.next(); - this.contextClassLoader = Thread.currentThread().getContextClassLoader(); - } - - @SuppressWarnings("hiding") + @SuppressWarnings({"hiding", "deprecation"}) @Substitute private void start0() { if (!SubstrateOptions.MultiThreaded.getValue()) { @@ -594,15 +572,9 @@ private static Thread[] getAllThreads() { private static native void clearInterruptEvent(); @Substitute - @TargetElement(onlyWith = LoomJDK.class) - static Object[] scopedCache() { - throw VMError.unimplemented(); - } - - @Substitute - @TargetElement(onlyWith = LoomJDK.class) - static void setScopedCache(Object[] cache) { - throw VMError.unimplemented(); + @TargetElement(onlyWith = JDK19OrLater.class) + boolean getAndClearInterrupt() { + return JavaThreads.getAndClearInterruptedFlag(JavaThreads.fromTarget(this)); } @Alias @TargetElement(onlyWith = LoomJDK.class) // @@ -616,6 +588,10 @@ static void setScopedCache(Object[] cache) { @TargetElement(onlyWith = LoomJDK.class) public static native Thread startVirtualThread(Runnable task); + @Alias + @TargetElement(onlyWith = JDK19OrLater.class) + static native String genThreadName(); + } @TargetClass(value = Thread.class, innerClass = "FieldHolder", onlyWith = JDK19OrLater.class) @@ -658,6 +634,15 @@ static long next() { } } +@Substitute// +@TargetClass(value = Thread.class, innerClass = "ThreadNumbering", onlyWith = JDK19OrLater.class) +final class Target_java_lang_Thread_ThreadNumbering { + @Substitute// + static int next() { + return JavaThreads.threadNumber.incrementAndGet(); + } +} + @TargetClass(value = Thread.class, innerClass = "VirtualThreads", onlyWith = {LoomJDK.class, JDK17OrEarlier.class}) final class Target_java_lang_Thread_VirtualThreads { } From 28a117439065346a6f4e9e590ae0c2fed66fd241 Mon Sep 17 00:00:00 2001 From: Yichen Yan Date: Mon, 4 Jul 2022 15:09:43 +0800 Subject: [PATCH 2/3] svm: sync with AARCH64.CPUFeature in JDK 19 --- .../com/oracle/svm/core/aarch64/AArch64LibCHelper.java | 8 ++++++++ .../include/aarch64cpufeatures.h | 2 ++ .../src/com.oracle.svm.native.libchelper/src/cpuid.c | 10 ++++++++++ 3 files changed, 20 insertions(+) diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java index 7fdb62f79f00..53c142c44e07 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/aarch64/AArch64LibCHelper.java @@ -123,6 +123,14 @@ public interface CPUFeatures extends PointerBase { @AllowNarrowingCast @CField boolean fDMB_ATOMICS(); + + @AllowNarrowingCast + @CField + boolean fPACA(); + + @AllowNarrowingCast + @CField + boolean fSVEBITPERM(); } // Checkstyle: resume } diff --git a/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h b/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h index faa8434867b5..af2d26fad279 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h +++ b/substratevm/src/com.oracle.svm.native.libchelper/include/aarch64cpufeatures.h @@ -42,4 +42,6 @@ typedef struct { char fSTXR_PREFETCH; char fA53MAC; char fDMB_ATOMICS; + char fPACA; + char fSVEBITPERM; } CPUFeatures; diff --git a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c index 0f326c8808b4..73e65922fc44 100644 --- a/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c +++ b/substratevm/src/com.oracle.svm.native.libchelper/src/cpuid.c @@ -623,6 +623,8 @@ void determineCPUFeatures(CPUFeatures* features) { features->fSTXR_PREFETCH = 0; features->fA53MAC = 0; features->fDMB_ATOMICS = 0; + features->fPACA = 0; + features->fSVEBITPERM = 0; } /* @@ -674,9 +676,15 @@ void determineCPUFeatures(CPUFeatures* features) { #ifndef HWCAP_SVE #define HWCAP_SVE (1L << 22) #endif +#ifndef HWCAP_PACA +#define HWCAP_PACA (1L << 30) +#endif #ifndef HWCAP2_SVE2 #define HWCAP2_SVE2 (1L << 1) #endif +#ifndef HWCAP2_SVEBITPERM +#define HWCAP2_SVEBITPERM (1L << 4) +#endif #define CPU_ARM 'A' #define CPU_CAVIUM 'C' @@ -706,6 +714,8 @@ void determineCPUFeatures(CPUFeatures* features) { features->fSTXR_PREFETCH = 0; features->fA53MAC = 0; features->fDMB_ATOMICS = 0; + features->fPACA = !!(auxv & HWCAP_PACA); + features->fSVEBITPERM = !!(auxv2 & HWCAP2_SVEBITPERM); //checking for features signaled in another way From 1507ee4693407cced6891ecbe57714c3db1d72e5 Mon Sep 17 00:00:00 2001 From: Yichen Yan Date: Mon, 4 Jul 2022 17:46:24 +0800 Subject: [PATCH 3/3] wip: use continuation via Loom --- substratevm/mx.substratevm/suite.py | 15 +++++++++++++++ .../svm/core/jdk19}/LoomVirtualThreads.java | 9 ++++++--- .../com/oracle/svm/core/SubstrateOptions.java | 4 +++- .../svm/core/thread/ContinuationsFeature.java | 18 +++++++++++------- 4 files changed, 35 insertions(+), 11 deletions(-) rename substratevm/src/{com.oracle.svm.core/src/com/oracle/svm/core/thread => com.oracle.svm.core.jdk19/src/com/oracle/svm/core/jdk19}/LoomVirtualThreads.java (92%) diff --git a/substratevm/mx.substratevm/suite.py b/substratevm/mx.substratevm/suite.py index cf1979ce4f2b..e8acab414f86 100644 --- a/substratevm/mx.substratevm/suite.py +++ b/substratevm/mx.substratevm/suite.py @@ -304,6 +304,20 @@ }, + "com.oracle.svm.core.jdk19": { + "subDir": "src", + "sourceDirs": ["src"], + "dependencies": ["com.oracle.svm.core"], + "requiresConcealed" : { + "java.base" : [ + ], + }, + "javaCompliance": "19+", + "checkstyle": "com.oracle.svm.core", + "workingSets": "SVM", + }, + + "com.oracle.svm.core.genscavenge": { "subDir": "src", "sourceDirs": [ @@ -1086,6 +1100,7 @@ "com.oracle.svm.hosted.jdk17", "com.oracle.svm.core", "com.oracle.svm.core.jdk17", + "com.oracle.svm.core.jdk19", "com.oracle.svm.core.graal.amd64", "com.oracle.svm.core.graal.aarch64", "com.oracle.svm.core.posix", diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomVirtualThreads.java b/substratevm/src/com.oracle.svm.core.jdk19/src/com/oracle/svm/core/jdk19/LoomVirtualThreads.java similarity index 92% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomVirtualThreads.java rename to substratevm/src/com.oracle.svm.core.jdk19/src/com/oracle/svm/core/jdk19/LoomVirtualThreads.java index d54be60ce806..42a185e36a5a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomVirtualThreads.java +++ b/substratevm/src/com.oracle.svm.core.jdk19/src/com/oracle/svm/core/jdk19/LoomVirtualThreads.java @@ -22,13 +22,16 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package com.oracle.svm.core.thread; +package com.oracle.svm.core.jdk19; import static java.util.concurrent.TimeUnit.MILLISECONDS; import java.util.concurrent.Executor; import java.util.concurrent.ThreadFactory; +import com.oracle.svm.core.thread.Target_java_lang_Thread; +import com.oracle.svm.core.thread.Target_java_lang_VirtualThread; +import com.oracle.svm.core.thread.VirtualThreads; import org.graalvm.nativeimage.Platforms; import com.oracle.svm.core.SubstrateUtil; @@ -49,7 +52,7 @@ private static Target_java_lang_VirtualThread cast(Thread thread) { @Override public ThreadFactory createFactory() { - throw VMError.unimplemented(); + return Thread.ofVirtual().factory(); } @Override @@ -61,7 +64,7 @@ public boolean isVirtual(Thread thread) { public void join(Thread thread, long millis) throws InterruptedException { if (thread.isAlive()) { long nanos = MILLISECONDS.toNanos(millis); - cast(thread).joinNanos(nanos); +// cast(thread).joinNanos(nanos); } } 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 170bc969d5d7..90eb157085fa 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 @@ -47,6 +47,7 @@ import org.graalvm.compiler.options.OptionStability; import org.graalvm.compiler.options.OptionType; import org.graalvm.compiler.options.OptionValues; +import org.graalvm.compiler.serviceprovider.JavaVersionUtil; import org.graalvm.nativeimage.ImageInfo; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -134,11 +135,12 @@ 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") // + @Option(help = "Support continuations via Virtual Threads") // public static final HostedOptionKey UseLoom = new HostedOptionKey<>(false) { @Override protected void onValueUpdate(EconomicMap, Object> values, Boolean oldValue, Boolean newValue) { if (newValue) { + assert JavaVersionUtil.JAVA_SPEC >= 19; SupportContinuations.update(values, true); } } 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..7a4a4564a9b3 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 @@ -49,7 +49,11 @@ public void afterRegistration(AfterRegistrationAccess access) { if (Continuation.isSupported()) { VirtualThreads impl; if (LoomSupport.isEnabled()) { - impl = new LoomVirtualThreads(); + try { + impl = (VirtualThreads) Class.forName("com.oracle.svm.core.jdk19.LoomVirtualThreads").getDeclaredConstructor().newInstance(); + } catch (Exception e) { + throw UserError.abort(e, "Error initializing LoomVirtualThreads"); + } } else { /* * GR-37518: ForkJoinPool on 11 syncs on a String which doesn't have its own monitor @@ -57,15 +61,15 @@ public void afterRegistration(AfterRegistrationAccess access) { * 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, "+")); + SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); impl = new SubstrateVirtualThreads(); } 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, "+")); + SubstrateOptionsParser.commandArgument(SubstrateOptions.UseLoom, "+"), + SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+")); } } @@ -77,7 +81,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { } access.registerReachabilityHandler(a -> access.registerAsInHeap(StoredContinuation.class), - ReflectionUtil.lookupMethod(StoredContinuationAccess.class, "allocate", int.class)); + ReflectionUtil.lookupMethod(StoredContinuationAccess.class, "allocate", int.class)); if (LoomSupport.isEnabled()) { RuntimeReflection.register(ReflectionUtil.lookupMethod(ForkJoinPool.class, "compensatedBlock", ForkJoinPool.ManagedBlocker.class)); @@ -90,8 +94,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, "+")); + SubstrateOptionsParser.commandArgument(SubstrateOptions.SupportContinuations, "+"), + SubstrateOptionsParser.commandArgument(SubstrateOptions.UseLoom, "+")); } } }