The thread dump will include output for all platform threads. It may
* include output for some or all virtual threads.
diff --git a/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.html b/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.html
new file mode 100644
index 00000000000..f7dd84d4f32
--- /dev/null
+++ b/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.html
@@ -0,0 +1,283 @@
+
+
+
+
+ JSON Thread Dump Format
+
+
+
+
JSON Thread Dump Format
+
+The JSON text is an object with a member named "threadDump" that is an object with the
+following members:
+
+
threadDump members
+
+
+
Name
+
Data type
+
Optional
+
Description
+
+
+
+
+
formatVersion
+
number
+
no
+
The format version. Its value is 2.
+
+
+
processId
+
number
+
no
+
The process identifier (pid) of the VM that generated the thread dump.
+
+
+
time
+
string
+
no
+
The timestamp, in ISO 8601 format, when the thread dump was generated.
+
+
+
runtimeVersion
+
string
+
no
+
The {@linkplain java.lang.Runtime.Version runtime version} of the VM that
+ generated the thread dump.
+
+
+
threadContainers
+
array
+
no
+
The array of thread "groupings". The first element is the root grouping/container
+ with name "<root>".
+
+
+
+
+
Each element in the "threadContainers" array is an object that represents a
+ grouping/container of threads with the following members:
+
+
threadContainers members
+
+
+
Name
+
Data type
+
Optional
+
Description
+
+
+
+
+
container
+
string
+
no
+
The thread container name. The name is unique.
+
+
+
parent
+
string or null
+
no
+
The thread container parent's name or {@code null} for the root container.
+
+
+
owner
+
number or null
+
no
+
The {@linkplain java.lang.Thread#threadId() thread identifier} of the thread
+ that owns the thread container or {@code null} if no owner.
+
+
+
threads
+
array
+
no
+
The array of threads in the thread grouping/container.
+
+
+
threadCount
+
number
+
yes
+
The number of threads in the thread grouping/container. If the thread dump
+ includes all virtual threads then this count is the same as the number of
+ elements in the threads array. If all virtual threads are not included then
+ it may be larger than the number of elements in the threads array.
+
+
+
+
+
Each element in a "threads" array is an object with the following members:
+
+
threads members
+
+
+
Name
+
Data type
+
Optional
+
Description
+
+
+
+
+
tid
+
number
+
no
+
The {@linkplain java.lang.Thread#threadId() thread identifier}.
+
+
+
time
+
string
+
no
+
The timestamp, in ISO 8601 format, when the thread was sampled.
+
+
+
name
+
string
+
no
+
The {@linkplain java.lang.Thread#getName() thread name}.
+
+
+
state
+
string
+
no
+
The string representation of the {@linkplain java.lang.Thread#getState() thread state}.
+
+
+
virtual
+
boolean
+
yes
+
{@code true} if the thread is a {@linkplain java.lang.Thread#isVirtual() virtual thread}.
+
+
+
carrier
+
number
+
yes
+
The thread identifier of the carrier thread when this thread is a mounted
+ virtual thread.
+
+
+
stack
+
array
+
no
+
The thread stack. The elements in the array are of type string with the string
+ representation of a {@linkplain java.lang.StackTraceElement stack trace element}.
+ If the thread stack has one or more elements, then the first element is the top
+ of the stack.
+
+
+
parkBlocker
+
object
+
yes
+
The object responsible for the thread parking. Its members identify the
+ blocker object, and the exclusive owner thread if owned.
+
+
+
blockedOn
+
string
+
yes
+
The {@linkplain java.util.Objects#toIdentityString(Object) identity string} of the
+ object that the thread is blocked on waiting to enter/re-enter a synchronization
+ method or block.
+
+
+
waitingOn
+
string
+
yes
+
The {@linkplain java.util.Objects#toIdentityString(Object) identity string}
+ of the object that the thread is {@linkplain java.lang.Object#wait() waiting}
+ to be notified.
+
+
+
monitorsOwned
+
array
+
yes
+
The objects for which a monitor is owned by the thread.
+
+
+
+
+
A "parkBlocker" object has the following members:
+
+
parkBlocker members
+
+
+
Name
+
Data type
+
Optional
+
Description
+
+
+
+
+
object
+
string
+
no
+
The {@linkplain java.util.Objects#toIdentityString(Object) identity string}
+ of the {@linkplain java.util.concurrent.locks.LockSupport#park(Object) blocker
+ object} responsible for the thread parking.
+
+
+
owner
+
number
+
yes
+
The thread identifier of the exclusive owner thread when the parkBlocker is
+ an {@link java.util.concurrent.locks.AbstractOwnableSynchronizer}.
+
+
+
+
+
Each element in a "monitorsOwned" array is an object with the following members:
+
+
monitorsOwned members
+
+
+
Name
+
Data type
+
Optional
+
Description
+
+
+
+
+
depth
+
number
+
no
+
The stack depth at which the monitors are owned.
+
+
+
locks
+
array
+
no
+
The elements of the array are of type string or null. An element of type string
+ has a value that is the {@linkplain java.util.Objects#toIdentityString(Object)
+ identity string} of the object for which the monitor is owned by the thread.
+ The element is of type null when the object has been eliminated.
+
+
+
+
+
+
diff --git a/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json b/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json
deleted file mode 100644
index 30161b0bb74..00000000000
--- a/src/jdk.management/share/classes/com/sun/management/doc-files/threadDump.schema.json
+++ /dev/null
@@ -1,169 +0,0 @@
-{
- "type": "object",
- "properties": {
- "threadDump": {
- "type": "object",
- "properties": {
- "formatVersion": {
- "type": "integer",
- "description": "Format version (2)."
- },
- "processId": {
- "type": "integer",
- "description": "The native process id of the Java virtual machine."
- },
- "time": {
- "type": "string",
- "description": "The time in ISO 8601 format when the thread dump was generated."
- },
- "runtimeVersion": {
- "type": "string",
- "description": "The runtime version, see java.lang.Runtime.Version"
- },
- "threadContainers": {
- "type": "array",
- "description": "The array of thread containers (thread groupings).",
- "items": [
- {
- "type": "object",
- "properties": {
- "container": {
- "type": "string",
- "description": "The container name. The container name is unique."
- },
- "parent": {
- "type": [ "string", "null" ],
- "description": "The parent container name or null for the root container."
- },
- "owner": {
- "type": [ "integer", "null" ],
- "description": "The thread identifier of the owner thread or null if no owner."
- },
- "threads": {
- "type": "array",
- "description": "The array of threads in the thread container.",
- "items": [
- {
- "type": "object",
- "properties": {
- "tid": {
- "type": "integer",
- "description": "The thread identifier."
- },
- "time": {
- "type": "string",
- "description": "The time in ISO 8601 format that the thread was sampled."
- },
- "name": {
- "type": "string",
- "description": "The thread name."
- },
- "state": {
- "type": "string",
- "description": "The thread state (Thread::getState)."
- },
- "virtual" : {
- "type": "boolean",
- "description": "true for a virtual thread."
- },
- "parkBlocker": {
- "type": "object",
- "properties": {
- "object": {
- "type": "string",
- "description": "The blocker object responsible for the thread parking."
- }
- },
- "owner": {
- "type": "integer",
- "description": "The thread identifier of the owner when the parkBlocker is an AbstractOwnableSynchronizer."
- },
- "required": [
- "object"
- ]
- },
- "blockedOn": {
- "type": "string",
- "description": "The object that the thread is blocked on waiting to enter/re-enter a synchronization block/method."
- },
- "waitingOn": {
- "type": "string",
- "description": "The object that the thread is waiting to be notified (Object.wait)."
- },
- "stack": {
- "type": "array",
- "description": "The thread stack. The first element is the top of the stack.",
- "items": [
- {
- "type": "string",
- "description": "A stack trace element (java.lang.StackTraceElement)."
- }
- ]
- },
- "monitorsOwned": {
- "type": "array",
- "description": "The objects for which monitors are owned by the thread.",
- "items": {
- "type": "object",
- "properties": {
- "depth": {
- "type": "integer",
- "description": "The stack depth at which the monitors are owned."
- },
- "locks": {
- "type": "array",
- "items": {
- "type": [ "string", "null" ],
- "description": "The object for which the monitor is owned by the thread, null if eliminated."
- }
- }
- },
- "required": [
- "depth",
- "locks"
- ]
- }
- },
- "carrier": {
- "type": "integer",
- "description": "The thread identifier of the carrier thread if mounted."
- }
- },
- "required": [
- "tid",
- "time",
- "name",
- "state",
- "stack"
- ]
- }
- ]
- },
- "threadCount": {
- "type": "integer",
- "description": "The number of threads in the thread container."
- }
- },
- "required": [
- "container",
- "parent",
- "owner",
- "threads"
- ]
- }
- ]
- }
- },
- "required": [
- "formatVersion",
- "processId",
- "time",
- "runtimeVersion",
- "threadContainers"
- ]
- }
- },
- "required": [
- "threadDump"
- ]
-}
From 81b6fcc3e9e6a5a53a7a53d8371d86a2f48f3d90 Mon Sep 17 00:00:00 2001
From: Vladimir Petko
Date: Thu, 2 Apr 2026 13:12:48 +0000
Subject: [PATCH 03/60] 8381555:
test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java fails on 32 bit
architectures
Reviewed-by: jsikstro
---
test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java | 1 +
1 file changed, 1 insertion(+)
diff --git a/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java
index 3aec113990c..c4c1d364308 100644
--- a/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java
+++ b/test/hotspot/jtreg/gc/arguments/TestG1CompressedOops.java
@@ -27,6 +27,7 @@
/*
* @test TestG1CompressedOops
* @bug 8354145
+ * @requires vm.bits == 64
* @requires vm.flagless
* @summary Verify that the flag UseCompressedOops is updated properly
* @library /test/lib
From 06c9aebce3aefec4c75c5ebb46bd9ffc62d09266 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?=
Date: Thu, 2 Apr 2026 13:40:51 +0000
Subject: [PATCH 04/60] 8377550: [REDO] Need to keep leading zeros in
TlsPremasterSecret of TLS1.3 DHKeyAgreement
Reviewed-by: hchao, mullan
---
.../share/classes/sun/security/ssl/KAKeyDerivation.java | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java
index dea86351cc8..0ca197160a9 100644
--- a/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java
+++ b/src/java.base/share/classes/sun/security/ssl/KAKeyDerivation.java
@@ -49,6 +49,9 @@
*/
public class KAKeyDerivation implements SSLKeyDerivation {
+ // Algorithm used to derive TLS 1.3 shared secrets
+ private static final String t13KeyDerivationAlgorithm =
+ System.getProperty("jdk.tls.t13KeyDerivationAlgorithm", "Generic");
private final String algorithmName;
private final HandshakeContext context;
private final PrivateKey localPrivateKey;
@@ -234,7 +237,7 @@ private SecretKey t13DeriveKey(String type)
var decapsulator = kem.newDecapsulator(localPrivateKey);
sharedSecret = decapsulator.decapsulate(
keyshare, 0, decapsulator.secretSize(),
- "TlsPremasterSecret");
+ t13KeyDerivationAlgorithm);
} catch (IllegalArgumentException | InvalidKeyException |
DecapsulateException e) {
// Peer validation failure
@@ -252,7 +255,7 @@ private SecretKey t13DeriveKey(String type)
KeyAgreement ka = KeyAgreement.getInstance(algorithmName);
ka.init(localPrivateKey);
ka.doPhase(peerPublicKey, true);
- sharedSecret = ka.generateSecret("TlsPremasterSecret");
+ sharedSecret = ka.generateSecret(t13KeyDerivationAlgorithm);
}
return deriveHandshakeSecret(type, sharedSecret);
From 0ada293cb4b1e7ec492d20fb8d99bb3db35974c8 Mon Sep 17 00:00:00 2001
From: Matias Saavedra Silva
Date: Thu, 2 Apr 2026 14:10:46 +0000
Subject: [PATCH 05/60] 8380091: Tests in runtime/cds are failing with log
parsing errors - missing output - but the output seems present
Reviewed-by: coleenp, dholmes
---
.../jtreg/runtime/cds/BootAppendTests.java | 10 +++++-----
.../cds/appcds/SpecifySysLoaderProp.java | 20 +++++++++++--------
2 files changed, 17 insertions(+), 13 deletions(-)
diff --git a/test/hotspot/jtreg/runtime/cds/BootAppendTests.java b/test/hotspot/jtreg/runtime/cds/BootAppendTests.java
index 43466734fa3..642aa2209f4 100644
--- a/test/hotspot/jtreg/runtime/cds/BootAppendTests.java
+++ b/test/hotspot/jtreg/runtime/cds/BootAppendTests.java
@@ -162,7 +162,7 @@ public static void testBootAppendDuplicateModuleClass() throws Exception {
.addSuffix("-Xlog:class+load=info",
APP_CLASS, BOOT_APPEND_DUPLICATE_MODULE_CLASS_NAME);
- String MATCH_PATTERN = ".class.load. javax.annotation.processing.FilerException source:.*bootAppend.jar*";
+ String MATCH_PATTERN = ".class.load.*javax.annotation.processing.FilerException source:.*bootAppend.jar*";
CDSTestUtils.run(opts)
.assertNormalExit(out -> {
out.shouldNotMatch(MATCH_PATTERN);
@@ -188,7 +188,7 @@ public static void testBootAppendExcludedModuleClass() throws Exception {
APP_CLASS, BOOT_APPEND_MODULE_CLASS_NAME);
CDSTestUtils.Result res = CDSTestUtils.run(opts);
String MATCH_PATTERN =
- ".class.load. javax.sound.sampled.MyClass source:.*bootAppend.jar*";
+ ".class.load.*javax.sound.sampled.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
res.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
@@ -225,7 +225,7 @@ public static void testBootAppendDuplicateExcludedModuleClass() throws Exception
CDSTestUtils.Result res = CDSTestUtils.run(opts);
String MATCH_PATTERN =
- ".class.load. javax.annotation.processing.FilerException source:.*bootAppend.jar*";
+ ".class.load.*javax.annotation.processing.FilerException source:.*bootAppend.jar*";
if (mode.equals("on")) {
res.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
@@ -258,7 +258,7 @@ public static void testBootAppendClass() throws Exception {
CDSTestUtils.Result res = CDSTestUtils.run(opts);
String MATCH_PATTERN =
- ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
+ ".class.load.*nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
res.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
@@ -287,7 +287,7 @@ public static void testBootAppendExtraDir() throws Exception {
CDSTestUtils.Result res = CDSTestUtils.run(opts);
String MATCH_PATTERN =
- ".class.load. nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
+ ".class.load.*nonjdk.myPackage.MyClass source:.*bootAppend.jar*";
if (mode.equals("on")) {
res.assertSilentlyDisabledCDS(out -> {
out.shouldHaveExitValue(0)
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java b/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java
index ed7f02569ef..8548f76d2ec 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/SpecifySysLoaderProp.java
@@ -53,8 +53,10 @@ public static void main(String[] args) throws Exception {
"-verbose:class",
"-cp", appJar,
"ReportMyLoader")
- .assertNormalExit("[class,load] ReportMyLoader source: shared objects file",
- "ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@");
+ .assertNormalExit(output -> {
+ output.shouldMatch(".class,load.*ReportMyLoader source: shared objects file");
+ output.shouldContain("ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@");
+ });
// (1) Try to execute the archive with -Djava.system.class.loader=no.such.Klass,
// it should fail
@@ -79,8 +81,8 @@ public static void main(String[] args) throws Exception {
"TestClassLoader.called = true", //<-but this proves that TestClassLoader was indeed called.
"TestClassLoader: loadClass(\"ReportMyLoader\",") //<- this also proves that TestClassLoader was indeed called.
.assertNormalExit(output -> {
- output.shouldMatch(".class,load. TestClassLoader source: file:");
- output.shouldMatch(".class,load. ReportMyLoader source: file:.*" + jarFileName);
+ output.shouldMatch(".class,load.*TestClassLoader source: file:");
+ output.shouldMatch(".class,load.*ReportMyLoader source: file:.*" + jarFileName);
output.shouldContain("full module graph: disabled due to incompatible property: java.system.class.loader=");
});
@@ -91,9 +93,11 @@ public static void main(String[] args) throws Exception {
"-verbose:class",
"-cp", appJar,
"TrySwitchMyLoader")
- .assertNormalExit("[class,load] ReportMyLoader source: shared objects file",
- "TrySwitchMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@",
- "ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@",
- "TestClassLoader.called = false");
+ .assertNormalExit(output -> {
+ output.shouldMatch(".class,load.*ReportMyLoader source: shared objects file");
+ output.shouldContain("TrySwitchMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@");
+ output.shouldContain("ReportMyLoader's loader = jdk.internal.loader.ClassLoaders$AppClassLoader@");
+ output.shouldContain("TestClassLoader.called = false");
+ });
}
}
From 5e89669d180a4ac969f13cf6c066efbdb9998dc5 Mon Sep 17 00:00:00 2001
From: Mahendra Chhipa
Date: Thu, 2 Apr 2026 19:59:21 +0000
Subject: [PATCH 06/60] 8381568: Refactor
java/net/spi/InetAddressResolverProvider test from testNg to use JUnit
Reviewed-by: dfuchs
---
.../AddressesCachingTest.java | 37 +++++++------
.../AddressesStaleCachingTest.java | 24 +++++----
.../BootstrapResolverUsageTest.java | 12 ++---
.../BuiltInResolverTest.java | 22 ++++----
.../EmptyResultsStreamTest.java | 28 +++++-----
.../InetAddressUsageInGetProviderTest.java | 7 ++-
.../LookupPolicyMappingTest.java | 53 ++++++++++---------
.../LookupPolicyOfTest.java | 25 ++++-----
.../ProviderGetExceptionTest.java | 20 +++----
.../ResolutionWithExceptionTest.java | 18 ++++---
.../ReverseLookupDelegationTest.java | 14 ++---
.../classpath/ClasspathProviderTest.java | 9 ++--
.../module/ModularProviderTest.java | 7 +--
13 files changed, 148 insertions(+), 128 deletions(-)
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesCachingTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesCachingTest.java
index 26dabc00063..f4fa2016983 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesCachingTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesCachingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,13 @@
import java.net.InetAddress;
import java.net.UnknownHostException;
-import org.testng.Assert;
-import org.testng.annotations.Test;
import impl.SimpleResolverProviderImpl;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
/*
@@ -37,26 +40,26 @@
* @library lib providers/simple
* @build test.library/testlib.ResolutionRegistry
* simple.provider/impl.SimpleResolverProviderImpl AddressesCachingTest
- * @run testng/othervm -Djava.security.properties=${test.src}/props/NeverCache.props
+ * @run junit/othervm -Djava.security.properties=${test.src}/props/NeverCache.props
* -Dtest.cachingDisabled=true AddressesCachingTest
- * @run testng/othervm -Djava.security.properties=${test.src}/props/ForeverCache.props
+ * @run junit/othervm -Djava.security.properties=${test.src}/props/ForeverCache.props
* -Dtest.cachingDisabled=false AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/NeverCacheIgnoreMinusStale.props
* -Dtest.cachingDisabled=true AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/NeverCacheIgnorePositiveStale.props
* -Dtest.cachingDisabled=true AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/NeverCacheIgnoreZeroStale.props
* -Dtest.cachingDisabled=true AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/ForeverCacheIgnoreMinusStale.props
* -Dtest.cachingDisabled=false AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/ForeverCacheIgnorePositiveStale.props
* -Dtest.cachingDisabled=false AddressesCachingTest
- * @run testng/othervm
+ * @run junit/othervm
* -Djava.security.properties=${test.src}/props/ForeverCacheIgnoreZeroStale.props
* -Dtest.cachingDisabled=false AddressesCachingTest
*/
@@ -66,10 +69,10 @@ public class AddressesCachingTest {
public void testPositiveCaching() {
boolean observedTwoLookups = performLookups(false);
if (CACHING_DISABLED) {
- Assert.assertTrue(observedTwoLookups,
+ assertTrue(observedTwoLookups,
"Two positive lookups are expected with caching disabled");
} else {
- Assert.assertFalse(observedTwoLookups,
+ assertFalse(observedTwoLookups,
"Only one positive lookup is expected with caching enabled");
}
}
@@ -78,10 +81,10 @@ public void testPositiveCaching() {
public void testNegativeCaching() {
boolean observedTwoLookups = performLookups(true);
if (CACHING_DISABLED) {
- Assert.assertTrue(observedTwoLookups,
+ assertTrue(observedTwoLookups,
"Two negative lookups are expected with caching disabled");
} else {
- Assert.assertFalse(observedTwoLookups,
+ assertFalse(observedTwoLookups,
"Only one negative lookup is expected with caching enabled");
}
}
@@ -107,11 +110,11 @@ private static void doLookup(boolean performNegativeLookup) {
try {
InetAddress.getByName(hostName);
if (performNegativeLookup) {
- Assert.fail("Host name is expected to get unresolved");
+ fail("Host name is expected to get unresolved");
}
} catch (UnknownHostException uhe) {
if (!performNegativeLookup) {
- Assert.fail("Host name is expected to get resolved");
+ fail("Host name is expected to get resolved");
}
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesStaleCachingTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesStaleCachingTest.java
index a8393221a72..a2c5c3e8443 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesStaleCachingTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/AddressesStaleCachingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2023, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,8 +27,11 @@
import java.util.concurrent.TimeUnit;
import impl.SimpleResolverProviderImpl;
-import org.testng.Assert;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotEquals;
/*
@@ -38,7 +41,7 @@
* @library lib providers/simple
* @build test.library/testlib.ResolutionRegistry
* simple.provider/impl.SimpleResolverProviderImpl AddressesStaleCachingTest
- * @run testng/othervm -Djava.security.properties=${test.src}/props/CacheStale.props AddressesStaleCachingTest
+ * @run junit/othervm -Djava.security.properties=${test.src}/props/CacheStale.props AddressesStaleCachingTest
*/
public class AddressesStaleCachingTest {
@@ -64,20 +67,21 @@ public void testRefresh() throws Exception{
Thread.sleep(10000); // intentionally big delay > x2 stale property
// The refreshTime is expired, we will do the successful lookup.
Lookup second = doLookup(false, 0);
- Assert.assertNotEquals(first.timestamp, second.timestamp,
+ assertNotEquals(first.timestamp, second.timestamp,
"Two lookups are expected");
Thread.sleep(10000); // intentionally big delay > x2 stale property
// The refreshTime is expired again, we will do the failed lookup.
Lookup third = doLookup(true, 0);
- Assert.assertNotEquals(second.timestamp, third.timestamp,
+ assertNotEquals(second.timestamp, third.timestamp,
"Two lookups are expected");
// The stale cache is enabled, so we should get valid/same data for
// all requests(even for the failed request).
- Assert.assertEquals(first.address, second.address,
+ assertArrayEquals(first.address, second.address,
"Same address is expected");
- Assert.assertEquals(second.address, third.address,
+
+ assertArrayEquals(second.address, third.address,
"Same address is expected");
}
@@ -133,10 +137,10 @@ private static Lookup doLookup(boolean error, long timeout) {
byte[] secondAddress = InetAddress.getByName("javaTest.org").getAddress();
long secondTimestamp = SimpleResolverProviderImpl.getLastLookupTimestamp();
- Assert.assertEquals(firstAddress, secondAddress,
+ assertArrayEquals(firstAddress, secondAddress,
"Same address is expected");
if (timeout == 0 || timeout - System.nanoTime() > 0) {
- Assert.assertEquals(firstTimestamp, secondTimestamp,
+ assertEquals(firstTimestamp, secondTimestamp,
"Only one positive lookup is expected with caching enabled");
}
return new Lookup(firstAddress, firstTimestamp);
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/BootstrapResolverUsageTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/BootstrapResolverUsageTest.java
index 9f0902d2c1d..012410c1566 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/BootstrapResolverUsageTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/BootstrapResolverUsageTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,12 +21,13 @@
* questions.
*/
+import org.junit.jupiter.api.Test;
+
import java.net.InetAddress;
-import org.testng.Assert;
-import org.testng.annotations.Test;
import static impl.WithBootstrapResolverUsageProvider.numberOfGetCalls;
+import static org.junit.jupiter.api.Assertions.assertEquals;
/**
* @test
@@ -35,7 +36,7 @@
* InetAddressResolverProvider.get method uses InetAddress lookup API.
* @library providers/bootstrapUsage
* @build bootstrap.usage.provider/impl.WithBootstrapResolverUsageProvider
- * @run testng/othervm BootstrapResolverUsageTest
+ * @run junit/othervm BootstrapResolverUsageTest
*/
public class BootstrapResolverUsageTest {
@@ -43,7 +44,6 @@ public class BootstrapResolverUsageTest {
@Test
public void testSuccessfulProviderInstantiationTest() throws Exception {
System.err.println(InetAddress.getAllByName(InetAddress.getLocalHost().getHostName()));
- Assert.assertEquals(numberOfGetCalls, 1,
- "InetAddressResolverProvider.get was called more than once");
+ assertEquals(1, numberOfGetCalls, "InetAddressResolverProvider.get was called more than once");
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/BuiltInResolverTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/BuiltInResolverTest.java
index 8b8b866d7b2..e91446e540a 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/BuiltInResolverTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/BuiltInResolverTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,30 +21,34 @@
* questions.
*/
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import java.lang.reflect.Field;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.net.spi.InetAddressResolver;
-import static org.testng.Assert.*;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
/*
* @test
* @summary white-box test to check that the built-in resolver
* is used by default.
* @modules java.base/java.net:open
- * @run testng/othervm BuiltInResolverTest
+ * @run junit/othervm BuiltInResolverTest
*/
public class BuiltInResolverTest {
- private Field builtInResolverField, resolverField;
+ private static Field builtInResolverField, resolverField;
- @BeforeTest
- public void beforeTest() throws NoSuchFieldException {
+ @BeforeAll
+ public static void beforeTest() throws NoSuchFieldException {
Class inetAddressClass = InetAddress.class;
// Needs to happen for InetAddress.resolver to be initialized
try {
@@ -72,7 +76,7 @@ public void testDefaultNSContext() throws IllegalAccessException {
assertNotNull(defaultClassName, "defaultClassName not set");
assertNotNull(currentClassName, "currentClassName name not set");
- assertEquals(currentClassName, defaultClassName,
+ assertEquals(defaultClassName, currentClassName,
"BUILTIN_RESOLVER resolver was not used.");
System.err.println("Resolver used by default is the built-in resolver");
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/EmptyResultsStreamTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/EmptyResultsStreamTest.java
index 17b9aa5d011..db0f293b712 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/EmptyResultsStreamTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/EmptyResultsStreamTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,32 +21,36 @@
* questions.
*/
-import org.testng.Assert;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Arrays;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/*
* @test
* @summary checks that InetAddress forward lookup API throw UnknownHostException
* when resolver returns empty address stream.
* @library providers/empty
* @build empty.results.provider/impl.EmptyResultsProviderImpl
- * @run testng/othervm EmptyResultsStreamTest
+ * @run junit/othervm EmptyResultsStreamTest
*/
public class EmptyResultsStreamTest {
- @Test(expectedExceptions = UnknownHostException.class)
- public void getAllByNameTest() throws UnknownHostException {
- System.err.println("getAllByName unexpectedly completed: " +
- Arrays.deepToString(InetAddress.getAllByName("test1.org")));
+ @Test()
+ public void getAllByNameTest() {
+ assertThrows(UnknownHostException.class, () -> {
+ System.err.println("getAllByName unexpectedly completed: " +
+ Arrays.deepToString(InetAddress.getAllByName("test1.org")));
+ });
}
- @Test(expectedExceptions = UnknownHostException.class)
- public void getByNameTest() throws UnknownHostException {
- System.err.println("getByName unexpectedly completed: " +
- InetAddress.getByName("test2.org"));
+ @Test()
+ public void getByNameTest() {
+ assertThrows(UnknownHostException.class, () -> {
+ System.err.println("getByName unexpectedly completed: " +
+ InetAddress.getByName("test2.org"));
+ });
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/InetAddressUsageInGetProviderTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/InetAddressUsageInGetProviderTest.java
index dd52893c1e8..3458270960b 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/InetAddressUsageInGetProviderTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/InetAddressUsageInGetProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,8 +21,7 @@
* questions.
*/
-import org.testng.Assert;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Test;
import java.net.InetAddress;
@@ -32,7 +31,7 @@
* wouldn't cause stack overflow and will be successfully installed.
* @library providers/recursive
* @build recursive.init.provider/impl.InetAddressUsageInGetProviderImpl
- * @run testng/othervm InetAddressUsageInGetProviderTest
+ * @run junit/othervm InetAddressUsageInGetProviderTest
*/
public class InetAddressUsageInGetProviderTest {
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyMappingTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyMappingTest.java
index e845e2e0461..bbfa9f5555c 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyMappingTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyMappingTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -34,9 +34,10 @@
import jdk.test.lib.net.IPSupport;
import jdk.test.lib.NetworkConfiguration;
-import org.testng.annotations.Test;
-import org.testng.Assert;
-import org.testng.SkipException;
+import org.junit.jupiter.api.Test;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.abort;
/*
* @test
@@ -45,26 +46,26 @@
* @library lib providers/simple /test/lib
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
* jdk.test.lib.net.IPSupport LookupPolicyMappingTest
- * @run testng/othervm LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=true LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack=false LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv4Stack LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
- * @run testng/othervm -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
+ * @run junit/othervm LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=true -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=true LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=false -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack=false LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv4Stack LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv6Addresses=true LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv6Addresses=false LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv6Addresses=system LookupPolicyMappingTest
+ * @run junit/othervm -Djava.net.preferIPv6Addresses LookupPolicyMappingTest
*/
public class LookupPolicyMappingTest {
@@ -88,7 +89,7 @@ public void testSystemProperties() throws Exception {
String expectedResultsKey = calculateMapKey(preferIPv4Stack, preferIPv6Addresses);
int expectedCharacteristics = EXPECTED_RESULTS_MAP.get(expectedResultsKey);
- Assert.assertTrue(characteristicsMatch(
+ assertTrue(characteristicsMatch(
runtimeCharacteristics, expectedCharacteristics), "Unexpected LookupPolicy observed");
}
@@ -100,7 +101,7 @@ static void checkPlatformNetworkConfiguration() {
// If preferIPv4=true and no IPv4 - skip
if (IPSupport.preferIPv4Stack()) {
if (!IPSupport.hasIPv4()) {
- throw new SkipException("Skip tests - IPv4 support required");
+ abort("Skip tests - IPv4 support required");
}
return;
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyOfTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyOfTest.java
index 73e2581f5cd..09585322c83 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyOfTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/LookupPolicyOfTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,11 +25,11 @@
* @test
* @summary check if LookupPolicy.of correctly handles valid and illegal
* combinations of characteristics bit mask flags.
- * @run testng LookupPolicyOfTest
+ * @run junit LookupPolicyOfTest
*/
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
import java.net.spi.InetAddressResolver.LookupPolicy;
import java.util.List;
@@ -38,21 +38,23 @@
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV4_FIRST;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6;
import static java.net.spi.InetAddressResolver.LookupPolicy.IPV6_FIRST;
+import static org.junit.jupiter.api.Assertions.assertThrows;
public class LookupPolicyOfTest {
- @Test(dataProvider = "validCharacteristics")
+ @ParameterizedTest
+ @MethodSource("validCharacteristicValue")
public void testValidCharacteristicCombinations(List validCombination) {
LookupPolicy.of(bitFlagsToCharacteristicsValue(validCombination));
}
- @Test(dataProvider = "invalidCharacteristics", expectedExceptions = IllegalArgumentException.class)
- public void testInvalidCharacteristicCombinations(List invalidCombination) {
- LookupPolicy.of(bitFlagsToCharacteristicsValue(invalidCombination));
+ @ParameterizedTest
+ @MethodSource("illegalCharacteristicValue")
+ public void testInvalidCharacteristicCombination(List invalidCombination) {
+ assertThrows(IllegalArgumentException.class, () -> LookupPolicy.of(bitFlagsToCharacteristicsValue(invalidCombination)));
}
- @DataProvider(name = "validCharacteristics")
- public Object[][] validCharacteristicValue() {
+ public static Object[][] validCharacteristicValue() {
return new Object[][]{
{List.of(IPV4)},
{List.of(IPV4, IPV4_FIRST)},
@@ -68,8 +70,7 @@ public Object[][] validCharacteristicValue() {
};
}
- @DataProvider(name = "invalidCharacteristics")
- public Object[][] illegalCharacteristicValue() {
+ public static Object[][] illegalCharacteristicValue() {
return new Object[][]{
{List.of()},
{List.of(IPV4_FIRST)},
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/ProviderGetExceptionTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/ProviderGetExceptionTest.java
index fe5269c7b46..7df304bc235 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/ProviderGetExceptionTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/ProviderGetExceptionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,13 +21,15 @@
* questions.
*/
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.function.Executable;
import java.net.InetAddress;
import java.util.Arrays;
-import org.testng.Assert;
-import org.testng.annotations.Test;
-
import static impl.FaultyResolverProviderGetImpl.EXCEPTION_MESSAGE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
/*
* @test
@@ -35,7 +37,7 @@
* instantiate a resolver.
* @library providers/faulty
* @build faulty.provider/impl.FaultyResolverProviderGetImpl
- * @run testng/othervm ProviderGetExceptionTest
+ * @run junit/othervm ProviderGetExceptionTest
*/
public class ProviderGetExceptionTest {
@@ -54,10 +56,10 @@ public void getByAddressExceptionTest() {
callInetAddressAndCheckException(() -> InetAddress.getByAddress(address).getHostName());
}
- private void callInetAddressAndCheckException(Assert.ThrowingRunnable apiCall) {
- IllegalArgumentException iae = Assert.expectThrows(IllegalArgumentException.class, apiCall);
+ private void callInetAddressAndCheckException(Executable apiCall) {
+ IllegalArgumentException iae = assertThrows(IllegalArgumentException.class, apiCall);
System.out.println("Got exception of expected type:" + iae);
- Assert.assertNull(iae.getCause(), "cause is not null");
- Assert.assertEquals(iae.getMessage(), EXCEPTION_MESSAGE);
+ assertNull(iae.getCause(), "cause is not null");
+ assertEquals(EXCEPTION_MESSAGE, iae.getMessage());
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/ResolutionWithExceptionTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/ResolutionWithExceptionTest.java
index dd17c1d987c..ce68f8a8e6f 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/ResolutionWithExceptionTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/ResolutionWithExceptionTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -27,9 +27,11 @@
import impl.ThrowingLookupsProviderImpl;
import static impl.ThrowingLookupsProviderImpl.RUNTIME_EXCEPTION_MESSAGE;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.fail;
-import org.testng.Assert;
-import org.testng.annotations.Test;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
/*
* @test
@@ -37,7 +39,7 @@
* implementation throws RuntimeException during forward or reverse lookup.
* @library providers/throwing
* @build throwing.lookups.provider/impl.ThrowingLookupsProviderImpl
- * @run testng/othervm ResolutionWithExceptionTest
+ * @run junit/othervm ResolutionWithExceptionTest
*/
public class ResolutionWithExceptionTest {
@@ -68,7 +70,7 @@ public void getByAddressRuntimeException() throws UnknownHostException {
private void runGetByNameTest() {
// InetAddress.getByName() is expected to throw UnknownHostException in all cases
- UnknownHostException uhe = Assert.expectThrows(UnknownHostException.class,
+ UnknownHostException uhe = Assertions.assertThrows(UnknownHostException.class,
() -> InetAddress.getByName("doesnt.matter.com"));
// If provider is expected to throw RuntimeException - check that UnknownHostException
// is set as its cause
@@ -76,10 +78,10 @@ private void runGetByNameTest() {
Throwable cause = uhe.getCause();
if (cause instanceof RuntimeException re) {
// Check RuntimeException message
- Assert.assertEquals(re.getMessage(), RUNTIME_EXCEPTION_MESSAGE,
+ assertEquals(RUNTIME_EXCEPTION_MESSAGE, re.getMessage(),
"incorrect exception message");
} else {
- Assert.fail("UnknownHostException cause is not RuntimeException");
+ fail("UnknownHostException cause is not RuntimeException");
}
}
}
@@ -89,6 +91,6 @@ private void runGetByAddressTest() throws UnknownHostException {
// if there is an error during reverse lookup operation the literal IP
// address String will be returned.
String literalIP = InetAddress.getByAddress(new byte[]{1, 2, 3, 4}).getCanonicalHostName();
- Assert.assertEquals(literalIP, "1.2.3.4");
+ assertEquals("1.2.3.4", literalIP);
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/ReverseLookupDelegationTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/ReverseLookupDelegationTest.java
index 439521736db..d72a6b1fc0e 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/ReverseLookupDelegationTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/ReverseLookupDelegationTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,9 +21,9 @@
* questions.
*/
-import impl.DelegatingProviderImpl;
-import org.testng.Assert;
-import org.testng.annotations.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import org.junit.jupiter.api.Test;
import java.net.InetAddress;
import java.net.UnknownHostException;
@@ -37,7 +37,7 @@
* InetAddressResolver.
* @library providers/delegating
* @build delegating.provider/impl.DelegatingProviderImpl
- * @run testng/othervm ReverseLookupDelegationTest
+ * @run junit/othervm ReverseLookupDelegationTest
*/
public class ReverseLookupDelegationTest {
@@ -53,10 +53,10 @@ public void delegateHostNameLookupWithWrongByteArray() throws UnknownHostExcepti
// Check that originally supplied byte array was used to construct canonical host name after
// failed reverse lookup.
- Assert.assertEquals("1.2.3.4", canonicalHostName, "unexpected canonical hostname");
+ assertEquals("1.2.3.4", canonicalHostName, "unexpected canonical hostname");
// Check that on a provider side the IllegalArgumentException has been thrown by the built-in resolver
- Assert.assertTrue(lastReverseLookupThrowable instanceof IllegalArgumentException,
+ assertTrue(lastReverseLookupThrowable instanceof IllegalArgumentException,
"wrong exception type is thrown by the built-in resolver");
}
}
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/classpath/ClasspathProviderTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/classpath/ClasspathProviderTest.java
index 51285fb045c..c82f2442831 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/classpath/ClasspathProviderTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/classpath/ClasspathProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,18 +21,17 @@
* questions.
*/
-import java.net.InetAddress;
+import org.junit.jupiter.api.Test;
-import org.testng.annotations.Test;
+import java.net.InetAddress;
-import static org.testng.Assert.assertThrows;
/*
* @test
* @summary Test that InetAddressResolverProvider implementation can be installed to a class path.
* @library ../../lib
* @build test.library/testlib.ResolutionRegistry ClasspathResolverProviderImpl
- * @run testng/othervm ClasspathProviderTest
+ * @run junit/othervm ClasspathProviderTest
*/
public class ClasspathProviderTest {
diff --git a/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/module/ModularProviderTest.java b/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/module/ModularProviderTest.java
index 410f25aa9c3..56e52d52729 100644
--- a/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/module/ModularProviderTest.java
+++ b/test/jdk/java/net/spi/InetAddressResolverProvider/serviceProviderOriginType/module/ModularProviderTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2021, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -21,9 +21,10 @@
* questions.
*/
+import org.junit.jupiter.api.Test;
+
import java.net.InetAddress;
-import org.testng.annotations.Test;
/*
* @test
@@ -31,7 +32,7 @@
* @library ../../lib ../../providers/simple
* @build test.library/testlib.ResolutionRegistry simple.provider/impl.SimpleResolverProviderImpl
* ModularProviderTest
- * @run testng/othervm ModularProviderTest
+ * @run junit/othervm ModularProviderTest
*/
From e05eb1418e73b69c9c4571006a009bb1d3cf21ce Mon Sep 17 00:00:00 2001
From: Vicente Romero
Date: Thu, 2 Apr 2026 22:57:35 +0000
Subject: [PATCH 07/60] 8381475: Test
tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java fails for
DocSourcePositions.java
Reviewed-by: mikael
---
.../share/classes/com/sun/source/util/DocSourcePositions.java | 2 ++
.../share/classes/com/sun/source/util/SourcePositions.java | 2 ++
.../modules/jdk.compiler/JdkCompilerCheckSince.java | 2 +-
3 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java
index d0afd126bf6..4eb6d12fd38 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/DocSourcePositions.java
@@ -83,6 +83,7 @@ default long getStartPosition(CompilationUnitTree file, DocCommentTree comment,
* @param comment the comment tree that encloses the tree for which the
* position is being sought
* @param tree tree for which a position is sought
+ * @since 27
*/
long getStartPosition(DocCommentTree comment, DocTree tree);
@@ -146,6 +147,7 @@ default long getEndPosition(CompilationUnitTree file, DocCommentTree comment, Do
* @param comment the comment tree that encloses the tree for which the
* position is being sought
* @param tree tree for which a position is sought
+ * @since 27
*/
long getEndPosition(DocCommentTree comment, DocTree tree);
diff --git a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java
index 460f4f2a1ce..3ff6fafe58b 100644
--- a/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java
+++ b/src/jdk.compiler/share/classes/com/sun/source/util/SourcePositions.java
@@ -74,6 +74,7 @@ default long getStartPosition(CompilationUnitTree file, Tree tree) {
*
*
* @param tree tree for which a position is sought
+ * @since 27
*/
long getStartPosition(Tree tree);
@@ -130,6 +131,7 @@ default long getEndPosition(CompilationUnitTree file, Tree tree) {
*
*
* @param tree tree for which a position is sought
+ * @since 27
*/
long getEndPosition(Tree tree);
}
diff --git a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java
index 5eb819786e9..bf4b906b623 100644
--- a/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java
+++ b/test/jdk/tools/sincechecker/modules/jdk.compiler/JdkCompilerCheckSince.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8341399
+ * @bug 8341399 8381475
* @summary Test for `@since` in jdk.compiler module
* @library /test/lib /test/jdk/tools/sincechecker
* @run main SinceChecker jdk.compiler
From f1a414b61cab8bf839e3d6e4437ad4ef527c9aa3 Mon Sep 17 00:00:00 2001
From: Shiv Shah
Date: Fri, 3 Apr 2026 00:44:00 +0000
Subject: [PATCH 08/60] 8338594: Update nsk/aod tests to use driver instead of
othervm
Reviewed-by: lmesnik, cjplummer
---
.../AttachProvider/AttachProvider01/AttachProvider01.java | 5 ++---
.../VirtualMachine/VirtualMachine01/VirtualMachine01.java | 5 ++---
.../VirtualMachine/VirtualMachine04/VirtualMachine04.java | 5 ++---
.../VirtualMachine/VirtualMachine05/VirtualMachine05.java | 5 ++---
.../VirtualMachine/VirtualMachine06/VirtualMachine06.java | 5 ++---
.../VirtualMachine/VirtualMachine07/VirtualMachine07.java | 3 +--
.../VirtualMachine/VirtualMachine08/TestDescription.java | 3 +--
.../VirtualMachine/VirtualMachine09/VirtualMachine09.java | 3 +--
.../VirtualMachine/VirtualMachine10/TestDescription.java | 3 +--
.../VirtualMachineDescriptor01.java | 5 ++---
.../jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java | 7 ++++++-
11 files changed, 22 insertions(+), 27 deletions(-)
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java
index 7e3f7a9687d..dbe640a8719 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/AttachProvider/AttachProvider01/AttachProvider01.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,8 +36,7 @@
* @library /vmTestbase /test/hotspot/jtreg/vmTestbase
* /test/lib
* @build nsk.share.aod.DummyTargetApplication
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.AttachProvider.AttachProvider01.AttachProvider01
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java
index 257d4022d2b..3f171367361 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine01/VirtualMachine01.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,8 +40,7 @@
* @library /vmTestbase /test/hotspot/jtreg/vmTestbase
* /test/lib
* @build nsk.share.aod.DummyTargetApplication
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.VirtualMachine.VirtualMachine01.VirtualMachine01
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java
index 3bd98cd5043..066b2ef8a0f 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine04/VirtualMachine04.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,8 +39,7 @@
* @library /vmTestbase /test/hotspot/jtreg/vmTestbase
* /test/lib
* @build nsk.aod.VirtualMachine.VirtualMachine04.VM04Target
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.VirtualMachine.VirtualMachine04.VirtualMachine04
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java
index 3c7e90a7ffa..c8e7299fd39 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine05/VirtualMachine05.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -36,8 +36,7 @@
* @library /vmTestbase /test/hotspot/jtreg/vmTestbase
* /test/lib
* @build nsk.share.aod.DummyTargetApplication
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.VirtualMachine.VirtualMachine05.VirtualMachine05
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java
index 0fd11e6b8d5..f9bf43d2fe0 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine06/VirtualMachine06.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -76,8 +76,7 @@
*
*
* @build nsk.share.aod.TargetApplicationWaitingAgents
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.VirtualMachine.VirtualMachine06.VirtualMachine06
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java
index 73b4522ae6e..ab37e253fc8 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine07/VirtualMachine07.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -42,7 +42,6 @@
* /test/lib
* @build nsk.share.aod.TargetApplicationWaitingAgents
* @run main/othervm/native
- * -XX:+UsePerfData
* nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java
index e484641dd2a..14a05f53702 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine08/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -43,7 +43,6 @@
* /test/lib
* @build nsk.share.aod.TargetApplicationWaitingAgents
* @run main/othervm/native
- * -XX:+UsePerfData
* nsk.aod.VirtualMachine.VirtualMachine07.VirtualMachine07
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java
index 47d1a718e88..3b2852fc0ad 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine09/VirtualMachine09.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -39,7 +39,6 @@
* /test/lib
* @build nsk.aod.VirtualMachine.VirtualMachine09.VM09Target
* @run main/othervm/native
- * -XX:+UsePerfData
* nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09
* -jdk ${test.jdk}
* -javaOpts="-agentlib:VirtualMachine09agent00 -XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java
index c9c5b1ee64f..139fe236635 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachine/VirtualMachine10/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,7 +40,6 @@
* /test/lib
* @build nsk.aod.VirtualMachine.VirtualMachine09.VM09Target
* @run main/othervm/native
- * -XX:+UsePerfData
* nsk.aod.VirtualMachine.VirtualMachine09.VirtualMachine09
* -jdk ${test.jdk}
* -javaOpts="-agentlib:VirtualMachine09agent00 -XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java
index 47f837a110f..02448528f12 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/aod/VirtualMachineDescriptor/VirtualMachineDescriptor01/VirtualMachineDescriptor01.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2020, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -38,8 +38,7 @@
* @library /vmTestbase /test/hotspot/jtreg/vmTestbase
* /test/lib
* @build nsk.share.aod.DummyTargetApplication
- * @run main/othervm
- * -XX:+UsePerfData
+ * @run driver
* nsk.aod.VirtualMachineDescriptor.VirtualMachineDescriptor01.VirtualMachineDescriptor01
* -jdk ${test.jdk}
* -javaOpts="-XX:+UsePerfData ${test.vm.opts} ${test.java.opts}"
diff --git a/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
index 9899c762a7a..abfca89ca4d 100644
--- a/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
+++ b/test/hotspot/jtreg/vmTestbase/nsk/share/aod/AODTestRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2008, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2008, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -103,9 +103,14 @@ protected void runTest() {
/*
* Create target application id required by the Utils.findVMIdUsingJPS
*/
+ String classPath = System.getProperty("test.class.path");
+ if (classPath == null) {
+ throw new RuntimeException("test.class.path is not set");
+ }
String targetAppCmd =
// path to java
argParser.getTestedJDK() + File.separator + "bin" + File.separator + "java " +
+ "-classpath " + classPath + " " +
// VM property to identify VM running target application
"-D" + appIdProperty + "=" + targetAppId + " " +
// VM opts
From fbbf2c3af34411f108bf983e52faf8f63a224a31 Mon Sep 17 00:00:00 2001
From: Shiv Shah
Date: Fri, 3 Apr 2026 00:52:00 +0000
Subject: [PATCH 09/60] 8269613:
vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java fails
with OOME in CodeCache
Reviewed-by: lmesnik, epavlova
---
.../mlvm/mixed/stress/java/findDeadlock/TestDescription.java | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java b/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java
index ec2b2753340..ed186aa3f84 100644
--- a/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java
+++ b/test/hotspot/jtreg/vmTestbase/vm/mlvm/mixed/stress/java/findDeadlock/TestDescription.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2018, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -40,6 +40,8 @@
* @library /vmTestbase
* /test/lib
*
+ * @requires vm.compMode != "Xcomp"
+ *
* @comment build test class and indify classes
* @build vm.mlvm.mixed.stress.java.findDeadlock.INDIFY_Test
* @run driver vm.mlvm.share.IndifiedClassesBuilder
From 95e90299b47c3f82c8711ba8799810fbb01ab5df Mon Sep 17 00:00:00 2001
From: Ioi Lam
Date: Fri, 3 Apr 2026 03:20:38 +0000
Subject: [PATCH 10/60] 8381553: Clean up AOTCodeCache configuration checks
Reviewed-by: kvn, asmehra
---
src/hotspot/share/code/aotCodeCache.cpp | 382 ++++--------------
src/hotspot/share/code/aotCodeCache.hpp | 216 +++++-----
.../aotCode/AOTCodeCompressedOopsTest.java | 14 +-
.../JDKMethodHandlesTestRunner.java | 4 +-
4 files changed, 199 insertions(+), 417 deletions(-)
diff --git a/src/hotspot/share/code/aotCodeCache.cpp b/src/hotspot/share/code/aotCodeCache.cpp
index 938cf4eaa41..e3cbc3c3c8b 100644
--- a/src/hotspot/share/code/aotCodeCache.cpp
+++ b/src/hotspot/share/code/aotCodeCache.cpp
@@ -73,11 +73,23 @@ const char* aot_code_entry_kind_name[] = {
#undef DECL_KIND_STRING
};
+// Stream to printing AOTCodeCache loading failure.
+// Print to error channel when -XX:AOTMode is set to "on"
+static LogStream& load_failure_log() {
+ static LogStream err_stream(LogLevel::Error, LogTagSetMapping::tagset());
+ static LogStream dbg_stream(LogLevel::Debug, LogTagSetMapping::tagset());
+ if (RequireSharedSpaces) {
+ return err_stream;
+ } else {
+ return dbg_stream;
+ }
+}
+
static void report_load_failure() {
if (AbortVMOnAOTCodeFailure) {
vm_exit_during_initialization("Unable to use AOT Code Cache.", nullptr);
}
- log_info(aot, codecache, init)("Unable to use AOT Code Cache.");
+ load_failure_log().print_cr("Unable to use AOT Code Cache.");
AOTCodeCache::disable_caching();
}
@@ -86,7 +98,7 @@ static void report_store_failure() {
tty->print_cr("Unable to create AOT Code Cache.");
vm_abort(false);
}
- log_info(aot, codecache, exit)("Unable to create AOT Code Cache.");
+ log_error(aot, codecache, exit)("Unable to create AOT Code Cache.");
AOTCodeCache::disable_caching();
}
@@ -380,110 +392,27 @@ void AOTCodeCache::init_early_c1_table() {
}
}
-// macro to record which flags are set -- flag_type selects the
-// relevant accessor e.g. set_flag, set_x86_flag, set_x86_use_flag.
-// n.b. flag_enum_name and global_flag_name are both needed because we
-// don't have consistent conventions for naming global flags e.g.
-// EnableContended vs UseMulAddIntrinsic vs UseCRC32Intrinsics
+void AOTCodeCache::Config::record(uint cpu_features_offset) {
-#define RECORD_FLAG(flag_type, flag_enum_name, global_flag_name) \
- if (global_flag_name) { \
- set_ ## flag_type ## flag(flag_enum_name); \
- }
+#define AOTCODECACHE_SAVE_VAR(type, name) _saved_ ## name = name;
+#define AOTCODECACHE_SAVE_FUN(type, name, fun) _saved_ ## name = fun;
-void AOTCodeCache::Config::record(uint cpu_features_offset) {
- _flags = 0;
-#ifdef ASSERT
- set_flag(debugVM);
-#endif
- RECORD_FLAG(, compressedOops, UseCompressedOops);
- RECORD_FLAG(, useTLAB, UseTLAB);
- if (JavaAssertions::systemClassDefault()) {
- set_flag(systemClassAssertions);
- }
- if (JavaAssertions::userClassDefault()) {
- set_flag(userClassAssertions);
- }
- RECORD_FLAG(, enableContendedPadding, EnableContended);
- RECORD_FLAG(, restrictContendedPadding, RestrictContended);
+ AOTCODECACHE_CONFIGS_DO(AOTCODECACHE_SAVE_VAR, AOTCODECACHE_SAVE_FUN);
- _compressedOopShift = CompressedOops::shift();
+ // Special configs that cannot be checked with macros
_compressedOopBase = CompressedOops::base();
- _compressedKlassShift = CompressedKlassPointers::shift();
- _contendedPaddingWidth = ContendedPaddingWidth;
- _gc = (uint)Universe::heap()->kind();
- _optoLoopAlignment = (uint)OptoLoopAlignment;
- _codeEntryAlignment = (uint)CodeEntryAlignment;
- _allocatePrefetchLines = (uint)AllocatePrefetchLines;
- _allocateInstancePrefetchLines = (uint)AllocateInstancePrefetchLines;
- _allocatePrefetchDistance = (uint)AllocatePrefetchDistance;
- _allocatePrefetchStepSize = (uint)AllocatePrefetchStepSize;
- _use_intrinsics_flags = 0;
- RECORD_FLAG(use_, useCRC32, UseCRC32Intrinsics);
- RECORD_FLAG(use_, useCRC32C, UseCRC32CIntrinsics);
-#ifdef COMPILER2
- _maxVectorSize = (uint)MaxVectorSize;
- _arrayOperationPartialInlineSize = (uint)ArrayOperationPartialInlineSize;
- RECORD_FLAG(use_, useMultiplyToLen, UseMultiplyToLenIntrinsic);
- RECORD_FLAG(use_, useSquareToLen, UseSquareToLenIntrinsic);
- RECORD_FLAG(use_, useMulAdd, UseMulAddIntrinsic);
- RECORD_FLAG(use_, useMontgomeryMultiply, UseMontgomeryMultiplyIntrinsic);
- RECORD_FLAG(use_, useMontgomerySquare, UseMontgomerySquareIntrinsic);
-#endif // COMPILER2
- RECORD_FLAG(use_, useChaCha20, UseChaCha20Intrinsics);
- RECORD_FLAG(use_, useDilithium, UseDilithiumIntrinsics);
- RECORD_FLAG(use_, useKyber, UseKyberIntrinsics);
- RECORD_FLAG(use_, useBASE64, UseBASE64Intrinsics);
- RECORD_FLAG(use_, useAdler32, UseAdler32Intrinsics);
- RECORD_FLAG(use_, useAES, UseAESIntrinsics);
- RECORD_FLAG(use_, useAESCTR, UseAESCTRIntrinsics);
- RECORD_FLAG(use_, useGHASH, UseGHASHIntrinsics);
- RECORD_FLAG(use_, useMD5, UseMD5Intrinsics);
- RECORD_FLAG(use_, useSHA1, UseSHA1Intrinsics);
- RECORD_FLAG(use_, useSHA256, UseSHA256Intrinsics);
- RECORD_FLAG(use_, useSHA512, UseSHA512Intrinsics);
- RECORD_FLAG(use_, useSHA3, UseSHA3Intrinsics);
- RECORD_FLAG(use_, usePoly1305, UsePoly1305Intrinsics);
- RECORD_FLAG(use_, useVectorizedMismatch,UseVectorizedMismatchIntrinsic );
- RECORD_FLAG(use_, useSecondarySupersTable, UseSecondarySupersTable);
+
#if defined(X86) && !defined(ZERO)
- _avx3threshold = (uint)AVX3Threshold;
- _useAVX = (uint)UseAVX;
- _x86_flags = 0;
- RECORD_FLAG(x86_, x86_enableX86ECoreOpts, EnableX86ECoreOpts);
- RECORD_FLAG(x86_, x86_useUnalignedLoadStores, UseUnalignedLoadStores);
- RECORD_FLAG(x86_, x86_useAPX, UseAPX);
-
- _x86_use_intrinsics_flags = 0;
- RECORD_FLAG(x86_use_, x86_useLibm, UseLibmIntrinsic);
- RECORD_FLAG(x86_use_, x86_useIntPoly, UseIntPolyIntrinsics);
-#endif // defined(X86) && !defined(ZERO)
+ _useUnalignedLoadStores = UseUnalignedLoadStores;
+#endif
+
#if defined(AARCH64) && !defined(ZERO)
- _prefetchCopyIntervalInBytes = (uint)PrefetchCopyIntervalInBytes;
- _blockZeroingLowLimit = (uint)BlockZeroingLowLimit;
- _softwarePrefetchHintDistance = (uint)SoftwarePrefetchHintDistance;
- _useSVE = (uint)UseSVE;
- _aarch64_flags = 0;
- RECORD_FLAG(aarch64_, aarch64_avoidUnalignedAccesses, AvoidUnalignedAccesses);
- RECORD_FLAG(aarch64_, aarch64_useSIMDForMemoryOps, UseSIMDForMemoryOps);
- RECORD_FLAG(aarch64_, aarch64_useSIMDForArrayEquals, UseSIMDForArrayEquals);
- RECORD_FLAG(aarch64_, aarch64_useSIMDForSHA3, UseSIMDForSHA3Intrinsic);
- RECORD_FLAG(aarch64_, aarch64_useLSE, UseLSE);
-
- _aarch64_use_intrinsics_flags = 0;
- RECORD_FLAG(aarch64_use_, aarch64_useBlockZeroing, UseBlockZeroing);
- RECORD_FLAG(aarch64_use_, aarch64_useSIMDForBigIntegerShift, UseSIMDForBigIntegerShiftIntrinsics);
- RECORD_FLAG(aarch64_use_, aarch64_useSimpleArrayEquals, UseSimpleArrayEquals);
- RECORD_FLAG(aarch64_use_, aarch64_useSecondarySupersCache, UseSecondarySupersCache);
-#endif // defined(AARCH64) && !defined(ZERO)
-#if INCLUDE_JVMCI
- _enableJVMCI = (uint)EnableJVMCI;
+ _avoidUnalignedAccesses = AvoidUnalignedAccesses;
#endif
+
_cpu_features_offset = cpu_features_offset;
}
-#undef RECORD_FLAG
-
bool AOTCodeCache::Config::verify_cpu_features(AOTCodeCache* cache) const {
LogStreamHandle(Debug, aot, codecache, init) log;
uint offset = _cpu_features_offset;
@@ -511,271 +440,114 @@ bool AOTCodeCache::Config::verify_cpu_features(AOTCodeCache* cache) const {
}
}
} else {
- if (log.is_enabled()) {
+ if (load_failure_log().is_enabled()) {
ResourceMark rm; // required for stringStream::as_string()
stringStream ss;
char* runtime_cpu_features = NEW_RESOURCE_ARRAY(char, VM_Version::cpu_features_size());
VM_Version::store_cpu_features(runtime_cpu_features);
VM_Version::get_missing_features_name(cached_cpu_features_buffer, runtime_cpu_features, ss);
- log.print_cr("AOT Code Cache disabled: required cpu features are missing: %s", ss.as_string());
+ load_failure_log().print_cr("AOT Code Cache disabled: required cpu features are missing: %s", ss.as_string());
}
return false;
}
return true;
}
-// macro to do *standard* flag eq checks -- flag_type selects the
-// relevant accessor e.g. test_flag, test_x86_flag, test_x86_use_flag.
-// n.b. flag_enum_name and global_flag_name are both needed because we
-// don't have consistent conventions for naming global flags e.g.
-// EnableContended vs UseMulAddIntrinsic vs UseCRC32Intrinsics
+#define AOTCODECACHE_DISABLED_MSG "AOT Code Cache disabled: it was created with %s = "
-#define CHECK_FLAG(flag_type, flag_enum_name, global_flag_name) \
- if (test_ ## flag_type ## flag(flag_enum_name) != global_flag_name) { \
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with " # global_flag_name " = %s vs current %s" , (global_flag_name ? "false" : "true"), (global_flag_name ? "true" : "false")); \
- return false; \
- }
+// Special case, print "GC = ..." to be more understandable.
+inline void log_config_mismatch(CollectedHeap::Name saved, CollectedHeap::Name current, const char* name/*unused*/) {
+ load_failure_log().print_cr("AOT Code Cache disabled: it was created with GC = \"%s\" vs current \"%s\"",
+ GCConfig::hs_err_name(saved), GCConfig::hs_err_name(current));
+}
-bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const {
- // First checks affect all cached AOT code
-#ifdef ASSERT
- if (!test_flag(debugVM)) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created by product VM, it can't be used by debug VM");
- return false;
- }
-#else
- if (test_flag(debugVM)) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created by debug VM, it can't be used by product VM");
- return false;
- }
-#endif
+inline void log_config_mismatch(bool saved, bool current, const char* name) {
+ load_failure_log().print_cr(AOTCODECACHE_DISABLED_MSG "%s vs current %s", name,
+ saved ? "true" : "false", current ? "true" : "false");
+}
- CollectedHeap::Name aot_gc = (CollectedHeap::Name)_gc;
- if (aot_gc != Universe::heap()->kind()) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with different GC: %s vs current %s", GCConfig::hs_err_name(aot_gc), GCConfig::hs_err_name());
- return false;
- }
+inline void log_config_mismatch(int saved, int current, const char* name) {
+ load_failure_log().print_cr(AOTCODECACHE_DISABLED_MSG "%d vs current %d", name, saved, current);
+}
+
+inline void log_config_mismatch(uint saved, uint current, const char* name) {
+ load_failure_log().print_cr(AOTCODECACHE_DISABLED_MSG "%u vs current %u", name, saved, current);
+}
- if (_compressedKlassShift != (uint)CompressedKlassPointers::shift()) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CompressedKlassPointers::shift() = %d vs current %d", _compressedKlassShift, CompressedKlassPointers::shift());
+#ifdef _LP64
+inline void log_config_mismatch(intx saved, intx current, const char* name) {
+ load_failure_log().print_cr(AOTCODECACHE_DISABLED_MSG "%zd vs current %zd", name, saved, current);
+}
+
+inline void log_config_mismatch(uintx saved, uintx current, const char* name) {
+ load_failure_log().print_cr(AOTCODECACHE_DISABLED_MSG "%zu vs current %zu", name, saved, current);
+}
+#endif
+
+template
+bool check_config(T saved, T current, const char* name) {
+ if (saved != current) {
+ log_config_mismatch(saved, current, name);
return false;
+ } else {
+ return true;
}
+}
+bool AOTCodeCache::Config::verify(AOTCodeCache* cache) const {
// check CPU features before checking flags that may be
// auto-configured in response to them
if (!verify_cpu_features(cache)) {
return false;
}
- // change to EnableContended can affect validity of nmethods
- CHECK_FLAG(, enableContendedPadding, EnableContended);
- // change to RestrictContended can affect validity of nmethods
- CHECK_FLAG(, restrictContendedPadding, RestrictContended);
-
// Tests for config options which might affect validity of adapters,
// stubs or nmethods. Currently we take a pessemistic stand and
// drop the whole cache if any of these are changed.
- // change to opto alignment can affect performance of array copy
- // stubs and nmethods
- if (_optoLoopAlignment != (uint)OptoLoopAlignment) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with OptoLoopAlignment = %d vs current %d", (int)_optoLoopAlignment, (int)OptoLoopAlignment);
- return false;
- }
+#define AOTCODECACHE_CHECK_VAR(type, name) \
+ if (!check_config(_saved_ ## name, name, #name)) { return false; }
+#define AOTCODECACHE_CHECK_FUN(type, name, fun) \
+ if (!check_config(_saved_ ## name, fun, #fun)) { return false; }
- // change to CodeEntryAlignment can affect performance of array
- // copy stubs and nmethods
- if (_codeEntryAlignment != CodeEntryAlignment) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with CodeEntryAlignment = %d vs current %d", _codeEntryAlignment, CodeEntryAlignment);
- return false;
- }
+ AOTCODECACHE_CONFIGS_DO(AOTCODECACHE_CHECK_VAR, AOTCODECACHE_CHECK_FUN);
- // changing Prefetch configuration can affect validity of nmethods
- // and stubs
- if (_allocatePrefetchLines != (uint)AllocatePrefetchLines) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchLines, (int)AllocatePrefetchLines);
- return false;
- }
- if (_allocateInstancePrefetchLines != (uint)AllocateInstancePrefetchLines) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocateInstancePrefetchLines, (int)AllocateInstancePrefetchLines);
- return false;
- }
- if (_allocatePrefetchDistance != (uint)AllocatePrefetchDistance) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchDistance, (int)AllocatePrefetchDistance);
- return false;
- }
- if (_allocatePrefetchStepSize != (uint)AllocatePrefetchStepSize) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with = %d vs current %d", (int)_allocatePrefetchStepSize, (int)AllocatePrefetchStepSize);
- return false;
- }
-
- // check intrinsic use settings are compatible
+ // Special configs that cannot be checked with macros
- CHECK_FLAG(use_, useCRC32, UseCRC32Intrinsics);
- CHECK_FLAG(use_, useCRC32C, UseCRC32CIntrinsics);
-
-#ifdef COMPILER2
- // change to MaxVectorSize can affect validity of array copy/fill
- // stubs
- if (_maxVectorSize != (uint)MaxVectorSize) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with MaxVectorSize = %d vs current %d", (int)_maxVectorSize, (int)MaxVectorSize);
+ if ((_compressedOopBase == nullptr || CompressedOops::base() == nullptr) && (_compressedOopBase != CompressedOops::base())) {
+ load_failure_log().print_cr("AOT Code Cache disabled: incompatible CompressedOops::base(): %p vs current %p",
+ _compressedOopBase, CompressedOops::base());
return false;
}
- // changing ArrayOperationPartialInlineSize can affect validity of
- // nmethods and stubs
- if (_arrayOperationPartialInlineSize != (uint)ArrayOperationPartialInlineSize) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with ArrayOperationPartialInlineSize = %d vs current %d", (int)_arrayOperationPartialInlineSize, (int)ArrayOperationPartialInlineSize);
- return false;
- }
- CHECK_FLAG(use_, useMultiplyToLen, UseMultiplyToLenIntrinsic);
- CHECK_FLAG(use_, useSquareToLen, UseSquareToLenIntrinsic);
- CHECK_FLAG(use_, useMulAdd, UseMulAddIntrinsic);
- CHECK_FLAG(use_, useMontgomeryMultiply,UseMontgomeryMultiplyIntrinsic);
- CHECK_FLAG(use_, useMontgomerySquare, UseMontgomerySquareIntrinsic);
-#endif // COMPILER2
- CHECK_FLAG(use_, useChaCha20, UseChaCha20Intrinsics);
- CHECK_FLAG(use_, useDilithium, UseDilithiumIntrinsics);
- CHECK_FLAG(use_, useKyber, UseKyberIntrinsics);
- CHECK_FLAG(use_, useBASE64, UseBASE64Intrinsics);
- CHECK_FLAG(use_, useAES, UseAESIntrinsics);
- CHECK_FLAG(use_, useAESCTR, UseAESCTRIntrinsics);
- CHECK_FLAG(use_, useGHASH, UseGHASHIntrinsics);
- CHECK_FLAG(use_, useMD5, UseMD5Intrinsics);
- CHECK_FLAG(use_, useSHA1, UseSHA1Intrinsics);
- CHECK_FLAG(use_, useSHA256, UseSHA256Intrinsics);
- CHECK_FLAG(use_, useSHA512, UseSHA512Intrinsics);
- CHECK_FLAG(use_, useSHA3, UseSHA3Intrinsics);
- CHECK_FLAG(use_, usePoly1305, UsePoly1305Intrinsics);
- CHECK_FLAG(use_, useVectorizedMismatch, UseVectorizedMismatchIntrinsic);
- CHECK_FLAG(use_, useSecondarySupersTable, UseSecondarySupersTable);
-
#if defined(X86) && !defined(ZERO)
- // change to AVX3Threshold may affect validity of array copy stubs
- // and nmethods
- if (_avx3threshold != (uint)AVX3Threshold) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with AVX3Threshold = %d vs current %d", (int)_avx3threshold, AVX3Threshold);
- return false;
- }
-
- // change to UseAVX may affect validity of array copy stubs and
- // nmethods
- if (_useAVX != (uint)UseAVX) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with useAVX = %d vs current %d", (int)_useAVX, UseAVX);
- return false;
- }
-
- // change to EnableX86ECoreOpts may affect validity of nmethods
- CHECK_FLAG(x86_, x86_enableX86ECoreOpts, EnableX86ECoreOpts);
-
// switching off UseUnalignedLoadStores can affect validity of fill
// stubs
- if (test_x86_flag(x86_useUnalignedLoadStores) && !UseUnalignedLoadStores) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseUnalignedLoadStores = true vs current = false");
+ if (_useUnalignedLoadStores && !UseUnalignedLoadStores) {
+ log_config_mismatch(_useUnalignedLoadStores, UseUnalignedLoadStores, "UseUnalignedLoadStores");
return false;
}
-
- // change to UseAPX can affect validity of nmethods and stubs
- CHECK_FLAG(x86_, x86_useAPX, UseAPX);
-
- // check x86-specific intrinsic use settings are compatible
-
- CHECK_FLAG(x86_use_, x86_useLibm, UseLibmIntrinsic);
- CHECK_FLAG(x86_use_, x86_useIntPoly, UseIntPolyIntrinsics);
#endif // defined(X86) && !defined(ZERO)
#if defined(AARCH64) && !defined(ZERO)
- // change to PrefetchCopyIntervalInBytes may affect validity of
- // array copy stubs
- if (_prefetchCopyIntervalInBytes != (uint)PrefetchCopyIntervalInBytes) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with PrefetchCopyIntervalInBytes = %d vs current %d", (int)_prefetchCopyIntervalInBytes, (int)PrefetchCopyIntervalInBytes);
- return false;
- }
-
- // change to BlockZeroingLowLimit may affect validity of array fill
- // stubs
- if (_blockZeroingLowLimit != (uint)BlockZeroingLowLimit) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with BlockZeroingLowLimit = %d vs current %d", (int)_blockZeroingLowLimit, (int)BlockZeroingLowLimit);
- return false;
- }
-
- // change to SoftwarePrefetchHintDistance may affect validity of array fill
- // stubs
- if (_softwarePrefetchHintDistance != (uint)SoftwarePrefetchHintDistance) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with SoftwarePrefetchHintDistance = %d vs current %d", (int)_softwarePrefetchHintDistance, (int)SoftwarePrefetchHintDistance);
- return false;
- }
-
- // change to UseSVE may affect validity of stubs and nmethods
- if (_useSVE != (uint)UseSVE) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseSVE = %d vs current %d",(int)_useSVE, UseSVE);
- return false;
- }
-
// switching on AvoidUnalignedAccesses may affect validity of array
// copy stubs and nmethods
- if (!test_aarch64_flag(aarch64_avoidUnalignedAccesses) && AvoidUnalignedAccesses) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with AvoidUnalignedAccesses = false vs current = true");
+ if (!_avoidUnalignedAccesses && AvoidUnalignedAccesses) {
+ log_config_mismatch(_avoidUnalignedAccesses, AvoidUnalignedAccesses, "AvoidUnalignedAccesses");
return false;
}
-
- // change to UseSIMDForMemoryOps may affect validity of array
- // copy stubs and nmethods
- CHECK_FLAG(aarch64_, aarch64_useSIMDForMemoryOps, UseSIMDForMemoryOps);
- // change to UseSIMDForArrayEquals may affect validity of array
- // copy stubs and nmethods
- CHECK_FLAG(aarch64_, aarch64_useSIMDForArrayEquals, UseSIMDForArrayEquals);
- // change to useSIMDForSHA3 may affect validity of SHA3 stubs
- CHECK_FLAG(aarch64_, aarch64_useSIMDForSHA3, UseSIMDForSHA3Intrinsic);
- // change to UseLSE may affect validity of stubs and nmethods
- CHECK_FLAG(aarch64_, aarch64_useLSE, UseLSE);
-
- // check aarch64-specific intrinsic use settings are compatible
-
- CHECK_FLAG(aarch64_use_, aarch64_useBlockZeroing, UseBlockZeroing);
- CHECK_FLAG(aarch64_use_, aarch64_useSIMDForBigIntegerShift, UseSIMDForBigIntegerShiftIntrinsics);
- CHECK_FLAG(aarch64_use_, aarch64_useSimpleArrayEquals, UseSimpleArrayEquals);
- CHECK_FLAG(aarch64_use_, aarch64_useSecondarySupersCache, UseSecondarySupersCache);
#endif // defined(AARCH64) && !defined(ZERO)
-#if INCLUDE_JVMCI
- // change to EnableJVMCI will affect validity of adapters and
- // nmethods
- if (_enableJVMCI != (uint)EnableJVMCI) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with EnableJVMCI = %s vs current %s", (_enableJVMCI ? "true" : "false"), (EnableJVMCI ? "true" : "false"));
- return false;
- }
-#endif // INCLUDE_JVMCI
-
- // The following checks do not affect AOT adapters caching
-
- if (test_flag(compressedOops) != UseCompressedOops) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with UseCompressedOops = %s", UseCompressedOops ? "false" : "true");
- AOTStubCaching = false;
- }
- if (_compressedOopShift != (uint)CompressedOops::shift()) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: it was created with different CompressedOops::shift(): %d vs current %d", _compressedOopShift, CompressedOops::shift());
- AOTStubCaching = false;
- }
-
- // This should be the last check as it only disables AOTStubCaching
- if ((_compressedOopBase == nullptr || CompressedOops::base() == nullptr) && (_compressedOopBase != CompressedOops::base())) {
- log_debug(aot, codecache, init)("AOTStubCaching is disabled: incompatible CompressedOops::base(): %p vs current %p", _compressedOopBase, CompressedOops::base());
- AOTStubCaching = false;
- }
-
return true;
}
-#undef TEST_FLAG
-
bool AOTCodeCache::Header::verify(uint load_size) const {
if (_version != AOT_CODE_VERSION) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: different AOT Code version %d vs %d recorded in AOT Code header", AOT_CODE_VERSION, _version);
+ load_failure_log().print_cr("AOT Code Cache disabled: different AOT Code version %d vs %d recorded in AOT Code header", AOT_CODE_VERSION, _version);
return false;
}
if (load_size < _cache_size) {
- log_debug(aot, codecache, init)("AOT Code Cache disabled: AOT Code Cache size %d < %d recorded in AOT Code header", load_size, _cache_size);
+ load_failure_log().print_cr("AOT Code Cache disabled: AOT Code Cache size %d < %d recorded in AOT Code header", load_size, _cache_size);
return false;
}
return true;
diff --git a/src/hotspot/share/code/aotCodeCache.hpp b/src/hotspot/share/code/aotCodeCache.hpp
index 52b0adfba48..179f131c639 100644
--- a/src/hotspot/share/code/aotCodeCache.hpp
+++ b/src/hotspot/share/code/aotCodeCache.hpp
@@ -25,6 +25,7 @@
#ifndef SHARE_CODE_AOTCODECACHE_HPP
#define SHARE_CODE_AOTCODECACHE_HPP
+#include "gc/shared/collectedHeap.hpp"
#include "gc/shared/gc_globals.hpp"
#include "runtime/stubInfo.hpp"
@@ -163,120 +164,123 @@ class AOTCodeAddressTable : public CHeapObj {
address address_for_id(int id);
};
+#define AOTCODECACHE_CONFIGS_GENERIC_DO(do_var, do_fun) \
+ do_var(int, AllocateInstancePrefetchLines) /* stubs and nmethods */ \
+ do_var(int, AllocatePrefetchDistance) /* stubs and nmethods */ \
+ do_var(int, AllocatePrefetchLines) /* stubs and nmethods */ \
+ do_var(int, AllocatePrefetchStepSize) /* stubs and nmethods */ \
+ do_var(uint, CodeEntryAlignment) /* array copy stubs and nmethods */ \
+ do_var(bool, UseCompressedOops) /* stubs and nmethods */ \
+ do_var(bool, EnableContended) /* nmethods */ \
+ do_var(intx, OptoLoopAlignment) /* array copy stubs and nmethods */ \
+ do_var(bool, RestrictContended) /* nmethods */ \
+ do_var(bool, UseAESCTRIntrinsics) \
+ do_var(bool, UseAESIntrinsics) \
+ do_var(bool, UseBASE64Intrinsics) \
+ do_var(bool, UseChaCha20Intrinsics) \
+ do_var(bool, UseCRC32CIntrinsics) \
+ do_var(bool, UseCRC32Intrinsics) \
+ do_var(bool, UseDilithiumIntrinsics) \
+ do_var(bool, UseGHASHIntrinsics) \
+ do_var(bool, UseKyberIntrinsics) \
+ do_var(bool, UseMD5Intrinsics) \
+ do_var(bool, UsePoly1305Intrinsics) \
+ do_var(bool, UseSecondarySupersTable) \
+ do_var(bool, UseSHA1Intrinsics) \
+ do_var(bool, UseSHA256Intrinsics) \
+ do_var(bool, UseSHA3Intrinsics) \
+ do_var(bool, UseSHA512Intrinsics) \
+ do_var(bool, UseVectorizedMismatchIntrinsic) \
+ do_fun(int, CompressedKlassPointers_shift, CompressedKlassPointers::shift()) \
+ do_fun(int, CompressedOops_shift, CompressedOops::shift()) \
+ do_fun(bool, JavaAssertions_systemClassDefault, JavaAssertions::systemClassDefault()) \
+ do_fun(bool, JavaAssertions_userClassDefault, JavaAssertions::userClassDefault()) \
+ do_fun(CollectedHeap::Name, Universe_heap_kind, Universe::heap()->kind()) \
+ // END
+
+#ifdef COMPILER2
+#define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
+ do_var(intx, ArrayOperationPartialInlineSize) /* array copy stubs and nmethods */ \
+ do_var(intx, MaxVectorSize) /* array copy/fill stubs */ \
+ do_var(bool, UseMontgomeryMultiplyIntrinsic) \
+ do_var(bool, UseMontgomerySquareIntrinsic) \
+ do_var(bool, UseMulAddIntrinsic) \
+ do_var(bool, UseMultiplyToLenIntrinsic) \
+ do_var(bool, UseSquareToLenIntrinsic) \
+ // END
+#else
+#define AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun)
+#endif
+
+#if INCLUDE_JVMCI
+#define AOTCODECACHE_CONFIGS_JVMCI_DO(do_var, do_fun) \
+ do_var(bool, EnableJVMCI) /* adapters and nmethods */ \
+ // END
+#else
+#define AOTCODECACHE_CONFIGS_JVMCI_DO(do_var, do_fun)
+#endif
+
+#if defined(AARCH64) && !defined(ZERO)
+#define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
+ do_var(intx, BlockZeroingLowLimit) /* array fill stubs */ \
+ do_var(intx, PrefetchCopyIntervalInBytes) /* array copy stubs */ \
+ do_var(int, SoftwarePrefetchHintDistance) /* array fill stubs */ \
+ do_var(bool, UseBlockZeroing) \
+ do_var(bool, UseLSE) /* stubs and nmethods */ \
+ do_var(uint, UseSVE) /* stubs and nmethods */ \
+ do_var(bool, UseSecondarySupersCache) \
+ do_var(bool, UseSIMDForArrayEquals) /* array copy stubs and nmethods */ \
+ do_var(bool, UseSIMDForBigIntegerShiftIntrinsics) \
+ do_var(bool, UseSIMDForMemoryOps) /* array copy stubs and nmethods */ \
+ do_var(bool, UseSIMDForSHA3Intrinsic) /* SHA3 stubs */ \
+ do_var(bool, UseSimpleArrayEquals) \
+ // END
+#else
+#define AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun)
+#endif
+
+#if defined(X86) && !defined(ZERO)
+#define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
+ do_var(int, AVX3Threshold) /* array copy stubs and nmethods */ \
+ do_var(bool, EnableX86ECoreOpts) /* nmethods */ \
+ do_var(int, UseAVX) /* array copy stubs and nmethods */ \
+ do_var(bool, UseAPX) /* nmethods and stubs */ \
+ do_var(bool, UseLibmIntrinsic) \
+ do_var(bool, UseIntPolyIntrinsics) \
+ // END
+#else
+#define AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun)
+#endif
+
+#define AOTCODECACHE_CONFIGS_DO(do_var, do_fun) \
+ AOTCODECACHE_CONFIGS_GENERIC_DO(do_var, do_fun) \
+ AOTCODECACHE_CONFIGS_COMPILER2_DO(do_var, do_fun) \
+ AOTCODECACHE_CONFIGS_JVMCI_DO(do_var, do_fun) \
+ AOTCODECACHE_CONFIGS_AARCH64_DO(do_var, do_fun) \
+ AOTCODECACHE_CONFIGS_X86_DO(do_var, do_fun) \
+ // END
+
+#define AOTCODECACHE_DECLARE_VAR(type, name) type _saved_ ## name;
+#define AOTCODECACHE_DECLARE_FUN(type, name, func) type _saved_ ## name;
+
class AOTCodeCache : public CHeapObj {
// Classes used to describe AOT code cache.
protected:
class Config {
+ AOTCODECACHE_CONFIGS_DO(AOTCODECACHE_DECLARE_VAR, AOTCODECACHE_DECLARE_FUN)
+
+ // Special configs that cannot be checked with macros
address _compressedOopBase;
- uint _compressedOopShift;
- uint _compressedKlassShift;
- uint _contendedPaddingWidth;
- uint _gc;
- uint _optoLoopAlignment;
- uint _codeEntryAlignment;
- uint _allocatePrefetchLines;
- uint _allocateInstancePrefetchLines;
- uint _allocatePrefetchDistance;
- uint _allocatePrefetchStepSize;
-#ifdef COMPILER2
- uint _maxVectorSize;
- uint _arrayOperationPartialInlineSize;
-#endif // COMPILER2
- enum Flags {
- none = 0,
- debugVM = 1,
- compressedOops = 2,
- useTLAB = 4,
- systemClassAssertions = 8,
- userClassAssertions = 16,
- enableContendedPadding = 32,
- restrictContendedPadding = 64
- };
- uint _flags;
- enum IntrinsicsUseFlags {
- use_none = 0,
- useCRC32 = 1 << 0,
- useCRC32C = 1 << 1,
- useMultiplyToLen = 1 << 2,
- useSquareToLen = 1 << 3,
- useMulAdd = 1 << 4,
- useMontgomeryMultiply = 1 << 5,
- useMontgomerySquare = 1 << 6,
- useChaCha20 = 1 << 7,
- useDilithium = 1 << 8,
- useKyber = 1 << 9,
- useBASE64 = 1 << 10,
- useAdler32 = 1 << 11,
- useAES = 1 << 12,
- useAESCTR = 1 << 13,
- useGHASH = 1 << 14,
- useMD5 = 1 << 15,
- useSHA1 = 1 << 16,
- useSHA256 = 1 << 17,
- useSHA512 = 1 << 18,
- useSHA3 = 1 << 19,
- usePoly1305 = 1 << 20,
- useVectorizedMismatch = 1 << 21,
- useSecondarySupersTable = 1 << 22,
- };
- uint _use_intrinsics_flags;
- bool test_flag(enum Flags flag) const { return (_flags & flag) != 0; }
- bool test_use_flag(enum IntrinsicsUseFlags flag) const { return (_use_intrinsics_flags & flag) != 0; }
- void set_flag(enum Flags flag) { _flags |= flag; }
- void set_use_flag(enum IntrinsicsUseFlags flag) { _use_intrinsics_flags |= flag; }
+
#if defined(X86) && !defined(ZERO)
- uint _avx3threshold;
- uint _useAVX;
- enum X86Flags {
- x86_none = 0,
- x86_enableX86ECoreOpts = 1,
- x86_useUnalignedLoadStores = 2,
- x86_useAPX = 4
- };
- uint _x86_flags;
- enum X86IntrinsicsUseFlags {
- x86_use_none = 0,
- x86_useLibm = 1 << 1,
- x86_useIntPoly = 1 << 2,
- };
- uint _x86_use_intrinsics_flags;
- bool test_x86_flag(enum X86Flags flag) const { return (_x86_flags & flag) != 0; }
- bool test_x86_use_flag(enum X86IntrinsicsUseFlags flag) const { return (_x86_use_intrinsics_flags & flag) != 0; }
- void set_x86_flag(enum X86Flags flag) { _x86_flags |= flag; }
- void set_x86_use_flag(enum X86IntrinsicsUseFlags flag) { _x86_use_intrinsics_flags |= flag; }
-#endif // defined(X86) && !defined(ZERO)
+ bool _useUnalignedLoadStores;
+#endif
+
#if defined(AARCH64) && !defined(ZERO)
- // this is global but x86 does not use it and aarch64 does
- uint _prefetchCopyIntervalInBytes;
- uint _blockZeroingLowLimit;
- uint _softwarePrefetchHintDistance;
- uint _useSVE;
- enum AArch64Flags {
- aarch64_none = 0,
- aarch64_avoidUnalignedAccesses = 1,
- aarch64_useSIMDForMemoryOps = 2,
- aarch64_useSIMDForArrayEquals = 4,
- aarch64_useSIMDForSHA3 = 8,
- aarch64_useLSE = 16,
- };
- uint _aarch64_flags;
- enum AArch64IntrinsicsUseFlags {
- aarch64_use_none = 0,
- aarch64_useBlockZeroing = 1 << 0,
- aarch64_useSIMDForBigIntegerShift = 1 << 1,
- aarch64_useSimpleArrayEquals = 1 << 2,
- aarch64_useSecondarySupersCache = 1 << 3,
- };
- uint _aarch64_use_intrinsics_flags;
- bool test_aarch64_flag(enum AArch64Flags flag) const { return (_aarch64_flags & flag) != 0; }
- bool test_aarch64_use_flag(enum AArch64IntrinsicsUseFlags flag) const { return (_aarch64_use_intrinsics_flags & flag) != 0; }
- void set_aarch64_flag(enum AArch64Flags flag) { _aarch64_flags |= flag; }
- void set_aarch64_use_flag(enum AArch64IntrinsicsUseFlags flag) { _aarch64_use_intrinsics_flags |= flag; }
-#endif // defined(AARCH64) && !defined(ZERO)
-#if INCLUDE_JVMCI
- uint _enableJVMCI;
-#endif // INCLUDE_JVMCI
+ bool _avoidUnalignedAccesses;
+#endif
+
uint _cpu_features_offset; // offset in the cache where cpu features are stored
public:
void record(uint cpu_features_offset);
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java
index 09290960d2f..3b9458c14da 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCode/AOTCodeCompressedOopsTest.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -201,12 +201,18 @@ public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception
if (aotCacheShift == -1 || currentShift == -1 || aotCacheBase == -1 || currentBase == -1) {
throw new RuntimeException("Failed to find CompressedOops settings");
}
+
+ // Changes in compressed oop encoding could randomly affect flags like AllocatePrefetchDistance
+ // due to the OS-assigned range of the Java heap. If that happens, the exact error message may vary
+ String disabledMsg = "AOT Code Cache disabled:";
if (aotCacheShift != currentShift) {
- out.shouldContain("AOT Code Cache disabled: it was created with different CompressedOops::shift()");
+ out.shouldContain(disabledMsg);
} else if ((aotCacheBase == 0 || currentBase == 0) && (aotCacheBase != currentBase)) {
- out.shouldContain("AOTStubCaching is disabled: incompatible CompressedOops::base()");
+ out.shouldContain(disabledMsg);
} else {
- out.shouldMatch("Read \\d+ entries table at offset \\d+ from AOT Code Cache");
+ if (!out.contains(disabledMsg)) {
+ out.shouldMatch("Read \\d+ entries table at offset \\d+ from AOT Code Cache");
+ }
}
}
}
diff --git a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/JDKMethodHandlesTestRunner.java b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/JDKMethodHandlesTestRunner.java
index 19ab392c036..d9e1b15602c 100644
--- a/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/JDKMethodHandlesTestRunner.java
+++ b/test/hotspot/jtreg/runtime/cds/appcds/methodHandles/JDKMethodHandlesTestRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -91,7 +91,7 @@ public String[] appCommandLine(RunMode runMode) {
public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception {
out.shouldHaveExitValue(0);
if (runMode.isProductionRun()) {
- out.shouldMatch(".class.load. test.java.lang.invoke." + testClassName +
+ out.shouldMatch(".class.load.* test.java.lang.invoke." + testClassName +
"[$][$]Lambda.*/0x.*source:.*shared.*objects.*file");
}
}
From 4253db22526da9997f3b0140995cac09c41aeb22 Mon Sep 17 00:00:00 2001
From: Dean Long
Date: Fri, 3 Apr 2026 04:08:21 +0000
Subject: [PATCH 11/60] 8350208: CTW: GraphKit::add_safepoint_edges asserts
"not enough operands for reexecution"
Co-authored-by: Quan Anh Mai
Reviewed-by: mhaessig, vlivanov
---
src/hotspot/share/opto/doCall.cpp | 15 +--
src/hotspot/share/opto/parse.hpp | 6 +-
src/hotspot/share/opto/parse1.cpp | 11 +-
.../TestDebugDuringExceptionCatching.java | 126 ++++++++++++++++++
.../lang/invoke/lib/InstructionHelper.java | 25 +++-
5 files changed, 166 insertions(+), 17 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java
diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp
index e4418631d17..9a1da726f00 100644
--- a/src/hotspot/share/opto/doCall.cpp
+++ b/src/hotspot/share/opto/doCall.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1998, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -37,6 +37,7 @@
#include "opto/callGenerator.hpp"
#include "opto/castnode.hpp"
#include "opto/cfgnode.hpp"
+#include "opto/graphKit.hpp"
#include "opto/mulnode.hpp"
#include "opto/parse.hpp"
#include "opto/rootnode.hpp"
@@ -909,8 +910,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) {
if (handler_bci < 0) { // merge with corresponding rethrow node
throw_to_exit(make_exception_state(ex_oop));
} else { // Else jump to corresponding handle
- push_ex_oop(ex_oop); // Clear stack and push just the oop.
- merge_exception(handler_bci);
+ push_and_merge_exception(handler_bci, ex_oop);
}
}
@@ -1008,13 +1008,10 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
int handler_bci = handler->handler_bci();
if (remaining == 1) {
- push_ex_oop(ex_node); // Push exception oop for handler
if (PrintOpto && WizardMode) {
tty->print_cr(" Catching every inline exception bci:%d -> handler_bci:%d", bci(), handler_bci);
}
- // If this is a backwards branch in the bytecodes, add safepoint
- maybe_add_safepoint(handler_bci);
- merge_exception(handler_bci); // jump to handler
+ push_and_merge_exception(handler_bci, ex_node); // jump to handler
return; // No more handling to be done here!
}
@@ -1039,15 +1036,13 @@ void Parse::catch_inline_exceptions(SafePointNode* ex_map) {
const TypeInstPtr* tinst = TypeOopPtr::make_from_klass_unique(klass)->cast_to_ptr_type(TypePtr::NotNull)->is_instptr();
assert(klass->has_subklass() || tinst->klass_is_exact(), "lost exactness");
Node* ex_oop = _gvn.transform(new CheckCastPPNode(control(), ex_node, tinst));
- push_ex_oop(ex_oop); // Push exception oop for handler
if (PrintOpto && WizardMode) {
tty->print(" Catching inline exception bci:%d -> handler_bci:%d -- ", bci(), handler_bci);
klass->print_name();
tty->cr();
}
// If this is a backwards branch in the bytecodes, add safepoint
- maybe_add_safepoint(handler_bci);
- merge_exception(handler_bci);
+ push_and_merge_exception(handler_bci, ex_oop);
}
set_control(not_subtype_ctrl);
diff --git a/src/hotspot/share/opto/parse.hpp b/src/hotspot/share/opto/parse.hpp
index 397a7796f88..42f44f0f7ea 100644
--- a/src/hotspot/share/opto/parse.hpp
+++ b/src/hotspot/share/opto/parse.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -474,8 +474,8 @@ class Parse : public GraphKit {
void merge( int target_bci);
// Same as plain merge, except that it allocates a new path number.
void merge_new_path( int target_bci);
- // Merge the current mapping into an exception handler.
- void merge_exception(int target_bci);
+ // Push the exception oop and merge the current mapping into an exception handler.
+ void push_and_merge_exception(int target_bci, Node* ex_oop);
// Helper: Merge the current mapping into the given basic block
void merge_common(Block* target, int pnum);
// Helper functions for merging individual cells.
diff --git a/src/hotspot/share/opto/parse1.cpp b/src/hotspot/share/opto/parse1.cpp
index 647e8515b30..683633f6355 100644
--- a/src/hotspot/share/opto/parse1.cpp
+++ b/src/hotspot/share/opto/parse1.cpp
@@ -1651,9 +1651,14 @@ void Parse::merge_new_path(int target_bci) {
}
//-------------------------merge_exception-------------------------------------
-// Merge the current mapping into the basic block starting at bci
-// The ex_oop must be pushed on the stack, unlike throw_to_exit.
-void Parse::merge_exception(int target_bci) {
+// Push the given ex_oop onto the stack, then merge the current mapping into
+// the basic block starting at target_bci.
+void Parse::push_and_merge_exception(int target_bci, Node* ex_oop) {
+ // Add the safepoint before trimming the stack and pushing the exception oop.
+ // We could add the safepoint after, but then the bci would also need to be
+ // advanced to target_bci first, so the stack state matches.
+ maybe_add_safepoint(target_bci);
+ push_ex_oop(ex_oop); // Push exception oop for handler
#ifdef ASSERT
if (target_bci <= bci()) {
C->set_exception_backedge();
diff --git a/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java b/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java
new file mode 100644
index 00000000000..999c73fb73a
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/exceptions/TestDebugDuringExceptionCatching.java
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package compiler.exceptions;
+
+import compiler.lib.ir_framework.Run;
+import compiler.lib.ir_framework.Test;
+import compiler.lib.ir_framework.TestFramework;
+
+import java.lang.classfile.Label;
+import java.lang.constant.ClassDesc;
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+
+import jdk.test.lib.Asserts;
+import test.java.lang.invoke.lib.InstructionHelper;
+
+/**
+ * @test
+ * @bug 8350208
+ * @summary Safepoints added during the processing of exception handlers should never reexecute
+ * @library /test/lib /test/jdk/java/lang/invoke/common /
+ * @build test.java.lang.invoke.lib.InstructionHelper
+ *
+ * @run main/othervm ${test.main.class}
+ */
+public class TestDebugDuringExceptionCatching {
+
+ public static class V {
+ int v;
+ }
+
+ static final int ITERATIONS = 100;
+ static final RuntimeException EXCEPTION = new RuntimeException();
+
+ /**
+ * Construct something that looks like this:
+ *
{@code
+ * int snippet(V v) {
+ * int i = 0;
+ * LoopHead: {
+ * if (i >= 100) {
+ * goto LoopEnd;
+ * }
+ * i++;
+ * try {
+ * v.v = 1;
+ * } catch (Throwable) {
+ * // Not really, the LoopHead is the exception Handler
+ * goto LoopHead;
+ * }
+ * }
+ * LoopEnd:
+ * return i;
+ * }
+ * }
+ */
+ static final MethodHandle SNIPPET_HANDLE;
+ static final ClassDesc CLASS_DESC = TestDebugDuringExceptionCatching.class.describeConstable().get();
+ static {
+ SNIPPET_HANDLE = InstructionHelper.buildMethodHandle(MethodHandles.lookup(),
+ "snippet",
+ MethodType.methodType(int.class, V.class),
+ CODE -> {
+ Label loopHead = CODE.newLabel();
+ Label loopEnd = CODE.newLabel();
+ Label tryStart = CODE.newLabel();
+ Label tryEnd = CODE.newLabel();
+ CODE.
+ iconst_0().
+ istore(1).
+ // The loop head should have a RuntimeException as the sole element on the stack
+ getstatic(CLASS_DESC, "EXCEPTION", RuntimeException.class.describeConstable().get()).
+ labelBinding(loopHead).
+ pop().
+ iload(1).
+ ldc(ITERATIONS).
+ if_icmpge(loopEnd).
+ iinc(1, 1).
+ aload(0).
+ iconst_1().
+ labelBinding(tryStart).
+ putfield(V.class.describeConstable().get(), "v", int.class.describeConstable().get()).
+ labelBinding(tryEnd).
+ // The stack is empty here
+ labelBinding(loopEnd).
+ iload(1).
+ ireturn();
+ CODE.exceptionCatchAll(tryStart, tryEnd, loopHead);
+ });
+ }
+
+ @Test
+ private static int testBackwardHandler(V v) throws Throwable {
+ return (int) SNIPPET_HANDLE.invokeExact(v);
+ }
+
+ @Run(test = "testBackwardHandler")
+ public void run() throws Throwable {
+ Asserts.assertEQ(ITERATIONS, testBackwardHandler(null));
+ }
+
+ public static void main(String[] args) {
+ TestFramework.run();
+ }
+}
diff --git a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java
index 123cccd53e7..c7185f691b2 100644
--- a/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java
+++ b/test/jdk/java/lang/invoke/common/test/java/lang/invoke/lib/InstructionHelper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010, 2024, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2010, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -25,6 +25,7 @@
import java.lang.classfile.ClassBuilder;
import java.lang.classfile.ClassFile;
+import java.lang.classfile.CodeBuilder;
import java.lang.classfile.TypeKind;
import java.lang.constant.*;
@@ -32,6 +33,7 @@
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
import java.util.concurrent.atomic.AtomicInteger;
+import java.util.function.Consumer;
import static java.lang.invoke.MethodType.fromMethodDescriptorString;
@@ -135,4 +137,25 @@ public static ClassDesc classDesc(Class> c, String suffix) {
String classDescStr = sb.insert(sb.length() - 1, suffix).toString();
return ClassDesc.ofDescriptor(classDescStr);
}
+
+ public static MethodHandle buildMethodHandle(MethodHandles.Lookup l, String methodName, MethodType methodType, Consumer super CodeBuilder> builder) {
+ ClassDesc genClassDesc = classDesc(l.lookupClass(), "$Code_" + COUNT.getAndIncrement());
+ return buildMethodHandle(l, genClassDesc, methodName, methodType, builder);
+ }
+
+ private static MethodHandle buildMethodHandle(MethodHandles.Lookup l, ClassDesc classDesc, String methodName, MethodType methodType, Consumer super CodeBuilder> builder) {
+ try {
+ byte[] bytes = ClassFile.of().build(classDesc, classBuilder -> {
+ classBuilder.withMethod(methodName,
+ MethodTypeDesc.ofDescriptor(methodType.toMethodDescriptorString()),
+ ClassFile.ACC_PUBLIC + ClassFile.ACC_STATIC,
+ methodBuilder -> methodBuilder.withCode(builder));
+ });
+ Class> clazz = l.defineClass(bytes);
+ return l.findStatic(clazz, methodName, methodType);
+ } catch (Throwable t) {
+ t.printStackTrace();
+ throw new RuntimeException("Failed to buildMethodHandle: " + methodName + " type " + methodType);
+ }
+ }
}
From 4bb7204fa91cc86daca35f816265e2258bd95a7f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?=
Date: Fri, 3 Apr 2026 05:48:24 +0000
Subject: [PATCH 12/60] 8377181: HttpClient may leak closed QUIC connection
objects
Reviewed-by: dfuchs
---
.../http/quic/ConnectionTerminatorImpl.java | 8 +++++-
.../net/http/quic/PeerConnIdManager.java | 25 ++++++++++++++++---
.../net/http/quic/QuicConnectionImpl.java | 4 +++
.../internal/net/http/quic/QuicEndpoint.java | 12 +++++----
.../net/httpclient/CancelRequestTest.java | 2 +-
.../httpclient/http3/H3ErrorHandlingTest.java | 2 +-
6 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/ConnectionTerminatorImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/ConnectionTerminatorImpl.java
index 5e2384dce27..3fc013b4fde 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/ConnectionTerminatorImpl.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/ConnectionTerminatorImpl.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -203,6 +203,9 @@ private void unregisterConnFromEndpoint() {
// an endpoint has been established (which is OK)
return;
}
+ // close the connection ID managers; any in-flight connection ID changes should be ignored.
+ connection.localConnectionIdManager().close();
+ connection.peerConnectionIdManager().close();
endpoint.removeConnection(this.connection);
}
@@ -434,6 +437,9 @@ private void pushConnectionCloseFrame(final KeySpace keySpace,
final QuicPacket packet = connection.newQuicPacket(keySpace, List.of(toSend));
final ProtectionRecord protectionRecord = ProtectionRecord.single(packet,
connection::allocateDatagramForEncryption);
+ // close the connection ID managers; any in-flight connection ID changes should be ignored.
+ connection.localConnectionIdManager().close();
+ connection.peerConnectionIdManager().close();
// while sending the packet containing the CONNECTION_CLOSE frame, the pushDatagram will
// remap the QuicConnectionImpl in QuicEndpoint.
connection.pushDatagram(protectionRecord);
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnIdManager.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnIdManager.java
index 2bc759a920a..0646026e28b 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnIdManager.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/PeerConnIdManager.java
@@ -65,6 +65,7 @@ final class PeerConnIdManager {
private final QuicConnectionImpl connection;
private final String logTag;
private final boolean isClient;
+ private boolean closed; // when true, no more reset tokens are registered
private enum State {
INITIAL_PKT_NOT_RECEIVED_FROM_PEER,
@@ -267,6 +268,7 @@ void handshakeStatelessResetToken(final byte[] statelessResetToken) {
if (handshakeConnId == null) {
throw new IllegalStateException("No handshake peer connection available");
}
+ if (closed) return;
// recreate the conn id with the stateless token
this.peerConnectionIds.put(0L, new PeerConnectionId(handshakeConnId.asReadOnlyBuffer(),
statelessResetToken));
@@ -283,6 +285,10 @@ void handshakeStatelessResetToken(final byte[] statelessResetToken) {
public List activeResetTokens() {
lock.lock();
try {
+ // this method is currently only used to remove a connection from the endpoint
+ // after the connection is closed.
+ // The below assert can be removed if the method is needed elsewhere.
+ assert closed;
// we only support one active connection ID at the time
PeerConnectionId cid = peerConnectionIds.get(activeConnIdSeq);
byte[] statelessResetToken = null;
@@ -305,7 +311,7 @@ public List activeResetTokens() {
QuicConnectionId getPeerConnId() {
lock.lock();
try {
- if (activeConnIdSeq < largestReceivedRetirePriorTo) {
+ if (activeConnIdSeq < largestReceivedRetirePriorTo && !closed) {
// stop using the old connection ID
switchConnectionId();
}
@@ -496,9 +502,11 @@ private void retirePriorTo(final long priorTo) {
// connection ids. It does however store the peer-issued stateless reset token of a
// peer connection id, so we let the endpoint know that the stateless reset token needs
// to be forgotten since the corresponding peer connection id is being retired
- final byte[] resetTokenToForget = entry.getValue().getStatelessResetToken();
- if (resetTokenToForget != null) {
- this.connection.endpoint().forgetStatelessResetToken(resetTokenToForget);
+ if (seqNumToRetire == activeConnIdSeq) {
+ final byte[] resetTokenToForget = entry.getValue().getStatelessResetToken();
+ if (resetTokenToForget != null) {
+ this.connection.endpoint().forgetStatelessResetToken(resetTokenToForget);
+ }
}
}
for (Iterator iterator = gaps.iterator(); iterator.hasNext(); ) {
@@ -540,4 +548,13 @@ public QuicFrame nextFrame(int remaining) {
lock.unlock();
}
}
+
+ public void close() {
+ lock.lock();
+ try {
+ closed = true;
+ } finally {
+ lock.unlock();
+ }
+ }
}
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java
index 41b814a551c..b13d49ead7d 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicConnectionImpl.java
@@ -1758,6 +1758,10 @@ LocalConnIdManager localConnectionIdManager() {
return localConnIdManager;
}
+ PeerConnIdManager peerConnectionIdManager() {
+ return peerConnIdManager;
+ }
+
/**
* {@return the local connection id}
*/
diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java
index ef342d4cb56..3dee814e1f1 100644
--- a/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java
+++ b/src/java.net.http/share/classes/jdk/internal/net/http/quic/QuicEndpoint.java
@@ -1532,12 +1532,16 @@ public void pushClosedDatagram(QuicConnectionImpl connection,
*/
void removeConnection(final QuicPacketReceiver connection) {
if (debug.on()) debug.log("removing connection " + connection);
- // remove the connection completely
- connection.connectionIds().forEach(connections::remove);
- assert !connections.containsValue(connection) : connection;
// remove references to this connection from the map which holds the peer issued
// reset tokens
dropPeerIssuedResetTokensFor(connection);
+ // remove the connection completely
+ connection.connectionIds().forEach(connections::remove);
+ assert !connections.containsValue(connection) : connection;
+ // Check that if there are no connections, there are no reset tokens either.
+ // This is safe because connections are added before reset tokens and removed after,
+ // except when we're closing the endpoint and don't bother with removing tokens.
+ assert peerIssuedResetTokens.isEmpty() || !connections.isEmpty() || closed : peerIssuedResetTokens;
}
/**
@@ -1587,7 +1591,6 @@ public void draining(final QuicConnectionImpl connection) {
if (closed) return;
final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO
- connection.localConnectionIdManager().close();
DrainingConnection draining = new DrainingConnection(connection.connectionIds(),
connection.activeResetTokens(), idleTimeout);
// we can ignore stateless reset in the draining state.
@@ -1626,7 +1629,6 @@ protected void closing(QuicConnectionImpl connection, ByteBuffer datagram) {
closingDatagram.flip();
final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO
- connection.localConnectionIdManager().close();
var closingConnection = new ClosingConnection(connection.connectionIds(),
connection.activeResetTokens(), idleTimeout, datagram);
remapPeerIssuedResetToken(closingConnection);
diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java
index df808ad2dab..dcb60a55061 100644
--- a/test/jdk/java/net/httpclient/CancelRequestTest.java
+++ b/test/jdk/java/net/httpclient/CancelRequestTest.java
@@ -23,7 +23,7 @@
/*
* @test
- * @bug 8245462 8229822 8254786 8297075 8297149 8298340 8302635
+ * @bug 8245462 8229822 8254786 8297075 8297149 8298340 8302635 8377181
* @summary Tests cancelling the request.
* @library /test/lib /test/jdk/java/net/httpclient/lib
* @key randomness
diff --git a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java
index 8dfef7417e3..8e20eac95fa 100644
--- a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java
+++ b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java
@@ -71,7 +71,7 @@
/*
* @test
- * @bug 8373409
+ * @bug 8373409 8377181
* @key intermittent
* @comment testResetControlStream may fail if the client doesn't read the stream type
* before the stream is reset,
From f8ca6f6f09908c5106d262cfaaf82e88f37e9a32 Mon Sep 17 00:00:00 2001
From: Dingli Zhang
Date: Fri, 3 Apr 2026 06:15:19 +0000
Subject: [PATCH 13/60] 8381554: RISC-V: Small refactoring for
cmp_klass_compressed macro-assembler routine
Reviewed-by: fyang, gcao, wenanjian
---
.../riscv/c1_LIRAssembler_arraycopy_riscv.cpp | 52 ++++++++-----------
.../riscv/c1_LIRAssembler_arraycopy_riscv.hpp | 3 +-
.../cpu/riscv/macroAssembler_riscv.cpp | 25 ++++++---
.../cpu/riscv/macroAssembler_riscv.hpp | 9 +++-
4 files changed, 49 insertions(+), 40 deletions(-)
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp
index 58eb1a55553..8aced227a06 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.cpp
@@ -240,35 +240,6 @@ void LIR_Assembler::arraycopy_type_check(Register src, Register src_pos, Registe
}
}
-void LIR_Assembler::arraycopy_assert(Register src, Register dst, Register tmp, ciArrayKlass *default_type, int flags) {
- assert(default_type != nullptr, "null default_type!");
- BasicType basic_type = default_type->element_type()->basic_type();
- if (basic_type == T_ARRAY) { basic_type = T_OBJECT; }
- if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) {
- // Sanity check the known type with the incoming class. For the
- // primitive case the types must match exactly with src.klass and
- // dst.klass each exactly matching the default type. For the
- // object array case, if no type check is needed then either the
- // dst type is exactly the expected type and the src type is a
- // subtype which we can't check or src is the same array as dst
- // but not necessarily exactly of type default_type.
- Label known_ok, halt;
- __ mov_metadata(tmp, default_type->constant_encoding());
- __ encode_klass_not_null(tmp);
-
- if (basic_type != T_OBJECT) {
- __ cmp_klass_compressed(dst, tmp, t0, halt, false);
- __ cmp_klass_compressed(src, tmp, t0, known_ok, true);
- } else {
- __ cmp_klass_compressed(dst, tmp, t0, known_ok, true);
- __ beq(src, dst, known_ok);
- }
- __ bind(halt);
- __ stop("incorrect type information in arraycopy");
- __ bind(known_ok);
- }
-}
-
void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
ciArrayKlass *default_type = op->expected_type();
Register src = op->src()->as_register();
@@ -299,7 +270,28 @@ void LIR_Assembler::emit_arraycopy(LIR_OpArrayCopy* op) {
}
#ifdef ASSERT
- arraycopy_assert(src, dst, tmp, default_type, flags);
+ if (basic_type != T_OBJECT || !(flags & LIR_OpArrayCopy::type_check)) {
+ // Sanity check the known type with the incoming class. For the
+ // primitive case the types must match exactly with src.klass and
+ // dst.klass each exactly matching the default type. For the
+ // object array case, if no type check is needed then either the
+ // dst type is exactly the expected type and the src type is a
+ // subtype which we can't check or src is the same array as dst
+ // but not necessarily exactly of type default_type.
+ Label known_ok, halt;
+ __ mov_metadata(tmp, default_type->constant_encoding());
+
+ if (basic_type != T_OBJECT) {
+ __ cmp_klass_bne(dst, tmp, t0, t1, halt);
+ __ cmp_klass_beq(src, tmp, t0, t1, known_ok);
+ } else {
+ __ cmp_klass_beq(dst, tmp, t0, t1, known_ok);
+ __ beq(src, dst, known_ok);
+ }
+ __ bind(halt);
+ __ stop("incorrect type information in arraycopy");
+ __ bind(known_ok);
+ }
#endif
#ifndef PRODUCT
diff --git a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp
index 06a0f248ca6..b5452f3e4cd 100644
--- a/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp
+++ b/src/hotspot/cpu/riscv/c1_LIRAssembler_arraycopy_riscv.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2020, 2021, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
@@ -39,7 +39,6 @@
void arraycopy_type_check(Register src, Register src_pos, Register length,
Register dst, Register dst_pos, Register tmp,
CodeStub *stub, BasicType basic_type, int flags);
- void arraycopy_assert(Register src, Register dst, Register tmp, ciArrayKlass *default_type, int flags);
void arraycopy_prepare_params(Register src, Register src_pos, Register length,
Register dst, Register dst_pos, BasicType basic_type);
void arraycopy_checkcast_prepare_params(Register src, Register src_pos, Register length,
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
index b0305fa2977..d031161db87 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp
@@ -3511,17 +3511,30 @@ void MacroAssembler::orptr(Address adr, RegisterOrConstant src, Register tmp1, R
sd(tmp1, adr);
}
-void MacroAssembler::cmp_klass_compressed(Register oop, Register trial_klass, Register tmp, Label &L, bool equal) {
+void MacroAssembler::cmp_klass_beq(Register obj, Register klass,
+ Register tmp1, Register tmp2,
+ Label &L, bool is_far) {
+ assert_different_registers(obj, klass, tmp1, tmp2);
if (UseCompactObjectHeaders) {
- load_narrow_klass_compact(tmp, oop);
+ load_narrow_klass_compact(tmp1, obj);
} else {
- lwu(tmp, Address(oop, oopDesc::klass_offset_in_bytes()));
+ lwu(tmp1, Address(obj, oopDesc::klass_offset_in_bytes()));
}
- if (equal) {
- beq(trial_klass, tmp, L);
+ decode_klass_not_null(tmp1, tmp2);
+ beq(klass, tmp1, L, is_far);
+}
+
+void MacroAssembler::cmp_klass_bne(Register obj, Register klass,
+ Register tmp1, Register tmp2,
+ Label &L, bool is_far) {
+ assert_different_registers(obj, klass, tmp1, tmp2);
+ if (UseCompactObjectHeaders) {
+ load_narrow_klass_compact(tmp1, obj);
} else {
- bne(trial_klass, tmp, L);
+ lwu(tmp1, Address(obj, oopDesc::klass_offset_in_bytes()));
}
+ decode_klass_not_null(tmp1, tmp2);
+ bne(klass, tmp1, L, is_far);
}
// Move an oop into a register.
diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
index f5e985c28a2..95821c29eec 100644
--- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
+++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2014, 2020, Red Hat Inc. All rights reserved.
* Copyright (c) 2020, 2024, Huawei Technologies Co., Ltd. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
@@ -198,7 +198,12 @@ class MacroAssembler: public Assembler {
void load_klass(Register dst, Register src, Register tmp = t0);
void load_narrow_klass_compact(Register dst, Register src);
void store_klass(Register dst, Register src, Register tmp = t0);
- void cmp_klass_compressed(Register oop, Register trial_klass, Register tmp, Label &L, bool equal);
+ void cmp_klass_beq(Register obj, Register klass,
+ Register tmp1, Register tmp2,
+ Label &L, bool is_far = false);
+ void cmp_klass_bne(Register obj, Register klass,
+ Register tmp1, Register tmp2,
+ Label &L, bool is_far = false);
void encode_klass_not_null(Register r, Register tmp = t0);
void decode_klass_not_null(Register r, Register tmp = t0);
From 4a4701106c68aee7ba33c41d1e4f72d72ac1a3d6 Mon Sep 17 00:00:00 2001
From: Emanuel Peter
Date: Fri, 3 Apr 2026 12:39:49 +0000
Subject: [PATCH 14/60] 8369699: Template Framework Library: add VectorAPI
types and operations
Reviewed-by: mhaessig, vlivanov, galder
---
.../jtreg/compiler/igvn/ExpressionFuzzer.java | 9 +-
.../library/CodeGenerationDataNameType.java | 78 ++-
.../library/Expression.java | 68 ++-
.../library/Operations.java | 548 +++++++++++++++++-
.../library/PrimitiveType.java | 17 +
.../lib/template_framework/library/Utils.java | 41 ++
.../library/VectorType.java | 237 ++++++++
.../vectorapi/VectorExpressionFuzzer.java | 345 +++++++++++
.../examples/TestExpressions.java | 21 +-
.../examples/TestPrimitiveTypes.java | 12 +
.../examples/TestVectorTypes.java | 134 +++++
11 files changed, 1479 insertions(+), 31 deletions(-)
create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/Utils.java
create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/VectorType.java
create mode 100644 test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java
create mode 100644 test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestVectorTypes.java
diff --git a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java
index 33be24a0367..dfb2ec1405c 100644
--- a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java
+++ b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java
@@ -30,7 +30,7 @@
* @modules jdk.incubator.vector
* @library /test/lib /
* @compile ../lib/verify/Verify.java
- * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:CompileTaskTimeout=10000 compiler.igvn.ExpressionFuzzer
+ * @run driver compiler.igvn.ExpressionFuzzer
*/
package compiler.igvn;
@@ -73,6 +73,10 @@
// - Some basic IR tests to ensure that the constraints / checksum mechanics work.
// We may even have to add some IGVN optimizations to be able to better observe things right.
// - Lower the CompileTaskTimeout, if possible. It is chosen conservatively (rather high) for now.
+// - I also had to exclude the compilation of the following method. It would lead to compilation
+// timeouts and even compilation memory limit reached. It is a really large method, so I'm not
+// sure if that is to be expected, or if we could still improve the situation.
+// compiler.lib.template_framework.library.Operations::generateVectorOperations
public class ExpressionFuzzer {
private static final Random RANDOM = Utils.getRandomInstance();
@@ -93,7 +97,8 @@ public static void main(String[] args) {
comp.invoke("compiler.igvn.templated.ExpressionFuzzerInnerTest", "main", new Object[] {new String[] {
"--add-modules=jdk.incubator.vector",
"--add-opens", "jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED",
- "--add-opens", "java.base/java.lang=ALL-UNNAMED"
+ "--add-opens", "java.base/java.lang=ALL-UNNAMED",
+ "-XX:+IgnoreUnrecognizedVMOptions", "-XX:CompileTaskTimeout=10000"
}});
}
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java
index b461e3e857f..33eba66cd8c 100644
--- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -132,6 +132,14 @@ public interface CodeGenerationDataNameType extends DataName.Type {
longs()
);
+ /**
+ * List of {@link PrimitiveType}s (int, long).
+ */
+ List INT_LONG_TYPES = List.of(
+ ints(),
+ longs()
+ );
+
/**
* List of all subword {@link PrimitiveType}s (byte, char, short).
*/
@@ -176,4 +184,72 @@ public interface CodeGenerationDataNameType extends DataName.Type {
booleans(),
float16()
);
+
+ List VECTOR_BYTE_VECTOR_TYPES = List.of(
+ VectorType.BYTE_64,
+ VectorType.BYTE_128,
+ VectorType.BYTE_256,
+ VectorType.BYTE_512
+ );
+
+ List VECTOR_SHORT_VECTOR_TYPES = List.of(
+ VectorType.SHORT_64,
+ VectorType.SHORT_128,
+ VectorType.SHORT_256,
+ VectorType.SHORT_512
+ );
+
+ List VECTOR_INT_VECTOR_TYPES = List.of(
+ VectorType.INT_64,
+ VectorType.INT_128,
+ VectorType.INT_256,
+ VectorType.INT_512
+ );
+
+ List VECTOR_LONG_VECTOR_TYPES = List.of(
+ VectorType.LONG_64,
+ VectorType.LONG_128,
+ VectorType.LONG_256,
+ VectorType.LONG_512
+ );
+
+ List VECTOR_FLOAT_VECTOR_TYPES = List.of(
+ VectorType.FLOAT_64,
+ VectorType.FLOAT_128,
+ VectorType.FLOAT_256,
+ VectorType.FLOAT_512
+ );
+
+ List VECTOR_DOUBLE_VECTOR_TYPES = List.of(
+ VectorType.DOUBLE_64,
+ VectorType.DOUBLE_128,
+ VectorType.DOUBLE_256,
+ VectorType.DOUBLE_512
+ );
+
+ List VECTOR_VECTOR_TYPES = Utils.concat(
+ VECTOR_BYTE_VECTOR_TYPES,
+ VECTOR_SHORT_VECTOR_TYPES,
+ VECTOR_INT_VECTOR_TYPES,
+ VECTOR_LONG_VECTOR_TYPES,
+ VECTOR_FLOAT_VECTOR_TYPES,
+ VECTOR_DOUBLE_VECTOR_TYPES
+ );
+
+ List VECTOR_MASK_TYPES =
+ VECTOR_VECTOR_TYPES.stream().map(t -> t.maskType).toList();
+
+ List VECTOR_SHUFFLE_TYPES =
+ VECTOR_VECTOR_TYPES.stream().map(t -> t.shuffleType).toList();
+
+ List VECTOR_TYPES = Utils.concat(
+ VECTOR_VECTOR_TYPES,
+ VECTOR_MASK_TYPES,
+ VECTOR_SHUFFLE_TYPES
+ );
+
+ List ALL_TYPES = Utils.concat(
+ SCALAR_NUMERIC_TYPES,
+ VECTOR_TYPES
+ );
}
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/Expression.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/Expression.java
index 37ad4debde6..f3e7b6ed0d3 100644
--- a/test/hotspot/jtreg/compiler/lib/template_framework/library/Expression.java
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/Expression.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -332,6 +332,72 @@ public static Expression make(CodeGenerationDataNameType returnType,
return new Expression(returnType, List.of(t0, t1, t2, t3), List.of(s0, s1, s2, s3, s4), info);
}
+ /**
+ * Creates a new Expression with 5 arguments.
+ *
+ * @param returnType The return type of the {@link Expression}.
+ * @param s0 The first string, to be placed before {@code t0}.
+ * @param t0 The type of the first argument.
+ * @param s1 The second string, to be placed before {@code t1}.
+ * @param t1 The type of the second argument.
+ * @param s2 The third string, to be placed before {@code t2}.
+ * @param t2 The type of the third argument.
+ * @param s3 The fourth string, to be placed before {@code t3}.
+ * @param t3 The type of the fourth argument.
+ * @param s4 The fifth string, to be placed before {@code t4}.
+ * @param t4 The type of the fifth argument.
+ * @param s5 The last string, finishing the {@link Expression}.
+ * @return the new {@link Expression}.
+ */
+ public static Expression make(CodeGenerationDataNameType returnType,
+ String s0,
+ CodeGenerationDataNameType t0,
+ String s1,
+ CodeGenerationDataNameType t1,
+ String s2,
+ CodeGenerationDataNameType t2,
+ String s3,
+ CodeGenerationDataNameType t3,
+ String s4,
+ CodeGenerationDataNameType t4,
+ String s5) {
+ return make(returnType, s0, t0, s1, t1, s2, t2, s3, t3, s4, t4, s5, new Info());
+ }
+
+ /**
+ * Creates a new Expression with 5 arguments.
+ *
+ * @param returnType The return type of the {@link Expression}.
+ * @param s0 The first string, to be placed before {@code t0}.
+ * @param t0 The type of the first argument.
+ * @param s1 The second string, to be placed before {@code t1}.
+ * @param t1 The type of the second argument.
+ * @param s2 The third string, to be placed before {@code t2}.
+ * @param t2 The type of the third argument.
+ * @param s3 The fourth string, to be placed before {@code t3}.
+ * @param t3 The type of the fourth argument.
+ * @param s4 The fifth string, to be placed before {@code t4}.
+ * @param t4 The type of the fifth argument.
+ * @param s5 The last string, finishing the {@link Expression}.
+ * @param info Additional information about the {@link Expression}.
+ * @return the new {@link Expression}.
+ */
+ public static Expression make(CodeGenerationDataNameType returnType,
+ String s0,
+ CodeGenerationDataNameType t0,
+ String s1,
+ CodeGenerationDataNameType t1,
+ String s2,
+ CodeGenerationDataNameType t2,
+ String s3,
+ CodeGenerationDataNameType t3,
+ String s4,
+ CodeGenerationDataNameType t4,
+ String s5,
+ Info info) {
+ return new Expression(returnType, List.of(t0, t1, t2, t3, t4), List.of(s0, s1, s2, s3, s4, s5), info);
+ }
+
/**
* Creates a {@link TemplateToken} for the use in a {@link Template} by applying the
* {@code arguments} to the {@link Expression}. It is the users responsibility to
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java
index 2ea251cc5e5..4c598506e70 100644
--- a/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java
@@ -24,11 +24,8 @@
package compiler.lib.template_framework.library;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.List;
import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
import static compiler.lib.template_framework.library.PrimitiveType.BYTES;
import static compiler.lib.template_framework.library.PrimitiveType.SHORTS;
@@ -39,6 +36,10 @@
import static compiler.lib.template_framework.library.PrimitiveType.DOUBLES;
import static compiler.lib.template_framework.library.PrimitiveType.BOOLEANS;
import static compiler.lib.template_framework.library.Float16Type.FLOAT16;
+import static compiler.lib.template_framework.library.CodeGenerationDataNameType.PRIMITIVE_TYPES;
+import static compiler.lib.template_framework.library.CodeGenerationDataNameType.INTEGRAL_TYPES;
+import static compiler.lib.template_framework.library.CodeGenerationDataNameType.FLOATING_TYPES;
+import static compiler.lib.template_framework.library.CodeGenerationDataNameType.INT_LONG_TYPES;
/**
* This class provides various lists of {@link Expression}s, that represent Java operators or library
@@ -51,27 +52,8 @@ private Operations() {}
private static Expression.Info WITH_ARITHMETIC_EXCEPTION = new Expression.Info().withExceptions(Set.of("ArithmeticException"));
private static Expression.Info WITH_NONDETERMINISTIC_RESULT = new Expression.Info().withNondeterministicResult();
-
-
- /**
- * Provides a lits of operations on {@link PrimitiveType}s, such as arithmetic, logical,
- * and cast operations.
- */
- public static final List PRIMITIVE_OPERATIONS = generatePrimitiveOperations();
-
- public static final List FLOAT16_OPERATIONS = generateFloat16Operations();
-
- public static final List SCALAR_NUMERIC_OPERATIONS = concat(
- PRIMITIVE_OPERATIONS,
- FLOAT16_OPERATIONS
- );
-
- @SafeVarargs
- private static List concat(List... lists) {
- return Arrays.stream(lists)
- .flatMap(List::stream)
- .collect(Collectors.toList());
- }
+ private static Expression.Info WITH_ILLEGAL_ARGUMENT_EXCEPTION = new Expression.Info().withExceptions(Set.of("IllegalArgumentException"));
+ private static Expression.Info WITH_OUT_OF_BOUNDS_EXCEPTION = new Expression.Info().withExceptions(Set.of("IndexOutOfBoundsException"));
private static void addComparisonOperations(List ops, String operatorName, CodeGenerationDataNameType type) {
for (String mask : List.of("==", "!=", "<", ">", "<=", ">=")) {
@@ -332,4 +314,522 @@ private static List generateFloat16Operations() {
// Make sure the list is not modifiable.
return List.copyOf(ops);
}
+
+ private enum VOPType {
+ UNARY,
+ BINARY,
+ ASSOCIATIVE, // Binary and associative - safe for reductions of any type
+ INTEGRAL_ASSOCIATIVE, // Binary - but only safe for integral reductions
+ TERNARY
+ }
+ private record VOP(String name, VOPType type, List elementTypes, boolean isDeterministic) {
+ VOP(String name, VOPType type, List elementTypes) {
+ this(name, type, elementTypes, true);
+ }
+ }
+
+ // TODO: consider enforcing precision instead of just blanket non-determinism
+ // We could annotate the exact ulp, and so if some test can use it: great
+ // But if a test is just interested in determinism, they are still
+ // non-deterministic.
+ private static final List VECTOR_OPS = List.of(
+ new VOP("ABS", VOPType.UNARY, PRIMITIVE_TYPES),
+ new VOP("ACOS", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("ADD", VOPType.INTEGRAL_ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("AND", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("AND_NOT", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("ASHR", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("ASIN", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("ATAN", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("ATAN2", VOPType.BINARY, FLOATING_TYPES, false), // 2 ulp
+ new VOP("BIT_COUNT", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("BITWISE_BLEND", VOPType.TERNARY, INTEGRAL_TYPES),
+ new VOP("CBRT", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("COMPRESS_BITS", VOPType.BINARY, INT_LONG_TYPES),
+ new VOP("COS", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("COSH", VOPType.UNARY, FLOATING_TYPES, false), // 2.5 ulp
+ new VOP("DIV", VOPType.BINARY, FLOATING_TYPES),
+ new VOP("EXP", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("EXPAND_BITS", VOPType.BINARY, INT_LONG_TYPES),
+ new VOP("EXPM1", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("FIRST_NONZERO", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("FMA", VOPType.TERNARY, FLOATING_TYPES),
+ new VOP("HYPOT", VOPType.BINARY, FLOATING_TYPES, false), // 1.5 ulp
+ new VOP("LEADING_ZEROS_COUNT", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("LOG", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("LOG10", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("LOG1P", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("LSHL", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("LSHR", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("MIN", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("MAX", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("MUL", VOPType.INTEGRAL_ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("NEG", VOPType.UNARY, PRIMITIVE_TYPES),
+ new VOP("NOT", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("OR", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("POW", VOPType.BINARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("REVERSE", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("REVERSE_BYTES", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("ROL", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("ROR", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("SADD", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("SIN", VOPType.UNARY, FLOATING_TYPES, false), // 1 ulp
+ new VOP("SINH", VOPType.UNARY, FLOATING_TYPES, false), // 2.5 ulp
+ new VOP("SQRT", VOPType.UNARY, FLOATING_TYPES),
+ new VOP("SSUB", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("SUADD", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("SUB", VOPType.BINARY, PRIMITIVE_TYPES),
+ new VOP("SUSUB", VOPType.BINARY, INTEGRAL_TYPES),
+ new VOP("TAN", VOPType.UNARY, FLOATING_TYPES, false), // 1.25 ulp
+ new VOP("TANH", VOPType.UNARY, FLOATING_TYPES, false), // 2.5 ulp
+ new VOP("TRAILING_ZEROS_COUNT", VOPType.UNARY, INTEGRAL_TYPES),
+ new VOP("UMAX", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("UMIN", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("XOR", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("ZOMO", VOPType.UNARY, INTEGRAL_TYPES)
+ );
+
+ private static final List VECTOR_CMP = List.of(
+ new VOP("EQ", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("GE", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("GT", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("LE", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("LT", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("NE", VOPType.ASSOCIATIVE, PRIMITIVE_TYPES),
+ new VOP("UGE", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("UGT", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("ULE", VOPType.ASSOCIATIVE, INTEGRAL_TYPES),
+ new VOP("ULT", VOPType.ASSOCIATIVE, INTEGRAL_TYPES)
+ );
+
+ private static final List VECTOR_TEST = List.of(
+ new VOP("IS_DEFAULT", VOPType.UNARY, PRIMITIVE_TYPES),
+ new VOP("IS_NEGATIVE", VOPType.UNARY, PRIMITIVE_TYPES),
+ new VOP("IS_FINITE", VOPType.UNARY, FLOATING_TYPES),
+ new VOP("IS_NAN", VOPType.UNARY, FLOATING_TYPES),
+ new VOP("IS_INFINITE", VOPType.UNARY, FLOATING_TYPES)
+ );
+
+ // TODO: Conversion VectorOperators -> convertShape
+
+ private static List generateVectorOperations() {
+ List ops = new ArrayList<>();
+
+ for (var type : CodeGenerationDataNameType.VECTOR_VECTOR_TYPES) {
+ // ----------------- IntVector, FloatVector, ... --------------------
+ ops.add(Expression.make(type, "", type, ".abs()"));
+ ops.add(Expression.make(type, "", type, ".add(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".add(", type.elementType, ", ", type.maskType, ")"));
+ ops.add(Expression.make(type, "", type, ".add(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".add(", type, ", ", type.maskType, ")"));
+
+ // If VLENGTH*scale overflows, then a IllegalArgumentException is thrown.
+ ops.add(Expression.make(type, "", type, ".addIndex(1)"));
+ ops.add(Expression.make(type, "", type, ".addIndex(", INTS, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+
+ if (!type.elementType.isFloating()) {
+ ops.add(Expression.make(type, "", type, ".and(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".and(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".bitwiseBlend(", type.elementType, ", ", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".bitwiseBlend(", type.elementType, ", ", type, ")"));
+ ops.add(Expression.make(type, "", type, ".bitwiseBlend(", type, ", ", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".bitwiseBlend(", type, ", ", type, ")"));
+ ops.add(Expression.make(type, "", type, ".not()"));
+ ops.add(Expression.make(type, "", type, ".or(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".or(", type, ")"));
+ }
+
+ ops.add(Expression.make(type, "", type, ".blend(", type.elementType, ", ", type.maskType, ")"));
+ ops.add(Expression.make(type, "", type, ".blend(", LONGS, ", ", type.maskType, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".blend(", type, ", ", type.maskType, ")"));
+
+ ops.add(Expression.make(type, type.name() + ".broadcast(" + type.speciesName + ", ", type.elementType, ")"));
+ ops.add(Expression.make(type, type.name() + ".broadcast(" + type.speciesName + ", ", LONGS, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+
+ for (var type2 : CodeGenerationDataNameType.VECTOR_VECTOR_TYPES) {
+ ops.add(Expression.make(type, "((" + type.name() + ")", type2 , ".castShape(" + type.speciesName + ", 0))"));
+ ops.add(Expression.make(type, "((" + type.name() + ")", type2 , ".castShape(" + type.speciesName + ", ", INTS, "))", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ }
+
+ // skip check
+
+ for (VOP cmp : VECTOR_CMP) {
+ if (cmp.elementTypes().contains(type.elementType)) {
+ ops.add(Expression.make(type.maskType, "", type, ".compare(VectorOperators." + cmp.name() + ", ", type.elementType, ")"));
+ ops.add(Expression.make(type.maskType, "", type, ".compare(VectorOperators." + cmp.name() + ", ", type.elementType, ", ", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type, ".compare(VectorOperators." + cmp.name() + ", ", LONGS, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+ ops.add(Expression.make(type.maskType, "", type, ".compare(VectorOperators." + cmp.name() + ", ", LONGS, ", ", type.maskType, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+ ops.add(Expression.make(type.maskType, "", type, ".compare(VectorOperators." + cmp.name() + ", ", type, ")"));
+ }
+ }
+
+ ops.add(Expression.make(type, "", type, ".compress(", type.maskType, ")"));
+
+ for (var type2 : CodeGenerationDataNameType.VECTOR_VECTOR_TYPES) {
+ // "convert" keeps the same shape, i.e. length of the vector in bits.
+ if (type.byteSize() == type2.byteSize()) {
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convert(VectorOperators.Conversion.ofCast("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), 0))"));
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convert(VectorOperators.Conversion.ofCast("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class),",
+ INTS, // part
+ "))", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ }
+
+ // Reinterpretation FROM floating is not safe, because of different NaN encodings, i.e.
+ // we will not get deterministic results.
+ var reinterpretInfo = type2.elementType.isFloating() ? WITH_NONDETERMINISTIC_RESULT : new Expression.Info();
+
+ // The following "reinterpret" operations require same input and output shape.
+ if (type.byteSize() == type2.byteSize()) {
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convert(VectorOperators.Conversion.ofReinterpret("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), 0))", reinterpretInfo));
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convert(VectorOperators.Conversion.ofReinterpret("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class),",
+ INTS, // part
+ "))", reinterpretInfo.combineWith(WITH_OUT_OF_BOUNDS_EXCEPTION)));
+ if (type.elementType == BYTES) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsBytes()", reinterpretInfo));
+ }
+ if (type.elementType == SHORTS) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsShorts()", reinterpretInfo));
+ }
+ if (type.elementType == INTS) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsInts()", reinterpretInfo));
+ }
+ if (type.elementType == LONGS) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsLongs()", reinterpretInfo));
+ }
+ if (type.elementType == FLOATS) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsFloats()", reinterpretInfo));
+ }
+ if (type.elementType == DOUBLES) {
+ ops.add(Expression.make(type, "", type2, ".reinterpretAsDoubles()", reinterpretInfo));
+ }
+ if (type.elementType.isFloating() && type.elementType.byteSize() == type2.elementType.byteSize()) {
+ ops.add(Expression.make(type, "", type2, ".viewAsFloatingLanes()", reinterpretInfo));
+ }
+ if (!type.elementType.isFloating() && type.elementType.byteSize() == type2.elementType.byteSize()) {
+ ops.add(Expression.make(type, "", type2, ".viewAsIntegralLanes()", reinterpretInfo));
+ }
+ }
+
+ // reinterpretShape
+ if (type2.byteSize() >= type.byteSize()) {
+ // Output overflows, is truncated (Expansion): part >= 0
+ int partMask = type2.byteSize() / type.byteSize() - 1;
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".reinterpretShape(" + type.speciesName + ", ",
+ INTS, " & " + partMask + "))", reinterpretInfo));
+ } else {
+ // Logical output too small to fill output vector (Contraction): part <= 0
+ int partMask = type.byteSize() / type2.byteSize() - 1;
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".reinterpretShape(" + type.speciesName + ", "
+ + "-(", INTS, " & " + partMask + ")))", reinterpretInfo));
+ }
+
+ // convertShape - Cast/Reinterpret
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofCast("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", ",
+ INTS, // part
+ "))", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofReinterpret("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", ",
+ INTS, // part
+ "))", reinterpretInfo.combineWith(WITH_OUT_OF_BOUNDS_EXCEPTION)));
+ // Compute size of logical output, before it is "fit" into the output vector.
+ // Each element is cast/reinterpret individually, and so the logical output
+ // has the lane count of the input vector, and the element size that of the output element size.
+ // Note: reinterpret of float -> long means we expand each element from 4->8 bytes, and so
+ // we take the lower 4 bytes from the float and add 4 bytes of zero padding.
+ int conversionLogicalByteSize = type2.length * type.elementType.byteSize();
+ if (conversionLogicalByteSize >= type.byteSize()) {
+ // Output overflows, is truncated (Expansion): part >= 0
+ int partMask = conversionLogicalByteSize / type.byteSize() - 1;
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofCast("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", ",
+ INTS, " & " + partMask + "))"));
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofReinterpret("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", ",
+ INTS, " & " + partMask + "))", reinterpretInfo));
+ } else {
+ // Logical output too small to fill output vector (Contraction): part <= 0
+ int partMask = type.byteSize() / conversionLogicalByteSize - 1;
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofCast("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", "
+ + "-(", INTS, " & " + partMask + ")))"));
+ ops.add(Expression.make(type,
+ "((" + type.name() + ")",
+ type2,
+ ".convertShape(VectorOperators.Conversion.ofReinterpret("
+ + type2.elementType.name() + ".class, "
+ + type.elementType.name() + ".class), "
+ + type.speciesName + ", "
+ + "-(", INTS, " & " + partMask + ")))", reinterpretInfo));
+ }
+ // TODO: convertShape - using VectorOperators.I2S,REINTERPRET_I2F,ZERO_EXTEND_B2I etc.
+ }
+
+ ops.add(Expression.make(type, "", type, ".div(", type.elementType, ")", WITH_ARITHMETIC_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".div(", type.elementType, ", ", type.maskType, ")", WITH_ARITHMETIC_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".div(", type, ")", WITH_ARITHMETIC_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".div(", type, ", ", type.maskType, ")", WITH_ARITHMETIC_EXCEPTION));
+
+ ops.add(Expression.make(type.maskType, "", type, ".eq(", type.elementType, ")"));
+ ops.add(Expression.make(type.maskType, "", type, ".eq(", type, ")"));
+ // skip equals
+ ops.add(Expression.make(type, "", type, ".expand(", type.maskType, ")"));
+ // skip fromArray
+ // skip fromMemorySegment
+ // skip hashCode
+ // skip intoArray
+ // skip intoMemorySegment
+ // TODO: memory accesses. It is not clear yet if these are to be modeled as Expressions, or rather statements.
+ ops.add(Expression.make(type.elementType, "", type, ".lane(", INTS, " & " + (type.length-1) + ")"));
+ ops.add(Expression.make(type.elementType, "", type, ".lane(", INTS, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+
+ for (VOP vop : VECTOR_OPS) {
+ var vopInfo = vop.isDeterministic ? new Expression.Info() : WITH_NONDETERMINISTIC_RESULT;
+ if (vop.elementTypes().contains(type.elementType)) {
+ switch(vop.type()) {
+ case VOPType.UNARY:
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.maskType, ")", vopInfo));
+ break;
+ case VOPType.ASSOCIATIVE:
+ case VOPType.INTEGRAL_ASSOCIATIVE:
+ if (vop.type() == VOPType.ASSOCIATIVE || !type.elementType.isFloating()) {
+ ops.add(Expression.make(type.elementType, "", type, ".reduceLanes(VectorOperators." + vop.name() + ")", vopInfo));
+ ops.add(Expression.make(type.elementType, "", type, ".reduceLanes(VectorOperators." + vop.name() + ", ", type.maskType, ")", vopInfo));
+ }
+ // fall-through
+ case VOPType.BINARY:
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ", ", type.maskType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", LONGS, ")", vopInfo.combineWith(WITH_ILLEGAL_ARGUMENT_EXCEPTION)));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", LONGS, ", ", type.maskType, ")", vopInfo.combineWith(WITH_ILLEGAL_ARGUMENT_EXCEPTION)));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ", ", type.maskType, ")", vopInfo));
+ break;
+ case VOPType.TERNARY:
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ", ", type.elementType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ", ", type.elementType, ", ", type.maskType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ", ", type, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type.elementType, ", ", type, ", ", type.maskType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ", ", type.elementType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ", ", type.elementType, ", ", type.maskType, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ", ", type, ")", vopInfo));
+ ops.add(Expression.make(type, "", type, ".lanewise(VectorOperators." + vop.name() + ", ", type, ", ", type, ", ", type.maskType, ")", vopInfo));
+ break;
+ }
+ }
+ }
+
+ ops.add(Expression.make(type.maskType, "", type, ".lt(", type.elementType, ")"));
+ ops.add(Expression.make(type.maskType, "", type, ".lt(", type, ")"));
+
+ ops.add(Expression.make(type.maskType, "", type, ".maskAll(", BOOLEANS, ")"));
+
+ ops.add(Expression.make(type, "", type, ".max(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".max(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".min(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".min(", type, ")"));
+
+ ops.add(Expression.make(type, "", type, ".mul(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".mul(", type.elementType, ", ", type.maskType, ")"));
+ ops.add(Expression.make(type, "", type, ".mul(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".mul(", type, ", ", type.maskType, ")"));
+
+ ops.add(Expression.make(type, "", type, ".neg()"));
+
+ ops.add(Expression.make(type, "", type, ".rearrange(", type.shuffleType, ")"));
+ ops.add(Expression.make(type, "", type, ".rearrange(", type.shuffleType, ", ", type, ")"));
+ ops.add(Expression.make(type, "", type, ".rearrange(", type.shuffleType, ", ", type.maskType, ")"));
+
+ ops.add(Expression.make(type, "", type, ".selectFrom(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".selectFrom(", type, ", ", type, ")"));
+ ops.add(Expression.make(type, "", type, ".selectFrom(", type, ", ", type.maskType, ")"));
+
+ ops.add(Expression.make(type, "", type, ".slice(", INTS, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".slice(", INTS, ", ", type, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".slice(", INTS, ", ", type, ", ", type.maskType, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+
+ ops.add(Expression.make(type, "", type, ".sub(", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".sub(", type.elementType, ", ", type.maskType, ")"));
+ ops.add(Expression.make(type, "", type, ".sub(", type, ")"));
+ ops.add(Expression.make(type, "", type, ".sub(", type, ", ", type.maskType, ")"));
+
+
+ for (VOP test : VECTOR_TEST) {
+ if (test.elementTypes().contains(type.elementType)) {
+ ops.add(Expression.make(type.maskType, "", type, ".test(VectorOperators." + test.name() + ")"));
+ ops.add(Expression.make(type.maskType, "", type, ".test(VectorOperators." + test.name() + ", ", type.maskType, ")"));
+ }
+ }
+
+ // skip toArray and friends
+
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, " & " + (type.length-1) + ")"));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, " & " + (type.length-1) + ", ", type, ", ", INTS, " & 2)"));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, ", ", type, ", 0)", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, ", ", type, ", ", INTS, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, ", ", type, ", 0, ", type.maskType, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type, "", type, ".unslice(", INTS, ", ", type, ", ", INTS, ", ", type.maskType, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+
+ ops.add(Expression.make(type, "", type, ".withLane(", INTS, ", ", type.elementType, ")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+
+ if (type.elementType.isFloating()) {
+ ops.add(Expression.make(type, "", type, ".fma(", type.elementType, ", ", type.elementType, ")"));
+ ops.add(Expression.make(type, "", type, ".fma(", type, ", ", type, ")"));
+
+ // TODO: enforce precision instead of just making it non-deterministic?
+ // See similar comment at VOP definition.
+ ops.add(Expression.make(type, "", type, ".pow(", type.elementType, ")", WITH_NONDETERMINISTIC_RESULT));
+ ops.add(Expression.make(type, "", type, ".pow(", type, ")", WITH_NONDETERMINISTIC_RESULT));
+ ops.add(Expression.make(type, "", type, ".sqrt()"));
+ }
+
+ ops.add(Expression.make(type.shuffleType, "", type, ".toShuffle()"));
+ // skip zero - can get it from type.con() anyway.
+
+ // ----------------- MaskVector --------------------
+ // skip fromValues, too many inputs
+ // skip fromArray
+ ops.add(Expression.make(type.maskType, "VectorMask.fromLong(" + type.speciesName + ", ", LONGS, ")"));
+ for (var type2 : CodeGenerationDataNameType.VECTOR_VECTOR_TYPES) {
+ var mask = type.maskType;
+ var mask2 = type2.maskType;
+ if (type.length == type2.length) {
+ ops.add(Expression.make(mask, "((" + mask.name() + ")", mask2 , ".cast(" + type.speciesName + "))"));
+ }
+ }
+ ops.add(Expression.make(LONGS, "", type.maskType , ".toLong()"));
+ // skip toArray
+ // skip intoArray
+ ops.add(Expression.make(BOOLEANS, "", type.maskType , ".anyTrue()"));
+ ops.add(Expression.make(BOOLEANS, "", type.maskType , ".allTrue()"));
+ ops.add(Expression.make(INTS, "", type.maskType , ".trueCount()"));
+ ops.add(Expression.make(INTS, "", type.maskType , ".firstTrue()"));
+ ops.add(Expression.make(INTS, "", type.maskType , ".lastTrue()"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".and(", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".or(", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".xor(", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".andNot(", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".eq(", type.maskType, ")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".not()"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".indexInRange(", INTS, ", ", INTS,")"));
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".indexInRange(", LONGS, ", ", LONGS,")"));
+ ops.add(Expression.make(type, "((" + type.name() + ")", type.maskType , ".toVector())"));
+ ops.add(Expression.make(BOOLEANS, "", type.maskType , ".laneIsSet(", INTS, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(BOOLEANS, "", type.maskType , ".laneIsSet(", INTS, " & " + (type.length-1) + ")"));
+ // skip check
+ // skip toString
+ // skip equals
+ // skip hashCode
+ ops.add(Expression.make(type.maskType, "", type.maskType , ".compress()"));
+
+ // ----------------- ShuffleVector --------------------
+ for (var type2 : CodeGenerationDataNameType.VECTOR_VECTOR_TYPES) {
+ var shuffle = type.shuffleType;
+ var shuffle2 = type2.shuffleType;
+ if (type.length == type2.length) {
+ ops.add(Expression.make(shuffle, "((" + shuffle.name() + ")", shuffle2 , ".cast(" + type.speciesName + "))"));
+ }
+ }
+ ops.add(Expression.make(INTS, "", type.shuffleType , ".checkIndex(", INTS, ")", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(INTS, "", type.shuffleType , ".wrapIndex(", INTS, ")"));
+ ops.add(Expression.make(type.shuffleType, "", type.shuffleType , ".checkIndexes()", WITH_OUT_OF_BOUNDS_EXCEPTION));
+ ops.add(Expression.make(type.shuffleType, "", type.shuffleType , ".wrapIndexes()"));
+ ops.add(Expression.make(type.maskType, "", type.shuffleType , ".laneIsValid()"));
+ // skip fromValues, too many inputs
+ // skip fromArray
+ // skip fromMemorySegment
+ // skip fromOp
+ // skip iota
+ // skip makeZip
+ // skip makeUnzip
+ // skip toArray
+ // skip intoArray
+ // skip intoMemorySegment
+ ops.add(Expression.make(type, "((" + type.name() + ")", type.shuffleType , ".toVector())"));
+ ops.add(Expression.make(INTS, "", type.shuffleType , ".laneSource(", INTS,")", WITH_ILLEGAL_ARGUMENT_EXCEPTION));
+ ops.add(Expression.make(INTS, "", type.shuffleType , ".laneSource(", INTS," & " + (type.length-1) + ")"));
+ ops.add(Expression.make(type.shuffleType, "", type.shuffleType, ".rearrange(", type.shuffleType, ")"));
+ // skip toString
+ // skip equals
+ // skip hashCode
+ }
+
+ // TODO: VectorSpecies API methods
+
+ // Make sure the list is not modifiable.
+ return List.copyOf(ops);
+ }
+
+ /**
+ * Provides a lits of operations on {@link PrimitiveType}s, such as arithmetic, logical,
+ * and cast operations.
+ */
+ public static final List PRIMITIVE_OPERATIONS = generatePrimitiveOperations();
+
+ public static final List FLOAT16_OPERATIONS = generateFloat16Operations();
+
+ public static final List SCALAR_NUMERIC_OPERATIONS = Utils.concat(
+ PRIMITIVE_OPERATIONS,
+ FLOAT16_OPERATIONS
+ );
+
+ public static final List VECTOR_OPERATIONS = generateVectorOperations();
+
+ public static final List ALL_OPERATIONS = Utils.concat(
+ SCALAR_NUMERIC_OPERATIONS,
+ VECTOR_OPERATIONS
+ );
}
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java
index b20dbb28d22..cd796fd0d31 100644
--- a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java
@@ -34,6 +34,7 @@
import compiler.lib.template_framework.Template;
import compiler.lib.template_framework.TemplateToken;
import static compiler.lib.template_framework.Template.scope;
+import static compiler.lib.template_framework.Template.let;
/**
* The {@link PrimitiveType} models Java's primitive types, and provides a set
@@ -281,6 +282,22 @@ public static double nextDouble() {
public static boolean nextBoolean() {
return RANDOM.nextBoolean();
}
+
+ """,
+ CodeGenerationDataNameType.PRIMITIVE_TYPES.stream().map(type -> scope(
+ let("type", type),
+ """
+ public static void fill(#type[] a) {
+ for (int i = 0; i < a.length; i++) {
+ """,
+ " a[i] = ", type.callLibraryRNG(), ";\n",
+ """
+ }
+ }
+ """
+ )).toList(),
+ """
+
}
"""
));
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/Utils.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/Utils.java
new file mode 100644
index 00000000000..b96ad830a4b
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/Utils.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.lib.template_framework.library;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.stream.Collectors;
+
+/**
+ * Package private class with some helpful utility methods, used in multiple
+ * places of the template library.
+ */
+final class Utils {
+ @SafeVarargs
+ public static List concat(List extends T>... lists) {
+ return Arrays.stream(lists)
+ .flatMap(List::stream)
+ .collect(Collectors.toList());
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/VectorType.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/VectorType.java
new file mode 100644
index 00000000000..7eabd42a723
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/VectorType.java
@@ -0,0 +1,237 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+package compiler.lib.template_framework.library;
+
+import java.util.List;
+import java.util.stream.Stream;
+import java.util.Random;
+import jdk.test.lib.Utils;
+
+import compiler.lib.template_framework.DataName;
+import static compiler.lib.template_framework.library.PrimitiveType.BYTES;
+import static compiler.lib.template_framework.library.PrimitiveType.SHORTS;
+import static compiler.lib.template_framework.library.PrimitiveType.INTS;
+import static compiler.lib.template_framework.library.PrimitiveType.LONGS;
+import static compiler.lib.template_framework.library.PrimitiveType.FLOATS;
+import static compiler.lib.template_framework.library.PrimitiveType.DOUBLES;
+import static compiler.lib.template_framework.library.PrimitiveType.BOOLEANS;
+
+/**
+ * The {@link VectorType} models the Vector API types.
+ */
+public abstract class VectorType implements CodeGenerationDataNameType {
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ public static final VectorType.Vector BYTE_64 = new VectorType.Vector(BYTES, 8);
+ public static final VectorType.Vector BYTE_128 = new VectorType.Vector(BYTES, 16);
+ public static final VectorType.Vector BYTE_256 = new VectorType.Vector(BYTES, 32);
+ public static final VectorType.Vector BYTE_512 = new VectorType.Vector(BYTES, 64);
+
+ public static final VectorType.Vector SHORT_64 = new VectorType.Vector(SHORTS, 4);
+ public static final VectorType.Vector SHORT_128 = new VectorType.Vector(SHORTS, 8);
+ public static final VectorType.Vector SHORT_256 = new VectorType.Vector(SHORTS, 16);
+ public static final VectorType.Vector SHORT_512 = new VectorType.Vector(SHORTS, 32);
+
+ public static final VectorType.Vector INT_64 = new VectorType.Vector(INTS, 2);
+ public static final VectorType.Vector INT_128 = new VectorType.Vector(INTS, 4);
+ public static final VectorType.Vector INT_256 = new VectorType.Vector(INTS, 8);
+ public static final VectorType.Vector INT_512 = new VectorType.Vector(INTS, 16);
+
+ public static final VectorType.Vector LONG_64 = new VectorType.Vector(LONGS, 1);
+ public static final VectorType.Vector LONG_128 = new VectorType.Vector(LONGS, 2);
+ public static final VectorType.Vector LONG_256 = new VectorType.Vector(LONGS, 4);
+ public static final VectorType.Vector LONG_512 = new VectorType.Vector(LONGS, 8);
+
+ public static final VectorType.Vector FLOAT_64 = new VectorType.Vector(FLOATS, 2);
+ public static final VectorType.Vector FLOAT_128 = new VectorType.Vector(FLOATS, 4);
+ public static final VectorType.Vector FLOAT_256 = new VectorType.Vector(FLOATS, 8);
+ public static final VectorType.Vector FLOAT_512 = new VectorType.Vector(FLOATS, 16);
+
+ public static final VectorType.Vector DOUBLE_64 = new VectorType.Vector(DOUBLES, 1);
+ public static final VectorType.Vector DOUBLE_128 = new VectorType.Vector(DOUBLES, 2);
+ public static final VectorType.Vector DOUBLE_256 = new VectorType.Vector(DOUBLES, 4);
+ public static final VectorType.Vector DOUBLE_512 = new VectorType.Vector(DOUBLES, 8);
+
+ private final String vectorTypeName;
+
+ private VectorType(String vectorTypeName) {
+ this.vectorTypeName = vectorTypeName;
+ }
+
+ @Override
+ public final String name() {
+ return vectorTypeName;
+ }
+
+ @Override
+ public String toString() {
+ return name();
+ }
+
+ @Override
+ public boolean isSubtypeOf(DataName.Type other) {
+ // Each type has a unique instance.
+ return this == other;
+ }
+
+ private static final String vectorTypeName(PrimitiveType elementType) {
+ return switch(elementType.name()) {
+ case "byte" -> "ByteVector";
+ case "short" -> "ShortVector";
+ case "char" -> throw new UnsupportedOperationException("VectorAPI has no char vector type");
+ case "int" -> "IntVector";
+ case "long" -> "LongVector";
+ case "float" -> "FloatVector";
+ case "double" -> "DoubleVector";
+ default -> throw new UnsupportedOperationException("Not supported: " + elementType.name());
+ };
+ }
+
+ public static final class Vector extends VectorType {
+ public final PrimitiveType elementType;
+ public final int length; // lane count
+ public final String speciesName;
+
+ public final Mask maskType;
+ public final Shuffle shuffleType;
+
+ private Vector(PrimitiveType elementType, int length) {
+ super(vectorTypeName(elementType));
+ this.elementType = elementType;
+ this.length = length;
+ this.speciesName = name() + ".SPECIES_" + (byteSize() * 8);
+ this.maskType = new Mask(this);
+ this.shuffleType = new Shuffle(this);
+ }
+
+ @Override
+ public final Object con() {
+ int r = RANDOM.nextInt(64);
+ if (r == 0) {
+ return List.of(name(), ".zero(", speciesName, ")");
+ } else if (r <= 8) {
+ return List.of(
+ name(), ".fromArray(", speciesName, ", new ", elementType.name(), "[] {",
+ elementType.con(),
+ Stream.generate(() ->
+ List.of(", ", elementType.con())
+ ).limit(length - 1).toList(),
+ "}, 0)"
+ );
+ } else {
+ return List.of(name(), ".broadcast(", speciesName, ", ", elementType.con(), ")");
+ }
+ }
+
+ public int byteSize() {
+ return elementType.byteSize() * length;
+ }
+ }
+
+ public static final class Mask extends VectorType {
+ public final Vector vectorType;
+
+ private Mask(Vector vectorType) {
+ super("VectorMask<" + vectorType.elementType.boxedTypeName() + ">");
+ this.vectorType = vectorType;
+ }
+
+ @Override
+ public final Object con() {
+ int r = RANDOM.nextInt(64);
+ if (r <= 8) {
+ return List.of(
+ "VectorMask.fromArray(", vectorType.speciesName, ", new boolean[] {",
+ BOOLEANS.con(),
+ Stream.generate(() ->
+ List.of(", ", BOOLEANS.con())
+ ).limit(vectorType.length - 1).toList(),
+ "}, 0)"
+ );
+ } else if (r <= 16) {
+ return List.of(
+ "VectorMask.fromValues(", vectorType.speciesName,
+ Stream.generate(() ->
+ List.of(", ", BOOLEANS.con())
+ ).limit(vectorType.length).toList(),
+ ")"
+ );
+ } else if (r <= 24) {
+ // All true or all false
+ var tf = BOOLEANS.con();
+ return List.of(
+ "VectorMask.fromValues(", vectorType.speciesName,
+ Stream.generate(() ->
+ List.of(", ", tf)
+ ).limit(vectorType.length).toList(),
+ ")"
+ );
+ } else {
+ return List.of("VectorMask.fromLong(", vectorType.speciesName, ", ", LONGS.con(), ")");
+ }
+ }
+ }
+
+ public static final class Shuffle extends VectorType {
+ public final Vector vectorType;
+
+ private Shuffle(Vector vectorType) {
+ super("VectorShuffle<" + vectorType.elementType.boxedTypeName() + ">");
+ this.vectorType = vectorType;
+ }
+
+ @Override
+ public final Object con() {
+ int r = RANDOM.nextInt(64);
+ if (r <= 8) {
+ return List.of(
+ "VectorShuffle.fromArray(", vectorType.speciesName, ", new int[] {",
+ INTS.con(),
+ Stream.generate(() ->
+ List.of(", ", INTS.con())
+ ).limit(vectorType.length - 1).toList(),
+ "}, 0)"
+ );
+ } else if (r <= 16) {
+ return List.of(
+ "VectorShuffle.fromValues(", vectorType.speciesName,
+ Stream.generate(() ->
+ List.of(", ", INTS.con())
+ ).limit(vectorType.length).toList(),
+ ")"
+ );
+ } else if (r <= 24) {
+ return List.of("VectorShuffle.makeZip(", vectorType.speciesName, ", ", RANDOM.nextInt(2), ")");
+ } else if (r <= 32) {
+ return List.of("VectorShuffle.makeUnzip(", vectorType.speciesName, ", ", RANDOM.nextInt(2), ")");
+ } else if (r <= 40) {
+ return List.of("VectorShuffle.fromOp(", vectorType.speciesName, ", i -> ",
+ INTS.con(), " + i * ", INTS.con(), " + i * i * ", INTS.con(), ")");
+ } else {
+ return List.of("VectorShuffle.iota(", vectorType.speciesName, ", ",
+ INTS.con(), ", ", INTS.con(), ", true)");
+ }
+ }
+ }
+}
diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java
new file mode 100644
index 00000000000..ea36cca4b92
--- /dev/null
+++ b/test/hotspot/jtreg/compiler/vectorapi/VectorExpressionFuzzer.java
@@ -0,0 +1,345 @@
+/*
+ * Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+/*
+ * @test id=AVX2
+ * @bug 8369699
+ * @key randomness
+ * @summary Test the Template Library's expression generation for the Vector API.
+ * @requires os.family == "linux" & os.simpleArch == "x64"
+ * @modules jdk.incubator.vector
+ * @modules java.base/jdk.internal.misc
+ * @library /test/lib /
+ * @compile ../../compiler/lib/verify/Verify.java
+ * @run driver ${test.main.class} -XX:UseAVX=2
+ */
+
+// TODO: remove the x64 and linux restriction above. I added that for now so we are not flooded
+// with failures in the CI. We should remove these restriction once more bugs are fixed.
+// x64 linux is the easiest to debug on for me, that's why I picked it.
+// In addition, I put a UseAVX=2 restriction below, to avoid AVX512 bugs for now.
+//
+// A trick to extend this to other platforms: create a new run block, so you have full
+// freedom to restrict it as necessary for platform and vector features.
+
+package compiler.vectorapi;
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.Random;
+import jdk.test.lib.Utils;
+import java.util.stream.IntStream;
+
+import compiler.lib.compile_framework.CompileFramework;
+
+import compiler.lib.template_framework.Template;
+import compiler.lib.template_framework.TemplateToken;
+import static compiler.lib.template_framework.Template.scope;
+import static compiler.lib.template_framework.Template.let;
+import static compiler.lib.template_framework.Template.$;
+import compiler.lib.template_framework.library.CodeGenerationDataNameType;
+import compiler.lib.template_framework.library.Expression;
+import compiler.lib.template_framework.library.Expression.Nesting;
+import compiler.lib.template_framework.library.Operations;
+import compiler.lib.template_framework.library.TestFrameworkClass;
+import compiler.lib.template_framework.library.PrimitiveType;
+import compiler.lib.template_framework.library.VectorType;
+
+/**
+ * Basic Expression Fuzzer for Vector API.
+ */
+public class VectorExpressionFuzzer {
+ private static final Random RANDOM = Utils.getRandomInstance();
+
+ public static void main(String[] args) {
+ // Create a new CompileFramework instance.
+ CompileFramework comp = new CompileFramework();
+
+ // Add a java source file.
+ comp.addJavaSourceCode("compiler.vectorapi.templated.Templated", generate(comp));
+
+ // Compile the source file.
+ comp.compile("--add-modules=jdk.incubator.vector");
+
+ List vmArgs = new ArrayList<>(List.of(
+ "--add-modules=jdk.incubator.vector",
+ "--add-opens", "jdk.incubator.vector/jdk.incubator.vector=ALL-UNNAMED",
+ "--add-opens", "java.base/java.lang=ALL-UNNAMED"
+ ));
+ vmArgs.addAll(Arrays.asList(args)); // Forward args
+ String[] vmArgsArray = vmArgs.toArray(new String[0]);
+
+ // compiler.vectorapi.templated.InnterTest.main(new String[] {});
+ comp.invoke("compiler.vectorapi.templated.Templated", "main", new Object[] { vmArgsArray } );
+ }
+
+ // For Example 2 below.
+ record TestArgument(
+ Object defineAndFill, // used once: to define and fill the input value
+ Object passMethodArgument, // used twice: to pass argument to test and reference
+ Object receiveMethodArgument, // used twice: to receive argument in test and reference
+ Object use) {} // used twice: to use the value as expression argument
+
+ // Generate a source Java file as String
+ public static String generate(CompileFramework comp) {
+ // Generate a list of test methods.
+ List tests = new ArrayList<>();
+
+ // We are going to use some random numbers in our tests, so import some good methods for that.
+ tests.add(PrimitiveType.generateLibraryRNG());
+
+ // Example 1:
+ // To start simple, we just call the expression with the same constant arguments
+ // every time. We can still compare the "gold" value obtained via interpreter with
+ // later results obtained from the compiled method.
+ var template1 = Template.make("type", (VectorType.Vector type) -> {
+ // The depth determines roughly how many operations are going to be used in the expression.
+ int depth = RANDOM.nextInt(1, 10);
+ Expression expression = Expression.nestRandomly(type, Operations.ALL_OPERATIONS, depth, Nesting.EXACT);
+ List