From 7da91533aaf2033cedee6e2a56fb693f26909df5 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Mon, 8 Dec 2025 09:06:21 +0000 Subject: [PATCH 001/211] 8369950: TLS connection to IPv6 address fails with BCJSSE due to IllegalArgumentException Co-authored-by: Mikhail Yankelevich Reviewed-by: djelinski, vyazici, dfuchs, myankelevich --- .../net/www/protocol/https/HttpsClient.java | 11 +- .../HttpsURLConnection/SubjectAltNameIP.java | 379 ++++++++++++++++++ 2 files changed, 388 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java diff --git a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java index 2f011f5805b..9f1d7b07021 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java +++ b/src/java.base/share/classes/sun/net/www/protocol/https/HttpsClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -44,6 +44,7 @@ import java.util.Objects; import java.util.StringTokenizer; import javax.net.ssl.*; +import sun.net.util.IPAddressUtil; import sun.net.www.http.HttpClient; import sun.net.www.protocol.http.AuthCacheImpl; import sun.net.www.protocol.http.HttpURLConnection; @@ -471,7 +472,13 @@ final class HttpsClient extends HttpClient SSLParameters parameters = s.getSSLParameters(); parameters.setEndpointIdentificationAlgorithm("HTTPS"); // host has been set previously for SSLSocketImpl - if (!(s instanceof SSLSocketImpl)) { + if (!(s instanceof SSLSocketImpl) && + !IPAddressUtil.isIPv4LiteralAddress(host) && + !(host.charAt(0) == '[' && host.charAt(host.length() - 1) == ']' && + IPAddressUtil.isIPv6LiteralAddress(host.substring(1, host.length() - 1)) + )) { + // Fully qualified DNS hostname of the server, as per section 3, RFC 6066 + // Literal IPv4 and IPv6 addresses are not permitted in "HostName". parameters.setServerNames(List.of(new SNIHostName(host))); } s.setSSLParameters(parameters); diff --git a/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java b/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java new file mode 100644 index 00000000000..2def2f69d6e --- /dev/null +++ b/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8369950 + * @summary Test that the HttpsURLConnection does not set IP address literals for + * SNI hostname during TLS handshake + * @library /test/lib + * @modules java.base/sun.net.util + * @comment Insert -Djavax.net.debug=all into the following lines to enable SSL debugging + * @run main/othervm SubjectAltNameIP 127.0.0.1 + * @run main/othervm SubjectAltNameIP [::1] + */ + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLServerSocketFactory; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.BufferedWriter; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.Socket; +import java.net.SocketAddress; +import java.net.URI; +import java.util.concurrent.CountDownLatch; +import java.util.function.Consumer; + +import jdk.test.lib.Asserts; +import jdk.test.lib.net.IPSupport; +import jdk.test.lib.net.SimpleSSLContext; +import jtreg.SkippedException; +import sun.net.util.IPAddressUtil; + +public class SubjectAltNameIP { + + // Is the server ready to serve? + private final CountDownLatch serverReady = new CountDownLatch(1); + + // Use any free port by default. + volatile int serverPort = 0; + + // Stores an exception thrown by server in a separate thread. + volatile Exception serverException = null; + + // SSLSocket object created by HttpsClient internally. + SSLSocket clientSSLSocket = null; + + // The hostname the server socket is bound to. + String hostName; + + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; + + // Read until the end of the request. + void readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + break; + } + } else { + requestEndCount = 0; + } + } + } + + /* + * Define the server side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doServerSide() throws Exception { + SSLServerSocketFactory sslssf = + new SimpleSSLContext().get().getServerSocketFactory(); + SSLServerSocket sslServerSocket = + (SSLServerSocket) sslssf.createServerSocket( + serverPort, 0, + InetAddress.getByName(hostName)); + sslServerSocket.setEnabledProtocols(new String[]{"TLSv1.3"}); + serverPort = sslServerSocket.getLocalPort(); + + /* + * Signal the client, the server is ready to accept connection. + */ + serverReady.countDown(); + + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); + OutputStream sslOS = sslSocket.getOutputStream(); + BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(sslOS)); + bw.write("HTTP/1.1 200 OK\r\n\r\n"); + bw.flush(); + readOneRequest(sslSocket.getInputStream()); + sslSocket.close(); + } + + /* + * Define the client side of the test. + * + * If the server prematurely exits, serverReady will be set to true + * to avoid infinite hangs. + */ + void doClientSide() throws Exception { + + /* + * Wait for server to get started. + */ + serverReady.await(); + if (serverException != null) { + throw new RuntimeException("Server failed to start.", serverException); + } + + SSLSocketFactory sf = new SimpleSSLContext().get().getSocketFactory(); + URI uri = new URI("https://" + hostName + ":" + serverPort + "/index.html"); + HttpsURLConnection conn = (HttpsURLConnection)uri.toURL().openConnection(); + + /* + * Simulate an external JSSE implementation and store the client SSLSocket + * used internally. + */ + conn.setSSLSocketFactory(wrapSocketFactory(sf, + sslSocket -> { + Asserts.assertEquals(null, clientSSLSocket, "clientSSLSocket is"); + clientSSLSocket = sslSocket; + })); + conn.getInputStream(); + + var sniSN = clientSSLSocket.getSSLParameters().getServerNames(); + if (sniSN != null && !sniSN.isEmpty()) { + throw new RuntimeException("SNI server name '" + + sniSN.getFirst() + "' must not be set."); + } + + if (conn.getResponseCode() == -1) { + throw new RuntimeException("getResponseCode() returns -1"); + } + } + + public static void main(String[] args) throws Exception { + + if (IPAddressUtil.isIPv6LiteralAddress(args[0]) && !IPSupport.hasIPv6()) { + throw new SkippedException("Skipping test - IPv6 is not supported"); + } + /* + * Start the tests. + */ + new SubjectAltNameIP(args[0]); + } + + Thread serverThread = null; + + /* + * Primary constructor, used to drive remainder of the test. + * + * Fork off the other side, then do your work. + */ + SubjectAltNameIP(String host) throws Exception { + hostName = host; + startServer(); + doClientSide(); + + /* + * Wait for other side to close down. + */ + serverThread.join(); + + if (serverException != null) + throw serverException; + } + + void startServer() { + serverThread = new Thread(() -> { + try { + doServerSide(); + } catch (Exception e) { + /* + * Our server thread just died. + * + * Store the exception and release the client. + */ + serverException = e; + serverReady.countDown(); + } + }); + serverThread.start(); + } + + /* + * Wraps SSLSocketImpl to simulate a different JSSE implementation + */ + private static SSLSocketFactory wrapSocketFactory(final SSLSocketFactory wrap, final Consumer store) { + return new SSLSocketFactory() { + @Override + public String[] getDefaultCipherSuites() { + return wrap.getDefaultCipherSuites(); + } + @Override + public String[] getSupportedCipherSuites() { + return wrap.getSupportedCipherSuites(); + } + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) + throws IOException { + final SSLSocket so = + (SSLSocket) wrap.createSocket(s, host, port, autoClose); + + // store the underlying SSLSocket for later use + store.accept(so); + + return new SSLSocket() { + @Override + public void connect(SocketAddress endpoint, + int timeout) throws IOException { + so.connect(endpoint, timeout); + } + @Override + public String[] getSupportedCipherSuites() { + return so.getSupportedCipherSuites(); + } + @Override + public String[] getEnabledCipherSuites() { + return so.getEnabledCipherSuites(); + } + @Override + public void setEnabledCipherSuites(String[] suites) { + so.setEnabledCipherSuites(suites); + } + @Override + public String[] getSupportedProtocols() { + return so.getSupportedProtocols(); + } + @Override + public String[] getEnabledProtocols() { + return so.getEnabledProtocols(); + } + @Override + public void setEnabledProtocols(String[] protocols) { + so.setEnabledProtocols(protocols); + } + @Override + public SSLSession getSession() { + return so.getSession(); + } + @Override + public SSLSession getHandshakeSession() { + return so.getHandshakeSession(); + } + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { + so.addHandshakeCompletedListener(listener); + } + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { + so.removeHandshakeCompletedListener(listener); + } + @Override + public void startHandshake() throws IOException { + so.startHandshake(); + } + @Override + public void setUseClientMode(boolean mode) { + so.setUseClientMode(mode); + } + @Override + public boolean getUseClientMode() { + return so.getUseClientMode(); + } + @Override + public void setNeedClientAuth(boolean need) { + } + @Override + public boolean getNeedClientAuth() { + return false; + } + @Override + public void setWantClientAuth(boolean want) { + } + @Override + public boolean getWantClientAuth() { + return false; + } + @Override + public void setEnableSessionCreation(boolean flag) { + so.setEnableSessionCreation(flag); + } + @Override + public boolean getEnableSessionCreation() { + return so.getEnableSessionCreation(); + } + @Override + public void close() throws IOException { + so.close(); + } + @Override + public boolean isClosed() { + return so.isClosed(); + } + @Override + public void shutdownInput() throws IOException { + so.shutdownInput(); + } + @Override + public boolean isInputShutdown() { + return so.isInputShutdown(); + } + @Override + public void shutdownOutput() throws IOException { + so.shutdownOutput(); + } + @Override + public boolean isOutputShutdown() { + return so.isOutputShutdown(); + } + @Override + public InputStream getInputStream() throws IOException { + return so.getInputStream(); + } + @Override + public OutputStream getOutputStream() throws IOException { + return so.getOutputStream(); + } + @Override + public SSLParameters getSSLParameters() { + return so.getSSLParameters(); + } + @Override + public void setSSLParameters(SSLParameters params) { + so.setSSLParameters(params); + } + }; + } + @Override + public Socket createSocket(String h, int p) { + return null; + } + @Override + public Socket createSocket(String h, int p, InetAddress ipa, int lp) { + return null; + } + @Override + public Socket createSocket(InetAddress h, int p) { + return null; + } + @Override + public Socket createSocket(InetAddress a, int p, InetAddress l, int lp) { + return null; + } + }; + } +} From 350015088281eb9e6e9e3a9811f38adac5f7a975 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 8 Dec 2025 10:04:44 +0000 Subject: [PATCH 002/211] 8373094: javac may fail because of unattributed break in a loop Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Attr.java | 16 +- .../tools/javac/recovery/AttrRecovery.java | 158 +++++++++++++++++- 2 files changed, 167 insertions(+), 7 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java index 3f72ada94e8..cc21113882f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Attr.java @@ -5634,12 +5634,16 @@ public class Attr extends JCTree.Visitor { chk.validateRepeatable(c, repeatable, cbPos); } } else { - // Check that all extended classes and interfaces - // are compatible (i.e. no two define methods with same arguments - // yet different return types). (JLS 8.4.8.3) - chk.checkCompatibleSupertypes(tree.pos(), c.type); - chk.checkDefaultMethodClashes(tree.pos(), c.type); - chk.checkPotentiallyAmbiguousOverloads(tree, c.type); + try { + // Check that all extended classes and interfaces + // are compatible (i.e. no two define methods with same arguments + // yet different return types). (JLS 8.4.8.3) + chk.checkCompatibleSupertypes(tree.pos(), c.type); + chk.checkDefaultMethodClashes(tree.pos(), c.type); + chk.checkPotentiallyAmbiguousOverloads(tree, c.type); + } catch (CompletionFailure cf) { + chk.completionError(tree.pos(), cf); + } } // Check that class does not import the same parameterized interface diff --git a/test/langtools/tools/javac/recovery/AttrRecovery.java b/test/langtools/tools/javac/recovery/AttrRecovery.java index 9a37ce60654..ac1455e71d7 100644 --- a/test/langtools/tools/javac/recovery/AttrRecovery.java +++ b/test/langtools/tools/javac/recovery/AttrRecovery.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 + * @bug 8301580 8322159 8333107 8332230 8338678 8351260 8366196 8372336 8373094 * @summary Verify error recovery w.r.t. Attr * @library /tools/lib * @modules jdk.compiler/com.sun.tools.javac.api @@ -32,8 +32,11 @@ * @run main AttrRecovery */ +import com.sun.source.tree.IdentifierTree; import com.sun.source.tree.MemberReferenceTree; +import com.sun.source.tree.MemberSelectTree; import com.sun.source.tree.MethodInvocationTree; +import com.sun.source.tree.MethodTree; import com.sun.source.tree.VariableTree; import com.sun.source.util.TaskEvent; import com.sun.source.util.TaskListener; @@ -41,11 +44,13 @@ import com.sun.source.util.TreePathScanner; import com.sun.source.util.Trees; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; import java.util.IdentityHashMap; import java.util.List; import java.util.Map; import java.util.Objects; import java.util.stream.Collectors; +import java.util.stream.Stream; import javax.lang.model.element.Element; import javax.lang.model.element.VariableElement; import javax.lang.model.type.DeclaredType; @@ -495,4 +500,155 @@ public class AttrRecovery extends TestRunner { } } } + + @Test //JDK-8373094 + public void testSensibleAttribution() throws Exception { + Path curPath = Path.of("."); + Path lib = curPath.resolve("lib"); + Path classes = lib.resolve("classes"); + Files.createDirectories(classes); + new JavacTask(tb) + .outdir(classes) + .sources(""" + package test; + public class Intermediate extends Base {} + """, + """ + package test; + public class Base { + public void t(Missing m) {} + } + """, + """ + package test; + public class Missing { + } + """) + .run() + .writeAll(); + + Files.delete(classes.resolve("test").resolve("Missing.class")); + + record TestCase(String code, List options, String... expectedErrors) {} + TestCase[] testCases = new TestCase[] { + new TestCase(""" + package test; + public class Test extends Intermediate { + private void test() { + int i = 0; + System.err.println(i); + while (true) { + break; + } + } + } + """, + List.of(), + "Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)", + "1 error"), + new TestCase(""" + package test; + public class Test extends Intermediate { + private void test() { + int i = 0; + System.err.println(i); + while (true) { + break; + } + } + } + """, + List.of("-XDshould-stop.at=FLOW"), + "Test.java:2:8: compiler.err.cant.access: test.Missing, (compiler.misc.class.file.not.found: test.Missing)", + "1 error"), + }; + + for (TestCase tc : testCases) { + List attributes = new ArrayList<>(); + List actual = new JavacTask(tb) + .options(Stream.concat(List.of("-XDrawDiagnostics", "-XDdev").stream(), + tc.options.stream()).toList()) + .classpath(classes) + .sources(tc.code()) + .outdir(curPath) + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void finished(TaskEvent e) { + if (e.getKind() != TaskEvent.Kind.ANALYZE) { + return ; + } + Trees trees = Trees.instance(task); + new TreePathScanner() { + boolean check; + + @Override + public Void visitMethod(MethodTree node, Void p) { + if (node.getName().contentEquals("test")) { + check = true; + try { + return super.visitMethod(node, p); + } finally { + check = false; + } + } + + return super.visitMethod(node, p); + } + + @Override + public Void visitMethodInvocation(MethodInvocationTree node, Void p) { + if (!node.toString().contains("super")) { + verifyElement(); + } + return super.visitMethodInvocation(node, p); + } + + @Override + public Void visitIdentifier(IdentifierTree node, Void p) { + verifyElement(); + return super.visitIdentifier(node, p); + } + + @Override + public Void visitMemberSelect(MemberSelectTree node, Void p) { + verifyElement(); + return super.visitMemberSelect(node, p); + } + + private void verifyElement() { + if (!check) { + return ; + } + + Element el = trees.getElement(getCurrentPath()); + if (el == null) { + error("Unattributed tree: " + getCurrentPath().getLeaf()); + } else { + attributes.add(el.toString()); + } + } + }.scan(e.getCompilationUnit(), null); + } + }); + }) + .run(Expect.FAIL) + .writeAll() + .getOutputLines(OutputKind.DIRECT); + + List expectedErrors = List.of(tc.expectedErrors); + + if (!Objects.equals(actual, expectedErrors)) { + error("Expected: " + expectedErrors + ", but got: " + actual); + } + + List expectedAttributes = + List.of("println(int)", "println(int)", "err", "java.lang.System", "i"); + + if (!Objects.equals(attributes, expectedAttributes)) { + error("Expected: " + expectedAttributes + ", but got: " + attributes); + } + } + } + } From a6594794839807d56434d6f28fe3d581fb1e36c0 Mon Sep 17 00:00:00 2001 From: Francesco Andreuzzi Date: Mon, 8 Dec 2025 11:45:53 +0000 Subject: [PATCH 003/211] 8367541: Parallel: Make young and old generation fields nonstatic in ParallelScavengeHeap Reviewed-by: ayang --- src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp | 2 -- src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp | 8 ++++---- src/hotspot/share/gc/parallel/psScavenge.hpp | 2 +- src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp | 4 ++-- 4 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index 9df3deedf89..b85b16f58b5 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -58,8 +58,6 @@ #include "utilities/macros.hpp" #include "utilities/vmError.hpp" -PSYoungGen* ParallelScavengeHeap::_young_gen = nullptr; -PSOldGen* ParallelScavengeHeap::_old_gen = nullptr; PSAdaptiveSizePolicy* ParallelScavengeHeap::_size_policy = nullptr; GCPolicyCounters* ParallelScavengeHeap::_gc_policy_counters = nullptr; size_t ParallelScavengeHeap::_desired_page_size = 0; diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp index 5d8ddbcaaed..588ddfa3f0c 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.hpp @@ -69,8 +69,8 @@ class ReservedSpace; class ParallelScavengeHeap : public CollectedHeap { friend class VMStructs; private: - static PSYoungGen* _young_gen; - static PSOldGen* _old_gen; + PSYoungGen* _young_gen; + PSOldGen* _old_gen; // Sizing policy for entire heap static PSAdaptiveSizePolicy* _size_policy; @@ -160,8 +160,8 @@ public: GrowableArray memory_managers() override; GrowableArray memory_pools() override; - static PSYoungGen* young_gen() { return _young_gen; } - static PSOldGen* old_gen() { return _old_gen; } + PSYoungGen* young_gen() const { return _young_gen; } + PSOldGen* old_gen() const { return _old_gen; } PSAdaptiveSizePolicy* size_policy() { return _size_policy; } diff --git a/src/hotspot/share/gc/parallel/psScavenge.hpp b/src/hotspot/share/gc/parallel/psScavenge.hpp index af9b91f74bc..df97a1c1ede 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.hpp +++ b/src/hotspot/share/gc/parallel/psScavenge.hpp @@ -115,7 +115,7 @@ class PSScavenge: AllStatic { } static bool is_obj_in_to_space(oop o) { - return ParallelScavengeHeap::young_gen()->to_space()->contains(o); + return ParallelScavengeHeap::heap()->young_gen()->to_space()->contains(o); } }; diff --git a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp index f5e7375fca1..e45bd45400c 100644 --- a/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp +++ b/src/hotspot/share/gc/parallel/vmStructs_parallelgc.hpp @@ -64,8 +64,8 @@ nonstatic_field(PSOldGen, _max_gen_size, const size_t) \ \ \ - static_field(ParallelScavengeHeap, _young_gen, PSYoungGen*) \ - static_field(ParallelScavengeHeap, _old_gen, PSOldGen*) \ + nonstatic_field(ParallelScavengeHeap, _young_gen, PSYoungGen*) \ + nonstatic_field(ParallelScavengeHeap, _old_gen, PSOldGen*) \ \ #define VM_TYPES_PARALLELGC(declare_type, \ From b83bf0717eb8926efcf85a32be08f33a41bb48dd Mon Sep 17 00:00:00 2001 From: Qizheng Xing Date: Mon, 8 Dec 2025 13:16:39 +0000 Subject: [PATCH 004/211] 8360192: C2: Make the type of count leading/trailing zero nodes more precise Reviewed-by: qamai, epeter, jbhateja --- src/hotspot/share/opto/countbitsnode.cpp | 149 +++-- .../compiler/c2/gvn/TestCountBitsRange.java | 570 ++++++++++++++++++ .../compiler/lib/ir_framework/IRNode.java | 20 + .../bench/vm/compiler/CountLeadingZeros.java | 74 +++ 4 files changed, 747 insertions(+), 66 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/CountLeadingZeros.java diff --git a/src/hotspot/share/opto/countbitsnode.cpp b/src/hotspot/share/opto/countbitsnode.cpp index aac874e94b1..1601b33ea2b 100644 --- a/src/hotspot/share/opto/countbitsnode.cpp +++ b/src/hotspot/share/opto/countbitsnode.cpp @@ -26,97 +26,114 @@ #include "opto/opcodes.hpp" #include "opto/phaseX.hpp" #include "opto/type.hpp" +#include "utilities/count_leading_zeros.hpp" +#include "utilities/count_trailing_zeros.hpp" #include "utilities/population_count.hpp" +static int count_leading_zeros_int(jint i) { + return i == 0 ? BitsPerInt : count_leading_zeros(i); +} + +static int count_leading_zeros_long(jlong l) { + return l == 0 ? BitsPerLong : count_leading_zeros(l); +} + +static int count_trailing_zeros_int(jint i) { + return i == 0 ? BitsPerInt : count_trailing_zeros(i); +} + +static int count_trailing_zeros_long(jlong l) { + return l == 0 ? BitsPerLong : count_trailing_zeros(l); +} + //------------------------------Value------------------------------------------ const Type* CountLeadingZerosINode::Value(PhaseGVN* phase) const { const Type* t = phase->type(in(1)); - if (t == Type::TOP) return Type::TOP; - const TypeInt* ti = t->isa_int(); - if (ti && ti->is_con()) { - jint i = ti->get_con(); - // HD, Figure 5-6 - if (i == 0) - return TypeInt::make(BitsPerInt); - int n = 1; - unsigned int x = i; - if (x >> 16 == 0) { n += 16; x <<= 16; } - if (x >> 24 == 0) { n += 8; x <<= 8; } - if (x >> 28 == 0) { n += 4; x <<= 4; } - if (x >> 30 == 0) { n += 2; x <<= 2; } - n -= x >> 31; - return TypeInt::make(n); + if (t == Type::TOP) { + return Type::TOP; } - return TypeInt::INT; + + // To minimize `count_leading_zeros(x)`, we should make the highest 1 bit in x + // as far to the left as possible. A bit in x can be 1 iff this bit is not + // forced to be 0, i.e. the corresponding bit in `x._bits._zeros` is 0. Thus: + // min(clz(x)) = number of bits to the left of the highest 0 bit in x._bits._zeros + // = count_leading_ones(x._bits._zeros) = clz(~x._bits._zeros) + // + // To maximize `count_leading_zeros(x)`, we should make the leading zeros as + // many as possible. A bit in x can be 0 iff this bit is not forced to be 1, + // i.e. the corresponding bit in `x._bits._ones` is 0. Thus: + // max(clz(x)) = clz(x._bits._ones) + // + // Therefore, the range of `count_leading_zeros(x)` is: + // [clz(~x._bits._zeros), clz(x._bits._ones)] + // + // A more detailed proof using Z3 can be found at: + // https://github.com/openjdk/jdk/pull/25928#discussion_r2256750507 + const TypeInt* ti = t->is_int(); + return TypeInt::make(count_leading_zeros_int(~ti->_bits._zeros), + count_leading_zeros_int(ti->_bits._ones), + ti->_widen); } //------------------------------Value------------------------------------------ const Type* CountLeadingZerosLNode::Value(PhaseGVN* phase) const { const Type* t = phase->type(in(1)); - if (t == Type::TOP) return Type::TOP; - const TypeLong* tl = t->isa_long(); - if (tl && tl->is_con()) { - jlong l = tl->get_con(); - // HD, Figure 5-6 - if (l == 0) - return TypeInt::make(BitsPerLong); - int n = 1; - unsigned int x = (((julong) l) >> 32); - if (x == 0) { n += 32; x = (int) l; } - if (x >> 16 == 0) { n += 16; x <<= 16; } - if (x >> 24 == 0) { n += 8; x <<= 8; } - if (x >> 28 == 0) { n += 4; x <<= 4; } - if (x >> 30 == 0) { n += 2; x <<= 2; } - n -= x >> 31; - return TypeInt::make(n); + if (t == Type::TOP) { + return Type::TOP; } - return TypeInt::INT; + + // The proof of correctness is same as the above comments + // in `CountLeadingZerosINode::Value`. + const TypeLong* tl = t->is_long(); + return TypeInt::make(count_leading_zeros_long(~tl->_bits._zeros), + count_leading_zeros_long(tl->_bits._ones), + tl->_widen); } //------------------------------Value------------------------------------------ const Type* CountTrailingZerosINode::Value(PhaseGVN* phase) const { const Type* t = phase->type(in(1)); - if (t == Type::TOP) return Type::TOP; - const TypeInt* ti = t->isa_int(); - if (ti && ti->is_con()) { - jint i = ti->get_con(); - // HD, Figure 5-14 - int y; - if (i == 0) - return TypeInt::make(BitsPerInt); - int n = 31; - y = i << 16; if (y != 0) { n = n - 16; i = y; } - y = i << 8; if (y != 0) { n = n - 8; i = y; } - y = i << 4; if (y != 0) { n = n - 4; i = y; } - y = i << 2; if (y != 0) { n = n - 2; i = y; } - y = i << 1; if (y != 0) { n = n - 1; } - return TypeInt::make(n); + if (t == Type::TOP) { + return Type::TOP; } - return TypeInt::INT; + + // To minimize `count_trailing_zeros(x)`, we should make the lowest 1 bit in x + // as far to the right as possible. A bit in x can be 1 iff this bit is not + // forced to be 0, i.e. the corresponding bit in `x._bits._zeros` is 0. Thus: + // min(ctz(x)) = number of bits to the right of the lowest 0 bit in x._bits._zeros + // = count_trailing_ones(x._bits._zeros) = ctz(~x._bits._zeros) + // + // To maximize `count_trailing_zeros(x)`, we should make the trailing zeros as + // many as possible. A bit in x can be 0 iff this bit is not forced to be 1, + // i.e. the corresponding bit in `x._bits._ones` is 0. Thus: + // max(ctz(x)) = ctz(x._bits._ones) + // + // Therefore, the range of `count_trailing_zeros(x)` is: + // [ctz(~x._bits._zeros), ctz(x._bits._ones)] + // + // A more detailed proof using Z3 can be found at: + // https://github.com/openjdk/jdk/pull/25928#discussion_r2256750507 + const TypeInt* ti = t->is_int(); + return TypeInt::make(count_trailing_zeros_int(~ti->_bits._zeros), + count_trailing_zeros_int(ti->_bits._ones), + ti->_widen); } //------------------------------Value------------------------------------------ const Type* CountTrailingZerosLNode::Value(PhaseGVN* phase) const { const Type* t = phase->type(in(1)); - if (t == Type::TOP) return Type::TOP; - const TypeLong* tl = t->isa_long(); - if (tl && tl->is_con()) { - jlong l = tl->get_con(); - // HD, Figure 5-14 - int x, y; - if (l == 0) - return TypeInt::make(BitsPerLong); - int n = 63; - y = (int) l; if (y != 0) { n = n - 32; x = y; } else x = (((julong) l) >> 32); - y = x << 16; if (y != 0) { n = n - 16; x = y; } - y = x << 8; if (y != 0) { n = n - 8; x = y; } - y = x << 4; if (y != 0) { n = n - 4; x = y; } - y = x << 2; if (y != 0) { n = n - 2; x = y; } - y = x << 1; if (y != 0) { n = n - 1; } - return TypeInt::make(n); + if (t == Type::TOP) { + return Type::TOP; } - return TypeInt::INT; + + // The proof of correctness is same as the above comments + // in `CountTrailingZerosINode::Value`. + const TypeLong* tl = t->is_long(); + return TypeInt::make(count_trailing_zeros_long(~tl->_bits._zeros), + count_trailing_zeros_long(tl->_bits._ones), + tl->_widen); } + // We use the KnownBits information from the integer types to derive how many one bits // we have at least and at most. // From the definition of KnownBits, we know: diff --git a/test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java b/test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java new file mode 100644 index 00000000000..00aa466e822 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/gvn/TestCountBitsRange.java @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2025 Alibaba Group Holding Limited. 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.c2.gvn; + +import compiler.lib.generators.Generator; +import compiler.lib.generators.Generators; +import compiler.lib.generators.RestrictableGenerator; +import compiler.lib.ir_framework.*; +import java.util.function.Function; +import jdk.test.lib.Asserts; + +/* + * @test + * @bug 8360192 + * @summary Tests that count bits nodes are handled correctly. + * @library /test/lib / + * @run driver compiler.c2.gvn.TestCountBitsRange + */ +public class TestCountBitsRange { + private static final Generator INTS = Generators.G.ints(); + private static final Generator LONGS = Generators.G.longs(); + + private static final RestrictableGenerator INTS_32 = Generators.G.ints().restricted(0, 32); + private static final RestrictableGenerator INTS_64 = Generators.G.ints().restricted(0, 64); + + private static final int LIMITS_32_0 = INTS_32.next(); + private static final int LIMITS_32_1 = INTS_32.next(); + private static final int LIMITS_32_2 = INTS_32.next(); + private static final int LIMITS_32_3 = INTS_32.next(); + private static final int LIMITS_32_4 = INTS_32.next(); + private static final int LIMITS_32_5 = INTS_32.next(); + private static final int LIMITS_32_6 = INTS_32.next(); + private static final int LIMITS_32_7 = INTS_32.next(); + + private static final int LIMITS_64_0 = INTS_64.next(); + private static final int LIMITS_64_1 = INTS_64.next(); + private static final int LIMITS_64_2 = INTS_64.next(); + private static final int LIMITS_64_3 = INTS_64.next(); + private static final int LIMITS_64_4 = INTS_64.next(); + private static final int LIMITS_64_5 = INTS_64.next(); + private static final int LIMITS_64_6 = INTS_64.next(); + private static final int LIMITS_64_7 = INTS_64.next(); + + private static final IntRange RANGE_INT = IntRange.generate(INTS); + private static final LongRange RANGE_LONG = LongRange.generate(LONGS); + + public static void main(String[] args) { + TestFramework.run(); + } + + @Run(test = { + "clzConstInts", "clzCompareInt", "clzDiv8Int", "clzRandLimitInt", + "clzConstLongs", "clzCompareLong", "clzDiv8Long", "clzRandLimitLong", + "ctzConstInts", "ctzCompareInt", "ctzDiv8Int", "ctzRandLimitInt", + "ctzConstLongs", "ctzCompareLong", "ctzDiv8Long", "ctzRandLimitLong", + }) + public void runTest() { + int randInt = INTS.next(); + long randLong = LONGS.next(); + assertResult(randInt, randLong); + } + + @DontCompile + public void assertResult(int randInt, long randLong) { + checkConstResults(clzConstInts(), x -> Integer.numberOfLeadingZeros(x.intValue())); + Asserts.assertEQ(Integer.numberOfLeadingZeros(randInt) < 0 + || Integer.numberOfLeadingZeros(randInt) > 32, + clzCompareInt(randInt)); + Asserts.assertEQ(Integer.numberOfLeadingZeros(randInt) / 8, + clzDiv8Int(randInt)); + Asserts.assertEQ(clzRandLimitInterpretedInt(randInt), clzRandLimitInt(randInt)); + + checkConstResults(clzConstLongs(), x -> Long.numberOfLeadingZeros(x.longValue())); + Asserts.assertEQ(Long.numberOfLeadingZeros(randLong) < 0 + || Long.numberOfLeadingZeros(randLong) > 64, + clzCompareLong(randLong)); + Asserts.assertEQ(Long.numberOfLeadingZeros(randLong) / 8, + clzDiv8Long(randLong)); + Asserts.assertEQ(clzRandLimitInterpretedLong(randLong), clzRandLimitLong(randLong)); + + checkConstResults(ctzConstInts(), x -> Integer.numberOfTrailingZeros(x.intValue())); + Asserts.assertEQ(Integer.numberOfTrailingZeros(randInt) < 0 + || Integer.numberOfTrailingZeros(randInt) > 32, + ctzCompareInt(randInt)); + Asserts.assertEQ(Integer.numberOfTrailingZeros(randInt) / 8, + ctzDiv8Int(randInt)); + Asserts.assertEQ(ctzRandLimitInterpretedInt(randInt), ctzRandLimitInt(randInt)); + + checkConstResults(ctzConstLongs(), x -> Long.numberOfTrailingZeros(x.longValue())); + Asserts.assertEQ(Long.numberOfTrailingZeros(randLong) < 0 + || Long.numberOfTrailingZeros(randLong) > 64, + ctzCompareLong(randLong)); + Asserts.assertEQ(Long.numberOfTrailingZeros(randLong) / 8, + ctzDiv8Long(randLong)); + Asserts.assertEQ(ctzRandLimitInterpretedLong(randLong), ctzRandLimitLong(randLong)); + } + + @DontCompile + public void checkConstResults(int[] results, Function op) { + Asserts.assertEQ(op.apply(Long.valueOf(0)), results[0]); + for (int i = 0; i < results.length - 1; ++i) { + Asserts.assertEQ(op.apply(Long.valueOf(1l << i)), results[i + 1]); + } + } + + // Test CLZ with constant integer inputs. + // All CLZs in this test are expected to be optimized away. + @Test + @IR(failOn = IRNode.COUNT_LEADING_ZEROS_I) + public int[] clzConstInts() { + return new int[] { + Integer.numberOfLeadingZeros(0), + Integer.numberOfLeadingZeros(1 << 0), + Integer.numberOfLeadingZeros(1 << 1), + Integer.numberOfLeadingZeros(1 << 2), + Integer.numberOfLeadingZeros(1 << 3), + Integer.numberOfLeadingZeros(1 << 4), + Integer.numberOfLeadingZeros(1 << 5), + Integer.numberOfLeadingZeros(1 << 6), + Integer.numberOfLeadingZeros(1 << 7), + Integer.numberOfLeadingZeros(1 << 8), + Integer.numberOfLeadingZeros(1 << 9), + Integer.numberOfLeadingZeros(1 << 10), + Integer.numberOfLeadingZeros(1 << 11), + Integer.numberOfLeadingZeros(1 << 12), + Integer.numberOfLeadingZeros(1 << 13), + Integer.numberOfLeadingZeros(1 << 14), + Integer.numberOfLeadingZeros(1 << 15), + Integer.numberOfLeadingZeros(1 << 16), + Integer.numberOfLeadingZeros(1 << 17), + Integer.numberOfLeadingZeros(1 << 18), + Integer.numberOfLeadingZeros(1 << 19), + Integer.numberOfLeadingZeros(1 << 20), + Integer.numberOfLeadingZeros(1 << 21), + Integer.numberOfLeadingZeros(1 << 22), + Integer.numberOfLeadingZeros(1 << 23), + Integer.numberOfLeadingZeros(1 << 24), + Integer.numberOfLeadingZeros(1 << 25), + Integer.numberOfLeadingZeros(1 << 26), + Integer.numberOfLeadingZeros(1 << 27), + Integer.numberOfLeadingZeros(1 << 28), + Integer.numberOfLeadingZeros(1 << 29), + Integer.numberOfLeadingZeros(1 << 30), + Integer.numberOfLeadingZeros(1 << 31), + }; + } + + // Test the range of CLZ with random integer input. + // The result of CLZ should be in range [0, 32], so CLZs in this test are + // expected to be optimized away, and the test should always return false. + @Test + @IR(failOn = IRNode.COUNT_LEADING_ZEROS_I) + public boolean clzCompareInt(int randInt) { + return Integer.numberOfLeadingZeros(randInt) < 0 + || Integer.numberOfLeadingZeros(randInt) > 32; + } + + // Test the combination of CLZ and division by 8. + // The result of CLZ should be positive, so the division by 8 should be + // optimized to a simple right shift without rounding. + @Test + @IR(counts = {IRNode.COUNT_LEADING_ZEROS_I, "1", + IRNode.RSHIFT_I, "1", + IRNode.URSHIFT_I, "0", + IRNode.ADD_I, "0"}) + public int clzDiv8Int(int randInt) { + return Integer.numberOfLeadingZeros(randInt) / 8; + } + + // Test the output range of CLZ with random input range. + @Test + public int clzRandLimitInt(int randInt) { + randInt = RANGE_INT.clamp(randInt); + int result = Integer.numberOfLeadingZeros(randInt); + return getResultChecksum32(result); + } + + @DontCompile + public int clzRandLimitInterpretedInt(int randInt) { + randInt = RANGE_INT.clamp(randInt); + int result = Integer.numberOfLeadingZeros(randInt); + return getResultChecksum32(result); + } + + // Test CLZ with constant long inputs. + // All CLZs in this test are expected to be optimized away. + @Test + @IR(failOn = IRNode.COUNT_LEADING_ZEROS_L) + public int[] clzConstLongs() { + return new int[] { + Long.numberOfLeadingZeros(0), + Long.numberOfLeadingZeros(1l << 0), + Long.numberOfLeadingZeros(1l << 1), + Long.numberOfLeadingZeros(1l << 2), + Long.numberOfLeadingZeros(1l << 3), + Long.numberOfLeadingZeros(1l << 4), + Long.numberOfLeadingZeros(1l << 5), + Long.numberOfLeadingZeros(1l << 6), + Long.numberOfLeadingZeros(1l << 7), + Long.numberOfLeadingZeros(1l << 8), + Long.numberOfLeadingZeros(1l << 9), + Long.numberOfLeadingZeros(1l << 10), + Long.numberOfLeadingZeros(1l << 11), + Long.numberOfLeadingZeros(1l << 12), + Long.numberOfLeadingZeros(1l << 13), + Long.numberOfLeadingZeros(1l << 14), + Long.numberOfLeadingZeros(1l << 15), + Long.numberOfLeadingZeros(1l << 16), + Long.numberOfLeadingZeros(1l << 17), + Long.numberOfLeadingZeros(1l << 18), + Long.numberOfLeadingZeros(1l << 19), + Long.numberOfLeadingZeros(1l << 20), + Long.numberOfLeadingZeros(1l << 21), + Long.numberOfLeadingZeros(1l << 22), + Long.numberOfLeadingZeros(1l << 23), + Long.numberOfLeadingZeros(1l << 24), + Long.numberOfLeadingZeros(1l << 25), + Long.numberOfLeadingZeros(1l << 26), + Long.numberOfLeadingZeros(1l << 27), + Long.numberOfLeadingZeros(1l << 28), + Long.numberOfLeadingZeros(1l << 29), + Long.numberOfLeadingZeros(1l << 30), + Long.numberOfLeadingZeros(1l << 31), + Long.numberOfLeadingZeros(1l << 32), + Long.numberOfLeadingZeros(1l << 33), + Long.numberOfLeadingZeros(1l << 34), + Long.numberOfLeadingZeros(1l << 35), + Long.numberOfLeadingZeros(1l << 36), + Long.numberOfLeadingZeros(1l << 37), + Long.numberOfLeadingZeros(1l << 38), + Long.numberOfLeadingZeros(1l << 39), + Long.numberOfLeadingZeros(1l << 40), + Long.numberOfLeadingZeros(1l << 41), + Long.numberOfLeadingZeros(1l << 42), + Long.numberOfLeadingZeros(1l << 43), + Long.numberOfLeadingZeros(1l << 44), + Long.numberOfLeadingZeros(1l << 45), + Long.numberOfLeadingZeros(1l << 46), + Long.numberOfLeadingZeros(1l << 47), + Long.numberOfLeadingZeros(1l << 48), + Long.numberOfLeadingZeros(1l << 49), + Long.numberOfLeadingZeros(1l << 50), + Long.numberOfLeadingZeros(1l << 51), + Long.numberOfLeadingZeros(1l << 52), + Long.numberOfLeadingZeros(1l << 53), + Long.numberOfLeadingZeros(1l << 54), + Long.numberOfLeadingZeros(1l << 55), + Long.numberOfLeadingZeros(1l << 56), + Long.numberOfLeadingZeros(1l << 57), + Long.numberOfLeadingZeros(1l << 58), + Long.numberOfLeadingZeros(1l << 59), + Long.numberOfLeadingZeros(1l << 60), + Long.numberOfLeadingZeros(1l << 61), + Long.numberOfLeadingZeros(1l << 62), + Long.numberOfLeadingZeros(1l << 63), + }; + } + + // Test the range of CLZ with random long input. + // The result of CLZ should be in range [0, 64], so CLZs in this test are + // expected to be optimized away, and the test should always return false. + @Test + @IR(failOn = IRNode.COUNT_LEADING_ZEROS_L) + public boolean clzCompareLong(long randLong) { + return Long.numberOfLeadingZeros(randLong) < 0 + || Long.numberOfLeadingZeros(randLong) > 64; + } + + // Test the combination of CLZ and division by 8. + // The result of CLZ should be positive, so the division by 8 should be + // optimized to a simple right shift without rounding. + @Test + @IR(counts = {IRNode.COUNT_LEADING_ZEROS_L, "1", + IRNode.RSHIFT_I, "1", + IRNode.URSHIFT_I, "0", + IRNode.ADD_I, "0"}) + public int clzDiv8Long(long randLong) { + return Long.numberOfLeadingZeros(randLong) / 8; + } + + // Test the output range of CLZ with random input range. + @Test + public int clzRandLimitLong(long randLong) { + randLong = RANGE_LONG.clamp(randLong); + int result = Long.numberOfLeadingZeros(randLong); + return getResultChecksum64(result); + } + + @DontCompile + public int clzRandLimitInterpretedLong(long randLong) { + randLong = RANGE_LONG.clamp(randLong); + int result = Long.numberOfLeadingZeros(randLong); + return getResultChecksum64(result); + } + + // Test CTZ with constant integer inputs. + // All CTZs in this test are expected to be optimized away. + @Test + @IR(failOn = IRNode.COUNT_TRAILING_ZEROS_I) + public int[] ctzConstInts() { + return new int[] { + Integer.numberOfTrailingZeros(0), + Integer.numberOfTrailingZeros(1 << 0), + Integer.numberOfTrailingZeros(1 << 1), + Integer.numberOfTrailingZeros(1 << 2), + Integer.numberOfTrailingZeros(1 << 3), + Integer.numberOfTrailingZeros(1 << 4), + Integer.numberOfTrailingZeros(1 << 5), + Integer.numberOfTrailingZeros(1 << 6), + Integer.numberOfTrailingZeros(1 << 7), + Integer.numberOfTrailingZeros(1 << 8), + Integer.numberOfTrailingZeros(1 << 9), + Integer.numberOfTrailingZeros(1 << 10), + Integer.numberOfTrailingZeros(1 << 11), + Integer.numberOfTrailingZeros(1 << 12), + Integer.numberOfTrailingZeros(1 << 13), + Integer.numberOfTrailingZeros(1 << 14), + Integer.numberOfTrailingZeros(1 << 15), + Integer.numberOfTrailingZeros(1 << 16), + Integer.numberOfTrailingZeros(1 << 17), + Integer.numberOfTrailingZeros(1 << 18), + Integer.numberOfTrailingZeros(1 << 19), + Integer.numberOfTrailingZeros(1 << 20), + Integer.numberOfTrailingZeros(1 << 21), + Integer.numberOfTrailingZeros(1 << 22), + Integer.numberOfTrailingZeros(1 << 23), + Integer.numberOfTrailingZeros(1 << 24), + Integer.numberOfTrailingZeros(1 << 25), + Integer.numberOfTrailingZeros(1 << 26), + Integer.numberOfTrailingZeros(1 << 27), + Integer.numberOfTrailingZeros(1 << 28), + Integer.numberOfTrailingZeros(1 << 29), + Integer.numberOfTrailingZeros(1 << 30), + Integer.numberOfTrailingZeros(1 << 31), + }; + } + + // Test the range of CTZ with random integer input. + // The result of CTZ should be in range [0, 32], so CTZs in this test are + // expected to be optimized away, and the test should always return false. + @Test + @IR(failOn = IRNode.COUNT_TRAILING_ZEROS_I) + public boolean ctzCompareInt(int randInt) { + return Integer.numberOfTrailingZeros(randInt) < 0 + || Integer.numberOfTrailingZeros(randInt) > 32; + } + + // Test the combination of CTZ and division by 8. + // The result of CTZ should be positive, so the division by 8 should be + // optimized to a simple right shift without rounding. + @Test + @IR(counts = {IRNode.COUNT_TRAILING_ZEROS_I, "1", + IRNode.RSHIFT_I, "1", + IRNode.URSHIFT_I, "0", + IRNode.ADD_I, "0"}) + public int ctzDiv8Int(int randInt) { + return Integer.numberOfTrailingZeros(randInt) / 8; + } + + // Test the output range of CTZ with random input range. + @Test + public int ctzRandLimitInt(int randInt) { + randInt = RANGE_INT.clamp(randInt); + int result = Integer.numberOfTrailingZeros(randInt); + return getResultChecksum32(result); + } + + @DontCompile + public int ctzRandLimitInterpretedInt(int randInt) { + randInt = RANGE_INT.clamp(randInt); + int result = Integer.numberOfTrailingZeros(randInt); + return getResultChecksum32(result); + } + + // Test CTZ with constant long inputs. + // All CTZs in this test are expected to be optimized away. + @Test + @IR(failOn = IRNode.COUNT_TRAILING_ZEROS_L) + public int[] ctzConstLongs() { + return new int[] { + Long.numberOfTrailingZeros(0), + Long.numberOfTrailingZeros(1l << 0), + Long.numberOfTrailingZeros(1l << 1), + Long.numberOfTrailingZeros(1l << 2), + Long.numberOfTrailingZeros(1l << 3), + Long.numberOfTrailingZeros(1l << 4), + Long.numberOfTrailingZeros(1l << 5), + Long.numberOfTrailingZeros(1l << 6), + Long.numberOfTrailingZeros(1l << 7), + Long.numberOfTrailingZeros(1l << 8), + Long.numberOfTrailingZeros(1l << 9), + Long.numberOfTrailingZeros(1l << 10), + Long.numberOfTrailingZeros(1l << 11), + Long.numberOfTrailingZeros(1l << 12), + Long.numberOfTrailingZeros(1l << 13), + Long.numberOfTrailingZeros(1l << 14), + Long.numberOfTrailingZeros(1l << 15), + Long.numberOfTrailingZeros(1l << 16), + Long.numberOfTrailingZeros(1l << 17), + Long.numberOfTrailingZeros(1l << 18), + Long.numberOfTrailingZeros(1l << 19), + Long.numberOfTrailingZeros(1l << 20), + Long.numberOfTrailingZeros(1l << 21), + Long.numberOfTrailingZeros(1l << 22), + Long.numberOfTrailingZeros(1l << 23), + Long.numberOfTrailingZeros(1l << 24), + Long.numberOfTrailingZeros(1l << 25), + Long.numberOfTrailingZeros(1l << 26), + Long.numberOfTrailingZeros(1l << 27), + Long.numberOfTrailingZeros(1l << 28), + Long.numberOfTrailingZeros(1l << 29), + Long.numberOfTrailingZeros(1l << 30), + Long.numberOfTrailingZeros(1l << 31), + Long.numberOfTrailingZeros(1l << 32), + Long.numberOfTrailingZeros(1l << 33), + Long.numberOfTrailingZeros(1l << 34), + Long.numberOfTrailingZeros(1l << 35), + Long.numberOfTrailingZeros(1l << 36), + Long.numberOfTrailingZeros(1l << 37), + Long.numberOfTrailingZeros(1l << 38), + Long.numberOfTrailingZeros(1l << 39), + Long.numberOfTrailingZeros(1l << 40), + Long.numberOfTrailingZeros(1l << 41), + Long.numberOfTrailingZeros(1l << 42), + Long.numberOfTrailingZeros(1l << 43), + Long.numberOfTrailingZeros(1l << 44), + Long.numberOfTrailingZeros(1l << 45), + Long.numberOfTrailingZeros(1l << 46), + Long.numberOfTrailingZeros(1l << 47), + Long.numberOfTrailingZeros(1l << 48), + Long.numberOfTrailingZeros(1l << 49), + Long.numberOfTrailingZeros(1l << 50), + Long.numberOfTrailingZeros(1l << 51), + Long.numberOfTrailingZeros(1l << 52), + Long.numberOfTrailingZeros(1l << 53), + Long.numberOfTrailingZeros(1l << 54), + Long.numberOfTrailingZeros(1l << 55), + Long.numberOfTrailingZeros(1l << 56), + Long.numberOfTrailingZeros(1l << 57), + Long.numberOfTrailingZeros(1l << 58), + Long.numberOfTrailingZeros(1l << 59), + Long.numberOfTrailingZeros(1l << 60), + Long.numberOfTrailingZeros(1l << 61), + Long.numberOfTrailingZeros(1l << 62), + Long.numberOfTrailingZeros(1l << 63), + }; + } + + // Test the range of CTZ with random long input. + // The result of CTZ should be in range [0, 64], so CTZs in this test are + // expected to be optimized away, and the test should always return false. + @Test + @IR(failOn = IRNode.COUNT_TRAILING_ZEROS_L) + public boolean ctzCompareLong(long randLong) { + return Long.numberOfTrailingZeros(randLong) < 0 + || Long.numberOfTrailingZeros(randLong) > 64; + } + + // Test the combination of CTZ and division by 8. + // The result of CTZ should be positive, so the division by 8 should be + // optimized to a simple right shift without rounding. + @Test + @IR(counts = {IRNode.COUNT_TRAILING_ZEROS_L, "1", + IRNode.RSHIFT_I, "1", + IRNode.URSHIFT_I, "0", + IRNode.ADD_I, "0"}) + public int ctzDiv8Long(long randLong) { + return Long.numberOfTrailingZeros(randLong) / 8; + } + + // Test the output range of CTZ with random input range. + @Test + public int ctzRandLimitLong(long randLong) { + randLong = RANGE_LONG.clamp(randLong); + int result = Long.numberOfLeadingZeros(randLong); + return getResultChecksum64(result); + } + + @DontCompile + public int ctzRandLimitInterpretedLong(long randLong) { + randLong = RANGE_LONG.clamp(randLong); + int result = Long.numberOfLeadingZeros(randLong); + return getResultChecksum64(result); + } + + record IntRange(int lo, int hi) { + IntRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + @ForceInline + int clamp(int v) { + return v < lo ? lo : v > hi ? hi : v; + } + + static IntRange generate(Generator g) { + int a = g.next(), b = g.next(); + return a < b ? new IntRange(a, b) : new IntRange(b, a); + } + } + + record LongRange(long lo, long hi) { + LongRange { + if (lo > hi) { + throw new IllegalArgumentException("lo > hi"); + } + } + + @ForceInline + long clamp(long v) { + return v < lo ? lo : v > hi ? hi : v; + } + + static LongRange generate(Generator g) { + long a = g.next(), b = g.next(); + return a < b ? new LongRange(a, b) : new LongRange(b, a); + } + } + + @ForceInline + int getResultChecksum32(int result) { + int sum = 0; + if (result < LIMITS_32_0) sum += 1; + if (result < LIMITS_32_1) sum += 2; + if (result < LIMITS_32_2) sum += 4; + if (result < LIMITS_32_3) sum += 8; + if (result > LIMITS_32_4) sum += 16; + if (result > LIMITS_32_5) sum += 32; + if (result > LIMITS_32_6) sum += 64; + if (result > LIMITS_32_7) sum += 128; + return sum; + } + + @ForceInline + int getResultChecksum64(int result) { + int sum = 0; + if (result < LIMITS_64_0) sum += 1; + if (result < LIMITS_64_1) sum += 2; + if (result < LIMITS_64_2) sum += 4; + if (result < LIMITS_64_3) sum += 8; + if (result > LIMITS_64_4) sum += 16; + if (result > LIMITS_64_5) sum += 32; + if (result > LIMITS_64_6) sum += 64; + if (result > LIMITS_64_7) sum += 128; + return sum; + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 85595b9b632..1648135434a 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1661,6 +1661,16 @@ public class IRNode { vectorNode(POPCOUNT_VL, "PopCountVL", TYPE_LONG); } + public static final String COUNT_TRAILING_ZEROS_I = PREFIX + "COUNT_TRAILING_ZEROS_I" + POSTFIX; + static { + beforeMatchingNameRegex(COUNT_TRAILING_ZEROS_I, "CountTrailingZerosI"); + } + + public static final String COUNT_TRAILING_ZEROS_L = PREFIX + "COUNT_TRAILING_ZEROS_L" + POSTFIX; + static { + beforeMatchingNameRegex(COUNT_TRAILING_ZEROS_L, "CountTrailingZerosL"); + } + public static final String COUNT_TRAILING_ZEROS_VL = VECTOR_PREFIX + "COUNT_TRAILING_ZEROS_VL" + POSTFIX; static { vectorNode(COUNT_TRAILING_ZEROS_VL, "CountTrailingZerosV", TYPE_LONG); @@ -1671,6 +1681,16 @@ public class IRNode { vectorNode(COUNT_TRAILING_ZEROS_VI, "CountTrailingZerosV", TYPE_INT); } + public static final String COUNT_LEADING_ZEROS_I = PREFIX + "COUNT_LEADING_ZEROS_I" + POSTFIX; + static { + beforeMatchingNameRegex(COUNT_LEADING_ZEROS_I, "CountLeadingZerosI"); + } + + public static final String COUNT_LEADING_ZEROS_L = PREFIX + "COUNT_LEADING_ZEROS_L" + POSTFIX; + static { + beforeMatchingNameRegex(COUNT_LEADING_ZEROS_L, "CountLeadingZerosL"); + } + public static final String COUNT_LEADING_ZEROS_VL = VECTOR_PREFIX + "COUNT_LEADING_ZEROS_VL" + POSTFIX; static { vectorNode(COUNT_LEADING_ZEROS_VL, "CountLeadingZerosV", TYPE_LONG); diff --git a/test/micro/org/openjdk/bench/vm/compiler/CountLeadingZeros.java b/test/micro/org/openjdk/bench/vm/compiler/CountLeadingZeros.java new file mode 100644 index 00000000000..dc06e3ae764 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/CountLeadingZeros.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2025 Alibaba Group Holding Limited. 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 org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; + +import java.util.concurrent.TimeUnit; +import java.util.concurrent.ThreadLocalRandom; + +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@Fork(value = 3) +@Warmup(iterations = 10, time = 1) +@Measurement(iterations = 5, time = 1) +@State(Scope.Thread) +public class CountLeadingZeros { + private long[] longArray = new long[1000]; + + @Setup + public void setup() { + for (int i = 0; i < longArray.length; i++) { + longArray[i] = ThreadLocalRandom.current().nextLong(); + } + } + + @Benchmark + public int benchNumberOfNibbles() { + int sum = 0; + for (long l : longArray) { + sum += numberOfNibbles((int) l); + } + return sum; + } + + public static int numberOfNibbles(int i) { + int mag = Integer.SIZE - Integer.numberOfLeadingZeros(i); + return Math.max((mag + 3) / 4, 1); + } + + @Benchmark + public int benchClzLongConstrained() { + int sum = 0; + for (long l : longArray) { + sum += clzLongConstrained(l); + } + return sum; + } + + public static int clzLongConstrained(long param) { + long constrainedParam = Math.min(175, Math.max(param, 160)); + return Long.numberOfLeadingZeros(constrainedParam); + } +} From 6700baa5052046f53eb1b04ed3205bbd8e9e9070 Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 8 Dec 2025 13:38:22 +0000 Subject: [PATCH 005/211] 8357551: RISC-V: support CMoveF/D vectorization Reviewed-by: fyang, luhenry --- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 77 ++ .../cpu/riscv/c2_MacroAssembler_riscv.hpp | 7 + .../cpu/riscv/macroAssembler_riscv.cpp | 256 +++- .../cpu/riscv/macroAssembler_riscv.hpp | 18 + src/hotspot/cpu/riscv/riscv.ad | 282 +++- ...onalMove.java => TestConditionalMove.java} | 731 ++++++++++- .../c2/irTests/TestFPComparison2.java | 1140 ++++++++++++++++- .../TestScalarConditionalMoveCmpObj.java | 357 ++++++ .../compiler/lib/ir_framework/IRNode.java | 30 + .../bench/java/lang/ClassComparison.java | 45 +- .../openjdk/bench/java/lang/FPComparison.java | 176 ++- .../bench/java/lang/IntegerComparison.java | 292 ++++- .../bench/java/lang/LongComparison.java | 291 ++++- .../bench/java/lang/PointerComparison.java | 45 +- 14 files changed, 3604 insertions(+), 143 deletions(-) rename test/hotspot/jtreg/compiler/c2/irTests/{TestVectorConditionalMove.java => TestConditionalMove.java} (76%) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index abbd7eedbba..dcf20752a21 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -2067,6 +2067,83 @@ void C2_MacroAssembler::enc_cmove_cmp_fp(int cmpFlag, FloatRegister op1, FloatRe } } +void C2_MacroAssembler::enc_cmove_fp_cmp(int cmpFlag, Register op1, Register op2, + FloatRegister dst, FloatRegister src, bool is_single) { + bool is_unsigned = (cmpFlag & unsigned_branch_mask) == unsigned_branch_mask; + int op_select = cmpFlag & (~unsigned_branch_mask); + + switch (op_select) { + case BoolTest::eq: + cmov_fp_eq(op1, op2, dst, src, is_single); + break; + case BoolTest::ne: + cmov_fp_ne(op1, op2, dst, src, is_single); + break; + case BoolTest::le: + if (is_unsigned) { + cmov_fp_leu(op1, op2, dst, src, is_single); + } else { + cmov_fp_le(op1, op2, dst, src, is_single); + } + break; + case BoolTest::ge: + if (is_unsigned) { + cmov_fp_geu(op1, op2, dst, src, is_single); + } else { + cmov_fp_ge(op1, op2, dst, src, is_single); + } + break; + case BoolTest::lt: + if (is_unsigned) { + cmov_fp_ltu(op1, op2, dst, src, is_single); + } else { + cmov_fp_lt(op1, op2, dst, src, is_single); + } + break; + case BoolTest::gt: + if (is_unsigned) { + cmov_fp_gtu(op1, op2, dst, src, is_single); + } else { + cmov_fp_gt(op1, op2, dst, src, is_single); + } + break; + default: + assert(false, "unsupported compare condition"); + ShouldNotReachHere(); + } +} + +void C2_MacroAssembler::enc_cmove_fp_cmp_fp(int cmpFlag, + FloatRegister op1, FloatRegister op2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + int op_select = cmpFlag & (~unsigned_branch_mask); + + switch (op_select) { + case BoolTest::eq: + cmov_fp_cmp_fp_eq(op1, op2, dst, src, cmp_single, cmov_single); + break; + case BoolTest::ne: + cmov_fp_cmp_fp_ne(op1, op2, dst, src, cmp_single, cmov_single); + break; + case BoolTest::le: + cmov_fp_cmp_fp_le(op1, op2, dst, src, cmp_single, cmov_single); + break; + case BoolTest::ge: + cmov_fp_cmp_fp_ge(op1, op2, dst, src, cmp_single, cmov_single); + break; + case BoolTest::lt: + cmov_fp_cmp_fp_lt(op1, op2, dst, src, cmp_single, cmov_single); + break; + case BoolTest::gt: + cmov_fp_cmp_fp_gt(op1, op2, dst, src, cmp_single, cmov_single); + break; + default: + assert(false, "unsupported compare condition"); + ShouldNotReachHere(); + } +} + // Set dst to NaN if any NaN input. void C2_MacroAssembler::minmax_fp(FloatRegister dst, FloatRegister src1, FloatRegister src2, FLOAT_TYPE ft, bool is_min) { diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp index f08e5e27c87..fa87ceba295 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.hpp @@ -132,6 +132,13 @@ FloatRegister op1, FloatRegister op2, Register dst, Register src, bool is_single); + void enc_cmove_fp_cmp(int cmpFlag, Register op1, Register op2, + FloatRegister dst, FloatRegister src, bool is_single); + + void enc_cmove_fp_cmp_fp(int cmpFlag, FloatRegister op1, FloatRegister op2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single); + void spill(Register r, bool is64, int offset) { is64 ? sd(r, Address(sp, offset)) : sw(r, Address(sp, offset)); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 7a8496ae42b..a14a051fd3b 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1233,7 +1233,119 @@ void MacroAssembler::cmov_gtu(Register cmp1, Register cmp2, Register dst, Regist bind(no_set); } -// ----------- cmove, compare float ----------- +// ----------- cmove float/double ----------- + +void MacroAssembler::cmov_fp_eq(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bne(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_ne(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + beq(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_le(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bgt(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_leu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bgtu(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_ge(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + blt(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_geu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bltu(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_lt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bge(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_ltu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bgeu(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_gt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + ble(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_gtu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single) { + Label no_set; + bleu(cmp1, cmp2, no_set); + if (is_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +// ----------- cmove, compare float/double ----------- // // For CmpF/D + CMoveI/L, ordered ones are quite straight and simple, // so, just list behaviour of unordered ones as follow. @@ -1391,6 +1503,148 @@ void MacroAssembler::cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Regi bind(no_set); } +// ----------- cmove float/double, compare float/double ----------- + +// Move src to dst only if cmp1 == cmp2, +// otherwise leave dst unchanged, including the case where one of them is NaN. +// Clarification: +// java code : cmp1 != cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 eq cmp2), dst, src +void MacroAssembler::cmov_fp_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 != cmp2, including the case of NaN + // not jump (i.e. move src to dst) if cmp1 == cmp2 + float_bne(cmp1, cmp2, no_set); + } else { + double_bne(cmp1, cmp2, no_set); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +// Keep dst unchanged only if cmp1 == cmp2, +// otherwise move src to dst, including the case where one of them is NaN. +// Clarification: +// java code : cmp1 == cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 ne cmp2), dst, src +void MacroAssembler::cmov_fp_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 == cmp2 + // not jump (i.e. move src to dst) if cmp1 != cmp2, including the case of NaN + float_beq(cmp1, cmp2, no_set); + } else { + double_beq(cmp1, cmp2, no_set); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +// When cmp1 <= cmp2 or any of them is NaN then dst = src, otherwise, dst = dst +// Clarification +// scenario 1: +// java code : cmp2 < cmp1 ? dst : src +// transformed to : CMove dst, (cmp1 le cmp2), dst, src +// scenario 2: +// java code : cmp1 > cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 le cmp2), dst, src +void MacroAssembler::cmov_fp_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 > cmp2 + // not jump (i.e. move src to dst) if cmp1 <= cmp2 or either is NaN + float_bgt(cmp1, cmp2, no_set); + } else { + double_bgt(cmp1, cmp2, no_set); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 < cmp2 or either is NaN + // not jump (i.e. move src to dst) if cmp1 >= cmp2 + float_blt(cmp1, cmp2, no_set, false, true); + } else { + double_blt(cmp1, cmp2, no_set, false, true); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +// When cmp1 < cmp2 or any of them is NaN then dst = src, otherwise, dst = dst +// Clarification +// scenario 1: +// java code : cmp2 <= cmp1 ? dst : src +// transformed to : CMove dst, (cmp1 lt cmp2), dst, src +// scenario 2: +// java code : cmp1 >= cmp2 ? dst : src +// transformed to : CMove dst, (cmp1 lt cmp2), dst, src +void MacroAssembler::cmov_fp_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 >= cmp2 + // not jump (i.e. move src to dst) if cmp1 < cmp2 or either is NaN + float_bge(cmp1, cmp2, no_set); + } else { + double_bge(cmp1, cmp2, no_set); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + +void MacroAssembler::cmov_fp_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, + FloatRegister dst, FloatRegister src, + bool cmp_single, bool cmov_single) { + Label no_set; + if (cmp_single) { + // jump if cmp1 <= cmp2 or either is NaN + // not jump (i.e. move src to dst) if cmp1 > cmp2 + float_ble(cmp1, cmp2, no_set, false, true); + } else { + double_ble(cmp1, cmp2, no_set, false, true); + } + if (cmov_single) { + fmv_s(dst, src); + } else { + fmv_d(dst, src); + } + bind(no_set); +} + // Float compare branch instructions #define INSN(NAME, FLOATCMP, BRANCH) \ diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 1908b9a9605..3b021388fa5 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -665,6 +665,24 @@ class MacroAssembler: public Assembler { void cmov_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); void cmov_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, Register dst, Register src, bool is_single); + void cmov_fp_eq(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_ne(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_le(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_leu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_ge(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_geu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_lt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_ltu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_gt(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + void cmov_fp_gtu(Register cmp1, Register cmp2, FloatRegister dst, FloatRegister src, bool is_single); + + void cmov_fp_cmp_fp_eq(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + void cmov_fp_cmp_fp_ne(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + void cmov_fp_cmp_fp_le(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + void cmov_fp_cmp_fp_ge(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + void cmov_fp_cmp_fp_lt(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + void cmov_fp_cmp_fp_gt(FloatRegister cmp1, FloatRegister cmp2, FloatRegister dst, FloatRegister src, bool cmp_single, bool cmov_single); + public: // We try to follow risc-v asm menomics. // But as we don't layout a reachable GOT, diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index 3f5dd4ad0ee..96984ba9a42 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1924,8 +1924,6 @@ bool Matcher::match_rule_supported(int opcode) { case Op_SubHF: return UseZfh; - case Op_CMoveF: - case Op_CMoveD: case Op_CMoveP: case Op_CMoveN: return false; @@ -10466,6 +10464,286 @@ instruct cmovL_cmpP(iRegLNoSp dst, iRegL src, iRegP op1, iRegP op2, cmpOpU cop) ins_pipe(pipe_class_compare); %} +// --------- CMoveF --------- + +instruct cmovF_cmpI(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpI op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpI\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpU(fRegF dst, fRegF src, iRegI op1, iRegI op2, cmpOpU cop) %{ + match(Set dst (CMoveF (Binary cop (CmpU op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpU\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpL\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpUL(fRegF dst, fRegF src, iRegL op1, iRegL op2, cmpOpU cop) %{ + match(Set dst (CMoveF (Binary cop (CmpUL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpUL\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpF(fRegF dst, fRegF src, fRegF op1, fRegF op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpF op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpF\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp_fp($cop$$cmpcode, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), + true /* cmp_single */, true /* cmov_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpD(fRegF dst, fRegF src, fRegD op1, fRegD op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpD op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpD\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), + false /* cmp_single */, true /* cmov_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpN(fRegF dst, fRegF src, iRegN op1, iRegN op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpN op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpN\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovF_cmpP(fRegF dst, fRegF src, iRegP op1, iRegP op2, cmpOp cop) %{ + match(Set dst (CMoveF (Binary cop (CmpP op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveF $dst, ($op1 $cop $op2), $dst, $src\t#@cmovF_cmpP\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), true /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +// --------- CMoveD --------- + +instruct cmovD_cmpI(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpI op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpI\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpU(fRegD dst, fRegD src, iRegI op1, iRegI op2, cmpOpU cop) %{ + match(Set dst (CMoveD (Binary cop (CmpU op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpU\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpL\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpUL(fRegD dst, fRegD src, iRegL op1, iRegL op2, cmpOpU cop) %{ + match(Set dst (CMoveD (Binary cop (CmpUL op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpUL\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpF(fRegD dst, fRegD src, fRegF op1, fRegF op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpF op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpF\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp_fp($cop$$cmpcode, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), + true /* cmp_single */, false /* cmov_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpD(fRegD dst, fRegD src, fRegD op1, fRegD op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpD op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpD\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp_fp($cop$$cmpcode | C2_MacroAssembler::double_branch_mask, + as_FloatRegister($op1$$reg), as_FloatRegister($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), + false /* cmp_single */, false /* cmov_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpN(fRegD dst, fRegD src, iRegN op1, iRegN op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpN op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpN\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + +instruct cmovD_cmpP(fRegD dst, fRegD src, iRegP op1, iRegP op2, cmpOp cop) %{ + match(Set dst (CMoveD (Binary cop (CmpP op1 op2)) (Binary dst src))); + ins_cost(ALU_COST + BRANCH_COST); + + format %{ + "CMoveD $dst, ($op1 $cop $op2), $dst, $src\t#@cmovD_cmpP\n\t" + %} + + ins_encode %{ + __ enc_cmove_fp_cmp($cop$$cmpcode | C2_MacroAssembler::unsigned_branch_mask, + as_Register($op1$$reg), as_Register($op2$$reg), + as_FloatRegister($dst$$reg), as_FloatRegister($src$$reg), false /* is_single */); + %} + + ins_pipe(pipe_class_compare); +%} + // ============================================================================ // Procedure Call/Return Instructions diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java b/test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java similarity index 76% rename from test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java rename to test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java index 4759add94e9..c531f73b71d 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestVectorConditionalMove.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java @@ -1,6 +1,7 @@ /* - * Copyright (c) 2022, Arm Limited. All rights reserved. - * Copyright (c) 2023, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, Arm Limited. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Rivos Inc. 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 @@ -35,14 +36,15 @@ import jdk.test.lib.Utils; * @key randomness * @summary Auto-vectorization enhancement to support vector conditional move. * @library /test/lib / - * @run driver compiler.c2.irTests.TestVectorConditionalMove + * @run driver compiler.c2.irTests.TestConditionalMove */ -public class TestVectorConditionalMove { +public class TestConditionalMove { final private static int SIZE = 1024; private static final Random RANDOM = Utils.getRandomInstance(); public static void main(String[] args) { + // Vectorizaion: +UseCMoveUnconditionally, +UseVectorCmov // Cross-product: +-AlignVector and +-UseCompactObjectHeaders TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", "-XX:-UseCompactObjectHeaders", "-XX:-AlignVector"); @@ -52,6 +54,12 @@ public class TestVectorConditionalMove { "-XX:+UseCompactObjectHeaders", "-XX:-AlignVector"); TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:+UseVectorCmov", "-XX:+UseCompactObjectHeaders", "-XX:+AlignVector"); + + // Scalar: +UseCMoveUnconditionally, -UseVectorCmov + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders"); + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders"); } // Compare 2 values, and pick one of them @@ -564,6 +572,7 @@ public class TestVectorConditionalMove { return (a > b) ? c : d; } + // Double comparison private int cmoveDGTforI(double a, double b, int c, int d) { return (a > b) ? c : d; } @@ -586,7 +595,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVFGT(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? a[i] : b[i]; @@ -598,7 +613,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVFGTSwap(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] > a[i]) ? a[i] : b[i]; @@ -610,7 +631,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVFLT(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? a[i] : b[i]; @@ -622,7 +649,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVFLTSwap(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] < a[i]) ? a[i] : b[i]; @@ -634,7 +667,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVFEQ(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? a[i] : b[i]; @@ -646,7 +685,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVDLE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? a[i] : b[i]; @@ -658,7 +703,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVDLESwap(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] <= a[i]) ? a[i] : b[i]; @@ -670,7 +721,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVDGE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? a[i] : b[i]; @@ -682,7 +739,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVDGESwap(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] >= a[i]) ? a[i] : b[i]; @@ -694,7 +757,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveVDNE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? a[i] : b[i]; @@ -707,7 +776,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? 0.1f : -0.1f; @@ -719,7 +794,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGEforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? 0.1f : -0.1f; @@ -731,7 +812,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFLTforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? 0.1f : -0.1f; @@ -743,7 +830,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFLEforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? 0.1f : -0.1f; @@ -755,7 +848,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFEQforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? 0.1f : -0.1f; @@ -767,7 +866,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFNEQforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? 0.1f : -0.1f; @@ -779,8 +884,19 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfAnd = {"UseCompactObjectHeaders", "false", "UseVectorCmov", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", + IRNode.VECTOR_MASK_CMP_F, ">0", + IRNode.VECTOR_BLEND_F, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfAnd = {"AlignVector", "false", "UseVectorCmov", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFLTforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; @@ -797,8 +913,19 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfOr = {"UseCompactObjectHeaders", "false", "AlignVector", "false"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfAnd = {"UseCompactObjectHeaders", "false", "UseVectorCmov", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) + @IR(counts = {IRNode.LOAD_VECTOR_F, ">0", + IRNode.VECTOR_MASK_CMP_F, ">0", + IRNode.VECTOR_BLEND_F, ">0", + IRNode.STORE_VECTOR, ">0"}, + applyIfAnd = {"AlignVector", "false", "UseVectorCmov", "true"}, + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFLEforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; @@ -815,7 +942,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, "=0", IRNode.VECTOR_BLEND_F, "=0", IRNode.STORE_VECTOR, "=0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFYYforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; @@ -828,7 +961,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, "=0", IRNode.VECTOR_BLEND_F, "=0", IRNode.STORE_VECTOR, "=0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFXXforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; @@ -841,7 +980,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? 0.1 : -0.1; @@ -853,7 +998,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? 0.1 : -0.1; @@ -865,7 +1016,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? 0.1 : -0.1; @@ -877,7 +1034,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? 0.1 : -0.1; @@ -889,7 +1052,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? 0.1 : -0.1; @@ -901,7 +1070,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? 0.1 : -0.1; @@ -913,7 +1088,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDLTforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; @@ -926,7 +1107,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDLEforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; @@ -939,7 +1126,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, "=0", IRNode.VECTOR_BLEND_D, "=0", IRNode.STORE_VECTOR, "=0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDYYforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; @@ -952,7 +1145,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, "=0", IRNode.VECTOR_BLEND_D, "=0", IRNode.STORE_VECTOR, "=0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDXXforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; @@ -966,10 +1165,15 @@ public class TestVectorConditionalMove { // do not float down into the branches, I compute a value, and store it to r2 (same as r, except that the // compilation does not know that). // So far, vectorization only works for CMoveF/D, with same data-width comparison (F/I for F, D/L for D). + // TODO: enable CMOVE_I/L verification when it's guaranteed to generate CMOVE_I/L, JDK-8371984. + // // Signed comparison: I/L // I fo I @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIEQforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -981,6 +1185,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveINEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -992,6 +1199,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1003,6 +1213,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1014,6 +1227,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1025,6 +1241,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1037,6 +1256,9 @@ public class TestVectorConditionalMove { // I fo L @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIEQforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1048,6 +1270,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveINEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1059,6 +1284,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1070,6 +1298,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1081,6 +1312,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1092,6 +1326,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_I, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1108,7 +1345,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIEQforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1124,7 +1367,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveINEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1140,7 +1389,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1156,7 +1411,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1172,7 +1433,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1188,7 +1455,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1201,6 +1474,9 @@ public class TestVectorConditionalMove { // I fo D @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIEQforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1212,6 +1488,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveINEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1223,6 +1502,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1234,6 +1516,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveIGEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1245,6 +1530,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1256,6 +1544,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveILEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1268,6 +1559,9 @@ public class TestVectorConditionalMove { // L fo I @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLEQforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1279,6 +1573,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLNEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1290,6 +1587,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1301,6 +1601,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1312,6 +1615,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1323,6 +1629,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1335,6 +1644,9 @@ public class TestVectorConditionalMove { // L fo L @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLEQforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1346,6 +1658,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLNEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1357,6 +1672,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1368,6 +1686,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1379,6 +1700,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1390,6 +1714,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_L, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1402,6 +1729,9 @@ public class TestVectorConditionalMove { // L fo F @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLEQforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1413,6 +1743,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLNEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1424,6 +1757,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1435,6 +1771,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLGEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1446,6 +1785,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1457,6 +1799,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveLLEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1473,7 +1818,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLEQforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1490,7 +1841,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLNEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1507,7 +1864,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1524,7 +1887,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLGEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1541,7 +1910,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLLTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1558,7 +1933,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLLEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1573,6 +1954,9 @@ public class TestVectorConditionalMove { // I fo I @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIEQforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1584,6 +1968,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUINEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1595,6 +1982,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1606,6 +1996,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1617,6 +2010,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILTforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1628,6 +2024,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILEforI(int[] a, int[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1640,6 +2039,9 @@ public class TestVectorConditionalMove { // I fo L @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIEQforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1651,6 +2053,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUINEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1662,6 +2067,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1673,6 +2081,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1684,6 +2095,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILTforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1695,6 +2109,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_U, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILEforL(int[] a, int[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1711,7 +2128,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIEQforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1727,7 +2150,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUINEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1743,7 +2172,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1759,7 +2194,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1775,7 +2216,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1791,7 +2238,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_I, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.VECTOR_BLEND_F, IRNode.VECTOR_SIZE + "min(max_int, max_float)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1804,6 +2257,9 @@ public class TestVectorConditionalMove { // I fo D @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIEQforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1815,6 +2271,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUINEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1826,6 +2285,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1837,6 +2299,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUIGEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1848,6 +2313,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1859,6 +2327,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveUILEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1871,6 +2342,9 @@ public class TestVectorConditionalMove { // L fo I @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULEQforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1882,6 +2356,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULNEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1893,6 +2370,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1904,6 +2384,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1915,6 +2398,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLTforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1926,6 +2412,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLEforI(long[] a, long[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -1938,6 +2427,9 @@ public class TestVectorConditionalMove { // L fo L @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULEQforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1949,6 +2441,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULNEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1960,6 +2455,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1971,6 +2469,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1982,6 +2483,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLTforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -1993,6 +2497,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_UL, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLEforL(long[] a, long[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -2005,6 +2512,9 @@ public class TestVectorConditionalMove { // L fo F @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULEQforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2016,6 +2526,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULNEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2027,6 +2540,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2038,6 +2554,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULGEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2049,6 +2568,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2060,6 +2582,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveULLEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2076,7 +2601,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULEQforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2093,7 +2624,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULNEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2110,7 +2647,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2127,7 +2670,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULGEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2144,7 +2693,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULLTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2161,7 +2716,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_L, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.VECTOR_BLEND_D, IRNode.VECTOR_SIZE + "min(max_long, max_double)", ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx2", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULLEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2174,6 +2735,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_F, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforI(float[] a, float[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -2185,6 +2749,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_F, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforL(float[] a, float[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -2199,7 +2766,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2211,6 +2784,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2222,6 +2798,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_D, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGTforI(double[] a, double[] b, int[] c, int[] d, int[] r, int[] r2) { for (int i = 0; i < a.length; i++) { int cc = c[i]; @@ -2233,6 +2812,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_D, ">0"}, + // applyIf = {"UseVectorCmov", "false"}, + // applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGTforL(double[] a, double[] b, long[] c, long[] d, long[] r, long[] r2) { for (int i = 0; i < a.length; i++) { long cc = c[i]; @@ -2244,6 +2826,9 @@ public class TestVectorConditionalMove { @Test @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2258,7 +2843,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_D, ">0", IRNode.VECTOR_BLEND_D, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2274,7 +2865,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < b.length; i++) { float cc = c[i]; @@ -2289,7 +2886,13 @@ public class TestVectorConditionalMove { IRNode.VECTOR_MASK_CMP_F, ">0", IRNode.VECTOR_BLEND_F, ">0", IRNode.STORE_VECTOR, ">0"}, - applyIfCPUFeatureOr = {"avx", "true", "asimd", "true"}) + applyIfCPUFeatureOr = {"avx", "true", "asimd", "true", "rvv", "true"}, + applyIf = {"UseVectorCmov", "true"}) + @IR(failOn = {IRNode.STORE_VECTOR}, + applyIf = {"UseVectorCmov", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, + applyIf = {"UseVectorCmov", "false"}, + applyIfPlatform = {"riscv64", "true"}) private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java index 59c70b6873f..8cf3f728666 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java @@ -28,7 +28,7 @@ import java.util.List; /* * @test - * @bug 8358892 + * @bug 8358892 8357551 * @summary The test is to trigger code path of BoolTest::ge/gt in C2_MacroAssembler::enc_cmove_cmp_fp * @requires os.arch == "riscv64" * @requires vm.debug @@ -77,18 +77,33 @@ public class TestFPComparison2 { public static void main(String[] args) { List options = List.of("-XX:-TieredCompilation", "-Xlog:jit+compilation=trace"); // Booltest::ge - TestFramework framework = new TestFramework(Test_ge_1.class); + TestFramework + framework = new TestFramework(Test_ge_1.class); + framework.addFlags(options.toArray(new String[0])).start(); + framework = new TestFramework(Test_ge_cmove_fp_1.class); framework.addFlags(options.toArray(new String[0])).start(); framework = new TestFramework(Test_ge_2.class); framework.addFlags(options.toArray(new String[0])).start(); + framework = new TestFramework(Test_ge_cmove_fp_2.class); + framework.addFlags(options.toArray(new String[0])).start(); // Booltest::gt framework = new TestFramework(Test_gt_1.class); framework.addFlags(options.toArray(new String[0])).start(); + framework = new TestFramework(Test_gt_cmove_fp_1.class); + framework.addFlags(options.toArray(new String[0])).start(); framework = new TestFramework(Test_gt_2.class); framework.addFlags(options.toArray(new String[0])).start(); + framework = new TestFramework(Test_gt_cmove_fp_2.class); + framework.addFlags(options.toArray(new String[0])).start(); + + // BoolTest::ge/gt in C2_MacroAssembler::enc_cmove_fp_cmp_fp + framework = new TestFramework(Test_cmov_fp_cmp_fp_ge_3.class); + framework.addFlags(options.toArray(new String[0])).start(); + framework = new TestFramework(Test_cmov_fp_cmp_fp_ge_4.class); + framework.addFlags(options.toArray(new String[0])).start(); } } @@ -320,6 +335,235 @@ class Test_ge_1 { } } + +class Test_ge_cmove_fp_1 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x > y + // return 0 + // when neither is NaN, and x <= y + return !(x <= y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_1_0(float x, float y) { + return !(x <= y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x > y + // return 0 + // when neither is NaN, and x <= y + return !(x <= y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_1_0(double x, double y) { + return !(x <= y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x <= y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x <= y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x <= y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x <= y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x <= y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x <= y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x <= y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x <= y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { + return !(x <= y) ? a : b; + } + @DontCompile + public static float golden_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { + return !(x <= y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { + return !(x <= y) ? a : b; + } + @DontCompile + public static float golden_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { + return !(x <= y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_ge_fixed_1_0", "test_double_BoolTest_ge_fixed_1_0", + "test_float_BoolTest_ge_fixed_0_1", "test_double_BoolTest_ge_fixed_0_1", + "test_float_BoolTest_ge_fixed_10_20", "test_double_BoolTest_ge_fixed_10_20", + "test_float_BoolTest_ge_variable_results", "test_double_BoolTest_ge_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_1_0(x, y); + float expected = golden_float_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 1, 0), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_1_0(x, y); + float expected = golden_double_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 1, 0), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_0_1(x, y); + float expected = golden_float_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_0_1(x, y); + float expected = golden_double_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_10_20(x, y); + float expected = golden_float_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_10_20(x, y); + float expected = golden_double_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_float_BoolTest_ge_variable_results(x, y, a, b); + float expected = golden_float_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_double_BoolTest_ge_variable_results(x, y, a, b); + float expected = golden_double_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + class Test_ge_2 { @Test @IR(counts = {IRNode.CMOVE_I, "1"}) @@ -548,6 +792,234 @@ class Test_ge_2 { } } +class Test_ge_cmove_fp_2 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x < y + // return 0 + // when neither is NaN, and x >= y + return !(x >= y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_1_0(float x, float y) { + return !(x >= y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x < y + // return 0 + // when neither is NaN, and x >= y + return !(x >= y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_1_0(double x, double y) { + return !(x >= y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x >= y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_0_1(float x, float y) { + return !(x >= y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x >= y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_0_1(double x, double y) { + return !(x >= y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x >= y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_float_BoolTest_ge_fixed_10_20(float x, float y) { + return !(x >= y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x >= y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_double_BoolTest_ge_fixed_10_20(double x, double y) { + return !(x >= y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { + return !(x >= y) ? a : b; + } + @DontCompile + public static float golden_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { + return !(x >= y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { + return !(x >= y) ? a : b; + } + @DontCompile + public static float golden_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { + return !(x >= y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_ge_fixed_1_0", "test_double_BoolTest_ge_fixed_1_0", + "test_float_BoolTest_ge_fixed_0_1", "test_double_BoolTest_ge_fixed_0_1", + "test_float_BoolTest_ge_fixed_10_20", "test_double_BoolTest_ge_fixed_10_20", + "test_float_BoolTest_ge_variable_results", "test_double_BoolTest_ge_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_1_0(x, y); + float expected = golden_float_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_1_0(x, y); + float expected = golden_double_BoolTest_ge_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_0_1(x, y); + float expected = golden_float_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_0_1(x, y); + float expected = golden_double_BoolTest_ge_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_ge_fixed_10_20(x, y); + float expected = golden_float_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_ge_fixed_10_20(x, y); + float expected = golden_double_BoolTest_ge_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (ge, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_float_BoolTest_ge_variable_results(x, y, a, b); + float expected = golden_float_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_double_BoolTest_ge_variable_results(x, y, a, b); + float expected = golden_double_BoolTest_ge_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Double failed (ge), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + class Test_gt_1 { @Test @IR(counts = {IRNode.CMOVE_I, "1"}) @@ -776,6 +1248,234 @@ class Test_gt_1 { } } +class Test_gt_cmove_fp_1 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x >= y + // return 0 + // when neither is NaN, and x < y + return !(x < y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_1_0(float x, float y) { + return !(x < y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x >= y + // return 0 + // when neither is NaN, and x < y + return !(x < y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_1_0(double x, double y) { + return !(x < y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x < y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x < y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x < y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x < y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x < y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x < y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x < y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x < y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { + return !(x < y) ? a : b; + } + @DontCompile + public static float golden_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { + return !(x < y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { + return !(x < y) ? a : b; + } + @DontCompile + public static float golden_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { + return !(x < y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_gt_fixed_1_0", "test_double_BoolTest_gt_fixed_1_0", + "test_float_BoolTest_gt_fixed_0_1", "test_double_BoolTest_gt_fixed_0_1", + "test_float_BoolTest_gt_fixed_10_20", "test_double_BoolTest_gt_fixed_10_20", + "test_float_BoolTest_gt_variable_results", "test_double_BoolTest_gt_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_1_0(x, y); + float expected = golden_float_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_1_0(x, y); + float expected = golden_double_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_0_1(x, y); + float expected = golden_float_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_0_1(x, y); + float expected = golden_double_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_10_20(x, y); + float expected = golden_float_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_10_20(x, y); + float expected = golden_double_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_float_BoolTest_gt_variable_results(x, y, a, b); + float expected = golden_float_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_double_BoolTest_gt_variable_results(x, y, a, b); + float expected = golden_double_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + class Test_gt_2 { @Test @IR(counts = {IRNode.CMOVE_I, "1"}) @@ -1003,3 +1703,439 @@ class Test_gt_2 { } } } + +class Test_gt_cmove_fp_2 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_1_0(float x, float y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x <= y + // return 0 + // when neither is NaN, and x > y + return !(x > y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_1_0(float x, float y) { + return !(x > y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_1_0(double x, double y) { + // return 1 + // when either x or y is NaN + // when neither is NaN, and x <= y + // return 0 + // when neither is NaN, and x > y + return !(x > y) ? 1.0f : 0.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_1_0(double x, double y) { + return !(x > y) ? 1.0f : 0.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x > y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_0_1(float x, float y) { + return !(x > y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x > y) ? 0.0f : 1.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_0_1(double x, double y) { + return !(x > y) ? 0.0f : 1.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x > y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_float_BoolTest_gt_fixed_10_20(float x, float y) { + return !(x > y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x > y) ? 10.0f : 20.0f; + } + @DontCompile + public static float golden_double_BoolTest_gt_fixed_10_20(double x, double y) { + return !(x > y) ? 10.0f : 20.0f; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { + return !(x > y) ? a : b; + } + @DontCompile + public static float golden_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { + return !(x > y) ? a : b; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { + return !(x > y) ? a : b; + } + @DontCompile + public static float golden_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { + return !(x > y) ? a : b; + } + + @Run(test = {"test_float_BoolTest_gt_fixed_1_0", "test_double_BoolTest_gt_fixed_1_0", + "test_float_BoolTest_gt_fixed_0_1", "test_double_BoolTest_gt_fixed_0_1", + "test_float_BoolTest_gt_fixed_10_20", "test_double_BoolTest_gt_fixed_10_20", + "test_float_BoolTest_gt_variable_results", "test_double_BoolTest_gt_variable_results"}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_1_0(x, y); + float expected = golden_float_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_1_0(x, y); + float expected = golden_double_BoolTest_gt_fixed_1_0(x, y); + if (actual != expected) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_0_1(x, y); + float expected = golden_float_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_0_1(x, y); + float expected = golden_double_BoolTest_gt_fixed_0_1(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 0, 1), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + float actual = test_float_BoolTest_gt_fixed_10_20(x, y); + float expected = golden_float_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Float failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + float actual = test_double_BoolTest_gt_fixed_10_20(x, y); + float expected = golden_double_BoolTest_gt_fixed_10_20(x, y); + if (actual != expected) { + System.out.println("Double failed (gt, 10, 20), x: " + x + ", y: " + y + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float y = TestFPComparison2.FLOATS[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_float_BoolTest_gt_variable_results(x, y, a, b); + float expected = golden_float_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + for (int i = 0; i < TestFPComparison2.DOUBLES.length; i++) { + for (int j = 0; j < TestFPComparison2.DOUBLES.length; j++) { + double x = TestFPComparison2.DOUBLES[i]; + double y = TestFPComparison2.DOUBLES[j]; + for (int m = 0; m < TestFPComparison2.FLOATS.length; m++) { + for (int n = 0; n < TestFPComparison2.FLOATS.length; n++) { + float a = TestFPComparison2.FLOATS[m]; + float b = TestFPComparison2.FLOATS[n]; + float actual = test_double_BoolTest_gt_variable_results(x, y, a, b); + float expected = golden_double_BoolTest_gt_variable_results(x, y, a, b); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Double failed (gt), x: " + x + ", y: " + y + ", a: " + a + ", b: " + b + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + +class Test_cmov_fp_cmp_fp_ge_3 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_x_lt_0(float x) { + return x < 0 ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_gt_x_lt_0(float x) { + return x < 0 ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_x_gt_0(float x) { + return x > 0 ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_gt_x_gt_0(float x) { + return x > 0 ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_neg_x_lt_0(float x) { + return !(x < 0) ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_gt_neg_x_lt_0(float x) { + return !(x < 0) ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_gt_neg_x_gt_0(float x) { + return !(x > 0) ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_gt_neg_x_gt_0(float x) { + return !(x > 0) ? 0 : x; + } + + @Run(test = {"test_float_BoolTest_gt_x_lt_0", "test_float_BoolTest_gt_x_gt_0", + "test_float_BoolTest_gt_neg_x_lt_0", "test_float_BoolTest_gt_neg_x_gt_0",}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_gt_x_lt_0(x); + float expected = golden_float_BoolTest_gt_x_lt_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (lt, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_gt_x_gt_0(x); + float expected = golden_float_BoolTest_gt_x_gt_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (gt, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_gt_neg_x_lt_0(x); + float expected = golden_float_BoolTest_gt_neg_x_lt_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (neg lt, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_gt_neg_x_gt_0(x); + float expected = golden_float_BoolTest_gt_neg_x_gt_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (neg gt, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} + +class Test_cmov_fp_cmp_fp_ge_4 { + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_x_le_0(float x) { + return x <= 0 ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_ge_x_le_0(float x) { + return x <= 0 ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_x_ge_0(float x) { + return x >= 0 ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_ge_x_ge_0(float x) { + return x >= 0 ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_neg_x_le_0(float x) { + return !(x <= 0) ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_ge_neg_x_le_0(float x) { + return !(x <= 0) ? 0 : x; + } + + @Test + @IR(counts = {IRNode.CMOVE_F, "1"}) + public static float test_float_BoolTest_ge_neg_x_ge_0(float x) { + return !(x >= 0) ? 0 : x; + } + @DontCompile + public static float golden_float_BoolTest_ge_neg_x_ge_0(float x) { + return !(x >= 0) ? 0 : x; + } + + @Run(test = {"test_float_BoolTest_ge_x_le_0", "test_float_BoolTest_ge_x_ge_0", + "test_float_BoolTest_ge_neg_x_le_0", "test_float_BoolTest_ge_neg_x_ge_0",}) + public void runTests() { + int err = 0; + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_ge_x_le_0(x); + float expected = golden_float_BoolTest_ge_x_le_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (le, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_ge_x_ge_0(x); + float expected = golden_float_BoolTest_ge_x_ge_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (ge, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_ge_neg_x_le_0(x); + float expected = golden_float_BoolTest_ge_neg_x_le_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (neg le, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + for (int i = 0; i < TestFPComparison2.FLOATS.length; i++) { + for (int j = 0; j < TestFPComparison2.FLOATS.length; j++) { + float x = TestFPComparison2.FLOATS[i]; + float actual = test_float_BoolTest_ge_neg_x_ge_0(x); + float expected = golden_float_BoolTest_ge_neg_x_ge_0(x); + if (actual != expected && (!Float.isNaN(actual) || !Float.isNaN(expected))) { + System.out.println("Float failed (neg ge, x, 0), x: " + x + + ", actual: " + actual + ", expected: " + expected); + err++; + } + } + } + + if (err != 0) { + throw new RuntimeException("Some tests failed"); + } + } +} diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java b/test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java new file mode 100644 index 00000000000..e332ac9e293 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java @@ -0,0 +1,357 @@ +/* + * Copyright (c) 2025, Rivos Inc. 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.c2.irTests; + +import compiler.lib.ir_framework.*; +import java.util.Random; +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; + +/* + * @test + * @summary Test conditional move + compare object. + * @requires vm.simpleArch == "riscv64" + * @library /test/lib / + * @run driver compiler.c2.irTests.TestScalarConditionalMoveCmpObj + */ + +public class TestScalarConditionalMoveCmpObj { + final private static int SIZE = 1024; + private static final Random RANDOM = Utils.getRandomInstance(); + + public static void main(String[] args) { + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:+UseCompressedOops"); + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:-UseCompactObjectHeaders", "-XX:-UseCompressedOops"); + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:+UseCompressedOops"); + TestFramework.runWithFlags("-XX:+UseCMoveUnconditionally", "-XX:-UseVectorCmov", + "-XX:+UnlockExperimentalVMOptions", "-XX:+UseCompactObjectHeaders", "-XX:-UseCompressedOops"); + } + + // Object comparison + // O for I + private int cmoveOEQforI(Object a, Object b, int c, int d) { + return (a == b) ? c : d; + } + + private int cmoveONEforI(Object a, Object b, int c, int d) { + return (a != b) ? c : d; + } + + // O for L + private long cmoveOEQforL(Object a, Object b, long c, long d) { + return (a == b) ? c : d; + } + + private long cmoveONEforL(Object a, Object b, long c, long d) { + return (a != b) ? c : d; + } + + // O for F + private float cmoveOEQforF(Object a, Object b, float c, float d) { + return (a == b) ? c : d; + } + + private float cmoveONEforF(Object a, Object b, float c, float d) { + return (a != b) ? c : d; + } + + // O for D + private double cmoveOEQforD(Object a, Object b, double c, double d) { + return (a == b) ? c : d; + } + + private double cmoveONEforD(Object a, Object b, double c, double d) { + return (a != b) ? c : d; + } + + // Tests shows CMoveI is generated, so let @IR verify CMOVE_I. + // + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveOEQforI(Object[] a, Object[] b, int[] c, int[] d, int[] r, int[] r2) { + for (int i = 0; i < a.length; i++) { + int cc = c[i]; + int dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] == b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_I, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveONEforI(Object[] a, Object[] b, int[] c, int[] d, int[] r, int[] r2) { + for (int i = 0; i < a.length; i++) { + int cc = c[i]; + int dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] != b[i]) ? cc : dd; + } + } + + // So far, CMoveL is not guaranteed to be generated, so @IR not verify CMOVE_L. + // TODO: enable CMOVE_L verification when it's guaranteed to generate CMOVE_L. + // + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_P, ">0"}, + // applyIf = {"UseCompressedOops", "false"}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_N, ">0"}, + // applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveOEQforL(Object[] a, Object[] b, long[] c, long[] d, long[] r, long[] r2) { + for (int i = 0; i < a.length; i++) { + long cc = c[i]; + long dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] == b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_P, ">0"}, + // applyIf = {"UseCompressedOops", "false"}) + // @IR(counts = {IRNode.CMOVE_L, ">0", IRNode.CMP_N, ">0"}, + // applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveONEforL(Object[] a, Object[] b, long[] c, long[] d, long[] r, long[] r2) { + for (int i = 0; i < a.length; i++) { + long cc = c[i]; + long dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] != b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveOEQforF(Object[] a, Object[] b, float[] c, float[] d, float[] r, float[] r2) { + for (int i = 0; i < a.length; i++) { + float cc = c[i]; + float dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] == b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveONEforF(Object[] a, Object[] b, float[] c, float[] d, float[] r, float[] r2) { + for (int i = 0; i < a.length; i++) { + float cc = c[i]; + float dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] != b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveOEQforD(Object[] a, Object[] b, double[] c, double[] d, double[] r, double[] r2) { + for (int i = 0; i < a.length; i++) { + double cc = c[i]; + double dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] == b[i]) ? cc : dd; + } + } + + @Test + @IR(failOn = {IRNode.STORE_VECTOR}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_P, ">0"}, + applyIf = {"UseCompressedOops", "false"}) + @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_N, ">0"}, + applyIf = {"UseCompressedOops", "true"}) + private static void testCMoveONEforD(Object[] a, Object[] b, double[] c, double[] d, double[] r, double[] r2) { + for (int i = 0; i < a.length; i++) { + double cc = c[i]; + double dd = d[i]; + r2[i] = cc + dd; + r[i] = (a[i] != b[i]) ? cc : dd; + } + } + + @Warmup(0) + @Run(test = {// Object + "testCMoveOEQforI", + "testCMoveONEforI", + "testCMoveOEQforL", + "testCMoveONEforL", + "testCMoveOEQforF", + "testCMoveONEforF", + "testCMoveOEQforD", + "testCMoveONEforD", + }) + private void testCMove_runner_two() { + Object[] aO = new Object[SIZE]; + Object[] bO = new Object[SIZE]; + int[] cI = new int[SIZE]; + int[] dI = new int[SIZE]; + int[] rI = new int[SIZE]; + long[] cL = new long[SIZE]; + long[] dL = new long[SIZE]; + long[] rL = new long[SIZE]; + float[] cF = new float[SIZE]; + float[] dF = new float[SIZE]; + float[] rF = new float[SIZE]; + double[] cD = new double[SIZE]; + double[] dD = new double[SIZE]; + double[] rD = new double[SIZE]; + + init(aO); + shuffle(aO, bO); + init(cL); + init(dL); + init(cF); + init(dF); + init(cD); + init(dD); + + testCMoveOEQforI(aO, bO, cI, dI, rI, rI); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rI[i], cmoveOEQforI(aO[i], bO[i], cI[i], dI[i])); + } + + testCMoveONEforI(aO, bO, cI, dI, rI, rI); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rI[i], cmoveONEforI(aO[i], bO[i], cI[i], dI[i])); + } + + testCMoveOEQforL(aO, bO, cL, dL, rL, rL); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rL[i], cmoveOEQforL(aO[i], bO[i], cL[i], dL[i])); + } + + testCMoveONEforL(aO, bO, cL, dL, rL, rL); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rL[i], cmoveONEforL(aO[i], bO[i], cL[i], dL[i])); + } + + testCMoveOEQforF(aO, bO, cF, dF, rF, rF); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rF[i], cmoveOEQforF(aO[i], bO[i], cF[i], dF[i])); + } + + testCMoveONEforF(aO, bO, cF, dF, rF, rF); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rF[i], cmoveONEforF(aO[i], bO[i], cF[i], dF[i])); + } + + testCMoveOEQforD(aO, bO, cD, dD, rD, rD); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rD[i], cmoveOEQforD(aO[i], bO[i], cD[i], dD[i])); + } + + testCMoveONEforD(aO, bO, cD, dD, rD, rD); + for (int i = 0; i < SIZE; i++) { + Asserts.assertEquals(rD[i], cmoveONEforD(aO[i], bO[i], cD[i], dD[i])); + } + + } + + private static void init(Object[] a) { + for (int i = 0; i < SIZE; i++) { + a[i] = new Object(); + } + } + + private static void shuffle(Object[] a, Object[] b) { + for (int i = 0; i < a.length; i++) { + b[i] = a[i]; + } + Random rand = new Random(); + for (int i = 0; i < SIZE; i++) { + if (rand.nextInt(5) == 0) { + Object t = b[i]; + b[i] = b[SIZE-1-i]; + b[SIZE-1-i] = t; + } + } + } + + private static void init(int[] a) { + for (int i = 0; i < SIZE; i++) { + a[i] = RANDOM.nextInt(); + } + } + + private static void init(long[] a) { + for (int i = 0; i < SIZE; i++) { + a[i] = RANDOM.nextLong(); + } + } + + private static void init(float[] a) { + for (int i = 0; i < SIZE; i++) { + a[i] = switch(RANDOM.nextInt() % 20) { + case 0 -> Float.NaN; + case 1 -> 0; + case 2 -> 1; + case 3 -> Float.POSITIVE_INFINITY; + case 4 -> Float.NEGATIVE_INFINITY; + case 5 -> Float.MAX_VALUE; + case 6 -> Float.MIN_VALUE; + case 7, 8, 9 -> RANDOM.nextFloat(); + default -> Float.intBitsToFloat(RANDOM.nextInt()); + }; + } + } + + private static void init(double[] a) { + for (int i = 0; i < SIZE; i++) { + a[i] = switch(RANDOM.nextInt() % 20) { + case 0 -> Double.NaN; + case 1 -> 0; + case 2 -> 1; + case 3 -> Double.POSITIVE_INFINITY; + case 4 -> Double.NEGATIVE_INFINITY; + case 5 -> Double.MAX_VALUE; + case 6 -> Double.MIN_VALUE; + case 7, 8, 9 -> RANDOM.nextDouble(); + default -> Double.longBitsToDouble(RANDOM.nextLong()); + }; + } + } +} diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 1648135434a..41f185f3686 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -545,11 +545,36 @@ public class IRNode { trapNodes(CLASS_CHECK_TRAP, "class_check"); } + public static final String CMOVE_F = PREFIX + "CMOVE_F" + POSTFIX; + static { + beforeMatchingNameRegex(CMOVE_F, "CMoveF"); + } + + public static final String CMOVE_D = PREFIX + "CMOVE_D" + POSTFIX; + static { + beforeMatchingNameRegex(CMOVE_D, "CMoveD"); + } + public static final String CMOVE_I = PREFIX + "CMOVE_I" + POSTFIX; static { beforeMatchingNameRegex(CMOVE_I, "CMoveI"); } + public static final String CMOVE_L = PREFIX + "CMOVE_L" + POSTFIX; + static { + beforeMatchingNameRegex(CMOVE_L, "CMoveL"); + } + + public static final String CMP_F = PREFIX + "CMP_F" + POSTFIX; + static { + beforeMatchingNameRegex(CMP_F, "CmpF"); + } + + public static final String CMP_D = PREFIX + "CMP_D" + POSTFIX; + static { + beforeMatchingNameRegex(CMP_D, "CmpD"); + } + public static final String CMP_I = PREFIX + "CMP_I" + POSTFIX; static { beforeMatchingNameRegex(CMP_I, "CmpI"); @@ -585,6 +610,11 @@ public class IRNode { beforeMatchingNameRegex(CMP_P, "CmpP"); } + public static final String CMP_N = PREFIX + "CMP_N" + POSTFIX; + static { + beforeMatchingNameRegex(CMP_N, "CmpN"); + } + public static final String CMP_LT_MASK = PREFIX + "CMP_LT_MASK" + POSTFIX; static { beforeMatchingNameRegex(CMP_LT_MASK, "CmpLTMask"); diff --git a/test/micro/org/openjdk/bench/java/lang/ClassComparison.java b/test/micro/org/openjdk/bench/java/lang/ClassComparison.java index 2a768f243e2..15e631bb7fc 100644 --- a/test/micro/org/openjdk/bench/java/lang/ClassComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/ClassComparison.java @@ -44,12 +44,8 @@ public class ClassComparison { Class[] c2; int[] res; long[] resLong; - Object[] resObject; - Object ro1; - Object ro2; - Object[] resClass; - Class rc1; - Class rc2; + float[] resFloat; + double[] resDouble; @Setup public void setup() { @@ -58,12 +54,8 @@ public class ClassComparison { c2 = new Class[INVOCATIONS]; res = new int[INVOCATIONS]; resLong = new long[INVOCATIONS]; - resObject = new Object[INVOCATIONS]; - ro1 = new Object(); - ro2 = new Object(); - resClass = new Class[INVOCATIONS]; - rc1 = Float.class; - rc2 = Double.class; + resFloat = new float[INVOCATIONS]; + resDouble = new double[INVOCATIONS]; for (int i = 0; i < INVOCATIONS; i++) { c1[i] = random.nextBoolean() ? Float.class : Double.class; } @@ -86,6 +78,7 @@ public class ClassComparison { } } + @Benchmark public void equalClassResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (c1[i] == c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -98,4 +91,32 @@ public class ClassComparison { resLong[i] = (c1[i] != c2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } + + @Benchmark + public void equalClassResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (c1[i] == c2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualClassResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (c1[i] != c2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void equalClassResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (c1[i] == c2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualClassResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (c1[i] != c2[i]) ? 0.1 : 0.2; + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/FPComparison.java b/test/micro/org/openjdk/bench/java/lang/FPComparison.java index 8074ada3257..18b2b79c7bd 100644 --- a/test/micro/org/openjdk/bench/java/lang/FPComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/FPComparison.java @@ -37,34 +37,18 @@ import java.util.random.RandomGenerator; public class FPComparison { static final int INVOCATIONS = 1024; - float[] f1; - double[] d1; - float[] f2; - double[] d2; - int[] res; - long[] resLong; - Object[] resObject; - Object ro1; - Object ro2; - Class[] resClass; - Class rc1; - Class rc2; + static final float[] f1 = new float[INVOCATIONS]; + static final double[] d1 = new double[INVOCATIONS]; + static final float[] f2 = new float[INVOCATIONS]; + static final double[] d2 = new double[INVOCATIONS]; + static final int[] res = new int[INVOCATIONS];; + static final long[] resLong = new long[INVOCATIONS]; + static final float[] resFloat = new float[INVOCATIONS]; + static final double[] resDouble = new double[INVOCATIONS]; @Setup public void setup() { var random = RandomGenerator.getDefault(); - f1 = new float[INVOCATIONS]; - d1 = new double[INVOCATIONS]; - f2 = new float[INVOCATIONS]; - d2 = new double[INVOCATIONS]; - res = new int[INVOCATIONS]; - resLong = new long[INVOCATIONS]; - resObject = new Object[INVOCATIONS]; - ro1 = new Object(); - ro2 = new Object(); - resClass = new Class[INVOCATIONS]; - rc1 = Float.class; - rc2 = Double.class; for (int i = 0; i < INVOCATIONS; i++) { int type = random.nextInt(5); if (type == 1) { @@ -274,4 +258,148 @@ public class FPComparison { resLong[i] = (d1[i] >= d2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } + + // --------- result: float --------- + + @Benchmark + public void equalFloatResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (f1[i] == f2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void equalDoubleResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (d1[i] == d2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessFloatResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (f1[i] < f2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessDoubleResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (d1[i] < d2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualFloatResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (f1[i] <= f2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualDoubleResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (d1[i] <= d2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterFloatResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (f1[i] > f2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterDoubleResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (d1[i] > d2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualFloatResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (f1[i] >= f2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualDoubleResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (d1[i] >= d2[i]) ? 0.1f : 0.2f; + } + } + + // --------- result: double --------- + + @Benchmark + public void equalFloatResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (f1[i] == f2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void equalDoubleResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (d1[i] == d2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessFloatResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (f1[i] < f2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessDoubleResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (d1[i] < d2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualFloatResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (f1[i] <= f2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualDoubleResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (d1[i] <= d2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterFloatResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (f1[i] > f2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterDoubleResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (d1[i] > d2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualFloatResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (f1[i] >= f2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualDoubleResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (d1[i] >= d2[i]) ? 0.1 : 0.2; + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java b/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java index 1853be8497d..832d398fc3d 100644 --- a/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/IntegerComparison.java @@ -42,12 +42,8 @@ public class IntegerComparison { int[] i2; int[] res; long[] resLong; - Object[] resObject; - Object ro1; - Object ro2; - Object[] resClass; - Class rc1; - Class rc2; + float[] resFloat; + double[] resDouble; @Setup public void setup() { @@ -56,18 +52,17 @@ public class IntegerComparison { i2 = new int[INVOCATIONS]; res = new int[INVOCATIONS]; resLong = new long[INVOCATIONS]; - resObject = new Object[INVOCATIONS]; - ro1 = new Object(); - ro2 = new Object(); - resClass = new Class[INVOCATIONS]; - rc1 = Float.class; - rc2 = Double.class; + resFloat = new float[INVOCATIONS]; + resDouble = new double[INVOCATIONS]; for (int i = 0; i < INVOCATIONS; i++) { i1[i] = random.nextInt(INVOCATIONS); i2[i] = random.nextInt(INVOCATIONS); } } + // --------- result: int --------- + // Signed comparison + @Benchmark public void equalInteger() { for (int i = 0; i < INVOCATIONS; i++) { @@ -110,8 +105,55 @@ public class IntegerComparison { } } - // --------- result: long --------- + // Unsigned comparison + @Benchmark + public void equalIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 1 : 2; + } + } + + @Benchmark + public void notEqualIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 1 : 2; + } + } + + @Benchmark + public void lessIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 1 : 2; + } + } + + @Benchmark + public void lessEqualIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 1 : 2; + } + } + + @Benchmark + public void greaterIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualIntegerUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 1 : 2; + } + } + + + // --------- result: long --------- + // Signed comparison + + @Benchmark public void equalIntegerResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (i1[i] == i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -125,6 +167,7 @@ public class IntegerComparison { } } + @Benchmark public void lessIntegerResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (i1[i] < i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -138,6 +181,7 @@ public class IntegerComparison { } } + @Benchmark public void greaterIntegerResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (i1[i] > i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -150,4 +194,226 @@ public class IntegerComparison { resLong[i] = (i1[i] >= i2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } + + // Unsigned comparison + + @Benchmark + public void equalIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualIntegerUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + // --------- result: float --------- + // Signed comparison + + @Benchmark + public void equalIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] == i2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] != i2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] < i2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] <= i2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] > i2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualIntegerResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (i1[i] >= i2[i]) ? 0.1f : 0.2f; + } + } + + // Unsigned comparison + + @Benchmark + public void equalIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualIntegerUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 0.1f : 0.2f; + } + } + + // --------- result: double --------- + // Signed comparison + + @Benchmark + public void equalIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] == i2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] != i2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] < i2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] <= i2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] > i2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualIntegerResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (i1[i] >= i2[i]) ? 0.1 : 0.2; + } + } + + // Unsigned comparison + + @Benchmark + public void equalIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) == 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) != 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) < 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) <= 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) > 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualIntegerUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Integer.compareUnsigned(i1[i], i2[i]) >= 0 ? 0.1 : 0.2; + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/LongComparison.java b/test/micro/org/openjdk/bench/java/lang/LongComparison.java index bed5ee245b2..a7317244c6f 100644 --- a/test/micro/org/openjdk/bench/java/lang/LongComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/LongComparison.java @@ -41,12 +41,8 @@ public class LongComparison { long[] l2; int[] res; long[] resLong; - Object[] resObject; - Object ro1; - Object ro2; - Object[] resClass; - Class rc1; - Class rc2; + float[] resFloat; + double[] resDouble; @Setup public void setup() { @@ -55,18 +51,17 @@ public class LongComparison { l2 = new long[INVOCATIONS]; res = new int[INVOCATIONS]; resLong = new long[INVOCATIONS]; - resObject = new Object[INVOCATIONS]; - ro1 = new Object(); - ro2 = new Object(); - resClass = new Class[INVOCATIONS]; - rc1 = Float.class; - rc2 = Double.class; + resFloat = new float[INVOCATIONS]; + resDouble = new double[INVOCATIONS]; for (int i = 0; i < INVOCATIONS; i++) { l1[i] = random.nextLong(INVOCATIONS); l2[i] = random.nextLong(INVOCATIONS); } } + // --------- result: int --------- + // Signed comparison + @Benchmark public void equalLong() { for (int i = 0; i < INVOCATIONS; i++) { @@ -109,8 +104,54 @@ public class LongComparison { } } - // --------- result: long --------- + // Unsigned comparison + @Benchmark + public void equalLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 1 : 2; + } + } + + @Benchmark + public void notEqualLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 1 : 2; + } + } + + @Benchmark + public void lessLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 1 : 2; + } + } + + @Benchmark + public void lessEqualLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 1 : 2; + } + } + + @Benchmark + public void greaterLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 1 : 2; + } + } + + @Benchmark + public void greaterEqualLongUnsigned() { + for (int i = 0; i < INVOCATIONS; i++) { + res[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 1 : 2; + } + } + + // --------- result: long --------- + // Signed comparison + + @Benchmark public void equalLongResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (l1[i] == l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -124,6 +165,7 @@ public class LongComparison { } } + @Benchmark public void lessLongResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (l1[i] < l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -137,6 +179,7 @@ public class LongComparison { } } + @Benchmark public void greaterLongResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (l1[i] > l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -149,4 +192,226 @@ public class LongComparison { resLong[i] = (l1[i] >= l2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } + + // Unsigned comparison + + @Benchmark + public void equalLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void notEqualLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void lessEqualLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + @Benchmark + public void greaterEqualLongUnsignedResLong() { + for (int i = 0; i < INVOCATIONS; i++) { + resLong[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? Long.MAX_VALUE : Long.MIN_VALUE; + } + } + + // --------- result: float --------- + // Signed comparison + + @Benchmark + public void equalLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] == l2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] != l2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] < l2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] <= l2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] > l2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualLongResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (l1[i] >= l2[i]) ? 0.1f : 0.2f; + } + } + + // Unsigned comparison + + @Benchmark + public void equalLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void lessEqualLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 0.1f : 0.2f; + } + } + + @Benchmark + public void greaterEqualLongUnsignedResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 0.1f : 0.2f; + } + } + + // --------- result: double --------- + // Signed comparison + + @Benchmark + public void equalLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] == l2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] != l2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] < l2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] <= l2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] > l2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualLongResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (l1[i] >= l2[i]) ? 0.1 : 0.2; + } + } + + // Unsigned comparison + + @Benchmark + public void equalLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) == 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) != 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) < 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void lessEqualLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) <= 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) > 0 ? 0.1 : 0.2; + } + } + + @Benchmark + public void greaterEqualLongUnsignedResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = Long.compareUnsigned(l1[i], l2[i]) >= 0 ? 0.1 : 0.2; + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/PointerComparison.java b/test/micro/org/openjdk/bench/java/lang/PointerComparison.java index b6bcf008619..fc2fd95b1c0 100644 --- a/test/micro/org/openjdk/bench/java/lang/PointerComparison.java +++ b/test/micro/org/openjdk/bench/java/lang/PointerComparison.java @@ -44,12 +44,8 @@ public class PointerComparison { Object[] o2; int[] res; long[] resLong; - Object[] resObject; - Object ro1; - Object ro2; - Object[] resClass; - Class rc1; - Class rc2; + float[] resFloat; + double[] resDouble; @Setup public void setup() { @@ -58,12 +54,8 @@ public class PointerComparison { o2 = new Object[INVOCATIONS]; res = new int[INVOCATIONS]; resLong = new long[INVOCATIONS]; - resObject = new Object[INVOCATIONS]; - ro1 = new Object(); - ro2 = new Object(); - resClass = new Class[INVOCATIONS]; - rc1 = Float.class; - rc2 = Double.class; + resFloat = new float[INVOCATIONS]; + resDouble = new double[INVOCATIONS]; for (int i = 0; i < INVOCATIONS; i++) { o1[i] = new Object(); } @@ -86,6 +78,7 @@ public class PointerComparison { } } + @Benchmark public void equalObjectResLong() { for (int i = 0; i < INVOCATIONS; i++) { resLong[i] = (o1[i] == o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; @@ -98,4 +91,32 @@ public class PointerComparison { resLong[i] = (o1[i] != o2[i]) ? Long.MAX_VALUE : Long.MIN_VALUE; } } + + @Benchmark + public void equalObjecResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (o1[i] == o2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void notEqualObjecResFloat() { + for (int i = 0; i < INVOCATIONS; i++) { + resFloat[i] = (o1[i] != o2[i]) ? 0.1f : 0.2f; + } + } + + @Benchmark + public void equalObjecResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (o1[i] == o2[i]) ? 0.1 : 0.2; + } + } + + @Benchmark + public void notEqualObjecResDouble() { + for (int i = 0; i < INVOCATIONS; i++) { + resDouble[i] = (o1[i] != o2[i]) ? 0.1 : 0.2; + } + } } From ed5fc9ad2defb75ea5a68fe6427a591376ce6d6b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 8 Dec 2025 14:21:40 +0000 Subject: [PATCH 006/211] 8373087: Parallel: Rename PSGenerationPool to PSOldGenerationPool Reviewed-by: tschatzl, jsikstro, iwalulya --- src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp | 6 +++--- src/hotspot/share/gc/parallel/psMemoryPool.cpp | 8 ++++---- src/hotspot/share/gc/parallel/psMemoryPool.hpp | 4 ++-- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index b85b16f58b5..cff53e84059 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -141,9 +141,9 @@ void ParallelScavengeHeap::initialize_serviceability() { "PS Survivor Space", false /* support_usage_threshold */); - _old_pool = new PSGenerationPool(_old_gen, - "PS Old Gen", - true /* support_usage_threshold */); + _old_pool = new PSOldGenerationPool(_old_gen, + "PS Old Gen", + true /* support_usage_threshold */); _young_manager = new GCMemoryManager("PS Scavenge"); _old_manager = new GCMemoryManager("PS MarkSweep"); diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp index c120664600b..81c7b17a1ef 100644 --- a/src/hotspot/share/gc/parallel/psMemoryPool.cpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.cpp @@ -24,14 +24,14 @@ #include "gc/parallel/psMemoryPool.hpp" -PSGenerationPool::PSGenerationPool(PSOldGen* old_gen, - const char* name, - bool support_usage_threshold) : +PSOldGenerationPool::PSOldGenerationPool(PSOldGen* old_gen, + const char* name, + bool support_usage_threshold) : CollectedMemoryPool(name, old_gen->capacity_in_bytes(), old_gen->reserved().byte_size(), support_usage_threshold), _old_gen(old_gen) { } -MemoryUsage PSGenerationPool::get_memory_usage() { +MemoryUsage PSOldGenerationPool::get_memory_usage() { size_t maxSize = (available_for_allocation() ? max_size() : 0); size_t used = used_in_bytes(); size_t committed = _old_gen->capacity_in_bytes(); diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.hpp b/src/hotspot/share/gc/parallel/psMemoryPool.hpp index 58f39cdc79f..0da47e5a8ef 100644 --- a/src/hotspot/share/gc/parallel/psMemoryPool.hpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.hpp @@ -31,12 +31,12 @@ #include "services/memoryPool.hpp" #include "services/memoryUsage.hpp" -class PSGenerationPool : public CollectedMemoryPool { +class PSOldGenerationPool : public CollectedMemoryPool { private: PSOldGen* _old_gen; public: - PSGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold); + PSOldGenerationPool(PSOldGen* pool, const char* name, bool support_usage_threshold); MemoryUsage get_memory_usage(); size_t used_in_bytes() { return _old_gen->used_in_bytes(); } From ac81ce51fa4ed04b6dbcc28cb2dd8eabcfe52ad7 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 8 Dec 2025 15:38:35 +0000 Subject: [PATCH 007/211] 8372555: Test com/sun/jdi/ExceptionEvents.java failed: ObjectCollectedException Reviewed-by: amenkov, dholmes --- test/jdk/com/sun/jdi/ExceptionEvents.java | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/test/jdk/com/sun/jdi/ExceptionEvents.java b/test/jdk/com/sun/jdi/ExceptionEvents.java index de5f51c4aa2..ee9e91b4dd9 100644 --- a/test/jdk/com/sun/jdi/ExceptionEvents.java +++ b/test/jdk/com/sun/jdi/ExceptionEvents.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -355,7 +355,16 @@ public class ExceptionEvents extends TestScaffold { if (event.request() == request) { try { System.out.print("ExceptionEvent: "); - System.out.print("" + event.exception().referenceType().name()); + try { + System.out.print("" + event.exception().referenceType().name()); + } catch (ObjectCollectedException e) { + if (event.request().suspendPolicy() == EventRequest.SUSPEND_NONE) { + // Since the thread was not suspended, the exception object can be collected. + System.out.print(""); + } else { + throw e; + } + } Location loc = event.location(); System.out.print(" @ " + loc.method().name()); System.out.print(":" + loc.lineNumber()); From 355755d35de5c3155d1ea8d1afdd0debe5296a13 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Mon, 8 Dec 2025 16:07:01 +0000 Subject: [PATCH 008/211] 8366671: Refactor Thread::SpinAcquire and Thread::SpinRelease Co-authored-by: Axel Boldt-Christmas Reviewed-by: coleenp, kbarrett, dholmes, aboldtch --- .../recorder/service/jfrEventThrottler.cpp | 4 +- .../share/jfr/support/jfrAdaptiveSampler.cpp | 4 +- .../share/jfr/support/jfrThreadLocal.cpp | 1 - .../share/jfr/utilities/jfrSpinlockHelper.hpp | 44 ------------ src/hotspot/share/runtime/objectMonitor.cpp | 24 +++---- src/hotspot/share/runtime/park.cpp | 7 +- .../share/runtime/safepointVerifiers.cpp | 4 +- src/hotspot/share/runtime/thread.cpp | 46 ------------- src/hotspot/share/runtime/thread.hpp | 5 -- .../share/utilities/spinCriticalSection.cpp | 69 +++++++++++++++++++ .../share/utilities/spinCriticalSection.hpp | 63 +++++++++++++++++ .../gtest/jfr/test_adaptiveSampler.cpp | 3 +- 12 files changed, 155 insertions(+), 119 deletions(-) delete mode 100644 src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp create mode 100644 src/hotspot/share/utilities/spinCriticalSection.cpp create mode 100644 src/hotspot/share/utilities/spinCriticalSection.hpp diff --git a/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp index 787b2d7456b..e5420d29d94 100644 --- a/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp +++ b/src/hotspot/share/jfr/recorder/service/jfrEventThrottler.cpp @@ -24,11 +24,11 @@ */ #include "jfr/recorder/service/jfrEventThrottler.hpp" -#include "jfr/utilities/jfrSpinlockHelper.hpp" #include "jfrfiles/jfrEventIds.hpp" #include "logging/log.hpp" #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/spinCriticalSection.hpp" constexpr static const JfrSamplerParams _disabled_params = { 0, // sample points per window @@ -128,7 +128,7 @@ JfrEventThrottler* JfrEventThrottler::create_throttler(JfrEventId id) { * - period_ms time period expressed in milliseconds */ void JfrEventThrottler::configure(int64_t sample_size, int64_t period_ms) { - JfrSpinlockHelper mutex(&_lock); + SpinCriticalSection scs(&_lock); _sample_size = sample_size; _period_ms = period_ms; _update = true; diff --git a/src/hotspot/share/jfr/support/jfrAdaptiveSampler.cpp b/src/hotspot/share/jfr/support/jfrAdaptiveSampler.cpp index 22399f42bbb..571b5656576 100644 --- a/src/hotspot/share/jfr/support/jfrAdaptiveSampler.cpp +++ b/src/hotspot/share/jfr/support/jfrAdaptiveSampler.cpp @@ -25,13 +25,13 @@ #include "jfr/support/jfrAdaptiveSampler.hpp" #include "jfr/utilities/jfrRandom.inline.hpp" -#include "jfr/utilities/jfrSpinlockHelper.hpp" #include "jfr/utilities/jfrTime.hpp" #include "jfr/utilities/jfrTimeConverter.hpp" #include "jfr/utilities/jfrTryLock.hpp" #include "logging/log.hpp" #include "runtime/atomicAccess.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/spinCriticalSection.hpp" #include @@ -342,7 +342,7 @@ JfrGTestFixedRateSampler::JfrGTestFixedRateSampler(size_t sample_points_per_wind bool JfrGTestFixedRateSampler::initialize() { const bool result = JfrAdaptiveSampler::initialize(); - JfrSpinlockHelper mutex(&_lock); + SpinCriticalSection scs(&_lock); reconfigure(); return result; } diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 5fe5546e0a9..39b0eb3656c 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -36,7 +36,6 @@ #include "jfr/recorder/storage/jfrStorage.hpp" #include "jfr/support/jfrThreadId.inline.hpp" #include "jfr/support/jfrThreadLocal.hpp" -#include "jfr/utilities/jfrSpinlockHelper.hpp" #include "jfr/writers/jfrJavaEventWriter.hpp" #include "logging/log.hpp" #include "memory/allocation.inline.hpp" diff --git a/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp b/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp deleted file mode 100644 index 4b5ca80470e..00000000000 --- a/src/hotspot/share/jfr/utilities/jfrSpinlockHelper.hpp +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2013, 2025, 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. - * - */ - -#ifndef SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP -#define SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP - -#include "runtime/javaThread.hpp" - -class JfrSpinlockHelper { - private: - volatile int* const _lock; - - public: - JfrSpinlockHelper(volatile int* lock) : _lock(lock) { - Thread::SpinAcquire(_lock); - } - - ~JfrSpinlockHelper() { - Thread::SpinRelease(_lock); - } -}; - -#endif // SHARE_JFR_UTILITIES_JFRSPINLOCKHELPER_HPP diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index ee7629ec6f5..785ee2af592 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -59,6 +59,7 @@ #include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" #include "utilities/preserveException.hpp" +#include "utilities/spinCriticalSection.hpp" #if INCLUDE_JFR #include "jfr/support/jfrFlush.hpp" #endif @@ -1863,9 +1864,10 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // returns because of a timeout of interrupt. Contention is exceptionally rare // so we use a simple spin-lock instead of a heavier-weight blocking lock. - Thread::SpinAcquire(&_wait_set_lock); - add_waiter(&node); - Thread::SpinRelease(&_wait_set_lock); + { + SpinCriticalSection scs(&_wait_set_lock); + add_waiter(&node); + } intx save = _recursions; // record the old recursion count _waiters++; // increment the number of waiters @@ -1922,12 +1924,11 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { // That is, we fail toward safety. if (node.TState == ObjectWaiter::TS_WAIT) { - Thread::SpinAcquire(&_wait_set_lock); + SpinCriticalSection scs(&_wait_set_lock); if (node.TState == ObjectWaiter::TS_WAIT) { dequeue_specific_waiter(&node); // unlink from wait_set node.TState = ObjectWaiter::TS_RUN; } - Thread::SpinRelease(&_wait_set_lock); } // The thread is now either on off-list (TS_RUN), @@ -2036,7 +2037,7 @@ void ObjectMonitor::wait(jlong millis, bool interruptible, TRAPS) { bool ObjectMonitor::notify_internal(JavaThread* current) { bool did_notify = false; - Thread::SpinAcquire(&_wait_set_lock); + SpinCriticalSection scs(&_wait_set_lock); ObjectWaiter* iterator = dequeue_waiter(); if (iterator != nullptr) { guarantee(iterator->TState == ObjectWaiter::TS_WAIT, "invariant"); @@ -2095,7 +2096,6 @@ bool ObjectMonitor::notify_internal(JavaThread* current) { } } } - Thread::SpinRelease(&_wait_set_lock); return did_notify; } @@ -2198,9 +2198,10 @@ void ObjectMonitor::vthread_wait(JavaThread* current, jlong millis, bool interru // returns because of a timeout or interrupt. Contention is exceptionally rare // so we use a simple spin-lock instead of a heavier-weight blocking lock. - Thread::SpinAcquire(&_wait_set_lock); - add_waiter(node); - Thread::SpinRelease(&_wait_set_lock); + { + SpinCriticalSection scs(&_wait_set_lock); + add_waiter(node); + } node->_recursions = _recursions; // record the old recursion count _recursions = 0; // set the recursion level to be 0 @@ -2221,12 +2222,11 @@ bool ObjectMonitor::vthread_wait_reenter(JavaThread* current, ObjectWaiter* node // need to check if we were interrupted or the wait timed-out, and // in that case remove ourselves from the _wait_set queue. if (node->TState == ObjectWaiter::TS_WAIT) { - Thread::SpinAcquire(&_wait_set_lock); + SpinCriticalSection scs(&_wait_set_lock); if (node->TState == ObjectWaiter::TS_WAIT) { dequeue_specific_waiter(node); // unlink from wait_set node->TState = ObjectWaiter::TS_RUN; } - Thread::SpinRelease(&_wait_set_lock); } // If this was an interrupted case, set the _interrupted boolean so that diff --git a/src/hotspot/share/runtime/park.cpp b/src/hotspot/share/runtime/park.cpp index 37dfe6fcc3d..338a01bbfb9 100644 --- a/src/hotspot/share/runtime/park.cpp +++ b/src/hotspot/share/runtime/park.cpp @@ -25,6 +25,7 @@ #include "memory/allocation.inline.hpp" #include "nmt/memTracker.hpp" #include "runtime/javaThread.hpp" +#include "utilities/spinCriticalSection.hpp" // Lifecycle management for TSM ParkEvents. // ParkEvents are type-stable (TSM). @@ -60,14 +61,13 @@ ParkEvent * ParkEvent::Allocate (Thread * t) { // Using a spin lock since we are part of the mutex impl. // 8028280: using concurrent free list without memory management can leak // pretty badly it turns out. - Thread::SpinAcquire(&ListLock); { + SpinCriticalSection scs(&ListLock); ev = FreeList; if (ev != nullptr) { FreeList = ev->FreeNext; } } - Thread::SpinRelease(&ListLock); if (ev != nullptr) { guarantee (ev->AssociatedWith == nullptr, "invariant") ; @@ -88,12 +88,11 @@ void ParkEvent::Release (ParkEvent * ev) { ev->AssociatedWith = nullptr ; // Note that if we didn't have the TSM/immortal constraint, then // when reattaching we could trim the list. - Thread::SpinAcquire(&ListLock); { + SpinCriticalSection scs(&ListLock); ev->FreeNext = FreeList; FreeList = ev; } - Thread::SpinRelease(&ListLock); } // Override operator new and delete so we can ensure that the diff --git a/src/hotspot/share/runtime/safepointVerifiers.cpp b/src/hotspot/share/runtime/safepointVerifiers.cpp index 6eb61efe0ca..0c6f2e9add3 100644 --- a/src/hotspot/share/runtime/safepointVerifiers.cpp +++ b/src/hotspot/share/runtime/safepointVerifiers.cpp @@ -30,7 +30,9 @@ #ifdef ASSERT -NoSafepointVerifier::NoSafepointVerifier(bool active) : _thread(Thread::current()), _active(active) { +NoSafepointVerifier::NoSafepointVerifier(bool active) + : _thread(active ? Thread::current() : nullptr), + _active(active) { if (!_active) { return; } diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index d018c8a1a3a..f3c08ae62f7 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -566,49 +566,3 @@ bool Thread::set_as_starting_thread(JavaThread* jt) { DEBUG_ONLY(_starting_thread = jt;) return os::create_main_thread(jt); } - -// Ad-hoc mutual exclusion primitive: spin lock -// -// We employ a spin lock _only for low-contention, fixed-length -// short-duration critical sections where we're concerned -// about native mutex_t or HotSpot Mutex:: latency. - -void Thread::SpinAcquire(volatile int * adr) { - if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) { - return; // normal fast-path return - } - - // Slow-path : We've encountered contention -- Spin/Yield/Block strategy. - int ctr = 0; - int Yields = 0; - for (;;) { - while (*adr != 0) { - ++ctr; - if ((ctr & 0xFFF) == 0 || !os::is_MP()) { - if (Yields > 5) { - os::naked_short_sleep(1); - } else { - os::naked_yield(); - ++Yields; - } - } else { - SpinPause(); - } - } - if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) return; - } -} - -void Thread::SpinRelease(volatile int * adr) { - assert(*adr != 0, "invariant"); - // Roach-motel semantics. - // It's safe if subsequent LDs and STs float "up" into the critical section, - // but prior LDs and STs within the critical section can't be allowed - // to reorder or float past the ST that releases the lock. - // Loads and stores in the critical section - which appear in program - // order before the store that releases the lock - must also appear - // before the store that releases the lock in memory visibility order. - // So we need a #loadstore|#storestore "release" memory barrier before - // the ST of 0 into the lock-word which releases the lock. - AtomicAccess::release_store(adr, 0); -} diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 240821e90bd..181dfc46f87 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -602,11 +602,6 @@ protected: jint _hashStateY; jint _hashStateZ; - // Low-level leaf-lock primitives used to implement synchronization. - // Not for general synchronization use. - static void SpinAcquire(volatile int * Lock); - static void SpinRelease(volatile int * Lock); - #if defined(__APPLE__) && defined(AARCH64) private: DEBUG_ONLY(bool _wx_init); diff --git a/src/hotspot/share/utilities/spinCriticalSection.cpp b/src/hotspot/share/utilities/spinCriticalSection.cpp new file mode 100644 index 00000000000..0bbbc82c12b --- /dev/null +++ b/src/hotspot/share/utilities/spinCriticalSection.cpp @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2025, 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. + * + */ + +#include "runtime/atomicAccess.hpp" +#include "utilities/spinCriticalSection.hpp" + +void SpinCriticalSection::spin_acquire(volatile int* adr) { + if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) { + return; // normal fast-path return + } + + // Slow-path : We've encountered contention -- Spin/Yield/Block strategy. + int ctr = 0; + int Yields = 0; + for (;;) { + while (*adr != 0) { + ++ctr; + if ((ctr & 0xFFF) == 0 || !os::is_MP()) { + if (Yields > 5) { + os::naked_short_sleep(1); + } + else { + os::naked_yield(); + ++Yields; + } + } + else { + SpinPause(); + } + } + if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) return; + } +} + +void SpinCriticalSection::spin_release(volatile int* adr) { + assert(*adr != 0, "invariant"); + // Roach-motel semantics. + // It's safe if subsequent LDs and STs float "up" into the critical section, + // but prior LDs and STs within the critical section can't be allowed + // to reorder or float past the ST that releases the lock. + // Loads and stores in the critical section - which appear in program + // order before the store that releases the lock - must also appear + // before the store that releases the lock in memory visibility order. + // So we need a #loadstore|#storestore "release" memory barrier before + // the ST of 0 into the lock-word which releases the lock. + AtomicAccess::release_store(adr, 0); +} + diff --git a/src/hotspot/share/utilities/spinCriticalSection.hpp b/src/hotspot/share/utilities/spinCriticalSection.hpp new file mode 100644 index 00000000000..0ebdc5de63e --- /dev/null +++ b/src/hotspot/share/utilities/spinCriticalSection.hpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, 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. + * + */ + +#ifndef SHARE_UTILITIES_SPINCRITICALSECTION_HPP +#define SHARE_UTILITIES_SPINCRITICALSECTION_HPP + +#include "runtime/javaThread.hpp" +#include "runtime/safepointVerifiers.hpp" +#include "runtime/thread.hpp" +#include "utilities/macros.hpp" + +// Ad-hoc mutual exclusion primitive: spin critical section, +// which employs a spin lock. +// +// We use this critical section only for low-contention code, and +// when it is know that the duration is short. To be used where +// we're concerned about native mutex_t or HotSpot Mutex:: latency. +// This class uses low-level leaf-lock primitives to implement +// synchronization and is not for general synchronization use. +// Should not be used in signal-handling contexts. +class SpinCriticalSection { +private: + // We use int type as 32-bit atomic operation is the most performant + // compared to smaller/larger types. + volatile int* const _lock; + DEBUG_ONLY(NoSafepointVerifier _nsv;) + + static void spin_acquire(volatile int* Lock); + static void spin_release(volatile int* Lock); +public: + NONCOPYABLE(SpinCriticalSection); + SpinCriticalSection(volatile int* lock) + : _lock(lock) + DEBUG_ONLY(COMMA _nsv(Thread::current_or_null() != nullptr)) { + spin_acquire(_lock); + } + ~SpinCriticalSection() { + spin_release(_lock); + } +}; + +#endif // SHARE_UTILITIES_SPINCRITICALSECTION_HPP diff --git a/test/hotspot/gtest/jfr/test_adaptiveSampler.cpp b/test/hotspot/gtest/jfr/test_adaptiveSampler.cpp index 69548b06e51..8625f64099d 100644 --- a/test/hotspot/gtest/jfr/test_adaptiveSampler.cpp +++ b/test/hotspot/gtest/jfr/test_adaptiveSampler.cpp @@ -34,13 +34,12 @@ #include "jfr/utilities/jfrAllocation.hpp" #include "jfr/utilities/jfrRandom.inline.hpp" -#include "jfr/utilities/jfrSpinlockHelper.hpp" #include "jfr/utilities/jfrTime.hpp" #include "jfr/utilities/jfrTimeConverter.hpp" #include "jfr/utilities/jfrTryLock.hpp" #include "logging/log.hpp" -#include "runtime/atomicAccess.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/spinCriticalSection.hpp" #include "unittest.hpp" #include From 811591c5c332e6427dc96819451e046841fe635b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 8 Dec 2025 16:11:28 +0000 Subject: [PATCH 009/211] 8373262: Parallel: gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java fails Reviewed-by: cjplummer --- .../sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java index 76125e33e80..b0d158f409d 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/parallel/ParallelScavengeHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -60,11 +60,11 @@ public class ParallelScavengeHeap extends CollectedHeap { // Accessors public PSYoungGen youngGen() { - return VMObjectFactory.newObject(PSYoungGen.class, youngGenField.getValue()); + return VMObjectFactory.newObject(PSYoungGen.class, youngGenField.getValue(addr)); } public PSOldGen oldGen() { - return VMObjectFactory.newObject(PSOldGen.class, oldGenField.getValue()); + return VMObjectFactory.newObject(PSOldGen.class, oldGenField.getValue(addr)); } public long capacity() { From d34ef196c298aa91f8511714cfb04b15ae7fbf0a Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 8 Dec 2025 18:51:34 +0000 Subject: [PATCH 010/211] 8370198: Test gc/arguments/TestShrinkHeapInSteps.java crashed: assert(left >= right) failed: avoid underflow Reviewed-by: stefank, tschatzl --- .../cpu/aarch64/macroAssembler_aarch64.cpp | 1 - src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 1 - src/hotspot/share/gc/serial/serialHeap.cpp | 17 +++++++++++++++++ src/hotspot/share/gc/serial/serialHeap.hpp | 2 ++ 4 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index ceedb4f1063..2ccc755be3c 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -5379,7 +5379,6 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int index = oop_recorder()->find_index(k); - assert(! Universe::heap()->is_in(k), "should not be an oop"); InstructionMark im(this); RelocationHolder rspec = metadata_Relocation::spec(index); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index a14a051fd3b..43b17a13c20 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -5187,7 +5187,6 @@ void MacroAssembler::set_narrow_klass(Register dst, Klass* k) { assert (UseCompressedClassPointers, "should only be used for compressed headers"); assert (oop_recorder() != nullptr, "this assembler needs an OopRecorder"); int index = oop_recorder()->find_index(k); - assert(!Universe::heap()->is_in(k), "should not be an oop"); narrowKlass nk = CompressedKlassPointers::encode(k); relocate(metadata_Relocation::spec(index), [&] { diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 932c06b8109..104924c1cad 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -630,6 +630,14 @@ bool SerialHeap::requires_barriers(stackChunkOop obj) const { // Returns "TRUE" iff "p" points into the committed areas of the heap. bool SerialHeap::is_in(const void* p) const { + // precondition + verify_not_in_native_if_java_thread(); + + if (!is_in_reserved(p)) { + // If it's not even in reserved. + return false; + } + return _young_gen->is_in(p) || _old_gen->is_in(p); } @@ -797,3 +805,12 @@ void SerialHeap::gc_epilogue(bool full) { MetaspaceCounters::update_performance_counters(); }; + +#ifdef ASSERT +void SerialHeap::verify_not_in_native_if_java_thread() { + if (Thread::current()->is_Java_thread()) { + JavaThread* thread = JavaThread::current(); + assert(thread->thread_state() != _thread_in_native, "precondition"); + } +} +#endif diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index ee016173c2a..f5286179abf 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -111,6 +111,8 @@ private: void print_tracing_info() const override; void stop() override {}; + static void verify_not_in_native_if_java_thread() NOT_DEBUG_RETURN; + public: // Returns JNI_OK on success jint initialize() override; From b118caf6777cbf5bf75b41156fdfaaa15479f924 Mon Sep 17 00:00:00 2001 From: Alexandre Iline Date: Mon, 8 Dec 2025 22:16:28 +0000 Subject: [PATCH 011/211] 8373285: Update JCov for class file version 71 Reviewed-by: erikj --- make/conf/jib-profiles.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 795335d7c3c..93aeebc0dd6 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1192,8 +1192,8 @@ var getJibProfilesDependencies = function (input, common) { server: "jpg", product: "jcov", version: "3.0", - build_number: "3", - file: "bundles/jcov-3.0+3.zip", + build_number: "5", + file: "bundles/jcov-3.0+5.zip", environment_name: "JCOV_HOME", }, From 8df3f3d3417bc8fdb5a75d986e084441bbf6ebd2 Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Mon, 8 Dec 2025 22:45:59 +0000 Subject: [PATCH 012/211] 8373117: Update build doc link in README.md Reviewed-by: ayang, tbell --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index b3f30676b3c..e939f6a9ca4 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # Welcome to the JDK! For build instructions please see the -[online documentation](https://openjdk.org/groups/build/doc/building.html), +[online documentation](https://git.openjdk.org/jdk/blob/master/doc/building.md), or either of these files: - [doc/building.html](doc/building.html) (html version) From b86b2cbc7d9dd57aeaf64f70f248a120ae3cb751 Mon Sep 17 00:00:00 2001 From: Ben Taylor Date: Tue, 9 Dec 2025 00:17:30 +0000 Subject: [PATCH 013/211] 8352914: Shenandoah: Change definition of ShenandoahSharedValue to int32_t to leverage platform atomics Reviewed-by: wkemper, ysr --- .../share/gc/shenandoah/shenandoahSharedVariables.hpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp index 127882201d7..12c01ad5c90 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahSharedVariables.hpp @@ -29,11 +29,7 @@ #include "memory/allocation.hpp" #include "runtime/atomicAccess.hpp" -typedef jbyte ShenandoahSharedValue; - -// Needed for cooperation with generated code. -STATIC_ASSERT(sizeof(ShenandoahSharedValue) == 1); - +typedef int32_t ShenandoahSharedValue; typedef struct ShenandoahSharedFlag { enum { UNSET = 0, From c03d445a8ccfced5a59da680c37587f1024f3eca Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 9 Dec 2025 00:34:58 +0000 Subject: [PATCH 014/211] 6223700: XP L&F: Non-TopLevel JMenu's painting error Reviewed-by: kizune, dnguyen --- .../swing/plaf/windows/WindowsMenuUI.java | 2 +- .../swing/JMenu/TestPaintSpillOverBug.java | 82 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 test/jdk/javax/swing/JMenu/TestPaintSpillOverBug.java diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java index 130b09227cc..a7aca0c5ccf 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsMenuUI.java @@ -301,7 +301,7 @@ public final class WindowsMenuUI extends BasicMenuUI { JMenu menu = (JMenu)evt.getSource(); ButtonModel model = menu.getModel(); - if (menu.isRolloverEnabled()) { + if (menu.isRolloverEnabled() && menu.isTopLevelMenu()) { model.setRollover(false); menuItem.repaint(); } diff --git a/test/jdk/javax/swing/JMenu/TestPaintSpillOverBug.java b/test/jdk/javax/swing/JMenu/TestPaintSpillOverBug.java new file mode 100644 index 00000000000..8452b93cf45 --- /dev/null +++ b/test/jdk/javax/swing/JMenu/TestPaintSpillOverBug.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025, 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 + * @bug 6223700 + * @requires (os.family == "windows") + * @summary Verifies no painting spillover in Win L&F + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestPaintSpillOverBug + */ + +import javax.swing.JFrame; +import javax.swing.JMenuBar; +import javax.swing.JMenu; +import javax.swing.UIManager; + +public class TestPaintSpillOverBug { + + static final String INSTRUCTIONS = """ + A JMenu "click Me" will be shown. Click on it. + Position the mouse in the "Slowly Move Mouse Out of This" JMenu + so that the popup menu appears to the right. + Slowly move the mouse towards the edge of the item, + one pixel at a time + When the mouse hits the edge, + if the selection background spill over on to the popup + press Fail else press Pass."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + + PassFailJFrame.builder() + .title("TestPaintSpillOverBug Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(TestPaintSpillOverBug::createUI) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .build() + .awaitAndCheck(); + + } + + static JFrame createUI() { + JFrame f = new JFrame("TestPaintSpillOverBug"); + JMenuBar bar = new JMenuBar(); + JMenu clickMe = new JMenu("Click Me"); + JMenu culprit = new JMenu("Slowly Move Mouse Out of This"); + culprit.add("This item gets partially obscured"); + culprit.add(" "); + clickMe.add(" "); + clickMe.addSeparator(); + clickMe.add(culprit); + clickMe.addSeparator(); + clickMe.add(" "); + bar.add(clickMe); + f.setJMenuBar(bar); + f.setSize(600, 200); + return f; + } +} From b1c955018281a228a67695e5077666d751cd87d2 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Tue, 9 Dec 2025 01:00:52 +0000 Subject: [PATCH 015/211] 8372554: Test windows-x64-cmp-baseline failed due to differences with splashscreen object file Reviewed-by: dholmes --- make/modules/java.desktop/lib/ClientLibraries.gmk | 1 - 1 file changed, 1 deletion(-) diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index f273065a6df..499d5bef841 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -226,7 +226,6 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \ EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \ OPTIMIZATION := SIZE, \ - LINK_TIME_OPTIMIZATION := true, \ CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) \ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS) \ $(ICONV_CFLAGS), \ From 3ea82b9ff90aebc1a169fdd967c44408dc4a4f51 Mon Sep 17 00:00:00 2001 From: Xiaolong Peng Date: Tue, 9 Dec 2025 01:16:48 +0000 Subject: [PATCH 016/211] 8373272: Genshen: ShenandoahOldGenerationTest fails after JDK-8373056 Reviewed-by: wkemper --- .../test_shenandoahOldGeneration.cpp | 29 ++----------------- 1 file changed, 3 insertions(+), 26 deletions(-) diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp index b2491226e5c..4167e33b706 100644 --- a/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahOldGeneration.cpp @@ -165,35 +165,12 @@ TEST_VM_F(ShenandoahOldGenerationTest, test_actual_size_exceeds_promotion_reserv EXPECT_FALSE(promotions_enabled()) << "New plab can only be used for evacuations"; } -TEST_VM_F(ShenandoahOldGenerationTest, test_shared_expends_promoted_but_does_not_change_plab) { +TEST_VM_F(ShenandoahOldGenerationTest, test_expend_promoted_should_increase_expended) { SKIP_IF_NOT_SHENANDOAH(); - ShenandoahAllocRequest req = ShenandoahAllocRequest::for_shared_gc(128, ShenandoahAffiliation::OLD_GENERATION, true); - req.set_actual_size(128); - size_t actual_size = req.actual_size() * HeapWordSize; - size_t expended_before = old->get_promoted_expended(); - old->configure_plab_for_current_thread(req); + old->expend_promoted(128); size_t expended_after = old->get_promoted_expended(); - - EXPECT_EQ(expended_before + actual_size, expended_after) << "Shared promotion still expends promotion"; - EXPECT_EQ(plab_promoted(), INITIAL_PLAB_PROMOTED) << "Shared promotion should not count in plab"; - EXPECT_EQ(plab_size(), INITIAL_PLAB_SIZE) << "Shared promotion should not change size of plab"; - EXPECT_FALSE(promotions_enabled()); -} - -TEST_VM_F(ShenandoahOldGenerationTest, test_shared_evacuation_has_no_side_effects) { - SKIP_IF_NOT_SHENANDOAH(); - ShenandoahAllocRequest req = ShenandoahAllocRequest::for_shared_gc(128, ShenandoahAffiliation::OLD_GENERATION, false); - req.set_actual_size(128); - - size_t expended_before = old->get_promoted_expended(); - old->configure_plab_for_current_thread(req); - size_t expended_after = old->get_promoted_expended(); - - EXPECT_EQ(expended_before, expended_after) << "Not a promotion, should not expend promotion reserve"; - EXPECT_EQ(plab_promoted(), INITIAL_PLAB_PROMOTED) << "Not a plab, should not have touched plab"; - EXPECT_EQ(plab_size(), INITIAL_PLAB_SIZE) << "Not a plab, should not have touched plab"; - EXPECT_FALSE(promotions_enabled()); + EXPECT_EQ(expended_before + 128, expended_after) << "Should expend promotion"; } #undef SKIP_IF_NOT_SHENANDOAH From c9ab330b7bdd3cc2410ffdb336a63aa0ac7256a3 Mon Sep 17 00:00:00 2001 From: Xiaolong Peng Date: Tue, 9 Dec 2025 03:28:11 +0000 Subject: [PATCH 017/211] 8373116: Genshen: arraycopy_work should be always done for arrays in old gen during young concurrent marking 8372498: [genshen] gc/TestAllocHumongousFragment.java#generational causes intermittent SIGSEGV crashes Reviewed-by: wkemper, kdnilsen --- .../share/gc/shenandoah/shenandoahBarrierSet.hpp | 4 ++-- .../gc/shenandoah/shenandoahBarrierSet.inline.hpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp index 2b5bc766a46..7db478a781a 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.hpp @@ -128,8 +128,8 @@ public: void write_ref_array(HeapWord* start, size_t count); private: - template - inline void arraycopy_marking(T* dst, size_t count); + template + void arraycopy_marking(T* dst, size_t count); template inline void arraycopy_evacuation(T* src, size_t count); template diff --git a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp index adeea8ebf96..199256ca31b 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahBarrierSet.inline.hpp @@ -429,7 +429,11 @@ void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count) { // If marking old or young, we must evaluate the SATB barrier. This will be the only // action if we are not marking old. If we are marking old, we must still evaluate the // load reference barrier for a young collection. - arraycopy_marking(dst, count); + if (_heap->mode()->is_generational()) { + arraycopy_marking(dst, count); + } else { + arraycopy_marking(dst, count); + } } if ((gc_state & ShenandoahHeap::EVACUATION) != 0) { @@ -441,11 +445,12 @@ void ShenandoahBarrierSet::arraycopy_barrier(T* src, T* dst, size_t count) { } } -template +template void ShenandoahBarrierSet::arraycopy_marking(T* dst, size_t count) { assert(_heap->is_concurrent_mark_in_progress(), "only during marking"); if (ShenandoahSATBBarrier) { - if (!_heap->marking_context()->allocated_after_mark_start(reinterpret_cast(dst))) { + if (!_heap->marking_context()->allocated_after_mark_start(reinterpret_cast(dst)) || + (IS_GENERATIONAL && _heap->heap_region_containing(dst)->is_old() && _heap->is_concurrent_young_mark_in_progress())) { arraycopy_work(dst, count); } } From 35fe0b11015bd3a88ee21c76b54f9d4969fdedf6 Mon Sep 17 00:00:00 2001 From: Harshit470250 <133243171+Harshit470250@users.noreply.github.com> Date: Tue, 9 Dec 2025 04:59:53 +0000 Subject: [PATCH 018/211] 8372641: [s390x] Test failure TestMergeStores.java Reviewed-by: mhaessig, amitkumar, lucy --- src/hotspot/cpu/s390/s390.ad | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/src/hotspot/cpu/s390/s390.ad b/src/hotspot/cpu/s390/s390.ad index 7d3e963a108..19bd3620228 100644 --- a/src/hotspot/cpu/s390/s390.ad +++ b/src/hotspot/cpu/s390/s390.ad @@ -1715,6 +1715,8 @@ bool Matcher::match_rule_supported(int opcode) { switch (opcode) { case Op_ReverseBytesI: case Op_ReverseBytesL: + case Op_ReverseBytesS: + case Op_ReverseBytesUS: return UseByteReverseInstruction; case Op_PopCountI: case Op_PopCountL: @@ -11615,6 +11617,38 @@ instruct vround2D_reg(vecX dst, vecX src, immI8 rmode) %{ // Byte reverse +instruct bytes_reverse_short(iRegI dst, iRegI src) %{ + match(Set dst (ReverseBytesS src)); + predicate(UseByteReverseInstruction); + ins_cost(2 * DEFAULT_COST); + size(8); + + format %{ "LRVR $dst, $src\n\t # byte reverse int" + "SRA $dst, 0x0010\t # right shift by 16, sign extended" %} + + ins_encode %{ + __ z_lrvr($dst$$Register, $src$$Register); + __ z_sra($dst$$Register, 0x0010); + %} + ins_pipe(pipe_class_dummy); +%} + +instruct bytes_reverse_unsigned_short(iRegI dst, iRegI src) %{ + match(Set dst (ReverseBytesUS src)); + predicate(UseByteReverseInstruction); + ins_cost(2 * DEFAULT_COST); + size(8); + + format %{ "LRVR $dst, $src\n\t # byte reverse int" + "SRL $dst, 0x0010\t # right shift by 16, zero extended" %} + + ins_encode %{ + __ z_lrvr($dst$$Register, $src$$Register); + __ z_srl($dst$$Register, 0x0010); + %} + ins_pipe(pipe_class_dummy); +%} + instruct bytes_reverse_int(iRegI dst, iRegI src) %{ match(Set dst (ReverseBytesI src)); predicate(UseByteReverseInstruction); // See Matcher::match_rule_supported From 020e3f959194029715c18891e79aeed020abd59c Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 9 Dec 2025 05:15:47 +0000 Subject: [PATCH 019/211] 8373293: Change the exception handling in TestNestHostErrorWithMultiThread.java Reviewed-by: jpai, iklam --- .../TestNestHostErrorWithMultiThread.java | 69 +++++++++++++------ 1 file changed, 47 insertions(+), 22 deletions(-) diff --git a/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestHostErrorWithMultiThread.java b/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestHostErrorWithMultiThread.java index 11025fd4c12..0559c5858e0 100644 --- a/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestHostErrorWithMultiThread.java +++ b/test/hotspot/jtreg/runtime/Nestmates/membership/TestNestHostErrorWithMultiThread.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Huawei Technologies Co., Ltd. All rights reserved. + * Copyright (c) 2025, 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,14 +41,12 @@ import java.util.concurrent.CountDownLatch; public class TestNestHostErrorWithMultiThread { - public static void main(String args[]) { + public static void main(String args[]) throws Throwable { CountDownLatch runLatch = new CountDownLatch(1); CountDownLatch startLatch = new CountDownLatch(2); - Runnable test = new Test(runLatch, startLatch); - - Thread t1 = new Thread(test); - Thread t2 = new Thread(test); + TestThread t1 = new TestThread(runLatch, startLatch); + TestThread t2 = new TestThread(runLatch, startLatch); t1.start(); t2.start(); @@ -59,39 +58,65 @@ public class TestNestHostErrorWithMultiThread { t1.join(); t2.join(); + + Throwable threadException = t1.exception() != null ? t1.exception() + : t2.exception(); + if (threadException != null) { + Throwable t = threadException; + try { + throw new Error("TestThread encountered unexpected exception", t); + } + catch (OutOfMemoryError oome) { + // If we encounter an OOME trying to create the wrapper Error, + // then just re-throw the original exception so we report it and + // not the secondary OOME. + throw t; + } + } } catch (InterruptedException e) { throw new Error("Unexpected interrupt"); } } - static class Test implements Runnable { + static class TestThread extends Thread { private CountDownLatch runLatch; private CountDownLatch startLatch; + private Throwable exception; - Test(CountDownLatch runLatch, CountDownLatch startLatch) { + Throwable exception() { + return exception; + } + + TestThread(CountDownLatch runLatch, CountDownLatch startLatch) { this.runLatch = runLatch; this.startLatch = startLatch; } @Override public void run() { + // Don't allow any exceptions to escape - the main thread will + // report them. try { - startLatch.countDown(); - // Try to have all threads trigger the nesthost check at the same time - runLatch.await(); - HostNoNestMember h = new HostNoNestMember(); - h.test(); - throw new Error("IllegalAccessError was not thrown as expected"); - } catch (IllegalAccessError expected) { - String msg = "current type is not listed as a nest member"; - if (!expected.getMessage().contains(msg)) { - throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" + - expected.getMessage() + "\" does not contain \"" + - msg + "\"", expected); + try { + startLatch.countDown(); + // Try to have all threads trigger the nesthost check at the same time + runLatch.await(); + HostNoNestMember h = new HostNoNestMember(); + h.test(); + throw new Error("IllegalAccessError was not thrown as expected"); + } catch (IllegalAccessError expected) { + String msg = "current type is not listed as a nest member"; + if (!expected.getMessage().contains(msg)) { + throw new Error("Wrong " + expected.getClass().getSimpleName() +": \"" + + expected.getMessage() + "\" does not contain \"" + + msg + "\"", expected); + } + System.out.println("OK - got expected exception: " + expected); + } catch (InterruptedException e) { + throw new Error("Unexpected interrupt", e); } - System.out.println("OK - got expected exception: " + expected); - } catch (InterruptedException e) { - throw new Error("Unexpected interrupt"); + } catch (Throwable t) { + exception = t; } } } From cba09cd10d4e4482852a317786242836419c313b Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 9 Dec 2025 07:40:52 +0000 Subject: [PATCH 020/211] 5107379: Component orientation in JOptionPane is not proper in Motif L&F. Reviewed-by: tr, kizune --- .../swing/plaf/motif/MotifOptionPaneUI.java | 5 +- .../javax/swing/plaf/motif/TestIconRTL.java | 119 ++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/swing/plaf/motif/TestIconRTL.java diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java index e68d7e2d8bf..21e8c0f6747 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/motif/MotifOptionPaneUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ package com.sun.java.swing.plaf.motif; +import java.awt.BorderLayout; import java.awt.Color; import java.awt.Container; import java.awt.Dimension; @@ -102,7 +103,7 @@ public class MotifOptionPaneUI extends BasicOptionPaneUI JLabel iconLabel = new JLabel(sideIcon); iconLabel.setVerticalAlignment(SwingConstants.CENTER); - top.add(iconLabel, "West"); + top.add(iconLabel, BorderLayout.BEFORE_LINE_BEGINS); } } diff --git a/test/jdk/javax/swing/plaf/motif/TestIconRTL.java b/test/jdk/javax/swing/plaf/motif/TestIconRTL.java new file mode 100644 index 00000000000..e86e1ab38a6 --- /dev/null +++ b/test/jdk/javax/swing/plaf/motif/TestIconRTL.java @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2025, 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 + * @bug 5107379 + * @summary Component orientation in JOptionPane is not proper in Motif L&F. + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TestIconRTL + */ + +import java.awt.ComponentOrientation; +import java.util.concurrent.atomic.AtomicBoolean; +import javax.swing.JFrame; +import javax.swing.JMenu; +import javax.swing.JMenuBar; +import javax.swing.JMenuItem; +import javax.swing.JOptionPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class TestIconRTL { + + private static JFrame frame; + private static JOptionPane pane; + + static final String INSTRUCTIONS = """ + A JOptionPane is shown in Motif LookAndFeel with "Orientation" menu. + Click on "Orientation" menu and + test with "Left To Right" and "Right to Left" Orientation + If JOptionPane is drawn properly in different orientation, + then test passed, otherwise it failed."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("com.sun.java.swing.plaf.motif.MotifLookAndFeel"); + PassFailJFrame.builder() + .title("TestIconRTL Instructions") + .instructions(INSTRUCTIONS) + .columns(60) + .testUI(TestIconRTL::createTestUI) + .build() + .awaitAndCheck(); + } + + static JFrame createTestUI() { + pane = new JOptionPane(new String("Testing CCC4265463"), + JOptionPane.INFORMATION_MESSAGE, JOptionPane.YES_NO_CANCEL_OPTION); + pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + pane.setVisible(true); + + frame = new JFrame("TestIconRTL"); + + JMenuBar menuBar = new JMenuBar(); + menuBar.add(getOrientationJMenu()); + + frame.setJMenuBar(menuBar); + + frame.getContentPane().add(pane); + frame.pack(); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + frame.setLocationRelativeTo(null); + return frame; + } + + public static void test() throws Exception { + AtomicBoolean leftToRightOrientationFlag = new AtomicBoolean(false); + SwingUtilities.invokeAndWait(() -> leftToRightOrientationFlag.set(pane.getComponentOrientation().isLeftToRight())); + if (leftToRightOrientationFlag.get()) { + System.out.println("LTR LOCATION ..."); + } else { + System.out.println("RTL LOCATION ..."); + } + } + + private static JMenu getOrientationJMenu() { + JMenu lafMenu = new JMenu("Orientation"); + JMenuItem leftToRight = new JMenuItem("Left to Right"); + leftToRight.addActionListener(e -> { + pane.setComponentOrientation(ComponentOrientation.LEFT_TO_RIGHT); + pane.invalidate(); + SwingUtilities.updateComponentTreeUI(frame); + }); + + JMenuItem rightToLeft = new JMenuItem("Right to Left"); + rightToLeft.addActionListener(e -> { + pane.setComponentOrientation(ComponentOrientation.RIGHT_TO_LEFT); + pane.invalidate(); + SwingUtilities.updateComponentTreeUI(frame); + }); + + pane.invalidate(); + lafMenu.add(leftToRight); + lafMenu.add(rightToLeft); + return lafMenu; + } + + +} From 3a8a6e07f2a2cffa467815df55e746e92765903d Mon Sep 17 00:00:00 2001 From: Ramkumar Sunderbabu Date: Tue, 9 Dec 2025 09:15:04 +0000 Subject: [PATCH 021/211] 8319326: GC: Make TestParallelRefProc use createTestJavaProcessBuilder Reviewed-by: stefank, iwalulya --- .../gc/arguments/TestParallelRefProc.java | 85 +++++++++++++------ 1 file changed, 57 insertions(+), 28 deletions(-) diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java index 6e2e3c0239e..2cd9e9cd60b 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelRefProc.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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,13 +24,30 @@ package gc.arguments; /* - * @test TestParallelRefProc - * @summary Test defaults processing for -XX:+ParallelRefProcEnabled. + * @test id=Serial + * @summary Test defaults processing for -XX:+ParallelRefProcEnabled with Serial GC. * @library /test/lib * @library / - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestParallelRefProc + * @requires vm.gc.Serial + * @run driver gc.arguments.TestParallelRefProc Serial + */ + +/* + * @test id=Parallel + * @summary Test defaults processing for -XX:+ParallelRefProcEnabled with Parallel GC. + * @library /test/lib + * @library / + * @requires vm.gc.Parallel + * @run driver gc.arguments.TestParallelRefProc Parallel + */ + +/* + * @test id=G1 + * @summary Test defaults processing for -XX:+ParallelRefProcEnabled with G1 GC. + * @library /test/lib + * @library / + * @requires vm.gc.G1 + * @run driver gc.arguments.TestParallelRefProc G1 */ import java.util.Arrays; @@ -38,34 +55,46 @@ import java.util.ArrayList; import jdk.test.lib.process.OutputAnalyzer; -import jtreg.SkippedException; -import jdk.test.whitebox.gc.GC; - public class TestParallelRefProc { public static void main(String args[]) throws Exception { - boolean noneGCSupported = true; - if (GC.Serial.isSupported()) { - noneGCSupported = false; - testFlag(new String[] { "-XX:+UseSerialGC" }, false); + if (args.length == 0) { + throw new IllegalArgumentException("Test type must be specified as argument"); } - if (GC.Parallel.isSupported()) { - noneGCSupported = false; - testFlag(new String[] { "-XX:+UseParallelGC", "-XX:ParallelGCThreads=1" }, false); - testFlag(new String[] { "-XX:+UseParallelGC", "-XX:ParallelGCThreads=2" }, true); - testFlag(new String[] { "-XX:+UseParallelGC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false); - } - if (GC.G1.isSupported()) { - noneGCSupported = false; - testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=1" }, false); - testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=2" }, true); - testFlag(new String[] { "-XX:+UseG1GC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false); - } - if (noneGCSupported) { - throw new SkippedException("Skipping test because none of Serial/Parallel/G1 is supported."); + + String testType = args[0]; + + switch (testType) { + case "Serial": + testSerial(); + break; + case "Parallel": + testParallel(); + break; + case "G1": + testG1(); + break; + default: + throw new IllegalArgumentException("Unknown test type \"" + testType + "\""); } } + private static void testSerial() throws Exception { + testFlag(new String[] { "-XX:+UseSerialGC" }, false); + } + + private static void testParallel() throws Exception { + testFlag(new String[] { "-XX:+UseParallelGC", "-XX:ParallelGCThreads=1" }, false); + testFlag(new String[] { "-XX:+UseParallelGC", "-XX:ParallelGCThreads=2" }, true); + testFlag(new String[] { "-XX:+UseParallelGC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false); + } + + private static void testG1() throws Exception { + testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=1" }, false); + testFlag(new String[] { "-XX:+UseG1GC", "-XX:ParallelGCThreads=2" }, true); + testFlag(new String[] { "-XX:+UseG1GC", "-XX:-ParallelRefProcEnabled", "-XX:ParallelGCThreads=2" }, false); + } + private static final String parallelRefProcEnabledPattern = " *bool +ParallelRefProcEnabled *= *true +\\{product\\}"; @@ -77,7 +106,7 @@ public class TestParallelRefProc { result.addAll(Arrays.asList(args)); result.add("-XX:+PrintFlagsFinal"); result.add("-version"); - OutputAnalyzer output = GCArguments.executeLimitedTestJava(result); + OutputAnalyzer output = GCArguments.executeTestJava(result); output.shouldHaveExitValue(0); From 24244e41210be5b71b9e8238badbf975ed4b02ef Mon Sep 17 00:00:00 2001 From: Ramkumar Sunderbabu Date: Tue, 9 Dec 2025 09:17:38 +0000 Subject: [PATCH 022/211] 8319161: GC: Make TestParallelGCThreads use createTestJavaProcessBuilder Reviewed-by: stefank, iwalulya --- .../gc/arguments/TestParallelGCThreads.java | 139 ++++++++++++------ 1 file changed, 91 insertions(+), 48 deletions(-) diff --git a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java index 0ce17efd1a7..9b5e9843b5e 100644 --- a/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java +++ b/test/hotspot/jtreg/gc/arguments/TestParallelGCThreads.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,30 +24,86 @@ package gc.arguments; /* - * @test TestParallelGCThreads + * @test id=DefaultValue * @bug 8059527 8081382 - * @summary Tests argument processing for ParallelGCThreads + * @summary Tests default value of ParallelGCThreads * @library /test/lib * @library / - * @modules java.base/jdk.internal.misc - * java.management - * @build jdk.test.whitebox.WhiteBox - * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox - * @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI gc.arguments.TestParallelGCThreads + * @requires vm.gc.Z | vm.gc.Parallel | vm.gc.G1 + * @run driver gc.arguments.TestParallelGCThreads DefaultValue + */ + +/* + * @test id=Z + * @bug 8059527 8081382 + * @summary Tests argument processing for ParallelGCThreads with ZGC + * @library /test/lib + * @library / + * @requires vm.gc.Z + * @run driver gc.arguments.TestParallelGCThreads Z + */ + +/* + * @test id=Parallel + * @bug 8059527 8081382 + * @summary Tests argument processing for ParallelGCThreads with Parallel GC + * @library /test/lib + * @library / + * @requires vm.gc.Parallel + * @run driver gc.arguments.TestParallelGCThreads Parallel + */ + +/* + * @test id=G1 + * @bug 8059527 8081382 + * @summary Tests argument processing for ParallelGCThreads with G1 GC + * @library /test/lib + * @library / + * @requires vm.gc.G1 + * @run driver gc.arguments.TestParallelGCThreads G1 + */ + +/* + * @test id=MaxValue + * @bug 8059527 8081382 + * @summary Tests max value for ParallelGCThreads + * @library /test/lib + * @library / + * @requires vm.gc.Serial + * @run driver gc.arguments.TestParallelGCThreads MaxValue */ -import java.util.ArrayList; -import java.util.List; import jdk.test.lib.Asserts; import jdk.test.lib.process.OutputAnalyzer; -import jtreg.SkippedException; -import jdk.test.whitebox.gc.GC; public class TestParallelGCThreads { public static void main(String args[]) throws Exception { - testFlags(); - testDefaultValue(); + if (args.length == 0) { + throw new IllegalArgumentException("Test type must be specified as argument"); + } + + String testType = args[0]; + + switch (testType) { + case "DefaultValue": + testDefaultValue(); + break; + case "Z": + testFlags("-XX:+UseZGC"); + break; + case "Parallel": + testFlags("-XX:+UseParallelGC"); + break; + case "G1": + testFlags("-XX:+UseG1GC"); + break; + case "MaxValue": + testMaxValue(); + break; + default: + throw new IllegalArgumentException("Unknown test type \"" + testType + "\""); + } } private static final String flagName = "ParallelGCThreads"; @@ -55,8 +111,8 @@ public class TestParallelGCThreads { // uint ParallelGCThreads = 23 {product} private static final String printFlagsFinalPattern = " *uint *" + flagName + " *:?= *(\\d+) *\\{product\\} *"; - public static void testDefaultValue() throws Exception { - OutputAnalyzer output = GCArguments.executeLimitedTestJava( + private static void testDefaultValue() throws Exception { + OutputAnalyzer output = GCArguments.executeTestJava( "-XX:+UnlockExperimentalVMOptions", "-XX:+PrintFlagsFinal", "-version"); String value = output.firstMatch(printFlagsFinalPattern, 1); @@ -64,10 +120,10 @@ public class TestParallelGCThreads { try { Asserts.assertNotNull(value, "Couldn't find uint flag " + flagName); - Long longValue = new Long(value); + Long longValue = Long.valueOf(value); // Sanity check that we got a non-zero value. - Asserts.assertNotEquals(longValue, "0"); + Asserts.assertNotEquals(longValue, 0L); output.shouldHaveExitValue(0); } catch (Exception e) { @@ -76,41 +132,28 @@ public class TestParallelGCThreads { } } - public static void testFlags() throws Exception { - // For each parallel collector (G1, Parallel) - List supportedGC = new ArrayList(); + private static void testFlags(String gcFlag) throws Exception { - if (GC.G1.isSupported()) { - supportedGC.add("G1"); - } - if (GC.Parallel.isSupported()) { - supportedGC.add("Parallel"); - } + // Make sure the VM does not allow ParallelGCThreads set to 0 + OutputAnalyzer output = GCArguments.executeTestJava( + gcFlag, + "-XX:ParallelGCThreads=0", + "-XX:+PrintFlagsFinal", + "-version"); + output.shouldHaveExitValue(1); - if (supportedGC.isEmpty()) { - throw new SkippedException("Skipping test because none of G1/Parallel is supported."); - } - - for (String gc : supportedGC) { - // Make sure the VM does not allow ParallelGCThreads set to 0 - OutputAnalyzer output = GCArguments.executeLimitedTestJava( - "-XX:+Use" + gc + "GC", - "-XX:ParallelGCThreads=0", + // Do some basic testing to ensure the flag updates the count + for (long i = 1; i <= 3; i++) { + long count = getParallelGCThreadCount( + gcFlag, + "-XX:ParallelGCThreads=" + i, "-XX:+PrintFlagsFinal", "-version"); - output.shouldHaveExitValue(1); - - // Do some basic testing to ensure the flag updates the count - for (long i = 1; i <= 3; i++) { - long count = getParallelGCThreadCount( - "-XX:+Use" + gc + "GC", - "-XX:ParallelGCThreads=" + i, - "-XX:+PrintFlagsFinal", - "-version"); - Asserts.assertEQ(count, i, "Specifying ParallelGCThreads=" + i + " for " + gc + "GC does not set the thread count properly!"); - } + Asserts.assertEQ(count, i, "Specifying ParallelGCThreads=" + i + " for \"" + gcFlag + "\" does not set the thread count properly!"); } + } + private static void testMaxValue() throws Exception { // Test the max value for ParallelGCThreads // So setting ParallelGCThreads=2147483647 should give back 2147483647 long count = getParallelGCThreadCount( @@ -122,7 +165,7 @@ public class TestParallelGCThreads { } public static long getParallelGCThreadCount(String... flags) throws Exception { - OutputAnalyzer output = GCArguments.executeLimitedTestJava(flags); + OutputAnalyzer output = GCArguments.executeTestJava(flags); output.shouldHaveExitValue(0); String stdout = output.getStdout(); return FlagsValue.getFlagLongValue("ParallelGCThreads", stdout); From 9c91c68d1d5938d7e2b9a90c82b0a36ef1a063cd Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Tue, 9 Dec 2025 09:18:04 +0000 Subject: [PATCH 023/211] 8373111: Test java/lang/management/MemoryMXBean/MemoryManagement.java timed out Reviewed-by: lmesnik --- .../management/MemoryMXBean/MemoryManagement.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/test/jdk/java/lang/management/MemoryMXBean/MemoryManagement.java b/test/jdk/java/lang/management/MemoryMXBean/MemoryManagement.java index b136b724b71..f6c7446d1f3 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/MemoryManagement.java +++ b/test/jdk/java/lang/management/MemoryMXBean/MemoryManagement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -49,7 +49,7 @@ * * @modules jdk.management * - * @run main/timeout=600 MemoryManagement + * @run main/othervm/timeout=600 -Xmn8m MemoryManagement */ import java.lang.management.*; @@ -58,6 +58,10 @@ import javax.management.*; import javax.management.openmbean.CompositeData; public class MemoryManagement { + + private static final int YOUNG_GEN_SIZE = 8 * 1024 * 1024; // Must match -Xmn set on the @run line + private static final int NUM_CHUNKS = 2; + private static final MemoryMXBean mm = ManagementFactory.getMemoryMXBean(); private static final List pools = Collections.synchronizedList(ManagementFactory.getMemoryPoolMXBeans()); @@ -66,9 +70,6 @@ public class MemoryManagement { private static volatile MemoryPoolMXBean mpool = null; private static volatile boolean trace = false; private static volatile boolean testFailed = false; - private static final int NUM_CHUNKS = 2; - // Must match -Xmn set on the @run line - private static final int YOUNG_GEN_SIZE = 8 * 1024 * 1024; private static volatile long chunkSize; private static volatile int listenerInvoked = 0; From 786833cd1bf8eda1cef25da392a055f4eb371abf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joel=20Sikstr=C3=B6m?= Date: Tue, 9 Dec 2025 09:44:18 +0000 Subject: [PATCH 024/211] 8373022: serviceability/sa/ClhsdbScanOops.java assumes no GC should occur Reviewed-by: cjplummer, stefank, ayang, tschatzl --- test/hotspot/jtreg/ProblemList.txt | 3 --- test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java | 5 ++++- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index ddc6e55dc05..48d0da048fe 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -140,9 +140,6 @@ serviceability/sa/ClhsdbPstack.java#core 8318754 macosx-aarch64 serviceability/sa/TestJmapCore.java 8318754 macosx-aarch64 serviceability/sa/TestJmapCoreMetaspace.java 8318754 macosx-aarch64 -serviceability/sa/ClhsdbScanOops.java#parallel 8373022 generic-all -serviceability/sa/ClhsdbScanOops.java#serial 8373022 generic-all - serviceability/sa/ClhsdbThreadContext.java 8356704 windows-x64 serviceability/jvmti/stress/StackTrace/NotSuspended/GetStackTraceNotSuspendedStressTest.java 8315980 linux-all,windows-x64 diff --git a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java index b6919a566a9..ef75b08c995 100644 --- a/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java +++ b/test/hotspot/jtreg/serviceability/sa/ClhsdbScanOops.java @@ -60,7 +60,10 @@ public class ClhsdbScanOops { try { ClhsdbLauncher test = new ClhsdbLauncher(); - theApp = LingeredApp.startApp(gc); + // This test assumes that no GC should happen during its execution. + // Setting the initial heap size to a reasonably high number avoids + // running a GC. + theApp = LingeredApp.startApp(gc, "-XX:InitialHeapSize=100M"); System.out.println ("Started LingeredApp with the GC option " + gc + " and pid " + theApp.getPid()); From 1f49edd9783ed4579d989d6939ee75e926f0716a Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 9 Dec 2025 10:02:01 +0000 Subject: [PATCH 025/211] 4459231: Focus of JTabbedPane(with Scrollable tablayout) changes on change in LookAndFeel Reviewed-by: tr, kizune --- .../swing/plaf/basic/BasicTabbedPaneUI.java | 10 ++ .../JTabbedPane/TabbedPaneBugWithLNF.java | 110 ++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 test/jdk/javax/swing/JTabbedPane/TabbedPaneBugWithLNF.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java index 59799f4d91a..842e8892c76 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicTabbedPaneUI.java @@ -293,6 +293,16 @@ public class BasicTabbedPaneUI extends TabbedPaneUI implements SwingConstants { installDefaults(); installListeners(); installKeyboardActions(); + setFocusIndex(tabPane.getSelectedIndex(), false); + + if (tabPane.getLayout() instanceof TabbedPaneScrollLayout) { + ensureCurrentLayout(); + int index = tabPane.getSelectedIndex(); + if (index < rects.length && index != -1) { + tabScroller.tabPanel.scrollRectToVisible( + (Rectangle)rects[index].clone()); + } + } } public void uninstallUI(JComponent c) { diff --git a/test/jdk/javax/swing/JTabbedPane/TabbedPaneBugWithLNF.java b/test/jdk/javax/swing/JTabbedPane/TabbedPaneBugWithLNF.java new file mode 100644 index 00000000000..cf989280da2 --- /dev/null +++ b/test/jdk/javax/swing/JTabbedPane/TabbedPaneBugWithLNF.java @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2025, 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 + * @bug 4459231 + * @summary Verifies if JTabbedPane(with Scrollable tablayout) changes focus + * on change in LookAndFeel + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual TabbedPaneBugWithLNF + */ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JTabbedPane; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; + +public class TabbedPaneBugWithLNF { + + private static String LNF = "com.sun.java.swing.plaf.motif.MotifLookAndFeel"; + private static JTabbedPane tabPane; + private static JButton testBtn; + + static final String INSTRUCTIONS = """ + A JTabbedPane with 10 tabs will be shown. + Scroll the tabs till the end, i.e., to "Testing Tab9". + Select that tab. + You will see the main tab JButton's text changed to 'Test Button9'. + Click on it, which will change the lookandfeel. + Verify if child tabs have scrolled back to starting child tab + i.e., 'Testing Tab0', where as the selected tab is still 'Testing Tab9'. + If it does, press Fail + else if focus of the child Tab is still at "Testing Tab9" press Pass."""; + + public static void main(String[] args) throws Exception { + UIManager.setLookAndFeel("javax.swing.plaf.metal.MetalLookAndFeel"); + PassFailJFrame.builder() + .title("TabbedPaneBugWithLNF Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(TabbedPaneBugWithLNF::createUI) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + JFrame frame = new JFrame("TabbedPaneBugWithLNF"); + frame.setSize(640, 180); + + tabPane = new JTabbedPane(JTabbedPane.BOTTOM,JTabbedPane.SCROLL_TAB_LAYOUT); + + tabPane.addTab("Testing Tab0", testBtn = new JButton("Test Button0")); + + tabPane.addTab("Testing Tab1", testBtn = new JButton("Test Button1")); + + tabPane.addTab("Testing Tab2", testBtn = new JButton("Test Button2")); + + tabPane.addTab("Testing Tab3", testBtn = new JButton("Test Button3")); + + tabPane.addTab("Testing Tab4", testBtn = new JButton("Test Button4")); + + tabPane.addTab("Testing Tab5", testBtn = new JButton("Test Button5")); + + tabPane.addTab("Testing Tab6", testBtn = new JButton("Test Button6")); + + tabPane.addTab("Testing Tab7", testBtn = new JButton("Test Button7")); + tabPane.addTab("Testing Tab8", testBtn = new JButton("Test Button8")); + JButton myBtn = null; + tabPane.addTab("Testing Tab9", myBtn = new JButton("Test Button9")); + myBtn.addActionListener( new ActionListener() { + public void actionPerformed(ActionEvent ae) { + try { + UIManager.setLookAndFeel(LNF); + SwingUtilities.updateComponentTreeUI(frame); + System.out.println("tabPane.selectedIndex " + tabPane.getSelectedIndex()); + } catch (Exception exc) { + System.out.println("Error changing L&F : " + LNF); + } + } + }); + frame.add(tabPane); + return frame; + } +} + From 0a557890a50b0dc83c70dc877027d951dcc05470 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 9 Dec 2025 10:04:25 +0000 Subject: [PATCH 026/211] 8373025: test/hotspot/jtreg/gc/cslocker/TestCSLocker.java may deadlock Reviewed-by: ayang, tschatzl, stefank --- test/hotspot/jtreg/ProblemList.txt | 1 - .../jtreg/gc/cslocker/TestCSLocker.java | 24 ++++------------- .../jtreg/gc/cslocker/libTestCSLocker.c | 26 +++++++++++-------- 3 files changed, 20 insertions(+), 31 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 48d0da048fe..177c14da785 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -94,7 +94,6 @@ gc/shenandoah/TestEvilSyncBug.java#generational 8345501 generic-all gc/shenandoah/TestRetainObjects.java#no-tlab 8361099 generic-all gc/shenandoah/TestSieveObjects.java#no-tlab 8361099 generic-all gc/shenandoah/TestSieveObjects.java#no-tlab-genshen 8361099 generic-all -gc/cslocker/TestCSLocker.java 8373025 generic-all ############################################################################# diff --git a/test/hotspot/jtreg/gc/cslocker/TestCSLocker.java b/test/hotspot/jtreg/gc/cslocker/TestCSLocker.java index 3550c4e5f14..82dc2fb99a1 100644 --- a/test/hotspot/jtreg/gc/cslocker/TestCSLocker.java +++ b/test/hotspot/jtreg/gc/cslocker/TestCSLocker.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -33,18 +33,11 @@ import static gc.testlibrary.Allocation.blackHole; * @summary completely in JNI CS, while other is trying to allocate memory * @summary provoking GC. OOM means FAIL, deadlock means PASS. * - * @comment This test assumes that no allocation happens during the sleep loop, - * which is something that we can't guarantee. With ZGC we see test - * timeouts because the main thread allocates and waits for the GC, - * which waits for the CSLocker, which waits for the main thread. - * @requires vm.gc != "Z" - * * @run main/native/othervm -Xmx256m gc.cslocker.TestCSLocker */ public class TestCSLocker extends Thread { - static int timeoutMillis = 5000; public static void main(String args[]) throws Exception { // start garbage producer thread GarbageProducer garbageProducer = new GarbageProducer(1000000, 10); @@ -53,15 +46,9 @@ public class TestCSLocker extends Thread // start CS locker thread CSLocker csLocker = new CSLocker(); csLocker.start(); - // After the CSLocker thread has started, any operation such as an allocation, - // which could rely on the GC to make progress, will cause a deadlock that will - // make the test time out. That includes printing. Please don't use any such - // code until unlock() is called below. - // check timeout to success deadlocking - sleep(timeoutMillis); - - csLocker.unlock(); + // Wait for the csLocker thread to finish its critical section + csLocker.join(); garbageProducer.interrupt(); } } @@ -97,11 +84,10 @@ class CSLocker extends Thread public void run() { int[] a = new int[10]; a[0] = 1; - if (!lock(a)) { + if (!criticalSection(a)) { throw new RuntimeException("failed to acquire CSLock"); } } - native boolean lock(int[] array); - native void unlock(); + native boolean criticalSection(int[] array); } diff --git a/test/hotspot/jtreg/gc/cslocker/libTestCSLocker.c b/test/hotspot/jtreg/gc/cslocker/libTestCSLocker.c index ae75c631072..58779d40cb9 100644 --- a/test/hotspot/jtreg/gc/cslocker/libTestCSLocker.c +++ b/test/hotspot/jtreg/gc/cslocker/libTestCSLocker.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -23,9 +23,15 @@ #include +#ifdef WINDOWS +#include +#else +#include +#endif + static volatile int release_critical = 0; -JNIEXPORT jboolean JNICALL Java_gc_cslocker_CSLocker_lock +JNIEXPORT jboolean JNICALL Java_gc_cslocker_CSLocker_criticalSection (JNIEnv *env, jobject obj, jintArray array) { jboolean retval = JNI_TRUE; @@ -33,17 +39,15 @@ JNIEXPORT jboolean JNICALL Java_gc_cslocker_CSLocker_lock if (nativeArray == NULL) { retval = JNI_FALSE; + } else { + // Wait for 5 seconds +#ifdef WINDOWS + Sleep(5000); +#else + sleep(5); +#endif } - // deadblock - while (!release_critical) /* empty */; - (*env)->ReleasePrimitiveArrayCritical(env, array, nativeArray, 0); return retval; } - -JNIEXPORT void JNICALL Java_gc_cslocker_CSLocker_unlock - (JNIEnv *env, jobject obj) -{ - release_critical = 1; -} From 830c4d3b198597b6af7a21b708bd3a852af200d4 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Tue, 9 Dec 2025 10:15:04 +0000 Subject: [PATCH 027/211] 8366272: The os::xxx APIs do not manage errno correctly Reviewed-by: dholmes --- src/hotspot/os/aix/os_aix.cpp | 2 +- src/hotspot/os/bsd/os_bsd.cpp | 2 +- src/hotspot/os/linux/os_linux.cpp | 2 +- src/hotspot/os/posix/os_posix.cpp | 1 + src/hotspot/os/posix/signals_posix.cpp | 3 +-- src/hotspot/os/windows/os_windows.cpp | 11 ++++++----- 6 files changed, 11 insertions(+), 10 deletions(-) diff --git a/src/hotspot/os/aix/os_aix.cpp b/src/hotspot/os/aix/os_aix.cpp index 7de031cac58..f88729cdc66 100644 --- a/src/hotspot/os/aix/os_aix.cpp +++ b/src/hotspot/os/aix/os_aix.cpp @@ -2333,8 +2333,8 @@ int os::open(const char *path, int oflag, int mode) { if (ret != -1) { if ((st_mode & S_IFMT) == S_IFDIR) { - errno = EISDIR; ::close(fd); + errno = EISDIR; return -1; } } else { diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index 0889cc4cdf8..dc8f5187b5a 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -2277,8 +2277,8 @@ int os::open(const char *path, int oflag, int mode) { if (ret != -1) { if ((st_mode & S_IFMT) == S_IFDIR) { - errno = EISDIR; ::close(fd); + errno = EISDIR; return -1; } } else { diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 880dbeccf7d..ba05fde7f12 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4932,8 +4932,8 @@ int os::open(const char *path, int oflag, int mode) { if (ret != -1) { if ((st_mode & S_IFMT) == S_IFDIR) { - errno = EISDIR; ::close(fd); + errno = EISDIR; return -1; } } else { diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index 8f1f07dd055..ef52b946cc6 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1028,6 +1028,7 @@ char* os::realpath(const char* filename, char* outbuf, size_t outbuflen) { } else { errno = ENAMETOOLONG; } + ErrnoPreserver ep; permit_forbidden_function::free(p); // *not* os::free } else { // Fallback for platforms struggling with modern Posix standards (AIX 5.3, 6.1). If realpath diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 625eb63445a..a989b40d49d 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -1645,7 +1645,7 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { // Save and restore errno to avoid confusing native code with EINTR // after sigsuspend. - int old_errno = errno; + ErrnoPreserver ep; PosixSignals::unblock_error_signals(); @@ -1727,7 +1727,6 @@ static void SR_handler(int sig, siginfo_t* siginfo, void* context) { // ignore } - errno = old_errno; } static int SR_initialize() { diff --git a/src/hotspot/os/windows/os_windows.cpp b/src/hotspot/os/windows/os_windows.cpp index b9aeb4e8dd6..0ac05e8a435 100644 --- a/src/hotspot/os/windows/os_windows.cpp +++ b/src/hotspot/os/windows/os_windows.cpp @@ -4782,8 +4782,8 @@ int os::stat(const char *path, struct stat *sbuf) { path_to_target = get_path_to_target(wide_path); if (path_to_target == nullptr) { // it is a symbolic link, but we failed to resolve it - errno = ENOENT; os::free(wide_path); + errno = ENOENT; return -1; } } @@ -4794,14 +4794,14 @@ int os::stat(const char *path, struct stat *sbuf) { // if getting attributes failed, GetLastError should be called immediately after that if (!bret) { DWORD errcode = ::GetLastError(); + log_debug(os)("os::stat() failed to GetFileAttributesExW: GetLastError->%lu.", errcode); + os::free(wide_path); + os::free(path_to_target); if (errcode == ERROR_FILE_NOT_FOUND || errcode == ERROR_PATH_NOT_FOUND) { errno = ENOENT; } else { errno = 0; } - log_debug(os)("os::stat() failed to GetFileAttributesExW: GetLastError->%lu.", errcode); - os::free(wide_path); - os::free(path_to_target); return -1; } @@ -5000,8 +5000,8 @@ int os::open(const char *path, int oflag, int mode) { path_to_target = get_path_to_target(wide_path); if (path_to_target == nullptr) { // it is a symbolic link, but we failed to resolve it - errno = ENOENT; os::free(wide_path); + errno = ENOENT; return -1; } } @@ -5275,6 +5275,7 @@ char* os::realpath(const char* filename, char* outbuf, size_t outbuflen) { } else { errno = ENAMETOOLONG; } + ErrnoPreserver ep; permit_forbidden_function::free(p); // *not* os::free } return result; From a4eb57c5ec6254e59e486042015dd00457284ef2 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 9 Dec 2025 12:45:36 +0000 Subject: [PATCH 028/211] 8367028: compiler/c2/irTests/TestFloat16ScalarOperations.java failing intermittently because of constant folding Reviewed-by: chagedorn, syan, rcastanedalo --- .../irTests/TestFloat16ScalarOperations.java | 25 +++++++++++++------ 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java index c8ee5e730fa..445fef5e55a 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFloat16ScalarOperations.java @@ -68,6 +68,15 @@ public class TestFloat16ScalarOperations { private static final Float16 RANDOM4 = Float16.valueOf(genF.next()); private static final Float16 RANDOM5 = Float16.valueOf(genF.next()); + // We have to ensure that the constants are not special values that lead the operations to + // constant fold. For example "x + 0" could constant fold to "x", so we need to avoid that + // the add constant is zero. + private static Generator genSmallRangeF = G.uniformFloats(0.1f, 0.9f); + private static final Float16 RANDOM_CON_ADD = Float16.valueOf(genSmallRangeF.next()); + private static final Float16 RANDOM_CON_SUB = Float16.valueOf(genSmallRangeF.next()); + private static final Float16 RANDOM_CON_MUL = Float16.valueOf(genSmallRangeF.next()); + private static final Float16 RANDOM_CON_DIV = Float16.valueOf(genSmallRangeF.next()); + private static Float16 RANDOM1_VAR = RANDOM1; private static Float16 RANDOM2_VAR = RANDOM2; private static Float16 RANDOM3_VAR = RANDOM3; @@ -435,10 +444,10 @@ public class TestFloat16ScalarOperations { @Warmup(10000) public short testRandomFP16ConstantPatternSet1() { short res = 0; - res += Float.floatToFloat16(RANDOM1_VAR.floatValue() + RANDOM2.floatValue()); - res += Float.floatToFloat16(RANDOM2_VAR.floatValue() - RANDOM3.floatValue()); - res += Float.floatToFloat16(RANDOM3_VAR.floatValue() * RANDOM4.floatValue()); - res += Float.floatToFloat16(RANDOM4_VAR.floatValue() / RANDOM5.floatValue()); + res += Float.floatToFloat16(RANDOM1_VAR.floatValue() + RANDOM_CON_ADD.floatValue()); + res += Float.floatToFloat16(RANDOM2_VAR.floatValue() - RANDOM_CON_SUB.floatValue()); + res += Float.floatToFloat16(RANDOM3_VAR.floatValue() * RANDOM_CON_MUL.floatValue()); + res += Float.floatToFloat16(RANDOM4_VAR.floatValue() / RANDOM_CON_DIV.floatValue()); return res; } @@ -456,10 +465,10 @@ public class TestFloat16ScalarOperations { @Warmup(10000) public short testRandomFP16ConstantPatternSet2() { short res = 0; - res += Float.floatToFloat16(RANDOM2.floatValue() + RANDOM1_VAR.floatValue()); - res += Float.floatToFloat16(RANDOM3.floatValue() - RANDOM2_VAR.floatValue()); - res += Float.floatToFloat16(RANDOM4.floatValue() * RANDOM3_VAR.floatValue()); - res += Float.floatToFloat16(RANDOM5.floatValue() / RANDOM4_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM_CON_ADD.floatValue() + RANDOM1_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM_CON_SUB.floatValue() - RANDOM2_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM_CON_MUL.floatValue() * RANDOM3_VAR.floatValue()); + res += Float.floatToFloat16(RANDOM_CON_DIV.floatValue() / RANDOM4_VAR.floatValue()); return res; } From 8c8d21db6f5bdc35f6eddf91065b4eec462a716f Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 9 Dec 2025 16:10:13 +0000 Subject: [PATCH 029/211] 8373295: Wrong log tag for UseCompressedOops ergo setting Reviewed-by: dholmes, ysuenaga --- src/hotspot/share/runtime/arguments.cpp | 8 +- .../appcds/sharedStrings/SysDictCrash.java | 84 ------------------- 2 files changed, 4 insertions(+), 88 deletions(-) delete mode 100644 test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 4a983095593..dab3a60c650 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1604,10 +1604,10 @@ void Arguments::set_heap_size() { // and UseCompressedOops was not specified. if (reasonable_max > max_coop_heap) { if (FLAG_IS_ERGO(UseCompressedOops) && has_ram_limit) { - aot_log_info(aot)("UseCompressedOops disabled due to " - "max heap %zu > compressed oop heap %zu. " - "Please check the setting of MaxRAMPercentage %5.2f.", - reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage); + log_debug(gc, heap, coops)("UseCompressedOops disabled due to " + "max heap %zu > compressed oop heap %zu. " + "Please check the setting of MaxRAMPercentage %5.2f.", + reasonable_max, (size_t)max_coop_heap, MaxRAMPercentage); FLAG_SET_ERGO(UseCompressedOops, false); } else { reasonable_max = max_coop_heap; diff --git a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java b/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java deleted file mode 100644 index 9462f4f9d0b..00000000000 --- a/test/hotspot/jtreg/runtime/cds/appcds/sharedStrings/SysDictCrash.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2015, 2025, 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 - * @summary Regression test for JDK-8098821 - * @bug 8098821 - * @requires vm.cds.write.archived.java.heap - * @requires vm.gc == null - * @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds - * @run driver SysDictCrash - */ - -import jdk.test.lib.cds.CDSOptions; -import jdk.test.lib.cds.CDSTestUtils; -import jdk.test.lib.process.OutputAnalyzer; - -public class SysDictCrash { - public static void main(String[] args) throws Exception { - SharedStringsUtils.run(args, SysDictCrash::test); - } - - public static void test(String[] args) throws Exception { - String vmOptionsPrefix[] = SharedStringsUtils.getChildVMOptionsPrefix(); - - // SharedBaseAddress=0 puts the archive at a very high address, which provokes the crash. - boolean continueTest = true; - - CDSOptions opts = (new CDSOptions()) - .addPrefix(vmOptionsPrefix, - "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", - "-cp", ".", - "-XX:SharedBaseAddress=0", - "-showversion", "-Xlog:cds,aot+hashtables") - .setArchiveName("./SysDictCrash.jsa"); - OutputAnalyzer output = CDSTestUtils.createArchive(opts); - try { - TestCommon.checkDump(output); - } catch (java.lang.RuntimeException re) { - if (!output.getStdout().contains("UseCompressedOops disabled due to")) { - throw re; - } else { - System.out.println("Shared archive was not created due to UseCompressedOops and UseCompressedClassPointers have been disabled."); - continueTest = false; - } - } - - if (!continueTest) { - return; - } - - opts = (new CDSOptions()) - .setArchiveName("./SysDictCrash.jsa") // prevents the assignment of a default archive name - .setUseVersion(false) // the -version must be the last arg for this test to work - .addSuffix(vmOptionsPrefix, - "-Xlog:cds", - "-XX:+UseG1GC", "-XX:MaxRAMPercentage=12.5", - "-XX:SharedArchiveFile=./SysDictCrash.jsa", - "-version"); - CDSTestUtils.run(opts) - .assertNormalExit(); - } -} From 831fe94c75c407b2399be9b89630d8d117c2996c Mon Sep 17 00:00:00 2001 From: Erik Joelsson Date: Tue, 9 Dec 2025 17:01:08 +0000 Subject: [PATCH 030/211] 8373255: Unexpected iobj and ipdb files after JDK-8370438 Reviewed-by: serb --- make/common/native/Flags.gmk | 3 +++ 1 file changed, 3 insertions(+) diff --git a/make/common/native/Flags.gmk b/make/common/native/Flags.gmk index efb4c08e74c..6353b490654 100644 --- a/make/common/native/Flags.gmk +++ b/make/common/native/Flags.gmk @@ -234,6 +234,9 @@ define SetupLinkerFlags ifeq ($(call isTargetOs, macosx), true) $1_EXTRA_LDFLAGS += -Wl,-object_path_lto,$$($1_OBJECT_DIR)/$$($1_NAME)_lto_helper.o endif + ifeq ($(TOOLCHAIN_TYPE), microsoft) + $1_EXTRA_LDFLAGS += -LTCGOUT:$$($1_OBJECT_DIR)/$$($1_NAME).iobj + endif endif $1_EXTRA_LDFLAGS += $$($1_LDFLAGS_$(OPENJDK_TARGET_OS_TYPE)) $$($1_LDFLAGS_$(OPENJDK_TARGET_OS)) \ From b99be505a5e3c8304be62a8b373d746fc52e8f0e Mon Sep 17 00:00:00 2001 From: Neha Joshi Date: Tue, 9 Dec 2025 18:06:39 +0000 Subject: [PATCH 031/211] 8368524: Tests are skipped and shown as passed in test/jdk/sun/security/pkcs11/Cipher/KeyWrap Reviewed-by: myankelevich, rhalade --- .../pkcs11/Cipher/KeyWrap/NISTWrapKAT.java | 18 ++++++++++-------- .../pkcs11/Cipher/KeyWrap/TestGeneral.java | 1 + 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java index e8f637e0b0c..b570a0dd030 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java +++ b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/NISTWrapKAT.java @@ -83,7 +83,7 @@ public class NISTWrapKAT extends PKCS11Test { private static String KEK2 = "5840DF6E29B02AF1AB493B705BF16EA1AE8338F4DCC176A8"; - private static final List skippedList = new ArrayList <>(); + private static final List skippedAlgoList = new ArrayList <>(); private static byte[] toBytes(String hex, int hexLen) { if (hexLen < hex.length()) { @@ -274,8 +274,8 @@ public class NISTWrapKAT extends PKCS11Test { dataLen + "-byte key with " + 8*keyLen + "-bit KEK"); int allowed = Cipher.getMaxAllowedKeyLength("AES"); if (keyLen > allowed) { - System.out.println("=> skip, exceeds max allowed size " + allowed); - skippedList.add(algo + " Cipher with wrapping " + + System.err.println("Skip, exceeds max allowed size " + allowed); + skippedAlgoList.add(algo + " Cipher with wrapping " + dataLen + "-byte key with " + 8 * keyLen + "-bit KEK exceeds max allowed size " + allowed); return; @@ -344,8 +344,8 @@ public class NISTWrapKAT extends PKCS11Test { dataLen + "-byte data with " + 8*keyLen + "-bit KEK"); int allowed = Cipher.getMaxAllowedKeyLength("AES"); if (keyLen > allowed) { - System.out.println("=> skip, exceeds max allowed size " + allowed); - skippedList.add(algo + " Cipher with enc " + + System.err.println("Skip, exceeds max allowed size " + allowed); + skippedAlgoList.add(algo + " Cipher with enc " + dataLen + "-byte data with " + 8 * keyLen + "-bit KEK exceeds max allowed size " + allowed); return; @@ -416,7 +416,9 @@ public class NISTWrapKAT extends PKCS11Test { for (Object[] td : testDatum) { String algo = (String) td[0]; if (p.getService("Cipher", algo) == null) { - skippedList.add("No support for " + algo); + System.err.println("Skip, due to no support: " + algo); + skippedAlgoList.add("No support for " + algo); + continue; } testKeyWrap(algo, (String) td[1], (int) td[2], (String) td[3], (int) td[4], (String) td[5], p); @@ -424,9 +426,9 @@ public class NISTWrapKAT extends PKCS11Test { (int) td[4], (String) td[5], p); } - if (!skippedList.isEmpty()) { + if (!skippedAlgoList.isEmpty()) { throw new SkippedException("One or more tests skipped " - + skippedList); + + skippedAlgoList); } else { System.out.println("All Tests Passed"); } diff --git a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java index f5e4494fc59..d7cdfc6c04c 100644 --- a/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java +++ b/test/jdk/sun/security/pkcs11/Cipher/KeyWrap/TestGeneral.java @@ -273,6 +273,7 @@ public class TestGeneral extends PKCS11Test { for (String a : algos) { if (p.getService("Cipher", a) == null) { skippedList.add(a); + continue; } System.out.println("Testing " + a); From b2daf9de3097de4d3b3c7d565e29a48b4aae19ee Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Tue, 9 Dec 2025 18:21:12 +0000 Subject: [PATCH 032/211] 8355522: Remove the `java.locale.useOldISOCodes` system property Reviewed-by: jlu, joehw --- .../share/classes/java/util/Locale.java | 38 ++++------------ .../jdk/internal/util/StaticProperty.java | 9 ---- .../classes/sun/util/locale/BaseLocale.java | 24 +++++----- .../util/locale/provider/LocaleResources.java | 11 ----- test/jdk/java/util/Locale/LocaleTest.java | 45 ++++++------------- .../java/util/Locale/UseOldISOCodesTest.java | 15 +++---- 6 files changed, 38 insertions(+), 104 deletions(-) diff --git a/src/java.base/share/classes/java/util/Locale.java b/src/java.base/share/classes/java/util/Locale.java index 54863d58782..f45a52c14fa 100644 --- a/src/java.base/share/classes/java/util/Locale.java +++ b/src/java.base/share/classes/java/util/Locale.java @@ -535,34 +535,13 @@ import sun.util.locale.provider.TimeZoneNameUtility; * *

Legacy language codes

* - *

Locale's constructors have always converted three language codes to - * their earlier, obsoleted forms: {@code he} maps to {@code iw}, - * {@code yi} maps to {@code ji}, and {@code id} maps to - * {@code in}. Since Java SE 17, this is no longer the case. Each - * language maps to its new form; {@code iw} maps to {@code he}, {@code ji} - * maps to {@code yi}, and {@code in} maps to {@code id}. - * - *

For backwards compatible behavior, the system property - * {@systemProperty java.locale.useOldISOCodes} reverts the behavior - * back to that of before Java SE 17. If the system property is set to - * {@code true}, those three current language codes are mapped to their - * backward compatible forms. The property is only read at Java runtime - * startup and subsequent calls to {@code System.setProperty()} will - * have no effect. As of Java SE 25, the use of the - * {@code java.locale.useOldISOCodes} system property is deprecated. - * This backwards compatible behavior will be removed in a future release - * of the JDK. - * - *

The APIs added in Java SE 7 map between the old and new language codes, - * maintaining the mapped codes internal to Locale (so that - * {@code getLanguage} and {@code toString} reflect the mapped - * code, which depends on the {@code java.locale.useOldISOCodes} system - * property), but using the new codes in the BCP 47 language tag APIs (so - * that {@code toLanguageTag} reflects the new one). This - * preserves the equivalence between Locales no matter which code or - * API is used to construct them. Java's default resource bundle - * lookup mechanism also implements this mapping, so that resources - * can be named using either convention, see {@link ResourceBundle.Control}. + *

For compatibility, a {@code Locale} created with one of the + * three obsolete language codes, {@code iw}, {@code ji}, or {@code in}, + * will map the language to its modern equivalent, {@code he}, {@code yi}, + * or {@code id}, respectively. + *

The default resource bundle lookup mechanism also implements + * this mapping, so that resources can be named using either convention, + * see {@link ResourceBundle.Control}. * * @spec https://www.rfc-editor.org/info/rfc4647 * RFC 4647: Matching of Language Tags @@ -2527,8 +2506,7 @@ public final class Locale implements Cloneable, Serializable { private static String convertOldISOCodes(String language) { // we accept both the old and the new ISO codes for the languages whose ISO - // codes have changed, but we always store the NEW code, unless the property - // java.locale.useOldISOCodes is set to "true" + // codes have changed, but we always store the NEW code return BaseLocale.convertOldISOCodes(LocaleUtils.toLowerString(language).intern()); } diff --git a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java index 4fb3ae7a184..4740062dcde 100644 --- a/src/java.base/share/classes/jdk/internal/util/StaticProperty.java +++ b/src/java.base/share/classes/jdk/internal/util/StaticProperty.java @@ -53,7 +53,6 @@ public final class StaticProperty { private static final String STDOUT_ENCODING; private static final String SUN_JNU_ENCODING; private static final String JAVA_PROPERTIES_DATE; - private static final String JAVA_LOCALE_USE_OLD_ISO_CODES; private static final String OS_NAME; private static final String OS_ARCH; private static final String OS_VERSION; @@ -94,7 +93,6 @@ public final class StaticProperty { STDOUT_ENCODING = getProperty(props, "stdout.encoding"); SUN_JNU_ENCODING = getProperty(props, "sun.jnu.encoding"); JAVA_PROPERTIES_DATE = getProperty(props, "java.properties.date", null); - JAVA_LOCALE_USE_OLD_ISO_CODES = getProperty(props, "java.locale.useOldISOCodes", ""); OS_NAME = getProperty(props, "os.name"); OS_ARCH = getProperty(props, "os.arch"); OS_VERSION = getProperty(props, "os.version"); @@ -258,13 +256,6 @@ public final class StaticProperty { return JAVA_PROPERTIES_DATE; } - /** - * {@return the {@code java.locale.useOldISOCodes} system property} - */ - public static String javaLocaleUseOldISOCodes() { - return JAVA_LOCALE_USE_OLD_ISO_CODES; - } - /** * {@return the {@code os.name} system property} */ diff --git a/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 91efc61d1bf..58ec6d76aa5 100644 --- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -34,7 +34,6 @@ package sun.util.locale; import jdk.internal.misc.CDS; import jdk.internal.util.ReferencedKeySet; -import jdk.internal.util.StaticProperty; import jdk.internal.vm.annotation.Stable; import java.util.StringJoiner; @@ -110,16 +109,14 @@ public final class BaseLocale { private @Stable int hash; /** - * Boolean for the old ISO language code compatibility. - * The system property "java.locale.useOldISOCodes" is not security sensitive, - * so no need to ensure privileged access here. + * Emit the warning message if the system property "java.locale.useOldISOCodes" is + * specified. */ - private static final boolean OLD_ISO_CODES = StaticProperty.javaLocaleUseOldISOCodes() - .equalsIgnoreCase("true"); static { - if (OLD_ISO_CODES) { - System.err.println("WARNING: The use of the system property \"java.locale.useOldISOCodes\"" + - " is deprecated. It will be removed in a future release of the JDK."); + if (System.getProperty("java.locale.useOldISOCodes") != null) { + System.err.println("WARNING: The system property" + + " \"java.locale.useOldISOCodes\" is no longer supported." + + " Any specified value will be ignored."); } } @@ -166,7 +163,8 @@ public final class BaseLocale { } } - // JDK uses deprecated ISO639.1 language codes for he, yi and id + // Normalize deprecated ISO 639-1 language codes for Hebrew, Yiddish, + // and Indonesian to their current standard forms. if (!language.isEmpty()) { language = convertOldISOCodes(language); } @@ -183,9 +181,9 @@ public final class BaseLocale { public static String convertOldISOCodes(String language) { return switch (language) { - case "he", "iw" -> OLD_ISO_CODES ? "iw" : "he"; - case "id", "in" -> OLD_ISO_CODES ? "in" : "id"; - case "yi", "ji" -> OLD_ISO_CODES ? "ji" : "yi"; + case "iw" -> "he"; + case "in" -> "id"; + case "ji" -> "yi"; default -> language; }; } diff --git a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java index c539f57141e..ac43b22a3bd 100644 --- a/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java +++ b/src/java.base/share/classes/sun/util/locale/provider/LocaleResources.java @@ -62,7 +62,6 @@ import java.util.concurrent.ConcurrentMap; import java.util.regex.Pattern; import java.util.stream.Stream; -import jdk.internal.util.StaticProperty; import sun.util.resources.LocaleData; import sun.util.resources.OpenListResourceBundle; import sun.util.resources.TimeZoneNamesBundle; @@ -288,16 +287,6 @@ public class LocaleResources { } public String getLocaleName(String key) { - // Get names for old ISO codes with new ISO code resources - if (StaticProperty.javaLocaleUseOldISOCodes().equalsIgnoreCase("true")) { - key = switch (key) { - case "iw" -> "he"; - case "in" -> "id"; - case "ji" -> "yi"; - default -> key; - }; - } - Object localeName = null; String cacheKey = LOCALE_NAMES + key; diff --git a/test/jdk/java/util/Locale/LocaleTest.java b/test/jdk/java/util/Locale/LocaleTest.java index 0cf272f20a0..76fbb83c11a 100644 --- a/test/jdk/java/util/Locale/LocaleTest.java +++ b/test/jdk/java/util/Locale/LocaleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -26,7 +26,7 @@ * 4118587 4118595 4122371 4126371 4126880 4135316 4135752 4139504 4139940 4143951 * 4147315 4147317 4147552 4335196 4778440 4940539 5010672 6475525 6544471 6627549 * 6786276 7066203 7085757 8008577 8030696 8170840 8174269 8255086 8263202 8287868 - * 8337603 + * 8337603 8355522 * @summary test Locales * @modules jdk.localedata * @run junit LocaleTest @@ -703,40 +703,21 @@ test commented out pending API-change approval @Test public void TestChangedISO639Codes() { Locale hebrewOld = Locale.of("iw", "IL"); - Locale hebrewNew = Locale.of("he", "IL"); Locale yiddishOld = Locale.of("ji", "IL"); - Locale yiddishNew = Locale.of("yi", "IL"); Locale indonesianOld = Locale.of("in"); - Locale indonesianNew = Locale.of("id"); - if ("true".equalsIgnoreCase(System.getProperty("java.locale.useOldISOCodes"))) { - if (!hebrewNew.getLanguage().equals("iw")) { - fail("Got back wrong language code for new Hebrew: expected \"iw\", got \"" - + hebrewNew.getLanguage() + "\""); - } - if (!yiddishNew.getLanguage().equals("ji")) { - fail("Got back wrong language code for new Yiddish: expected \"ji\", got \"" - + yiddishNew.getLanguage() + "\""); - } - if (!indonesianNew.getLanguage().equals("in")) { - fail("Got back wrong language code for new Indonesian: expected \"in\", got \"" - + indonesianNew.getLanguage() + "\""); - } - } else { - if (!hebrewOld.getLanguage().equals("he")) { - fail("Got back wrong language code for old Hebrew: expected \"he\", got \"" - + hebrewNew.getLanguage() + "\""); - } - if (!yiddishOld.getLanguage().equals("yi")) { - fail("Got back wrong language code for old Yiddish: expected \"yi\", got \"" - + yiddishNew.getLanguage() + "\""); - } - if (!indonesianOld.getLanguage().equals("id")) { - fail("Got back wrong language code for old Indonesian: expected \"id\", got \"" - + indonesianNew.getLanguage() + "\""); - } + if (!hebrewOld.getLanguage().equals("he")) { + fail("Got back wrong language code for old Hebrew: expected \"he\", got \"" + + hebrewOld.getLanguage() + "\""); + } + if (!yiddishOld.getLanguage().equals("yi")) { + fail("Got back wrong language code for old Yiddish: expected \"yi\", got \"" + + yiddishOld.getLanguage() + "\""); + } + if (!indonesianOld.getLanguage().equals("id")) { + fail("Got back wrong language code for old Indonesian: expected \"id\", got \"" + + indonesianOld.getLanguage() + "\""); } - } /** diff --git a/test/jdk/java/util/Locale/UseOldISOCodesTest.java b/test/jdk/java/util/Locale/UseOldISOCodesTest.java index 1909497535c..3e836782fc3 100644 --- a/test/jdk/java/util/Locale/UseOldISOCodesTest.java +++ b/test/jdk/java/util/Locale/UseOldISOCodesTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8295232 8353118 + * @bug 8295232 8353118 8355522 * @summary Tests for the "java.locale.useOldISOCodes" system property * @library /test/lib * @run junit UseOldISOCodesTest @@ -34,7 +34,7 @@ import jdk.test.lib.process.ProcessTools; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotEquals; public class UseOldISOCodesTest { @@ -44,7 +44,7 @@ public class UseOldISOCodesTest { .outputTo(System.out) .errorTo(System.err); oa.shouldHaveExitValue(0); - oa.stderrShouldMatch("WARNING: The use of the system property \"java.locale.useOldISOCodes\" is deprecated. It will be removed in a future release of the JDK."); + oa.stderrShouldMatch("WARNING: The system property \"java.locale.useOldISOCodes\" is no longer supported. Any specified value will be ignored."); } static class Runner { @@ -52,12 +52,9 @@ public class UseOldISOCodesTest { private static final String newCode = "he"; public static void main(String[] args) { - // Ensure java.locale.useOldISOCodes is only interpreted at runtime startup - // Should have no effect - System.setProperty("java.locale.useOldISOCodes", "false"); - Locale locale = Locale.of(newCode); - assertEquals(obsoleteCode, locale.getLanguage(), - "newCode 'he' was not mapped to 'iw' with useOldISOCodes=true"); + // Ensure java.locale.useOldISOCodes should have no effect + assertNotEquals(obsoleteCode, Locale.of(newCode).getLanguage(), + "newCode 'he' was mapped to 'iw' with useOldISOCodes=true"); } } } From 1ae4a6c43ea21d4b147bcfcfaf1484c6e618dce5 Mon Sep 17 00:00:00 2001 From: Matthew Donovan Date: Tue, 9 Dec 2025 18:48:33 +0000 Subject: [PATCH 033/211] 8373101: JdkClient and JdkServer test classes ignore namedGroups field Reviewed-by: rhalade --- .../javax/net/ssl/TLSCommon/interop/JdkClient.java | 13 ++++++++++++- .../javax/net/ssl/TLSCommon/interop/JdkServer.java | 14 ++++++++++++-- 2 files changed, 24 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkClient.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkClient.java index 79476cbb81e..eb6ecbb12b8 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkClient.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkClient.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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.io.IOException; import java.net.InetSocketAddress; import java.net.SocketException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.net.ssl.SNIHostName; @@ -86,6 +87,16 @@ public class JdkClient extends AbstractClient { if (builder.getAppProtocols() != null) { sslParams.setApplicationProtocols(builder.getAppProtocols()); } + + NamedGroup[] namedGroups = builder.getNamedGroups(); + if (namedGroups != null + && namedGroups.length > 0) { + String[] namedGroupStrs = Arrays.stream(namedGroups) + .map(NamedGroup::name) + .toArray(String[]::new); + sslParams.setNamedGroups(namedGroupStrs); + } + socket.setSSLParameters(sslParams); } diff --git a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkServer.java b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkServer.java index 1521325b65a..20bfffbac7d 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/interop/JdkServer.java +++ b/test/jdk/javax/net/ssl/TLSCommon/interop/JdkServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -22,9 +22,9 @@ */ import java.io.IOException; -import java.net.InetAddress; import java.net.SocketException; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import javax.net.ssl.SNIHostName; @@ -85,6 +85,16 @@ public class JdkServer extends AbstractServer { System.out.println("appProtocol: " + appProtocol); } } + + NamedGroup[] namedGroups = builder.getNamedGroups(); + if (namedGroups != null + && namedGroups.length > 0) { + String[] namedGroupStrs = Arrays.stream(namedGroups) + .map(NamedGroup::name) + .toArray(String[]::new); + sslParams.setNamedGroups(namedGroupStrs); + } + serverSocket.setSSLParameters(sslParams); } From 7f9951a93479ac0ddd74375fdef92095fb65741b Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 10 Dec 2025 00:07:28 +0000 Subject: [PATCH 034/211] 8373207: Make DeferredStatic class template constant initializable Reviewed-by: jsjolen, stefank, iwalulya --- src/hotspot/share/utilities/deferredStatic.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/utilities/deferredStatic.hpp b/src/hotspot/share/utilities/deferredStatic.hpp index 3a32f920fe8..a37b169803a 100644 --- a/src/hotspot/share/utilities/deferredStatic.hpp +++ b/src/hotspot/share/utilities/deferredStatic.hpp @@ -35,7 +35,7 @@ // object must be explicitly initialized before use. This avoids problems // resulting from the unspecified initialization time and ordering between // different objects that comes from using undeferred objects (the so-called -// "Static Initialization Order Fiasco). +// "Static Initialization Order Fiasco"). // // Once initialized, the object is never destroyed. This avoids similar issues // with the timing and ordering of destruction on normal program exit. @@ -53,7 +53,7 @@ class DeferredStatic { public: NONCOPYABLE(DeferredStatic); - DeferredStatic() + constexpr DeferredStatic() DEBUG_ONLY(: _initialized(false)) { // Do not construct value, on purpose. } From eef9813ad42b02db5fc636e661a751d5120a639e Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Wed, 10 Dec 2025 00:50:48 +0000 Subject: [PATCH 035/211] 8371446: VectorAPI: Add unit tests for masks from various long values Reviewed-by: psandoz --- .../incubator/vector/AbstractVectorTest.java | 53 +-- .../incubator/vector/Byte128VectorTests.java | 340 +++++++++++------- .../incubator/vector/Byte256VectorTests.java | 340 +++++++++++------- .../incubator/vector/Byte512VectorTests.java | 340 +++++++++++------- .../incubator/vector/Byte64VectorTests.java | 340 +++++++++++------- .../incubator/vector/ByteMaxVectorTests.java | 324 +++++++++++------ .../vector/Double128VectorTests.java | 336 ++++++++++------- .../vector/Double256VectorTests.java | 336 ++++++++++------- .../vector/Double512VectorTests.java | 336 ++++++++++------- .../incubator/vector/Double64VectorTests.java | 336 ++++++++++------- .../vector/DoubleMaxVectorTests.java | 320 +++++++++++------ .../incubator/vector/Float128VectorTests.java | 336 ++++++++++------- .../incubator/vector/Float256VectorTests.java | 336 ++++++++++------- .../incubator/vector/Float512VectorTests.java | 336 ++++++++++------- .../incubator/vector/Float64VectorTests.java | 336 ++++++++++------- .../incubator/vector/FloatMaxVectorTests.java | 320 +++++++++++------ .../incubator/vector/Int128VectorTests.java | 340 +++++++++++------- .../incubator/vector/Int256VectorTests.java | 340 +++++++++++------- .../incubator/vector/Int512VectorTests.java | 340 +++++++++++------- .../incubator/vector/Int64VectorTests.java | 340 +++++++++++------- .../incubator/vector/IntMaxVectorTests.java | 324 +++++++++++------ .../incubator/vector/Long128VectorTests.java | 340 +++++++++++------- .../incubator/vector/Long256VectorTests.java | 340 +++++++++++------- .../incubator/vector/Long512VectorTests.java | 340 +++++++++++------- .../incubator/vector/Long64VectorTests.java | 340 +++++++++++------- .../incubator/vector/LongMaxVectorTests.java | 324 +++++++++++------ .../incubator/vector/Short128VectorTests.java | 340 +++++++++++------- .../incubator/vector/Short256VectorTests.java | 340 +++++++++++------- .../incubator/vector/Short512VectorTests.java | 340 +++++++++++------- .../incubator/vector/Short64VectorTests.java | 340 +++++++++++------- .../incubator/vector/ShortMaxVectorTests.java | 324 +++++++++++------ test/jdk/jdk/incubator/vector/gen-template.sh | 15 +- .../templates/Kernel-BoolBinary-op.template | 11 + .../templates/Kernel-BoolUnary-op.template | 9 + .../templates/Unit-BoolBinary-op.template | 10 + .../templates/Unit-BoolUnary-op.template | 10 + .../templates/Unit-Mask-FromToLong.template | 27 ++ .../templates/Unit-Miscellaneous.template | 132 +------ .../vector/templates/Unit-header.template | 49 ++- 39 files changed, 6447 insertions(+), 3933 deletions(-) create mode 100644 test/jdk/jdk/incubator/vector/templates/Kernel-BoolBinary-op.template create mode 100644 test/jdk/jdk/incubator/vector/templates/Kernel-BoolUnary-op.template create mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-BoolBinary-op.template create mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-BoolUnary-op.template create mode 100644 test/jdk/jdk/incubator/vector/templates/Unit-Mask-FromToLong.template diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorTest.java index 71cabe75b76..b334e64ab80 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorTest.java @@ -110,19 +110,19 @@ public class AbstractVectorTest { } static final List> BOOLEAN_MASK_GENERATORS = List.of( - withToString("mask[i % 2]", (int l) -> { - boolean[] a = new boolean[l]; - for (int i = 0; i < l; i++) { - a[i] = (i % 2 == 0); - } - return a; + withToString("mask[i % 2]", (int s) -> { + return fill_boolean(s, + i -> ((i % 2) == 0)); }), - withToString("mask[true]", (int l) -> { - boolean[] a = new boolean[l]; + withToString("mask[true]", (int s) -> { + boolean[] a = new boolean[s]; Arrays.fill(a, true); return a; }), - withToString("mask[false]", boolean[]::new) + withToString("mask[false]", boolean[]::new), + withToString("mask[random]", (int s) -> { + return fill_boolean(s,_i -> RAND.nextBoolean()); + }) ); static final List>> @@ -131,6 +131,26 @@ public class AbstractVectorTest { flatMap(fa -> BOOLEAN_MASK_GENERATORS.stream().skip(1).map( fb -> List.of(fa, fb))).collect(Collectors.toList()); + static long[] pack_booleans_to_longs(boolean[] mask) { + int totalLongs = (mask.length + 63) / 64; // ceil division + long[] packed = new long[totalLongs]; + for (int i = 0; i < mask.length; i++) { + int longIndex = i / 64; + int bitIndex = i % 64; + if (mask[i]) { + packed[longIndex] |= 1L << bitIndex; + } + } + return packed; + } + + static final List> LONG_MASK_GENERATORS = BOOLEAN_MASK_GENERATORS.stream() + .map(f -> withToString( + f.toString().replace("mask", "long_mask"), + (IntFunction) (int l) -> pack_booleans_to_longs(f.apply(l)) + )) + .collect(Collectors.toList()); + static final List> INT_SHUFFLE_GENERATORS = List.of( withToStringBi("shuffle[random]", (Integer l, Integer m) -> RAND.ints(l, 0, m).toArray()) @@ -210,21 +230,6 @@ public class AbstractVectorTest { return a; } - interface FBooleanBinOp { - boolean apply(boolean a, boolean b); - } - - static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBooleanBinOp f) { - int i = 0; - try { - for (; i < a.length; i++) { - Assert.assertEquals(r[i], f.apply(a[i], b[i])); - } - } catch (AssertionError e) { - Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); - } - } - // Non-optimized test partial wrap derived from the Spec: // Validation function for lane indexes which may be out of the valid range of [0..VLENGTH-1]. // The index is forced into this range by adding or subtracting a suitable multiple of VLENGTH. diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index bea4d541987..4980c66c02a 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -393,6 +393,36 @@ public class Byte128VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { byte apply(byte a, byte b); } @@ -1095,12 +1125,6 @@ public class Byte128VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -1232,8 +1256,23 @@ public class Byte128VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4464,7 +4503,7 @@ public class Byte128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueByte128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4488,7 +4527,7 @@ public class Byte128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueByte128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6390,6 +6429,157 @@ public class Byte128VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Byte128VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandByte128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorByte128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorByte128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotByte128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqByte128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotByte128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Byte128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongByte128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "byteCompareOpProvider") static void ltByte128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { byte[] a = fa.apply(SPECIES.length()); @@ -6700,115 +6890,22 @@ public class Byte128VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsByte128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqByte128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeByte128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6913,23 +7010,6 @@ public class Byte128VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongByte128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index be5b3cf6198..b3cad54e101 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -393,6 +393,36 @@ public class Byte256VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { byte apply(byte a, byte b); } @@ -1095,12 +1125,6 @@ public class Byte256VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -1232,8 +1256,23 @@ public class Byte256VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4464,7 +4503,7 @@ public class Byte256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueByte256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4488,7 +4527,7 @@ public class Byte256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueByte256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6390,6 +6429,157 @@ public class Byte256VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Byte256VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandByte256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorByte256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorByte256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotByte256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqByte256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotByte256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Byte256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongByte256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "byteCompareOpProvider") static void ltByte256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { byte[] a = fa.apply(SPECIES.length()); @@ -6700,115 +6890,22 @@ public class Byte256VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsByte256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqByte256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeByte256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6913,23 +7010,6 @@ public class Byte256VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongByte256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 0fd68b6f712..83e48cd2fdc 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -393,6 +393,36 @@ public class Byte512VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { byte apply(byte a, byte b); } @@ -1095,12 +1125,6 @@ public class Byte512VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -1232,8 +1256,23 @@ public class Byte512VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4464,7 +4503,7 @@ public class Byte512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueByte512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4488,7 +4527,7 @@ public class Byte512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueByte512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6390,6 +6429,157 @@ public class Byte512VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Byte512VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandByte512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorByte512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorByte512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotByte512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqByte512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotByte512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Byte512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongByte512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "byteCompareOpProvider") static void ltByte512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { byte[] a = fa.apply(SPECIES.length()); @@ -6700,115 +6890,22 @@ public class Byte512VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsByte512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqByte512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeByte512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6913,23 +7010,6 @@ public class Byte512VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongByte512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 112b2e56b6f..0088b3fbf8e 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -393,6 +393,36 @@ public class Byte64VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { byte apply(byte a, byte b); } @@ -1095,12 +1125,6 @@ public class Byte64VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -1232,8 +1256,23 @@ public class Byte64VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4464,7 +4503,7 @@ public class Byte64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueByte64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4488,7 +4527,7 @@ public class Byte64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueByte64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6390,6 +6429,157 @@ public class Byte64VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Byte64VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandByte64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorByte64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorByte64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotByte64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqByte64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Byte64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotByte64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Byte64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongByte64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "byteCompareOpProvider") static void ltByte64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { byte[] a = fa.apply(SPECIES.length()); @@ -6700,115 +6890,22 @@ public class Byte64VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsByte64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqByte64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Byte64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeByte64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6913,23 +7010,6 @@ public class Byte64VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongByte64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index 435cacc013e..6df01fb48e3 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -398,6 +398,36 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { byte apply(byte a, byte b); } @@ -1100,12 +1130,6 @@ public class ByteMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -1237,8 +1261,23 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4469,7 +4508,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueByteMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4493,7 +4532,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueByteMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6395,6 +6434,157 @@ public class ByteMaxVectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, ByteMaxVectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandByteMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ByteMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorByteMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ByteMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorByteMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ByteMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotByteMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ByteMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqByteMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ByteMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotByteMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, ByteMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongByteMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "byteCompareOpProvider") static void ltByteMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { byte[] a = fa.apply(SPECIES.length()); @@ -6705,115 +6895,22 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsByteMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ByteMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ByteMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ByteMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ByteMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqByteMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ByteMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeByteMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6918,7 +7015,6 @@ public class ByteMaxVectorTests extends AbstractVectorTest { } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index f15ce88ddb8..879dac4c966 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { double apply(double a, double b); } @@ -1187,12 +1217,6 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). @@ -1291,8 +1315,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4806,6 +4845,157 @@ relativeError)); assertArraysEquals(r, a, mask, Double128VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandDouble128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorDouble128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorDouble128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotDouble128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqDouble128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotDouble128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Double128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongDouble128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "doubleCompareOpProvider") static void ltDouble128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { double[] a = fa.apply(SPECIES.length()); @@ -5095,115 +5285,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsDouble128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqDouble128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeDouble128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5308,23 +5405,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongDouble128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index e6c3662e0ad..87230330642 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { double apply(double a, double b); } @@ -1187,12 +1217,6 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). @@ -1291,8 +1315,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4806,6 +4845,157 @@ relativeError)); assertArraysEquals(r, a, mask, Double256VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandDouble256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorDouble256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorDouble256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotDouble256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqDouble256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotDouble256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Double256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongDouble256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "doubleCompareOpProvider") static void ltDouble256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { double[] a = fa.apply(SPECIES.length()); @@ -5095,115 +5285,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsDouble256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqDouble256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeDouble256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5308,23 +5405,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongDouble256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index 7c37c9878e8..af8fbf5f51f 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { double apply(double a, double b); } @@ -1187,12 +1217,6 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). @@ -1291,8 +1315,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4806,6 +4845,157 @@ relativeError)); assertArraysEquals(r, a, mask, Double512VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandDouble512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorDouble512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorDouble512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotDouble512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqDouble512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotDouble512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Double512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongDouble512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "doubleCompareOpProvider") static void ltDouble512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { double[] a = fa.apply(SPECIES.length()); @@ -5095,115 +5285,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsDouble512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqDouble512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeDouble512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5308,23 +5405,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongDouble512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 85b96288b37..67822ae5353 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { double apply(double a, double b); } @@ -1187,12 +1217,6 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). @@ -1291,8 +1315,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4806,6 +4845,157 @@ relativeError)); assertArraysEquals(r, a, mask, Double64VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandDouble64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorDouble64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorDouble64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotDouble64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqDouble64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Double64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotDouble64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Double64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongDouble64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "doubleCompareOpProvider") static void ltDouble64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { double[] a = fa.apply(SPECIES.length()); @@ -5095,115 +5285,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsDouble64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqDouble64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Double64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeDouble64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5308,23 +5405,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongDouble64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index 7245990d66c..5d7ae07c55a 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java @@ -416,6 +416,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { double apply(double a, double b); } @@ -1192,12 +1222,6 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). @@ -1296,8 +1320,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4811,6 +4850,157 @@ relativeError)); assertArraysEquals(r, a, mask, DoubleMaxVectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, DoubleMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, DoubleMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, DoubleMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, DoubleMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, DoubleMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotDoubleMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, DoubleMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongDoubleMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "doubleCompareOpProvider") static void ltDoubleMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { double[] a = fa.apply(SPECIES.length()); @@ -5100,115 +5290,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsDoubleMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, DoubleMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, DoubleMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, DoubleMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, DoubleMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqDoubleMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, DoubleMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeDoubleMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5313,7 +5410,6 @@ relativeError)); } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index c4f4ed1b966..0d3ce311a90 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { float apply(float a, float b); } @@ -1198,12 +1228,6 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). @@ -1302,8 +1326,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4775,6 +4814,157 @@ relativeError)); assertArraysEquals(r, a, mask, Float128VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "floatCompareOpProvider") static void ltFloat128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { float[] a = fa.apply(SPECIES.length()); @@ -5074,115 +5264,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqFloat128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeFloat128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5287,23 +5384,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongFloat128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 87cbc165d59..88ea856f17b 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { float apply(float a, float b); } @@ -1198,12 +1228,6 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). @@ -1302,8 +1326,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4775,6 +4814,157 @@ relativeError)); assertArraysEquals(r, a, mask, Float256VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "floatCompareOpProvider") static void ltFloat256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { float[] a = fa.apply(SPECIES.length()); @@ -5074,115 +5264,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqFloat256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeFloat256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5287,23 +5384,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongFloat256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index beb9561d882..cdccbfdd319 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { float apply(float a, float b); } @@ -1198,12 +1228,6 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). @@ -1302,8 +1326,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4775,6 +4814,157 @@ relativeError)); assertArraysEquals(r, a, mask, Float512VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "floatCompareOpProvider") static void ltFloat512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { float[] a = fa.apply(SPECIES.length()); @@ -5074,115 +5264,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqFloat512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeFloat512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5287,23 +5384,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongFloat512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index ee630abd8e0..056eae1974f 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -411,6 +411,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { float apply(float a, float b); } @@ -1198,12 +1228,6 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). @@ -1302,8 +1326,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4775,6 +4814,157 @@ relativeError)); assertArraysEquals(r, a, mask, Float64VectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloat64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloat64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloat64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloat64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloat64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Float64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloat64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Float64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloat64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "floatCompareOpProvider") static void ltFloat64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { float[] a = fa.apply(SPECIES.length()); @@ -5074,115 +5264,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloat64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqFloat64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Float64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeFloat64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5287,23 +5384,6 @@ relativeError)); } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongFloat64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index 41e4d6e4a5d..19bd385ca1f 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java @@ -416,6 +416,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { float apply(float a, float b); } @@ -1203,12 +1233,6 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). @@ -1307,8 +1331,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4780,6 +4819,157 @@ relativeError)); assertArraysEquals(r, a, mask, FloatMaxVectorTests::SQRT); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandFloatMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, FloatMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorFloatMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, FloatMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorFloatMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, FloatMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotFloatMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, FloatMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqFloatMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, FloatMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotFloatMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, FloatMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongFloatMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "floatCompareOpProvider") static void ltFloatMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { float[] a = fa.apply(SPECIES.length()); @@ -5079,115 +5269,22 @@ relativeError)); } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsFloatMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, FloatMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, FloatMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, FloatMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, FloatMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqFloatMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, FloatMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeFloatMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -5292,7 +5389,6 @@ relativeError)); } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index d6bca96ea6e..1bf3203790c 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -393,6 +393,36 @@ public class Int128VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { int apply(int a, int b); } @@ -1085,12 +1115,6 @@ public class Int128VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Int128VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4508,7 +4547,7 @@ public class Int128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueInt128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4532,7 +4571,7 @@ public class Int128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueInt128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6434,6 +6473,157 @@ public class Int128VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Int128VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandInt128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorInt128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorInt128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotInt128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqInt128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotInt128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Int128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongInt128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "intCompareOpProvider") static void ltInt128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { int[] a = fa.apply(SPECIES.length()); @@ -6733,115 +6923,22 @@ public class Int128VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsInt128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqInt128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeInt128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6946,23 +7043,6 @@ public class Int128VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongInt128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index ac98217b714..5973fec7e57 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -393,6 +393,36 @@ public class Int256VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { int apply(int a, int b); } @@ -1085,12 +1115,6 @@ public class Int256VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Int256VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4508,7 +4547,7 @@ public class Int256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueInt256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4532,7 +4571,7 @@ public class Int256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueInt256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6434,6 +6473,157 @@ public class Int256VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Int256VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandInt256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorInt256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorInt256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotInt256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqInt256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotInt256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Int256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongInt256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "intCompareOpProvider") static void ltInt256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { int[] a = fa.apply(SPECIES.length()); @@ -6733,115 +6923,22 @@ public class Int256VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsInt256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqInt256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeInt256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6946,23 +7043,6 @@ public class Int256VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongInt256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index b56236db322..a1e969fc852 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -393,6 +393,36 @@ public class Int512VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { int apply(int a, int b); } @@ -1085,12 +1115,6 @@ public class Int512VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Int512VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4508,7 +4547,7 @@ public class Int512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueInt512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4532,7 +4571,7 @@ public class Int512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueInt512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6434,6 +6473,157 @@ public class Int512VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Int512VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandInt512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorInt512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorInt512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotInt512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqInt512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotInt512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Int512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongInt512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "intCompareOpProvider") static void ltInt512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { int[] a = fa.apply(SPECIES.length()); @@ -6733,115 +6923,22 @@ public class Int512VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsInt512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqInt512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeInt512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6946,23 +7043,6 @@ public class Int512VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongInt512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index f87a0eb458c..15b3b68820e 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -393,6 +393,36 @@ public class Int64VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { int apply(int a, int b); } @@ -1085,12 +1115,6 @@ public class Int64VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Int64VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4508,7 +4547,7 @@ public class Int64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueInt64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4532,7 +4571,7 @@ public class Int64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueInt64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6434,6 +6473,157 @@ public class Int64VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Int64VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandInt64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorInt64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorInt64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotInt64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqInt64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Int64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotInt64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Int64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongInt64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "intCompareOpProvider") static void ltInt64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { int[] a = fa.apply(SPECIES.length()); @@ -6733,115 +6923,22 @@ public class Int64VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsInt64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqInt64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Int64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeInt64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6946,23 +7043,6 @@ public class Int64VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongInt64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index c61aab0013e..67368e0f70e 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -398,6 +398,36 @@ public class IntMaxVectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { int apply(int a, int b); } @@ -1090,12 +1120,6 @@ public class IntMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -1227,8 +1251,23 @@ public class IntMaxVectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4513,7 +4552,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueIntMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4537,7 +4576,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueIntMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6439,6 +6478,157 @@ public class IntMaxVectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, IntMaxVectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandIntMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, IntMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorIntMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, IntMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorIntMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, IntMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotIntMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, IntMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqIntMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, IntMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotIntMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, IntMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongIntMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "intCompareOpProvider") static void ltIntMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { int[] a = fa.apply(SPECIES.length()); @@ -6738,115 +6928,22 @@ public class IntMaxVectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsIntMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, IntMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, IntMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, IntMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, IntMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqIntMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, IntMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeIntMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6951,7 +7048,6 @@ public class IntMaxVectorTests extends AbstractVectorTest { } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index a8cf38c003a..6f91fb9ffbf 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -350,6 +350,36 @@ public class Long128VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { long apply(long a, long b); } @@ -1075,12 +1105,6 @@ public class Long128VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -1219,8 +1243,23 @@ public class Long128VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4530,7 +4569,7 @@ public class Long128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueLong128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4554,7 +4593,7 @@ public class Long128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueLong128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6386,6 +6425,157 @@ public class Long128VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Long128VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandLong128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorLong128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorLong128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotLong128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqLong128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotLong128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Long128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongLong128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "longCompareOpProvider") static void ltLong128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { long[] a = fa.apply(SPECIES.length()); @@ -6619,115 +6809,22 @@ public class Long128VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsLong128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqLong128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeLong128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6832,23 +6929,6 @@ public class Long128VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongLong128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index a394a59699f..118c955ad24 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -350,6 +350,36 @@ public class Long256VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { long apply(long a, long b); } @@ -1075,12 +1105,6 @@ public class Long256VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -1219,8 +1243,23 @@ public class Long256VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4530,7 +4569,7 @@ public class Long256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueLong256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4554,7 +4593,7 @@ public class Long256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueLong256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6386,6 +6425,157 @@ public class Long256VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Long256VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandLong256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorLong256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorLong256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotLong256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqLong256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotLong256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Long256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongLong256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "longCompareOpProvider") static void ltLong256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { long[] a = fa.apply(SPECIES.length()); @@ -6619,115 +6809,22 @@ public class Long256VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsLong256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqLong256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeLong256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6832,23 +6929,6 @@ public class Long256VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongLong256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 2f12ea98399..1bca0ef0ebd 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -350,6 +350,36 @@ public class Long512VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { long apply(long a, long b); } @@ -1075,12 +1105,6 @@ public class Long512VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -1219,8 +1243,23 @@ public class Long512VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4530,7 +4569,7 @@ public class Long512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueLong512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4554,7 +4593,7 @@ public class Long512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueLong512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6386,6 +6425,157 @@ public class Long512VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Long512VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandLong512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorLong512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorLong512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotLong512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqLong512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotLong512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Long512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongLong512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "longCompareOpProvider") static void ltLong512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { long[] a = fa.apply(SPECIES.length()); @@ -6619,115 +6809,22 @@ public class Long512VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsLong512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqLong512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeLong512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6832,23 +6929,6 @@ public class Long512VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongLong512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 0fda0abed58..212bbb5047c 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -350,6 +350,36 @@ public class Long64VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { long apply(long a, long b); } @@ -1075,12 +1105,6 @@ public class Long64VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -1219,8 +1243,23 @@ public class Long64VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4530,7 +4569,7 @@ public class Long64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueLong64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4554,7 +4593,7 @@ public class Long64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueLong64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6386,6 +6425,157 @@ public class Long64VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Long64VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandLong64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorLong64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorLong64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotLong64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqLong64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Long64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotLong64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Long64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongLong64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "longCompareOpProvider") static void ltLong64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { long[] a = fa.apply(SPECIES.length()); @@ -6619,115 +6809,22 @@ public class Long64VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsLong64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqLong64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Long64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeLong64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6832,23 +6929,6 @@ public class Long64VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongLong64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index 7aa2bc4c510..3eba905e4f8 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -355,6 +355,36 @@ public class LongMaxVectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { long apply(long a, long b); } @@ -1080,12 +1110,6 @@ public class LongMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -1224,8 +1248,23 @@ public class LongMaxVectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4535,7 +4574,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueLongMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4559,7 +4598,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueLongMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6391,6 +6430,157 @@ public class LongMaxVectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, LongMaxVectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandLongMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, LongMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorLongMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, LongMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorLongMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, LongMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotLongMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, LongMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqLongMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, LongMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotLongMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, LongMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongLongMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "longCompareOpProvider") static void ltLongMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { long[] a = fa.apply(SPECIES.length()); @@ -6624,115 +6814,22 @@ public class LongMaxVectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsLongMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, LongMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, LongMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, LongMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, LongMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqLongMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, LongMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeLongMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6837,7 +6934,6 @@ public class LongMaxVectorTests extends AbstractVectorTest { } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 5f4c54bb708..50be26b163a 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -393,6 +393,36 @@ public class Short128VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { short apply(short a, short b); } @@ -1085,12 +1115,6 @@ public class Short128VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Short128VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4455,7 +4494,7 @@ public class Short128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueShort128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4479,7 +4518,7 @@ public class Short128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueShort128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6381,6 +6420,157 @@ public class Short128VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Short128VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandShort128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short128VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorShort128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short128VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorShort128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short128VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotShort128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short128VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqShort128VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short128VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotShort128VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Short128VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongShort128VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "shortCompareOpProvider") static void ltShort128VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { short[] a = fa.apply(SPECIES.length()); @@ -6680,115 +6870,22 @@ public class Short128VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsShort128VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short128VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short128VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short128VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short128VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqShort128VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short128VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeShort128VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6893,23 +6990,6 @@ public class Short128VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongShort128VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 88986575f60..5f63164755b 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -393,6 +393,36 @@ public class Short256VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { short apply(short a, short b); } @@ -1085,12 +1115,6 @@ public class Short256VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Short256VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4455,7 +4494,7 @@ public class Short256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueShort256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4479,7 +4518,7 @@ public class Short256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueShort256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6381,6 +6420,157 @@ public class Short256VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Short256VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandShort256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short256VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorShort256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short256VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorShort256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short256VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotShort256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short256VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqShort256VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short256VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotShort256VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Short256VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongShort256VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "shortCompareOpProvider") static void ltShort256VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { short[] a = fa.apply(SPECIES.length()); @@ -6680,115 +6870,22 @@ public class Short256VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsShort256VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short256VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short256VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short256VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short256VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqShort256VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short256VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeShort256VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6893,23 +6990,6 @@ public class Short256VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongShort256VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 0f474375a47..5044f8db482 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -393,6 +393,36 @@ public class Short512VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { short apply(short a, short b); } @@ -1085,12 +1115,6 @@ public class Short512VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Short512VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4455,7 +4494,7 @@ public class Short512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueShort512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4479,7 +4518,7 @@ public class Short512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueShort512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6381,6 +6420,157 @@ public class Short512VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Short512VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandShort512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short512VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorShort512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short512VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorShort512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short512VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotShort512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short512VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqShort512VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short512VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotShort512VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Short512VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongShort512VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "shortCompareOpProvider") static void ltShort512VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { short[] a = fa.apply(SPECIES.length()); @@ -6680,115 +6870,22 @@ public class Short512VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsShort512VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short512VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short512VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short512VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short512VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqShort512VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short512VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeShort512VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6893,23 +6990,6 @@ public class Short512VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongShort512VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index 4b99ed6d84c..bc12c3f0938 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -393,6 +393,36 @@ public class Short64VectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { short apply(short a, short b); } @@ -1085,12 +1115,6 @@ public class Short64VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -1222,8 +1246,23 @@ public class Short64VectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4455,7 +4494,7 @@ public class Short64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueShort64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4479,7 +4518,7 @@ public class Short64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueShort64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6381,6 +6420,157 @@ public class Short64VectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, Short64VectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandShort64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short64VectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorShort64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short64VectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorShort64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short64VectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotShort64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short64VectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqShort64VectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, Short64VectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotShort64VectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, Short64VectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongShort64VectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "shortCompareOpProvider") static void ltShort64VectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { short[] a = fa.apply(SPECIES.length()); @@ -6680,115 +6870,22 @@ public class Short64VectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsShort64VectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short64VectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short64VectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short64VectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short64VectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqShort64VectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, Short64VectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeShort64VectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6893,23 +6990,6 @@ public class Short64VectorTests extends AbstractVectorTest { } } - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLongShort64VectorTestsSmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index 2bb3b9c1557..ec2df02b171 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -398,6 +398,36 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { short apply(short a, short b); } @@ -1090,12 +1120,6 @@ public class ShortMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); - @DataProvider - public Object[][] boolUnaryOpProvider() { - return BOOL_ARRAY_GENERATORS.stream(). - map(f -> new Object[]{f}). - toArray(Object[][]::new); - } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -1227,8 +1251,23 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } @@ -4460,7 +4499,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void anyTrueShortMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4484,7 +4523,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolUnaryOpProvider") + @Test(dataProvider = "boolMaskUnaryOpProvider") static void allTrueShortMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -6386,6 +6425,157 @@ public class ShortMaxVectorTests extends AbstractVectorTest { assertArraysEquals(r, a, mask, ShortMaxVectorTests::REVERSE_BYTES); } + static boolean band(boolean a, boolean b) { + return a & b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandShortMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.and(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ShortMaxVectorTests::band); + } + + static boolean bor(boolean a, boolean b) { + return a | b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskorShortMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.or(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ShortMaxVectorTests::bor); + } + + static boolean bxor(boolean a, boolean b) { + return a != b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskxorShortMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.xor(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ShortMaxVectorTests::bxor); + } + + static boolean bandNot(boolean a, boolean b) { + return a & !b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskandNotShortMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.andNot(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ShortMaxVectorTests::bandNot); + } + + static boolean beq(boolean a, boolean b) { + return a == b; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskeqShortMaxVectorTests(IntFunction fa, IntFunction fb) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.eq(bv).intoArray(r, i); + } + } + + assertArraysEquals(r, a, b, ShortMaxVectorTests::beq); + } + + static boolean unot(boolean a) { + return !a; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void masknotShortMaxVectorTests(IntFunction fa) { + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.not().intoArray(r, i); + } + } + + assertArraysEquals(r, a, ShortMaxVectorTests::unot); + } + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void maskFromToLongShortMaxVectorTests(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } + @Test(dataProvider = "shortCompareOpProvider") static void ltShortMaxVectorTestsBroadcastSmokeTest(IntFunction fa, IntFunction fb) { short[] a = fa.apply(SPECIES.length()); @@ -6685,115 +6875,22 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqualsShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEqualsShortMaxVectorTests(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ShortMaxVectorTests::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOrShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ShortMaxVectorTests::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXorShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ShortMaxVectorTests::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNotShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ShortMaxVectorTests::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEqShortMaxVectorTestsSmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, ShortMaxVectorTests::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCodeShortMaxVectorTestsSmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -6898,7 +6995,6 @@ public class ShortMaxVectorTests extends AbstractVectorTest { } } - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index a6f794a5559..46ccc0c8550 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -73,6 +73,9 @@ binary_math_template="Binary-op-math" binary_math_broadcast_template="Binary-Broadcast-op-math" bool_reduction_scalar="BoolReduction-Scalar-op" bool_reduction_template="BoolReduction-op" +bool_binary_template="BoolBinary-op" +bool_unary_template="BoolUnary-op" +mask_fromtolong_template="Mask-FromToLong" with_op_template="With-Op" shift_template="Shift-op" shift_masked_template="Shift-Masked-op" @@ -230,7 +233,8 @@ function gen_op_tmpl { local gen_perf_tests=$generate_perf_tests if [[ $template == *"-Broadcast-"* ]] || [[ $template == "Miscellaneous" ]] || - [[ $template == *"Compare-Masked"* ]] || [[ $template == *"Compare-Broadcast"* ]]; then + [[ $template == *"Compare-Masked"* ]] || [[ $template == *"Compare-Broadcast"* ]] || + [[ $template == *"Mask-Binary"* ]]; then gen_perf_tests=false fi if [ $gen_perf_tests == true ]; then @@ -625,6 +629,15 @@ gen_unary_alu_op "REVERSE_BYTES" "\$Boxtype\$.reverseBytes(a)" "intOrLong" gen_unary_alu_op "REVERSE_BYTES" "\$Boxtype\$.reverseBytes(a)" "short" gen_unary_alu_op "REVERSE_BYTES" "a" "byte" +# Mask operations +gen_op_tmpl $bool_binary_template "and" "a \& b" +gen_op_tmpl $bool_binary_template "or" "a | b" +gen_op_tmpl $bool_binary_template "xor" "a != b" +gen_op_tmpl $bool_binary_template "andNot" "a \& !b" +gen_op_tmpl $bool_binary_template "eq" "a == b" +gen_op_tmpl $bool_unary_template "not" "!a" +gen_op_tmpl $mask_fromtolong_template "FromToLong" "" + # Miscellaneous Smoke Tests gen_op_tmpl $miscellaneous_template "MISC" "" "" diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-BoolBinary-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-BoolBinary-op.template new file mode 100644 index 00000000000..3f5bc428cdd --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-BoolBinary-op.template @@ -0,0 +1,11 @@ + boolean[] a = fa.apply(SPECIES.length()); + boolean[] b = fb.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + VectorMask bv = SPECIES.loadMask(b, i); + av.[[TEST]](bv).intoArray(r, i); + } + } diff --git a/test/jdk/jdk/incubator/vector/templates/Kernel-BoolUnary-op.template b/test/jdk/jdk/incubator/vector/templates/Kernel-BoolUnary-op.template new file mode 100644 index 00000000000..836db281c1b --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Kernel-BoolUnary-op.template @@ -0,0 +1,9 @@ + boolean[] a = fa.apply(SPECIES.length()); + boolean[] r = new boolean[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + VectorMask av = SPECIES.loadMask(a, i); + av.[[TEST]]().intoArray(r, i); + } + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-BoolBinary-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-BoolBinary-op.template new file mode 100644 index 00000000000..9ee79e05363 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Unit-BoolBinary-op.template @@ -0,0 +1,10 @@ + + static boolean b[[TEST]](boolean a, boolean b) { + return [[TEST_OP]]; + } + + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void mask[[TEST]]$vectorteststype$(IntFunction fa, IntFunction fb) { +[[KERNEL]] + assertArraysEquals(r, a, b, $vectorteststype$::b[[TEST]]); + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-BoolUnary-op.template b/test/jdk/jdk/incubator/vector/templates/Unit-BoolUnary-op.template new file mode 100644 index 00000000000..6b1f2185528 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Unit-BoolUnary-op.template @@ -0,0 +1,10 @@ + + static boolean u[[TEST]](boolean a) { + return [[TEST_OP]]; + } + + @Test(dataProvider = "boolMaskUnaryOpProvider") + static void mask[[TEST]]$vectorteststype$(IntFunction fa) { +[[KERNEL]] + assertArraysEquals(r, a, $vectorteststype$::u[[TEST]]); + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Mask-FromToLong.template b/test/jdk/jdk/incubator/vector/templates/Unit-Mask-FromToLong.template new file mode 100644 index 00000000000..784ef5f81b9 --- /dev/null +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Mask-FromToLong.template @@ -0,0 +1,27 @@ + + private static final long LONG_MASK_BITS = 0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length()); + + static void assertArraysEquals(long[] r, long[] a, long bits) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], a[i] & bits); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], a[i] & bits, "(" + a[i] + ") at index #" + i); + } + } + + @Test(dataProvider = "longMaskProvider") + static void mask[[TEST]]$vectorteststype$(IntFunction fa) { + long[] a = fa.apply(SPECIES.length()); + long[] r = new long[a.length]; + + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i++) { + VectorMask vmask = VectorMask.fromLong(SPECIES, a[i]); + r[i] = vmask.toLong(); + } + } + assertArraysEquals(r, a, LONG_MASK_BITS); + } diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template index 9a020c66d52..460f7624f2c 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-Miscellaneous.template @@ -382,115 +382,22 @@ } } - @Test(dataProvider = "maskCompareOpProvider") - static void maskEquals$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { + @Test(dataProvider = "boolMaskBinaryOpProvider") + static void maskEquals$vectorteststype$(IntFunction fa, IntFunction fb) { boolean[] a = fa.apply(SPECIES.length()); boolean[] b = fb.apply(SPECIES.length()); - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - boolean equals = av.equals(bv); - int to = i + SPECIES.length(); - Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + for (int ic = 0; ic < INVOC_COUNT; ic++) { + for (int i = 0; i < a.length; i += SPECIES.length()) { + var av = SPECIES.loadMask(a, i); + var bv = SPECIES.loadMask(b, i); + boolean equals = av.equals(bv); + int to = i + SPECIES.length(); + Assert.assertEquals(equals, Arrays.equals(a, i, to, b, i, to)); + } } } - static boolean band(boolean a, boolean b) { - return a & b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAnd$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.and(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, $vectorteststype$::band); - } - - static boolean bor(boolean a, boolean b) { - return a | b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskOr$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.or(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, $vectorteststype$::bor); - } - - static boolean bxor(boolean a, boolean b) { - return a != b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskXor$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.xor(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, $vectorteststype$::bxor); - } - - static boolean bandNot(boolean a, boolean b) { - return a & !b; - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskAndNot$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.andNot(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, $vectorteststype$::bandNot); - } - - static boolean beq(boolean a, boolean b) { - return (a == b); - } - - @Test(dataProvider = "maskCompareOpProvider") - static void maskEq$vectorteststype$SmokeTest(IntFunction fa, IntFunction fb) { - boolean[] a = fa.apply(SPECIES.length()); - boolean[] b = fb.apply(SPECIES.length()); - boolean[] r = new boolean[a.length]; - - for (int i = 0; i < a.length; i += SPECIES.length()) { - var av = SPECIES.loadMask(a, i); - var bv = SPECIES.loadMask(b, i); - var cv = av.eq(bv); - cv.intoArray(r, i); - } - assertArraysEquals(r, a, b, $vectorteststype$::beq); - } - @Test(dataProvider = "maskProvider") static void maskHashCode$vectorteststype$SmokeTest(IntFunction fa) { boolean[] a = fa.apply(SPECIES.length()); @@ -595,25 +502,6 @@ } } -#if[!MaxBit] - @DataProvider - public static Object[][] longMaskProvider() { - return new Object[][]{ - {0xFFFFFFFFFFFFFFFFL}, - {0x0000000000000000L}, - {0x5555555555555555L}, - {0x0123456789abcdefL}, - }; - } - - @Test(dataProvider = "longMaskProvider") - static void maskFromToLong$vectorteststype$SmokeTest(long inputLong) { - var vmask = VectorMask.fromLong(SPECIES, inputLong); - long outputLong = vmask.toLong(); - Assert.assertEquals(outputLong, (inputLong & (((0xFFFFFFFFFFFFFFFFL >>> (64 - SPECIES.length())))))); - } -#end[!MaxBit] - @DataProvider public static Object[][] offsetProvider() { return new Object[][]{ diff --git a/test/jdk/jdk/incubator/vector/templates/Unit-header.template b/test/jdk/jdk/incubator/vector/templates/Unit-header.template index 33c52f18c1c..328a8335df3 100644 --- a/test/jdk/jdk/incubator/vector/templates/Unit-header.template +++ b/test/jdk/jdk/incubator/vector/templates/Unit-header.template @@ -490,6 +490,36 @@ relativeError)); } } + interface FBoolUnOp { + boolean apply(boolean a); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, FBoolUnOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i]), "(" + a[i] + ") at index #" + i); + } + } + + interface FBoolBinOp { + boolean apply(boolean a, boolean b); + } + + static void assertArraysEquals(boolean[] r, boolean[] a, boolean[] b, FBoolBinOp f) { + int i = 0; + try { + for (; i < a.length; i++) { + Assert.assertEquals(r[i], f.apply(a[i], b[i])); + } + } catch (AssertionError e) { + Assert.assertEquals(r[i], f.apply(a[i], b[i]), "(" + a[i] + ", " + b[i] + ") at index #" + i); + } + } + interface FBinOp { $type$ apply($type$ a, $type$ b); } @@ -1521,8 +1551,23 @@ relativeError)); } @DataProvider - public Object[][] maskCompareOpProvider() { - return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream().map(List::toArray). + public Object[][] longMaskProvider() { + return LONG_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskBinaryOpProvider() { + return BOOLEAN_MASK_COMPARE_GENERATOR_PAIRS.stream(). + map(List::toArray). + toArray(Object[][]::new); + } + + @DataProvider + public Object[][] boolMaskUnaryOpProvider() { + return BOOLEAN_MASK_GENERATORS.stream(). + map(f -> new Object[]{f}). toArray(Object[][]::new); } From a26221299e657b64379d2d56ed3b073f12b227d1 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Wed, 10 Dec 2025 02:04:12 +0000 Subject: [PATCH 036/211] 8255463: java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java failed with ThreadTimeoutException Reviewed-by: dfuchs, djelinski, bpb --- .../inheritedChannel/InheritedChannelTest.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java index 99a127ca5ad..934bf509d88 100644 --- a/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java +++ b/test/jdk/java/nio/channels/spi/SelectorProvider/inheritedChannel/InheritedChannelTest.java @@ -40,7 +40,6 @@ * @key intermittent */ -import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; @@ -77,7 +76,7 @@ public class InheritedChannelTest { }; } - @Test(dataProvider = "testCases", timeOut=30000) + @Test(dataProvider = "testCases") public void test(String desc, List opts) throws Throwable { String pathVar = Platform.sharedLibraryPathVariableName(); System.out.println(pathVar + "=" + libraryPath); From b6732d6048259de68a3dd5b4f66ac82f87270404 Mon Sep 17 00:00:00 2001 From: Xiaohong Gong Date: Wed, 10 Dec 2025 02:09:49 +0000 Subject: [PATCH 037/211] 8371603: C2: Missing Ideal optimizations for load and store vectors on SVE Co-authored-by: Emanuel Peter Reviewed-by: epeter, erfang, haosun --- src/hotspot/cpu/aarch64/aarch64_vector.ad | 29 +- src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 | 29 +- src/hotspot/share/opto/matcher.hpp | 4 + src/hotspot/share/opto/vectornode.cpp | 65 ++- src/hotspot/share/opto/vectornode.hpp | 1 - .../compiler/lib/ir_framework/IRNode.java | 10 + .../TestVectorLoadStoreOptimization.java | 105 +++++ .../TestVectorOperationsWithPartialSize.java | 432 ++++++++++++++++++ 8 files changed, 619 insertions(+), 56 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorLoadStoreOptimization.java create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 842784d1a29..78ef121bd29 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -346,8 +346,14 @@ source %{ } bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) { - // Only SVE has partial vector operations - if (UseSVE == 0) { + // 1. Only SVE requires partial vector operations. + // 2. The vector size in bytes must be smaller than MaxVectorSize. + // 3. Predicated vectors have a mask input, which guarantees that + // out-of-bounds lanes remain inactive. + int length_in_bytes = vt->length_in_bytes(); + if (UseSVE == 0 || + length_in_bytes == MaxVectorSize || + node->is_predicated_vector()) { return false; } @@ -370,21 +376,22 @@ source %{ return !node->in(1)->is_Con(); case Op_LoadVector: case Op_StoreVector: - // We use NEON load/store instructions if the vector length is <= 128 bits. - return vt->length_in_bytes() > 16; case Op_AddReductionVI: case Op_AddReductionVL: - // We may prefer using NEON instructions rather than SVE partial operations. - return !VM_Version::use_neon_for_vector(vt->length_in_bytes()); + // For these ops, we prefer using NEON instructions rather than SVE + // predicated instructions for better performance. + return !VM_Version::use_neon_for_vector(length_in_bytes); case Op_MinReductionV: case Op_MaxReductionV: - // For BYTE/SHORT/INT/FLOAT/DOUBLE types, we may prefer using NEON - // instructions rather than SVE partial operations. + // For BYTE/SHORT/INT/FLOAT/DOUBLE types, we prefer using NEON + // instructions rather than SVE predicated instructions for + // better performance. return vt->element_basic_type() == T_LONG || - !VM_Version::use_neon_for_vector(vt->length_in_bytes()); + !VM_Version::use_neon_for_vector(length_in_bytes); default: - // For other ops whose vector size is smaller than the max vector size, a - // full-sized unpredicated operation does not impact the final vector result. + // For other ops whose vector size is smaller than the max vector + // size, a full-sized unpredicated operation does not impact the + // vector result. return false; } } diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index dff82ce95ac..66dc22c3758 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -336,8 +336,14 @@ source %{ } bool Matcher::vector_needs_partial_operations(Node* node, const TypeVect* vt) { - // Only SVE has partial vector operations - if (UseSVE == 0) { + // 1. Only SVE requires partial vector operations. + // 2. The vector size in bytes must be smaller than MaxVectorSize. + // 3. Predicated vectors have a mask input, which guarantees that + // out-of-bounds lanes remain inactive. + int length_in_bytes = vt->length_in_bytes(); + if (UseSVE == 0 || + length_in_bytes == MaxVectorSize || + node->is_predicated_vector()) { return false; } @@ -360,21 +366,22 @@ source %{ return !node->in(1)->is_Con(); case Op_LoadVector: case Op_StoreVector: - // We use NEON load/store instructions if the vector length is <= 128 bits. - return vt->length_in_bytes() > 16; case Op_AddReductionVI: case Op_AddReductionVL: - // We may prefer using NEON instructions rather than SVE partial operations. - return !VM_Version::use_neon_for_vector(vt->length_in_bytes()); + // For these ops, we prefer using NEON instructions rather than SVE + // predicated instructions for better performance. + return !VM_Version::use_neon_for_vector(length_in_bytes); case Op_MinReductionV: case Op_MaxReductionV: - // For BYTE/SHORT/INT/FLOAT/DOUBLE types, we may prefer using NEON - // instructions rather than SVE partial operations. + // For BYTE/SHORT/INT/FLOAT/DOUBLE types, we prefer using NEON + // instructions rather than SVE predicated instructions for + // better performance. return vt->element_basic_type() == T_LONG || - !VM_Version::use_neon_for_vector(vt->length_in_bytes()); + !VM_Version::use_neon_for_vector(length_in_bytes); default: - // For other ops whose vector size is smaller than the max vector size, a - // full-sized unpredicated operation does not impact the final vector result. + // For other ops whose vector size is smaller than the max vector + // size, a full-sized unpredicated operation does not impact the + // vector result. return false; } } diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index ca13d0166a1..a071cff9e3c 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -329,6 +329,10 @@ public: static bool match_rule_supported_vector_masked(int opcode, int vlen, BasicType bt); + // Determines if a vector operation needs to be partially implemented with a mask + // controlling only the lanes in range [0, vector_length) are processed. This applies + // to operations whose vector length is less than the hardware-supported maximum + // vector length. Returns true if the operation requires masking, false otherwise. static bool vector_needs_partial_operations(Node* node, const TypeVect* vt); static bool vector_rearrange_requires_load_shuffle(BasicType elem_bt, int vlen); diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 57b94205e5e..271dc901dcb 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -936,28 +936,26 @@ bool VectorNode::is_scalar_op_that_returns_int_but_vector_op_returns_long(int op } } +// Idealize vector operations whose vector size is less than the hardware supported +// max vector size. Generate a vector mask for the operation. Lanes with indices +// inside of the vector size are set to true, while the remaining lanes are set to +// false. Returns the corresponding masked vector node. +static Node* ideal_partial_operations(PhaseGVN* phase, Node* node, const TypeVect* vt) { + if (!Matcher::vector_needs_partial_operations(node, vt)) { + return nullptr; + } -Node* VectorNode::try_to_gen_masked_vector(PhaseGVN* gvn, Node* node, const TypeVect* vt) { int vopc = node->Opcode(); uint vlen = vt->length(); BasicType bt = vt->element_basic_type(); + assert(Matcher::match_rule_supported_vector_masked(vopc, vlen, bt), + "The masked feature is required for the vector operation"); + assert(Matcher::match_rule_supported_vector(Op_VectorMaskGen, vlen, bt), + "'VectorMaskGen' is required to generate a vector mask"); - // Predicated vectors do not need to add another mask input - if (node->is_predicated_vector() || !Matcher::has_predicated_vectors() || - !Matcher::match_rule_supported_vector_masked(vopc, vlen, bt) || - !Matcher::match_rule_supported_vector(Op_VectorMaskGen, vlen, bt)) { - return nullptr; - } - - Node* mask = nullptr; - // Generate a vector mask for vector operation whose vector length is lower than the - // hardware supported max vector length. - if (vt->length_in_bytes() < (uint)MaxVectorSize) { - Node* length = gvn->transform(new ConvI2LNode(gvn->makecon(TypeInt::make(vlen)))); - mask = gvn->transform(VectorMaskGenNode::make(length, bt, vlen)); - } else { - return nullptr; - } + // Generate a vector mask, with lanes inside of the vector length set to true. + Node* length = phase->transform(new ConvI2LNode(phase->makecon(TypeInt::make(vlen)))); + Node* mask = phase->transform(VectorMaskGenNode::make(length, bt, vlen)); // Generate the related masked op for vector load/store/load_gather/store_scatter. // Or append the mask to the vector op's input list by default. @@ -1037,8 +1035,9 @@ bool VectorNode::should_swap_inputs_to_help_global_value_numbering() { } Node* VectorNode::Ideal(PhaseGVN* phase, bool can_reshape) { - if (Matcher::vector_needs_partial_operations(this, vect_type())) { - return try_to_gen_masked_vector(phase, this, vect_type()); + Node* n = ideal_partial_operations(phase, this, vect_type()); + if (n != nullptr) { + return n; } // Sort inputs of commutative non-predicated vector operations to help value numbering. @@ -1119,9 +1118,9 @@ LoadVectorNode* LoadVectorNode::make(int opc, Node* ctl, Node* mem, } Node* LoadVectorNode::Ideal(PhaseGVN* phase, bool can_reshape) { - const TypeVect* vt = vect_type(); - if (Matcher::vector_needs_partial_operations(this, vt)) { - return VectorNode::try_to_gen_masked_vector(phase, this, vt); + Node* n = ideal_partial_operations(phase, this, vect_type()); + if (n != nullptr) { + return n; } return LoadNode::Ideal(phase, can_reshape); } @@ -1133,9 +1132,9 @@ StoreVectorNode* StoreVectorNode::make(int opc, Node* ctl, Node* mem, Node* adr, } Node* StoreVectorNode::Ideal(PhaseGVN* phase, bool can_reshape) { - const TypeVect* vt = vect_type(); - if (Matcher::vector_needs_partial_operations(this, vt)) { - return VectorNode::try_to_gen_masked_vector(phase, this, vt); + Node* n = ideal_partial_operations(phase, this, vect_type()); + if (n != nullptr) { + return n; } return StoreNode::Ideal(phase, can_reshape); } @@ -1411,11 +1410,11 @@ ReductionNode* ReductionNode::make(int opc, Node* ctrl, Node* n1, Node* n2, Basi } Node* ReductionNode::Ideal(PhaseGVN* phase, bool can_reshape) { - const TypeVect* vt = vect_type(); - if (Matcher::vector_needs_partial_operations(this, vt)) { - return VectorNode::try_to_gen_masked_vector(phase, this, vt); + Node* n = ideal_partial_operations(phase, this, vect_type()); + if (n != nullptr) { + return n; } - return nullptr; + return Node::Ideal(phase, can_reshape); } // Convert fromLong to maskAll if the input sets or unsets all lanes. @@ -1893,11 +1892,11 @@ Node* VectorMaskOpNode::make(Node* mask, const Type* ty, int mopc) { } Node* VectorMaskOpNode::Ideal(PhaseGVN* phase, bool can_reshape) { - const TypeVect* vt = vect_type(); - if (Matcher::vector_needs_partial_operations(this, vt)) { - return VectorNode::try_to_gen_masked_vector(phase, this, vt); + Node* n = ideal_partial_operations(phase, this, vect_type()); + if (n != nullptr) { + return n; } - return nullptr; + return TypeNode::Ideal(phase, can_reshape); } Node* VectorMaskCastNode::Identity(PhaseGVN* phase) { diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 427aeff53fc..dc7aa13cf36 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -117,7 +117,6 @@ class VectorNode : public TypeNode { static bool is_vector_bitwise_not_pattern(Node* n); static Node* degenerate_vector_rotate(Node* n1, Node* n2, bool is_rotate_left, int vlen, BasicType bt, PhaseGVN* phase); - static Node* try_to_gen_masked_vector(PhaseGVN* gvn, Node* node, const TypeVect* vt); // [Start, end) half-open range defining which operands are vectors static void vector_operands(Node* n, uint* start, uint* end); diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 41f185f3686..608027e7ee1 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1478,6 +1478,16 @@ public class IRNode { beforeMatchingNameRegex(VECTOR_MASK_LANE_IS_SET, "ExtractUB"); } + public static final String VECTOR_MASK_GEN = PREFIX + "VECTOR_MASK_GEN" + POSTFIX; + static { + beforeMatchingNameRegex(VECTOR_MASK_GEN, "VectorMaskGen"); + } + + public static final String VECTOR_MASK_FIRST_TRUE = PREFIX + "VECTOR_MASK_FIRST_TRUE" + POSTFIX; + static { + beforeMatchingNameRegex(VECTOR_MASK_FIRST_TRUE, "VectorMaskFirstTrue"); + } + // Can only be used if avx512_vnni is available. public static final String MUL_ADD_VS2VI_VNNI = PREFIX + "MUL_ADD_VS2VI_VNNI" + POSTFIX; static { diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorLoadStoreOptimization.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLoadStoreOptimization.java new file mode 100644 index 00000000000..c603f450d0c --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorLoadStoreOptimization.java @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2025, NVIDIA CORPORATION & 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.vectorapi; + +import compiler.lib.generators.*; +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.*; +import jdk.test.lib.Asserts; + +/** + * @test 8371603 + * @key randomness + * @library /test/lib / + * @summary Test the missing optimization issues for vector load/store caused by JDK-8286941 + * @modules jdk.incubator.vector + * + * @run driver ${test.main.class} + */ +public class TestVectorLoadStoreOptimization { + private static final int LENGTH = 1024; + private static final Generators random = Generators.G; + + private static final VectorSpecies SPECIES = IntVector.SPECIES_PREFERRED; + + private static int[] a; + + static { + a = new int[LENGTH]; + random.fill(random.ints(), a); + } + + // Test that "LoadVectorNode::Ideal()" calls "LoadNode::Ideal()" as expected, + // which sees the previous stores that go to the same position in-dependently, + // and optimize out the load with matched store values. + @Test + @IR(counts = { IRNode.LOAD_VECTOR_I, "1" }, + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}) + public static void testLoadVector() { + IntVector v1 = IntVector.fromArray(SPECIES, a, 0); + v1.intoArray(a, SPECIES.length()); + v1.intoArray(a, 2 * SPECIES.length()); + // The second load vector equals to the first one and should be optimized + // out by "LoadNode::Ideal()". + IntVector v2 = IntVector.fromArray(SPECIES, a, SPECIES.length()); + v2.intoArray(a, 3 * SPECIES.length()); + } + + @Check(test = "testLoadVector") + public static void testLoadVectorVerify() { + for (int i = SPECIES.length(); i < 4 * SPECIES.length(); i += SPECIES.length()) { + for (int j = 0; j < SPECIES.length(); j++) { + Asserts.assertEquals(a[i + j], a[j]); + } + } + } + + // Test that "StoreVectorNode::Ideal()" calls "StoreNode::Ideal()" as expected, + // which can get rid of previous stores that go to the same position. + @Test + @IR(counts = { IRNode.STORE_VECTOR, "1" }, + applyIfCPUFeatureOr = {"asimd", "true", "avx", "true", "rvv", "true"}) + public static void testStoreVector() { + IntVector v1 = IntVector.fromArray(SPECIES, a, 0 * SPECIES.length()); + IntVector v2 = IntVector.fromArray(SPECIES, a, 1 * SPECIES.length()); + // Useless store to same position as below, which should be optimized out by + // "StoreNode::Ideal()". + v1.intoArray(a, 3 * SPECIES.length()); + v2.intoArray(a, 3 * SPECIES.length()); + } + + @Check(test = "testStoreVector") + public static void testStoreVectorVerify() { + for (int i = 3 * SPECIES.length(); i < 4 * SPECIES.length(); i++) { + Asserts.assertEquals(a[i], a[i - 2 * SPECIES.length()]); + } + } + + public static void main(String[] args) { + TestFramework testFramework = new TestFramework(); + testFramework.setDefaultWarmup(10000) + .addFlags("--add-modules=jdk.incubator.vector") + .start(); + } +} \ No newline at end of file diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java new file mode 100644 index 00000000000..6fd20b7e2fb --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorOperationsWithPartialSize.java @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2025, NVIDIA CORPORATION & 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.vectorapi; + +import compiler.lib.generators.*; +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.*; +import jdk.test.lib.Asserts; + +/** + * @test 8371603 + * @key randomness + * @library /test/lib / + * @summary Test vector operations with vector size less than MaxVectorSize + * @modules jdk.incubator.vector + * + * @run driver ${test.main.class} + */ + +public class TestVectorOperationsWithPartialSize { + private static final int SIZE = 1024; + private static final Generators random = Generators.G; + + private static final VectorSpecies ISPEC_128 = IntVector.SPECIES_128; + private static final VectorSpecies LSPEC_128 = LongVector.SPECIES_128; + private static final VectorSpecies FSPEC_128 = FloatVector.SPECIES_128; + private static final VectorSpecies DSPEC_128 = DoubleVector.SPECIES_128; + private static final VectorSpecies ISPEC_256 = IntVector.SPECIES_256; + private static final VectorSpecies LSPEC_256 = LongVector.SPECIES_256; + + private static int[] ia; + private static int[] ib; + private static long[] la; + private static long[] lb; + private static float[] fa; + private static float[] fb; + private static double[] da; + private static double[] db; + private static boolean[] m; + private static boolean[] mr; + private static int[] indices; + + static { + ia = new int[SIZE]; + ib = new int[SIZE]; + la = new long[SIZE]; + lb = new long[SIZE]; + fa = new float[SIZE]; + fb = new float[SIZE]; + da = new double[SIZE]; + db = new double[SIZE]; + m = new boolean[SIZE]; + mr = new boolean[SIZE]; + indices = new int[SIZE]; + + random.fill(random.ints(), ia); + random.fill(random.longs(), la); + random.fill(random.floats(), fa); + random.fill(random.doubles(), da); + random.fill(random.uniformInts(0, ISPEC_128.length()), indices); + for (int i = 0; i < SIZE; i++) { + m[i] = i % 2 == 0; + } + } + + // ================ Load/Store/Gather/Scatter Tests ================== + + private static void verifyLoadStore(int[] expected, int[] actual, int vlen) { + for (int i = 0; i < vlen; i++) { + Asserts.assertEquals(expected[i], actual[i]); + } + } + + private static void verifyLoadGatherStoreScatter(int[] expected, int[] actual, int[] indices, int vlen) { + for (int i = 0; i < vlen; i++) { + Asserts.assertEquals(expected[indices[i]], actual[indices[i]]); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "0", + IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE_4, "1", + IRNode.STORE_VECTOR, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public void testLoadStore_128() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + v.intoArray(ib, 0); + verifyLoadStore(ia, ib, ISPEC_128.length()); + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.LOAD_VECTOR_MASKED, "1", + IRNode.STORE_VECTOR_MASKED, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=64"}) + public void testLoadStore_256() { + IntVector v = IntVector.fromArray(ISPEC_256, ia, 0); + v.intoArray(ib, 0); + verifyLoadStore(ia, ib, ISPEC_256.length()); + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.LOAD_VECTOR_GATHER_MASKED, "1", + IRNode.STORE_VECTOR_SCATTER_MASKED, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public void testLoadGatherStoreScatter_128() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0, indices, 0); + v.intoArray(ib, 0, indices, 0); + verifyLoadGatherStoreScatter(ia, ib, indices, ISPEC_128.length()); + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.LOAD_VECTOR_GATHER_MASKED, "1", + IRNode.STORE_VECTOR_SCATTER_MASKED, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=64"}) + public void testLoadGatherStoreScatter_256() { + IntVector v = IntVector.fromArray(ISPEC_256, ia, 0, indices, 0); + v.intoArray(ib, 0, indices, 0); + verifyLoadGatherStoreScatter(ia, ib, indices, ISPEC_256.length()); + } + + // ===================== Reduction Tests - Add ===================== + + interface binOpInt { + int apply(int a, int b); + } + + interface binOpLong { + long apply(long a, long b); + } + + private static int reduceLanes(int init, int[] arr, int vlen, binOpInt f) { + int result = init; + for (int i = 0; i < vlen; i++) { + result = f.apply(arr[i], result); + } + return result; + } + + private static long reduceLanes(long init, long[] arr, int vlen,binOpLong f) { + long result = init; + for (int i = 0; i < vlen; i++) { + result = f.apply(arr[i], result); + } + return result; + } + + // Reduction add operations with integer types are implemented with NEON SIMD instructions + // when the vector size is less than or equal to 128-bit. + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "0", + IRNode.ADD_REDUCTION_VI, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public int testAddReductionInt_128() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.ADD); + Asserts.assertEquals(reduceLanes(0, ia, ISPEC_128.length(), (a, b) -> (a + b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.ADD_REDUCTION_VI, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=64"}) + public int testAddReductionInt_256() { + IntVector v = IntVector.fromArray(ISPEC_256, ia, 0); + int result = v.reduceLanes(VectorOperators.ADD); + Asserts.assertEquals(reduceLanes(0, ia, ISPEC_256.length(), (a, b) -> (a + b)), result); + return result; + } + + // Reduction add operations with long types are implemented with NEON SIMD instructions + // when the vector size is less than or equal to 128-bit. + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "0", + IRNode.ADD_REDUCTION_VL, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public long testAddReductionLong_128() { + LongVector v = LongVector.fromArray(LSPEC_128, la, 0); + long result = v.reduceLanes(VectorOperators.ADD); + Asserts.assertEquals(reduceLanes(0L, la, LSPEC_128.length(), (a, b) -> (a + b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.ADD_REDUCTION_VL, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=64"}) + public long testAddReductionLong_256() { + LongVector v = LongVector.fromArray(LSPEC_256, la, 0); + long result = v.reduceLanes(VectorOperators.ADD); + Asserts.assertEquals(reduceLanes(0L, la, LSPEC_256.length(), (a, b) -> (a + b)), result); + return result; + } + + private static void verifyAddReductionFloat(float actual, float[] arr, int vlen) { + float expected = 0.0f; + for (int i = 0; i < vlen; i++) { + expected += arr[i]; + } + // Floating point addition reduction ops may introduce rounding errors. + float ROUNDING_ERROR_FACTOR_ADD = 10.0f; + float tolerance = Math.ulp(expected) * ROUNDING_ERROR_FACTOR_ADD; + if (Math.abs(expected - actual) > tolerance) { + throw new RuntimeException( + "assertEqualsWithTolerance" + + ": expected " + expected + " but was " + actual + + " (tolerance: " + tolerance + ", diff: " + Math.abs(expected - actual) + ")" + ); + } + } + + private static void verifyAddReductionDouble(double actual, double[] arr, int vlen) { + double expected = 0.0; + for (int i = 0; i < vlen; i++) { + expected += arr[i]; + } + // Floating point addition reduction ops may introduce rounding errors. + double ROUNDING_ERROR_FACTOR_ADD = 10.0; + double tolerance = Math.ulp(expected) * ROUNDING_ERROR_FACTOR_ADD; + if (Math.abs(expected - actual) > tolerance) { + throw new RuntimeException( + "assertEqualsWithTolerance" + + ": expected " + expected + " but was " + actual + + " (tolerance: " + tolerance + ", diff: " + Math.abs(expected - actual) + ")" + ); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.ADD_REDUCTION_VF, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public float testAddReductionFloat() { + FloatVector v = FloatVector.fromArray(FSPEC_128, fa, 0); + float result = v.reduceLanes(VectorOperators.ADD); + verifyAddReductionFloat(result, fa, FSPEC_128.length()); + return result; + } + + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.ADD_REDUCTION_VD, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public double testAddReductionDouble() { + DoubleVector v = DoubleVector.fromArray(DSPEC_128, da, 0); + double result = v.reduceLanes(VectorOperators.ADD); + verifyAddReductionDouble(result, da, DSPEC_128.length()); + return result; + } + + // ============== Reduction Tests - Logical ============== + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.AND_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public int testAndReduction() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.AND); + Asserts.assertEquals(reduceLanes(-1, ia, ISPEC_128.length(), (a, b) -> (a & b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.OR_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public int testOrReduction() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.OR); + Asserts.assertEquals(reduceLanes(0, ia, ISPEC_128.length(), (a, b) -> (a | b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.XOR_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">=32"}) + public int testXorReduction() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.XOR); + Asserts.assertEquals(reduceLanes(0, ia, ISPEC_128.length(), (a, b) -> (a ^ b)), result); + return result; + } + + // ===================== Reduction Tests - Min/Max ===================== + + // Reduction min operations with non-long types are implemented with NEON SIMD instructions + // when the vector size is less than or equal to 128-bit. + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "0", + IRNode.MIN_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public int testMinReductionInt_128() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.MIN); + Asserts.assertEquals(reduceLanes(Integer.MAX_VALUE, ia, ISPEC_128.length(), (a, b) -> Math.min(a, b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.MIN_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 64"}) + public int testMinReductionInt_256() { + IntVector v = IntVector.fromArray(ISPEC_256, ia, 0); + int result = v.reduceLanes(VectorOperators.MIN); + Asserts.assertEquals(reduceLanes(Integer.MAX_VALUE, ia, ISPEC_256.length(), (a, b) -> Math.min(a, b)), result); + return result; + } + + // Reduction max operations with non-long types are implemented with NEON SIMD instructions + // when the vector size is less than or equal to 128-bit. + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "0", + IRNode.MAX_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public int testMaxReductionInt_128() { + IntVector v = IntVector.fromArray(ISPEC_128, ia, 0); + int result = v.reduceLanes(VectorOperators.MAX); + Asserts.assertEquals(reduceLanes(Integer.MIN_VALUE, ia, ISPEC_128.length(), (a, b) -> Math.max(a, b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.MAX_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 64"}) + public int testMaxReductionInt_256() { + IntVector v = IntVector.fromArray(ISPEC_256, ia, 0); + int result = v.reduceLanes(VectorOperators.MAX); + Asserts.assertEquals(reduceLanes(Integer.MIN_VALUE, ia, ISPEC_256.length(), (a, b) -> Math.max(a, b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.MIN_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public static long testMinReductionLong() { + LongVector v = LongVector.fromArray(LSPEC_128, la, 0); + long result = v.reduceLanes(VectorOperators.MIN); + Asserts.assertEquals(reduceLanes(Long.MAX_VALUE, la, LSPEC_128.length(), (a, b) -> Math.min(a, b)), result); + return result; + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.MAX_REDUCTION_V, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public static long testMaxReductionLong() { + LongVector v = LongVector.fromArray(LSPEC_128, la, 0); + long result = v.reduceLanes(VectorOperators.MAX); + Asserts.assertEquals(reduceLanes(Long.MIN_VALUE, la, LSPEC_128.length(), (a, b) -> Math.max(a, b)), result); + return result; + } + + // ====================== VectorMask Tests ====================== + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.VECTOR_LOAD_MASK, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public static void testLoadMask() { + VectorMask vm = VectorMask.fromArray(ISPEC_128, m, 0); + vm.not().intoArray(mr, 0); + // Verify that the mask is loaded correctly. + for (int i = 0; i < ISPEC_128.length(); i++) { + Asserts.assertEquals(!m[i], mr[i]); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.VECTOR_MASK_CMP, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public static void testVectorMaskCmp() { + IntVector v1 = IntVector.fromArray(ISPEC_128, ia, 0); + IntVector v2 = IntVector.fromArray(ISPEC_128, ib, 0); + VectorMask vm = v1.compare(VectorOperators.LT, v2); + vm.intoArray(mr, 0); + // Verify that the mask is generated correctly. + for (int i = 0; i < ISPEC_128.length(); i++) { + Asserts.assertEquals(ia[i] < ib[i], mr[i]); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_MASK_GEN, "1", + IRNode.VECTOR_MASK_FIRST_TRUE, "1"}, + applyIfCPUFeature = {"sve", "true"}, applyIf = {"MaxVectorSize", ">= 32"}) + public static int testFirstTrue() { + VectorMask vm = ISPEC_128.maskAll(false); + int result = vm.firstTrue(); + // The result is the vector length if no lane is true. + // This is the default behavior of the firstTrue method. + Asserts.assertEquals(ISPEC_128.length(), result); + return result; + } + + public static void main(String[] args) { + TestFramework testFramework = new TestFramework(); + testFramework.setDefaultWarmup(10000) + .addFlags("--add-modules=jdk.incubator.vector") + .start(); + } +} From d36a234c1228fdb12eb5931506ba1e03ebae95fc Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 10 Dec 2025 02:26:04 +0000 Subject: [PATCH 038/211] 8368701: CDS VerifierTest_1A.java failed on machines with 512 GB RAM Reviewed-by: dholmes, lmesnik --- test/hotspot/jtreg/runtime/cds/appcds/VerifierTest.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/runtime/cds/appcds/VerifierTest.java b/test/hotspot/jtreg/runtime/cds/appcds/VerifierTest.java index 3ff5da98b42..e0001e021ad 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/VerifierTest.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/VerifierTest.java @@ -221,6 +221,8 @@ public class VerifierTest implements Opcodes { runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting; } TestCommon.run("-cp", jar, + "-Xms256m", + "-Xmx256m", "-Xlog:cds", runtime_arg1, runtime_arg2, runtime_arg3, "VerifierTest0") @@ -302,6 +304,8 @@ public class VerifierTest implements Opcodes { runtime_arg1 = runtime_arg2 = runtime_arg3 = runtime_setting; } TestCommon.run("-cp", jar, + "-Xms256m", + "-Xmx256m", "-Xlog:cds", runtime_arg1, runtime_arg2, runtime_arg3, "Hi") From a5968f936462741a7edea5bbbe73cb067af3d34f Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Wed, 10 Dec 2025 02:34:52 +0000 Subject: [PATCH 039/211] 8371968: RISC-V: implement AES CBC intrinsics Reviewed-by: fyang, fjiang --- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 182 +++++++++++++++++- 1 file changed, 181 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index d0cbe8ea347..49c80dce88a 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -2606,6 +2606,184 @@ class StubGenerator: public StubCodeGenerator { return start; } + void cipherBlockChaining_encryptAESCrypt(int round, Register from, Register to, Register key, + Register rvec, Register input_len) { + const Register len = x29; + + VectorRegister working_vregs[] = { + v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15 + }; + + const unsigned int BLOCK_SIZE = 16; + + __ mv(len, input_len); + // load init rvec + __ vsetivli(x0, 4, Assembler::e32, Assembler::m1); + __ vle32_v(v16, rvec); + + generate_aes_loadkeys(key, working_vregs, round); + Label L_enc_loop; + __ bind(L_enc_loop); + // Encrypt from source by block size + __ vle32_v(v17, from); + __ addi(from, from, BLOCK_SIZE); + __ vxor_vv(v16, v16, v17); + generate_aes_encrypt(v16, working_vregs, round); + __ vse32_v(v16, to); + __ addi(to, to, BLOCK_SIZE); + __ subi(len, len, BLOCK_SIZE); + __ bnez(len, L_enc_loop); + + // save current rvec and return + __ vse32_v(v16, rvec); + __ mv(x10, input_len); + __ leave(); + __ ret(); + } + + // Arguments: + // + // Inputs: + // c_rarg0 - source byte array address + // c_rarg1 - destination byte array address + // c_rarg2 - K (key) in little endian int array + // c_rarg3 - r vector byte array address + // c_rarg4 - input length + // + // Output: + // x10 - input length + // + address generate_cipherBlockChaining_encryptAESCrypt() { + assert(UseAESIntrinsics, "Must be"); + assert(UseZvkn, "need AES instructions (Zvkned extension) support"); + __ align(CodeEntryAlignment); + StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; + StubCodeMark mark(this, stub_id); + + const Register from = c_rarg0; + const Register to = c_rarg1; + const Register key = c_rarg2; + const Register rvec = c_rarg3; + const Register input_len = c_rarg4; + + const Register keylen = x28; + + address start = __ pc(); + __ enter(); + + Label L_aes128, L_aes192; + // Compute #rounds for AES based on the length of the key array + __ lwu(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); + __ mv(t0, 52); + __ bltu(keylen, t0, L_aes128); + __ beq(keylen, t0, L_aes192); + // Else we fallthrough to the biggest case (256-bit key size) + + // Note: the following function performs key += 15*16 + cipherBlockChaining_encryptAESCrypt(15, from, to, key, rvec, input_len); + + // Note: the following function performs key += 11*16 + __ bind(L_aes128); + cipherBlockChaining_encryptAESCrypt(11, from, to, key, rvec, input_len); + + // Note: the following function performs key += 13*16 + __ bind(L_aes192); + cipherBlockChaining_encryptAESCrypt(13, from, to, key, rvec, input_len); + + return start; + } + + void cipherBlockChaining_decryptAESCrypt(int round, Register from, Register to, Register key, + Register rvec, Register input_len) { + const Register len = x29; + + VectorRegister working_vregs[] = { + v1, v2, v3, v4, v5, v6, v7, v8, + v9, v10, v11, v12, v13, v14, v15 + }; + + const unsigned int BLOCK_SIZE = 16; + + __ mv(len, input_len); + // load init rvec + __ vsetivli(x0, 4, Assembler::e32, Assembler::m1); + __ vle32_v(v16, rvec); + + generate_aes_loadkeys(key, working_vregs, round); + Label L_dec_loop; + // Decrypt from source by block size + __ bind(L_dec_loop); + __ vle32_v(v17, from); + __ addi(from, from, BLOCK_SIZE); + __ vmv_v_v(v18, v17); + generate_aes_decrypt(v17, working_vregs, round); + __ vxor_vv(v17, v17, v16); + __ vse32_v(v17, to); + __ vmv_v_v(v16, v18); + __ addi(to, to, BLOCK_SIZE); + __ subi(len, len, BLOCK_SIZE); + __ bnez(len, L_dec_loop); + + // save current rvec and return + __ vse32_v(v16, rvec); + __ mv(x10, input_len); + __ leave(); + __ ret(); + } + + // Arguments: + // + // Inputs: + // c_rarg0 - source byte array address + // c_rarg1 - destination byte array address + // c_rarg2 - K (key) in little endian int array + // c_rarg3 - r vector byte array address + // c_rarg4 - input length + // + // Output: + // x10 - input length + // + address generate_cipherBlockChaining_decryptAESCrypt() { + assert(UseAESIntrinsics, "Must be"); + assert(UseZvkn, "need AES instructions (Zvkned extension) support"); + __ align(CodeEntryAlignment); + StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; + StubCodeMark mark(this, stub_id); + + const Register from = c_rarg0; + const Register to = c_rarg1; + const Register key = c_rarg2; + const Register rvec = c_rarg3; + const Register input_len = c_rarg4; + + const Register keylen = x28; + + address start = __ pc(); + __ enter(); + + Label L_aes128, L_aes192, L_aes128_loop, L_aes192_loop, L_aes256_loop; + // Compute #rounds for AES based on the length of the key array + __ lwu(keylen, Address(key, arrayOopDesc::length_offset_in_bytes() - arrayOopDesc::base_offset_in_bytes(T_INT))); + __ mv(t0, 52); + __ bltu(keylen, t0, L_aes128); + __ beq(keylen, t0, L_aes192); + // Else we fallthrough to the biggest case (256-bit key size) + + // Note: the following function performs key += 15*16 + cipherBlockChaining_decryptAESCrypt(15, from, to, key, rvec, input_len); + + // Note: the following function performs key += 11*16 + __ bind(L_aes128); + cipherBlockChaining_decryptAESCrypt(11, from, to, key, rvec, input_len); + + // Note: the following function performs key += 13*16 + __ bind(L_aes192); + cipherBlockChaining_decryptAESCrypt(13, from, to, key, rvec, input_len); + + return start; + } + // Load big-endian 128-bit from memory. void be_load_counter_128(Register counter_hi, Register counter_lo, Register counter) { __ ld(counter_lo, Address(counter, 8)); // Load 128-bits from counter @@ -2772,8 +2950,8 @@ class StubGenerator: public StubCodeGenerator { // x10 - input length // address generate_counterMode_AESCrypt() { + assert(UseAESCTRIntrinsics, "Must be"); assert(UseZvkn, "need AES instructions (Zvkned extension) support"); - assert(UseAESCTRIntrinsics, "need AES instructions (Zvkned extension) support"); assert(UseZbb, "need basic bit manipulation (Zbb extension) support"); __ align(CodeEntryAlignment); @@ -7041,6 +7219,8 @@ static const int64_t right_3_bits = right_n_bits(3); if (UseAESIntrinsics) { StubRoutines::_aescrypt_encryptBlock = generate_aescrypt_encryptBlock(); StubRoutines::_aescrypt_decryptBlock = generate_aescrypt_decryptBlock(); + StubRoutines::_cipherBlockChaining_encryptAESCrypt = generate_cipherBlockChaining_encryptAESCrypt(); + StubRoutines::_cipherBlockChaining_decryptAESCrypt = generate_cipherBlockChaining_decryptAESCrypt(); } if (UseAESCTRIntrinsics) { From 1bbbce75c5e68429c2a32519eb3c36d964dcdf57 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Wed, 10 Dec 2025 04:31:37 +0000 Subject: [PATCH 040/211] 6726690: SwingUtilities.replaceUI*Map() methods do not remove previously installed maps Reviewed-by: azvegint, tr --- .../classes/javax/swing/SwingUtilities.java | 6 ++ .../javax/swing/SwingUtilities/UIMapTest.java | 90 +++++++++++++++++++ 2 files changed, 96 insertions(+) create mode 100644 test/jdk/javax/swing/SwingUtilities/UIMapTest.java diff --git a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java index 4633e9c4756..70fbeee8c7b 100644 --- a/src/java.desktop/share/classes/javax/swing/SwingUtilities.java +++ b/src/java.desktop/share/classes/javax/swing/SwingUtilities.java @@ -1813,6 +1813,9 @@ public class SwingUtilities implements SwingConstants while (map != null) { InputMap parent = map.getParent(); + if (uiInputMap == null) { + map.clear(); + } if (parent == null || (parent instanceof UIResource)) { map.setParent(uiInputMap); return; @@ -1837,6 +1840,9 @@ public class SwingUtilities implements SwingConstants while (map != null) { ActionMap parent = map.getParent(); + if (uiActionMap == null) { + map.clear(); + } if (parent == null || (parent instanceof UIResource)) { map.setParent(uiActionMap); return; diff --git a/test/jdk/javax/swing/SwingUtilities/UIMapTest.java b/test/jdk/javax/swing/SwingUtilities/UIMapTest.java new file mode 100644 index 00000000000..4a801580b35 --- /dev/null +++ b/test/jdk/javax/swing/SwingUtilities/UIMapTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025, 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 + * @bug 6726690 + * @summary Verifies SwingUtilities.replaceUI*Map() methods remove + * previously installed maps + * @run main UIMapTest + */ + +import java.awt.event.ActionEvent; +import java.awt.event.KeyEvent; +import javax.swing.AbstractAction; +import javax.swing.Action; +import javax.swing.ActionMap; +import javax.swing.ComponentInputMap; +import javax.swing.InputMap; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.KeyStroke; +import javax.swing.SwingUtilities; + +public class UIMapTest { + + public static void main(String[] args) { + + StringBuilder str = new StringBuilder(); + + // Create the test button + JButton button = new JButton("Test"); + + // Create an input map that maps ENTER to the button + ComponentInputMap map = new ComponentInputMap(button); + map.put(KeyStroke.getKeyStroke("pressed ENTER"), "pressed"); + map.put(KeyStroke.getKeyStroke("released ENTER"), "released"); + + // Add the map + SwingUtilities.replaceUIInputMap(button, JComponent.WHEN_IN_FOCUSED_WINDOW, map); + + // Attempt to remove the map + SwingUtilities.replaceUIInputMap(button, JComponent.WHEN_IN_FOCUSED_WINDOW, null); + + if (button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW). + get(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0)) != null) { + str.append("\nSwingUtilities.replaceUIInputMap " + + "didn't remove previously installed input map"); + } + + // Get the InputMap for the button when it has focus + InputMap inputMap = button.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW); + + // Map the VK_ENTER key stroke to a specific action name + inputMap.put(KeyStroke.getKeyStroke(KeyEvent.VK_ENTER, 0), "doEnterAction"); + Action enterAction = new AbstractAction() { + @Override + public void actionPerformed(ActionEvent e) { } + }; + button.getActionMap().put("doEnterAction", enterAction); + SwingUtilities.replaceUIActionMap(button, null); + if (button.getActionMap().size() != 0) { + str.append("\nSwingUtilities.replaceUIActionMap " + + "didn't remove previously installed action map"); + } + if (str.length() != 0) { + throw new RuntimeException(str.toString()); + } + } +} From 00068a80304a809297d0df8698850861e9a1c5e9 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 10 Dec 2025 08:45:20 +0000 Subject: [PATCH 041/211] 8354282: C2: more crashes in compiled code because of dependency on removed range check CastIIs Reviewed-by: chagedorn, qamai, galder, epeter --- .../gc/shenandoah/c2/shenandoahSupport.cpp | 2 +- src/hotspot/share/opto/castnode.cpp | 141 ++++++++++------ src/hotspot/share/opto/castnode.hpp | 151 +++++++++++++++--- src/hotspot/share/opto/cfgnode.cpp | 10 +- src/hotspot/share/opto/compile.cpp | 2 +- src/hotspot/share/opto/escape.cpp | 6 +- src/hotspot/share/opto/library_call.cpp | 4 +- src/hotspot/share/opto/loopTransform.cpp | 4 +- src/hotspot/share/opto/loopnode.cpp | 6 +- src/hotspot/share/opto/loopopts.cpp | 4 +- src/hotspot/share/opto/macroArrayCopy.cpp | 2 +- .../c2/irTests/TestPushAddThruCast.java | 29 +++- ...yAccessAboveRCAfterRCCastIIEliminated.java | 82 +++++++++- 13 files changed, 341 insertions(+), 102 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 35ec9ed5c8c..40fe0c00490 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -1394,7 +1394,7 @@ void ShenandoahBarrierC2Support::pin_and_expand(PhaseIdealLoop* phase) { } if (addr->Opcode() == Op_AddP) { Node* orig_base = addr->in(AddPNode::Base); - Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), ConstraintCastNode::StrongDependency); + Node* base = new CheckCastPPNode(ctrl, orig_base, orig_base->bottom_type(), ConstraintCastNode::DependencyType::NonFloatingNarrowing); phase->register_new_node(base, ctrl); if (addr->in(AddPNode::Base) == addr->in((AddPNode::Address))) { // Field access diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 6d899c1f950..9c764f22e38 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -22,7 +22,6 @@ * */ -#include "castnode.hpp" #include "opto/addnode.hpp" #include "opto/callnode.hpp" #include "opto/castnode.hpp" @@ -35,12 +34,22 @@ #include "opto/type.hpp" #include "utilities/checkedCast.hpp" +const ConstraintCastNode::DependencyType ConstraintCastNode::DependencyType::FloatingNarrowing(true, true, "floating narrowing dependency"); // not pinned, narrows type +const ConstraintCastNode::DependencyType ConstraintCastNode::DependencyType::FloatingNonNarrowing(true, false, "floating non-narrowing dependency"); // not pinned, doesn't narrow type +const ConstraintCastNode::DependencyType ConstraintCastNode::DependencyType::NonFloatingNarrowing(false, true, "non-floating narrowing dependency"); // pinned, narrows type +const ConstraintCastNode::DependencyType ConstraintCastNode::DependencyType::NonFloatingNonNarrowing(false, false, "non-floating non-narrowing dependency"); // pinned, doesn't narrow type + //============================================================================= // If input is already higher or equal to cast type, then this is an identity. Node* ConstraintCastNode::Identity(PhaseGVN* phase) { - if (_dependency == UnconditionalDependency) { + if (!_dependency.narrows_type()) { + // If this cast doesn't carry a type dependency (i.e. not used for type narrowing), we cannot optimize it. return this; } + + // This cast node carries a type dependency. We can remove it if: + // - Its input has a narrower type + // - There's a dominating cast with same input but narrower type Node* dom = dominating_cast(phase, phase); if (dom != nullptr) { return dom; @@ -109,7 +118,7 @@ Node* ConstraintCastNode::Ideal(PhaseGVN* phase, bool can_reshape) { } uint ConstraintCastNode::hash() const { - return TypeNode::hash() + (int)_dependency + (_extra_types != nullptr ? _extra_types->hash() : 0); + return TypeNode::hash() + _dependency.hash() + (_extra_types != nullptr ? _extra_types->hash() : 0); } bool ConstraintCastNode::cmp(const Node &n) const { @@ -117,7 +126,7 @@ bool ConstraintCastNode::cmp(const Node &n) const { return false; } ConstraintCastNode& cast = (ConstraintCastNode&) n; - if (cast._dependency != _dependency) { + if (!cast._dependency.cmp(_dependency)) { return false; } if (_extra_types == nullptr || cast._extra_types == nullptr) { @@ -130,7 +139,7 @@ uint ConstraintCastNode::size_of() const { return sizeof(*this); } -Node* ConstraintCastNode::make_cast_for_basic_type(Node* c, Node* n, const Type* t, DependencyType dependency, BasicType bt) { +Node* ConstraintCastNode::make_cast_for_basic_type(Node* c, Node* n, const Type* t, const DependencyType& dependency, BasicType bt) { switch(bt) { case T_INT: return new CastIINode(c, n, t, dependency); @@ -143,9 +152,9 @@ Node* ConstraintCastNode::make_cast_for_basic_type(Node* c, Node* n, const Type* } TypeNode* ConstraintCastNode::dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const { - if (_dependency == UnconditionalDependency) { - return nullptr; - } + // See discussion at definition of ConstraintCastNode::DependencyType: replacing this cast with a dominating one is + // not safe if _dependency.narrows_type() is not true. + assert(_dependency.narrows_type(), "cast can't be replaced by dominating one"); Node* val = in(1); Node* ctl = in(0); int opc = Opcode(); @@ -205,30 +214,21 @@ void ConstraintCastNode::dump_spec(outputStream *st) const { st->print(" extra types: "); _extra_types->dump_on(st); } - if (_dependency != RegularDependency) { - st->print(" %s dependency", _dependency == StrongDependency ? "strong" : "unconditional"); - } + st->print(" "); + _dependency.dump_on(st); } #endif -const Type* CastIINode::Value(PhaseGVN* phase) const { - const Type *res = ConstraintCastNode::Value(phase); - if (res == Type::TOP) { - return Type::TOP; - } - assert(res->isa_int(), "res must be int"); - - // Similar to ConvI2LNode::Value() for the same reasons - // see if we can remove type assertion after loop opts - res = widen_type(phase, res, T_INT); - - return res; +CastIINode* CastIINode::make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const { + return new CastIINode(in(0), parent, type, dependency, _range_check_dependency, _extra_types); } -Node* ConstraintCastNode::find_or_make_integer_cast(PhaseIterGVN* igvn, Node* parent, const TypeInteger* type) const { - Node* n = clone(); - n->set_req(1, parent); - n->as_ConstraintCast()->set_type(type); +CastLLNode* CastLLNode::make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const { + return new CastLLNode(in(0), parent, type, dependency, _extra_types); +} + +Node* ConstraintCastNode::find_or_make_integer_cast(PhaseIterGVN* igvn, Node* parent, const TypeInteger* type, const DependencyType& dependency) const { + Node* n = make_with(parent, type, dependency); Node* existing = igvn->hash_find_insert(n); if (existing != nullptr) { n->destruct(igvn); @@ -242,14 +242,13 @@ Node *CastIINode::Ideal(PhaseGVN *phase, bool can_reshape) { if (progress != nullptr) { return progress; } - if (can_reshape && !phase->C->post_loop_opts_phase()) { - // makes sure we run ::Value to potentially remove type assertion after loop opts + if (!phase->C->post_loop_opts_phase()) { + // makes sure we run widen_type() to potentially common type assertions after loop opts phase->C->record_for_post_loop_opts_igvn(this); } if (!_range_check_dependency || phase->C->post_loop_opts_phase()) { return optimize_integer_cast(phase, T_INT); } - phase->C->record_for_post_loop_opts_igvn(this); return nullptr; } @@ -279,9 +278,9 @@ void CastIINode::dump_spec(outputStream* st) const { #endif CastIINode* CastIINode::pin_array_access_node() const { - assert(_dependency == RegularDependency, "already pinned"); + assert(_dependency.is_floating(), "already pinned"); if (has_range_check()) { - return new CastIINode(in(0), in(1), bottom_type(), StrongDependency, has_range_check()); + return new CastIINode(in(0), in(1), bottom_type(), _dependency.with_pinned_dependency(), has_range_check()); } return nullptr; } @@ -315,16 +314,6 @@ void CastIINode::remove_range_check_cast(Compile* C) { } -const Type* CastLLNode::Value(PhaseGVN* phase) const { - const Type* res = ConstraintCastNode::Value(phase); - if (res == Type::TOP) { - return Type::TOP; - } - assert(res->isa_long(), "res must be long"); - - return widen_type(phase, res, T_LONG); -} - bool CastLLNode::is_inner_loop_backedge(ProjNode* proj) { if (proj != nullptr) { Node* ctrl_use = proj->unique_ctrl_out_or_null(); @@ -392,7 +381,7 @@ Node* CastLLNode::Ideal(PhaseGVN* phase, bool can_reshape) { return progress; } if (!phase->C->post_loop_opts_phase()) { - // makes sure we run ::Value to potentially remove type assertion after loop opts + // makes sure we run widen_type() to potentially common type assertions after loop opts phase->C->record_for_post_loop_opts_igvn(this); } // transform (CastLL (ConvI2L ..)) into (ConvI2L (CastII ..)) if the type of the CastLL is narrower than the type of @@ -543,7 +532,7 @@ Node* CastP2XNode::Identity(PhaseGVN* phase) { return this; } -Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency, +Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type, const DependencyType& dependency, const TypeTuple* types) { if (type->isa_int()) { return new CastIINode(c, in, type, dependency, false, types); @@ -564,7 +553,7 @@ Node* ConstraintCastNode::make_cast_for_type(Node* c, Node* in, const Type* type return nullptr; } -Node* ConstraintCastNode::optimize_integer_cast(PhaseGVN* phase, BasicType bt) { +Node* ConstraintCastNode::optimize_integer_cast_of_add(PhaseGVN* phase, BasicType bt) { PhaseIterGVN *igvn = phase->is_IterGVN(); const TypeInteger* this_type = this->type()->isa_integer(bt); if (this_type == nullptr) { @@ -586,8 +575,42 @@ Node* ConstraintCastNode::optimize_integer_cast(PhaseGVN* phase, BasicType bt) { Node* x = z->in(1); Node* y = z->in(2); - Node* cx = find_or_make_integer_cast(igvn, x, rx); - Node* cy = find_or_make_integer_cast(igvn, y, ry); + const TypeInteger* tx = phase->type(x)->is_integer(bt); + const TypeInteger* ty = phase->type(y)->is_integer(bt); + + // (Cast (Add x y) tz) is transformed into (Add (Cast x rx) (Cast y ry)) + // + // tz = [tzlo, tzhi] + // rx = [rxlo, rxhi] + // ry = [rylo, ryhi] + // with type of x, tx = [txlo, txhi] + // with type of y, ty = [tylo, tyhi] + // + // From Compile::push_thru_add(): + // rxlo = max(tzlo - tyhi, txlo) + // rxhi = min(tzhi - tylo, txhi) + // rylo = max(tzlo - txhi, tylo) + // ryhi = min(tzhi - txlo, tyhi) + // + // If x is a constant, then txlo = txhi + // rxlo = txlo, rxhi = txhi + // The bounds of the type of the Add after transformation then is: + // rxlo + rylo >= txlo + tzlo - txhi >= tzlo + // rxhi + ryhi <= txhi + tzhi - txlo <= tzhi + // The resulting type is not wider than the type of the Cast + // before transformation + // + // If neither x nor y are constant then the type of the resulting + // Add can be wider than the type of the type of the Cast before + // transformation. + // For instance, tx = [0, 10], ty = [0, 10], tz = [0, 10] + // then rx = [0, 10], ry = [0, 10] + // and rx + ry = [0, 20] which is wider than tz + // + // Same reasoning applies to (Cast (Sub x y) tz) + const DependencyType& dependency = (!tx->is_con() && !ty->is_con()) ? _dependency.with_non_narrowing() : _dependency; + Node* cx = find_or_make_integer_cast(igvn, x, rx, dependency); + Node* cy = find_or_make_integer_cast(igvn, y, ry, dependency); if (op == Op_Add(bt)) { return AddNode::make(cx, cy, bt); } else { @@ -599,11 +622,26 @@ Node* ConstraintCastNode::optimize_integer_cast(PhaseGVN* phase, BasicType bt) { return nullptr; } -const Type* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* res, BasicType bt) const { - if (!phase->C->post_loop_opts_phase()) { +Node* ConstraintCastNode::optimize_integer_cast(PhaseGVN* phase, BasicType bt) { + Node* res = optimize_integer_cast_of_add(phase, bt); + if (res != nullptr) { return res; } + const Type* t = Value(phase); + if (t != Type::TOP && phase->C->post_loop_opts_phase()) { + const Type* bottom_t = bottom_type(); + const TypeInteger* wide_t = widen_type(phase, bottom_t, bt); + if (wide_t != bottom_t) { + // Widening the type of the Cast (to allow some commoning) causes the Cast to change how it can be optimized (if + // type of its input is narrower than the Cast's type, we can't remove it to not loose the control dependency). + return make_with(in(1), wide_t, _dependency.with_non_narrowing()); + } + } + return nullptr; +} +const TypeInteger* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* res, BasicType bt) const { + const TypeInteger* this_type = res->is_integer(bt); // At VerifyConstraintCasts == 1, we verify the ConstraintCastNodes that are present during code // emission. This allows us detecting possible mis-scheduling due to these nodes being pinned at // the wrong control nodes. @@ -612,10 +650,9 @@ const Type* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* re // mis-transformations that may happen due to these nodes being pinned at the wrong control // nodes. if (VerifyConstraintCasts > 1) { - return res; + return this_type; } - const TypeInteger* this_type = res->is_integer(bt); const TypeInteger* in_type = phase->type(in(1))->isa_integer(bt); if (in_type != nullptr && (in_type->lo_as_long() != this_type->lo_as_long() || @@ -636,5 +673,5 @@ const Type* ConstraintCastNode::widen_type(const PhaseGVN* phase, const Type* re MIN2(in_type->hi_as_long(), hi1), MAX2((int)in_type->_widen, w1), bt); } - return res; + return this_type; } diff --git a/src/hotspot/share/opto/castnode.hpp b/src/hotspot/share/opto/castnode.hpp index 3c6ade64aa8..2ff13e44780 100644 --- a/src/hotspot/share/opto/castnode.hpp +++ b/src/hotspot/share/opto/castnode.hpp @@ -33,21 +33,119 @@ // cast to a different range class ConstraintCastNode: public TypeNode { public: - enum DependencyType { - RegularDependency, // if cast doesn't improve input type, cast can be removed - StrongDependency, // leave cast in even if _type doesn't improve input type, can be replaced by stricter dominating cast if one exist - UnconditionalDependency // leave cast in unconditionally + // Cast nodes are subject to a few optimizations: + // + // 1- if the type carried by the Cast doesn't narrow the type of its input, the cast can be replaced by its input. + // Similarly, if a dominating Cast with the same input and a narrower type constraint is found, it can replace the + // current cast. + // + // 2- if the condition that the Cast is control dependent is hoisted, the Cast is hoisted as well + // + // 1- and 2- are not always applied depending on what constraint are applied to the Cast: there are cases where 1- + // and 2- apply, where neither 1- nor 2- apply and where one or the other apply. This class abstract away these + // details. + // + // If _narrows_type is true, the cast carries a type dependency: "after" the control the cast is dependent on, its data + // input is known to have a narrower type (stored in the cast node itself). Optimizations 1- above only apply to cast + // nodes for which _narrows_type is true. + // if _floating is true, the cast only depends on a single control: its control input. Otherwise, it is pinned at its + // current location. Optimizations 2- only apply to cast nodes for which _floating is true. + // _floating here is similar to Node::depends_only_on_test(). + // The 4 combinations of _narrows_types/_floating true/false have some use. See below, at the end of this class + // definition, for examples. + class DependencyType { + private: + const bool _floating; // Does this Cast depends on its control input or is it pinned? + const bool _narrows_type; // Does this Cast narrows the type i.e. if input type is narrower can it be removed? + const char* _desc; + DependencyType(bool depends_on_test, bool narrows_type, const char* desc) + : _floating(depends_on_test), + _narrows_type(narrows_type), + _desc(desc) { + } + NONCOPYABLE(DependencyType); + + public: + + bool is_floating() const { + return _floating; + } + + bool narrows_type() const { + return _narrows_type; + } + + void dump_on(outputStream *st) const { + st->print("%s", _desc); + } + + uint hash() const { + return (_floating ? 1 : 0) + (_narrows_type ? 2 : 0); + } + + bool cmp(const DependencyType& other) const { + return _floating == other._floating && _narrows_type == other._narrows_type; + } + + const DependencyType& with_non_narrowing() const { + if (_floating) { + return FloatingNonNarrowing; + } + return NonFloatingNonNarrowing; + } + + const DependencyType& with_pinned_dependency() const { + if (_narrows_type) { + return NonFloatingNarrowing; + } + return NonFloatingNonNarrowing; + } + + // All the possible combinations of floating/narrowing with example use cases: + + // Use case example: Range Check CastII + // Floating: The Cast is only dependent on the single range check. If the range check was ever to be hoisted it + // would be safe to let the Cast float to where the range check is hoisted up to. + // Narrowing: The Cast narrows the type to a positive index. If the input to the Cast is narrower, we can safely + // remove the cast because the array access will be safe. + static const DependencyType FloatingNarrowing; + // Use case example: Widening Cast nodes' types after loop opts: We want to common Casts with slightly different types. + // Floating: These Casts only depend on the single control. + // NonNarrowing: Even when the input type is narrower, we are not removing the Cast. Otherwise, the dependency + // to the single control is lost, and an array access could float above its range check because we + // just removed the dependency to the range check by removing the Cast. This could lead to an + // out-of-bounds access. + static const DependencyType FloatingNonNarrowing; + // Use case example: An array accesses that is no longer dependent on a single range check (e.g. range check smearing). + // NonFloating: The array access must be pinned below all the checks it depends on. If the check it directly depends + // on with a control input is hoisted, we do not hoist the Cast as well. If we allowed the Cast to float, + // we risk that the array access ends up above another check it depends on (we cannot model two control + // dependencies for a node in the IR). This could lead to an out-of-bounds access. + // Narrowing: If the Cast does not narrow the input type, then it's safe to remove the cast because the array access + // will be safe. + static const DependencyType NonFloatingNarrowing; + // Use case example: Sinking nodes out of a loop + // Non-Floating & Non-Narrowing: We don't want the Cast that forces the node to be out of loop to be removed in any + // case. Otherwise, the sunk node could float back into the loop, undoing the sinking. + // This Cast is only used for pinning without caring about narrowing types. + static const DependencyType NonFloatingNonNarrowing; + }; - protected: - const DependencyType _dependency; +protected: + const DependencyType& _dependency; virtual bool cmp( const Node &n ) const; virtual uint size_of() const; virtual uint hash() const; // Check the type - const Type* widen_type(const PhaseGVN* phase, const Type* res, BasicType bt) const; - Node* find_or_make_integer_cast(PhaseIterGVN* igvn, Node* parent, const TypeInteger* type) const; + const TypeInteger* widen_type(const PhaseGVN* phase, const Type* res, BasicType bt) const; + + virtual ConstraintCastNode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const { + ShouldNotReachHere(); // Only implemented for CastII and CastLL + return nullptr; + } + + Node* find_or_make_integer_cast(PhaseIterGVN* igvn, Node* parent, const TypeInteger* type, const DependencyType& dependency) const; - private: // PhiNode::Ideal() transforms a Phi that merges a single uncasted value into a single cast pinned at the region. // The types of cast nodes eliminated as a consequence of this transformation are collected and stored here so the // type dependencies carried by the cast are known. The cast can then be eliminated if the type of its input is @@ -55,7 +153,7 @@ public: const TypeTuple* _extra_types; public: - ConstraintCastNode(Node* ctrl, Node* n, const Type* t, ConstraintCastNode::DependencyType dependency, + ConstraintCastNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency, const TypeTuple* extra_types) : TypeNode(t,2), _dependency(dependency), _extra_types(extra_types) { init_class_id(Class_ConstraintCast); @@ -67,18 +165,21 @@ public: virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); virtual int Opcode() const; virtual uint ideal_reg() const = 0; - virtual bool depends_only_on_test() const { return _dependency == RegularDependency; } - bool carry_dependency() const { return _dependency != RegularDependency; } + bool carry_dependency() const { return !_dependency.cmp(DependencyType::FloatingNarrowing); } + // A cast node depends_only_on_test if and only if it is floating + virtual bool depends_only_on_test() const { return _dependency.is_floating(); } + const DependencyType& dependency() const { return _dependency; } TypeNode* dominating_cast(PhaseGVN* gvn, PhaseTransform* pt) const; - static Node* make_cast_for_basic_type(Node* c, Node* n, const Type* t, DependencyType dependency, BasicType bt); + static Node* make_cast_for_basic_type(Node* c, Node* n, const Type* t, const DependencyType& dependency, BasicType bt); #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif - static Node* make_cast_for_type(Node* c, Node* in, const Type* type, DependencyType dependency, + static Node* make_cast_for_type(Node* c, Node* in, const Type* type, const DependencyType& dependency, const TypeTuple* types); + Node* optimize_integer_cast_of_add(PhaseGVN* phase, BasicType bt); Node* optimize_integer_cast(PhaseGVN* phase, BasicType bt); bool higher_equal_types(PhaseGVN* phase, const Node* other) const; @@ -102,7 +203,7 @@ class CastIINode: public ConstraintCastNode { virtual uint size_of() const; public: - CastIINode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, bool range_check_dependency = false, const TypeTuple* types = nullptr) + CastIINode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, bool range_check_dependency = false, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types), _range_check_dependency(range_check_dependency) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastII); @@ -110,7 +211,7 @@ class CastIINode: public ConstraintCastNode { virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegI; } virtual Node* Identity(PhaseGVN* phase); - virtual const Type* Value(PhaseGVN* phase) const; + virtual Node *Ideal(PhaseGVN *phase, bool can_reshape); bool has_range_check() const { #ifdef _LP64 @@ -122,6 +223,7 @@ class CastIINode: public ConstraintCastNode { } CastIINode* pin_array_access_node() const; + CastIINode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const; void remove_range_check_cast(Compile* C); #ifndef PRODUCT @@ -131,14 +233,12 @@ class CastIINode: public ConstraintCastNode { class CastLLNode: public ConstraintCastNode { public: - CastLLNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastLLNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastLL); } - virtual const Type* Value(PhaseGVN* phase) const; - static bool is_inner_loop_backedge(ProjNode* proj); static bool cmp_used_at_inner_loop_exit_test(CmpNode* cmp); @@ -147,11 +247,12 @@ public: virtual Node* Ideal(PhaseGVN* phase, bool can_reshape); virtual int Opcode() const; virtual uint ideal_reg() const { return Op_RegL; } + CastLLNode* make_with(Node* parent, const TypeInteger* type, const DependencyType& dependency) const; }; class CastHHNode: public ConstraintCastNode { public: - CastHHNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastHHNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastHH); @@ -162,7 +263,7 @@ public: class CastFFNode: public ConstraintCastNode { public: - CastFFNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastFFNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastFF); @@ -173,7 +274,7 @@ public: class CastDDNode: public ConstraintCastNode { public: - CastDDNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastDDNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastDD); @@ -184,7 +285,7 @@ public: class CastVVNode: public ConstraintCastNode { public: - CastVVNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastVVNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CastVV); @@ -198,7 +299,7 @@ public: // cast pointer to pointer (different type) class CastPPNode: public ConstraintCastNode { public: - CastPPNode (Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CastPPNode (Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { init_class_id(Class_CastPP); } @@ -210,7 +311,7 @@ class CastPPNode: public ConstraintCastNode { // for _checkcast, cast pointer to pointer (different type), without JOIN, class CheckCastPPNode: public ConstraintCastNode { public: - CheckCastPPNode(Node* ctrl, Node* n, const Type* t, DependencyType dependency = RegularDependency, const TypeTuple* types = nullptr) + CheckCastPPNode(Node* ctrl, Node* n, const Type* t, const DependencyType& dependency = DependencyType::FloatingNarrowing, const TypeTuple* types = nullptr) : ConstraintCastNode(ctrl, n, t, dependency, types) { assert(ctrl != nullptr, "control must be set"); init_class_id(Class_CheckCastPP); diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 0598f10b880..203aa69ce1b 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2192,7 +2192,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (phi_type->isa_ptr()) { const Type* uin_type = phase->type(uin); if (!phi_type->isa_oopptr() && !uin_type->isa_oopptr()) { - cast = new CastPPNode(r, uin, phi_type, ConstraintCastNode::StrongDependency, extra_types); + cast = new CastPPNode(r, uin, phi_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing, extra_types); } else { // Use a CastPP for a cast to not null and a CheckCastPP for // a cast to a new klass (and both if both null-ness and @@ -2202,7 +2202,7 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { // null, uin's type must be casted to not null if (phi_type->join(TypePtr::NOTNULL) == phi_type->remove_speculative() && uin_type->join(TypePtr::NOTNULL) != uin_type->remove_speculative()) { - cast = new CastPPNode(r, uin, TypePtr::NOTNULL, ConstraintCastNode::StrongDependency, extra_types); + cast = new CastPPNode(r, uin, TypePtr::NOTNULL, ConstraintCastNode::DependencyType::NonFloatingNarrowing, extra_types); } // If the type of phi and uin, both casted to not null, @@ -2214,14 +2214,14 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { cast = phase->transform(cast); n = cast; } - cast = new CheckCastPPNode(r, n, phi_type, ConstraintCastNode::StrongDependency, extra_types); + cast = new CheckCastPPNode(r, n, phi_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing, extra_types); } if (cast == nullptr) { - cast = new CastPPNode(r, uin, phi_type, ConstraintCastNode::StrongDependency, extra_types); + cast = new CastPPNode(r, uin, phi_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing, extra_types); } } } else { - cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type, ConstraintCastNode::StrongDependency, extra_types); + cast = ConstraintCastNode::make_cast_for_type(r, uin, phi_type, ConstraintCastNode::DependencyType::NonFloatingNarrowing, extra_types); } assert(cast != nullptr, "cast should be set"); cast = phase->transform(cast); diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index bf7feeed0a2..621ba684da1 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -4582,7 +4582,7 @@ Node* Compile::constrained_convI2L(PhaseGVN* phase, Node* value, const TypeInt* // node from floating above the range check during loop optimizations. Otherwise, the // ConvI2L node may be eliminated independently of the range check, causing the data path // to become TOP while the control path is still there (although it's unreachable). - value = new CastIINode(ctrl, value, itype, carry_dependency ? ConstraintCastNode::StrongDependency : ConstraintCastNode::RegularDependency, true /* range check dependency */); + value = new CastIINode(ctrl, value, itype, carry_dependency ? ConstraintCastNode::DependencyType::NonFloatingNarrowing : ConstraintCastNode::DependencyType::FloatingNarrowing, true /* range check dependency */); value = phase->transform(value); } const TypeLong* ltype = TypeLong::make(itype->_lo, itype->_hi, itype->_widen); diff --git a/src/hotspot/share/opto/escape.cpp b/src/hotspot/share/opto/escape.cpp index fb3b5dba42c..b067d93176a 100644 --- a/src/hotspot/share/opto/escape.cpp +++ b/src/hotspot/share/opto/escape.cpp @@ -748,7 +748,7 @@ Node* ConnectionGraph::specialize_castpp(Node* castpp, Node* base, Node* current _igvn->_worklist.push(current_control); _igvn->_worklist.push(control_successor); - return _igvn->transform(ConstraintCastNode::make_cast_for_type(not_eq_control, base, _igvn->type(castpp), ConstraintCastNode::UnconditionalDependency, nullptr)); + return _igvn->transform(ConstraintCastNode::make_cast_for_type(not_eq_control, base, _igvn->type(castpp), ConstraintCastNode::DependencyType::NonFloatingNonNarrowing, nullptr)); } Node* ConnectionGraph::split_castpp_load_through_phi(Node* curr_addp, Node* curr_load, Node* region, GrowableArray* bases_for_loads, GrowableArray &alloc_worklist) { @@ -1235,7 +1235,7 @@ bool ConnectionGraph::reduce_phi_on_safepoints_helper(Node* ophi, Node* cast, No Node* nsr_merge_pointer = ophi; if (cast != nullptr) { const Type* new_t = merge_t->meet(TypePtr::NULL_PTR); - nsr_merge_pointer = _igvn->transform(ConstraintCastNode::make_cast_for_type(cast->in(0), cast->in(1), new_t, ConstraintCastNode::RegularDependency, nullptr)); + nsr_merge_pointer = _igvn->transform(ConstraintCastNode::make_cast_for_type(cast->in(0), cast->in(1), new_t, ConstraintCastNode::DependencyType::FloatingNarrowing, nullptr)); } for (uint spi = 0; spi < safepoints.size(); spi++) { @@ -1376,7 +1376,7 @@ void ConnectionGraph::reset_scalar_replaceable_entries(PhiNode* ophi) { } if (change) { - Node* new_cast = ConstraintCastNode::make_cast_for_type(out->in(0), out->in(1), out_new_t, ConstraintCastNode::StrongDependency, nullptr); + Node* new_cast = ConstraintCastNode::make_cast_for_type(out->in(0), out->in(1), out_new_t, ConstraintCastNode::DependencyType::NonFloatingNarrowing, nullptr); _igvn->replace_node(out, new_cast); _igvn->register_new_node_with_optimizer(new_cast); } diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 113530c8835..2263fa720ce 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -1183,7 +1183,7 @@ bool LibraryCallKit::inline_preconditions_checkIndex(BasicType bt) { jlong upper_bound = _gvn.type(length)->is_integer(bt)->hi_as_long(); Node* casted_length = ConstraintCastNode::make_cast_for_basic_type( control(), length, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), - ConstraintCastNode::RegularDependency, bt); + ConstraintCastNode::DependencyType::FloatingNarrowing, bt); casted_length = _gvn.transform(casted_length); replace_in_map(length, casted_length); length = casted_length; @@ -1213,7 +1213,7 @@ bool LibraryCallKit::inline_preconditions_checkIndex(BasicType bt) { // index is now known to be >= 0 and < length, cast it Node* result = ConstraintCastNode::make_cast_for_basic_type( control(), index, TypeInteger::make(0, upper_bound, Type::WidenMax, bt), - ConstraintCastNode::RegularDependency, bt); + ConstraintCastNode::DependencyType::FloatingNarrowing, bt); result = _gvn.transform(result); set_result(result); replace_in_map(index, result); diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 5c65103677b..41bce0fe9b5 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1366,7 +1366,7 @@ Node *PhaseIdealLoop::clone_up_backedge_goo(Node *back_ctrl, Node *preheader_ctr // the backedge of the main or post loop is removed, a Div node won't be able to float above the zero trip guard of the // loop and can't execute even if the loop is not reached. void PhaseIdealLoop::cast_incr_before_loop(Node* incr, Node* ctrl, CountedLoopNode* loop) { - Node* castii = new CastIINode(ctrl, incr, TypeInt::INT, ConstraintCastNode::UnconditionalDependency); + Node* castii = new CastIINode(ctrl, incr, TypeInt::INT, ConstraintCastNode::DependencyType::NonFloatingNonNarrowing); register_new_node(castii, ctrl); Node* phi = loop->phi(); assert(phi->in(LoopNode::EntryControl) == incr, "replacing wrong input?"); @@ -3262,7 +3262,7 @@ bool IdealLoopTree::do_remove_empty_loop(PhaseIdealLoop *phase) { Node* cast_ii = ConstraintCastNode::make_cast_for_basic_type( cl->in(LoopNode::EntryControl), exact_limit, phase->_igvn.type(exact_limit), - ConstraintCastNode::UnconditionalDependency, T_INT); + ConstraintCastNode::DependencyType::NonFloatingNonNarrowing, T_INT); phase->register_new_node(cast_ii, cl->in(LoopNode::EntryControl)); Node* final_iv = new SubINode(cast_ii, cl->stride()); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 03cc5cbcff6..42d3ee105f8 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -1001,7 +1001,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { // a negative stride). We add a CastII here to guarantee that, when the counted loop is created in a subsequent loop // opts pass, an accurate range of values for the limits is found. const TypeInt* inner_iters_actual_int_range = TypeInt::make(0, iters_limit, Type::WidenMin); - inner_iters_actual_int = new CastIINode(outer_head, inner_iters_actual_int, inner_iters_actual_int_range, ConstraintCastNode::UnconditionalDependency); + inner_iters_actual_int = new CastIINode(outer_head, inner_iters_actual_int, inner_iters_actual_int_range, ConstraintCastNode::DependencyType::NonFloatingNonNarrowing); _igvn.register_new_node_with_optimizer(inner_iters_actual_int); } else { inner_iters_actual_int = inner_iters_actual; @@ -1315,7 +1315,7 @@ bool PhaseIdealLoop::try_make_short_running_loop(IdealLoopTree* loop, jint strid register_new_node(bol, iff->in(0)); new_limit = ConstraintCastNode::make_cast_for_basic_type(new_predicate_proj, new_limit, TypeInteger::make(1, iters_limit_long, Type::WidenMin, bt), - ConstraintCastNode::UnconditionalDependency, bt); + ConstraintCastNode::DependencyType::NonFloatingNonNarrowing, bt); register_new_node(new_limit, new_predicate_proj); #ifndef PRODUCT @@ -1334,7 +1334,7 @@ bool PhaseIdealLoop::try_make_short_running_loop(IdealLoopTree* loop, jint strid const TypeLong* new_limit_t = new_limit->Value(&_igvn)->is_long(); new_limit = ConstraintCastNode::make_cast_for_basic_type(predicates.entry(), new_limit, TypeLong::make(0, new_limit_t->_hi, new_limit_t->_widen), - ConstraintCastNode::UnconditionalDependency, bt); + ConstraintCastNode::DependencyType::NonFloatingNonNarrowing, bt); register_new_node(new_limit, predicates.entry()); } else { assert(bt == T_INT && known_short_running_loop, "only CountedLoop statically known to be short running"); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index ee3f138b8af..b1422d5db20 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1174,7 +1174,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { if ( nn ) return nn; } - if (n->is_ConstraintCast()) { + if (n->is_ConstraintCast() && n->as_ConstraintCast()->dependency().narrows_type()) { Node* dom_cast = n->as_ConstraintCast()->dominating_cast(&_igvn, this); // ConstraintCastNode::dominating_cast() uses node control input to determine domination. // Node control inputs don't necessarily agree with loop control info (due to @@ -1837,7 +1837,7 @@ void PhaseIdealLoop::try_sink_out_of_loop(Node* n) { if (in != nullptr && ctrl_is_member(n_loop, in)) { const Type* in_t = _igvn.type(in); cast = ConstraintCastNode::make_cast_for_type(x_ctrl, in, in_t, - ConstraintCastNode::UnconditionalDependency, nullptr); + ConstraintCastNode::DependencyType::NonFloatingNonNarrowing, nullptr); } if (cast != nullptr) { Node* prev = _igvn.hash_find_insert(cast); diff --git a/src/hotspot/share/opto/macroArrayCopy.cpp b/src/hotspot/share/opto/macroArrayCopy.cpp index 0ba8ed40c37..fb4a1842a36 100644 --- a/src/hotspot/share/opto/macroArrayCopy.cpp +++ b/src/hotspot/share/opto/macroArrayCopy.cpp @@ -233,7 +233,7 @@ void PhaseMacroExpand::generate_partial_inlining_block(Node** ctrl, MergeMemNode Node* inline_block = generate_guard(ctrl, bol_le, nullptr, PROB_FAIR); Node* stub_block = *ctrl; - Node* casted_length = new CastLLNode(inline_block, length, inline_range, ConstraintCastNode::RegularDependency); + Node* casted_length = new CastLLNode(inline_block, length, inline_range, ConstraintCastNode::DependencyType::FloatingNarrowing); transform_later(casted_length); Node* mask_gen = VectorMaskGenNode::make(casted_length, type); transform_later(mask_gen); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java b/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java index 7c5fa05f147..3aee78e9d6a 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestPushAddThruCast.java @@ -44,13 +44,13 @@ public class TestPushAddThruCast { TestFramework.run(); } - final static int length = RANDOM.nextInt(Integer.MAX_VALUE); - final static long llength = RANDOM.nextInt(Integer.MAX_VALUE); + final static int length = RANDOM.nextInt(5, Integer.MAX_VALUE); + final static long llength = RANDOM.nextInt(2, Integer.MAX_VALUE); static int i; static long l; @Test - @IR(counts = { IRNode.CAST_II, "1" }) + @IR(counts = { IRNode.CAST_II, "2" }) public static int test1() { int j = Objects.checkIndex(i, length); int k = Objects.checkIndex(i + 1, length); @@ -67,7 +67,7 @@ public class TestPushAddThruCast { } @Test - @IR(counts = { IRNode.CAST_LL, "1" }) + @IR(counts = { IRNode.CAST_LL, "2" }) public static long test2() { long j = Objects.checkIndex(l, llength); long k = Objects.checkIndex(l + 1, llength); @@ -82,4 +82,25 @@ public class TestPushAddThruCast { throw new RuntimeException("incorrect result: " + res); } } + + // Test commoning of Casts after loop opts when they are at the same control + @Test + @IR(phase = CompilePhase.ITER_GVN1, counts = { IRNode.CAST_II, "4" }) + @IR(phase = CompilePhase.OPTIMIZE_FINISHED, counts = { IRNode.CAST_II, "2" }) + public static int test3() { + int j = Objects.checkIndex(i - 3, length); + j += Objects.checkIndex(i, length); + j += Objects.checkIndex(i - 2, length); + j += Objects.checkIndex(i - 1, length); + return j; + } + + @Run(test = "test3") + public static void test3_runner() { + i = RANDOM.nextInt(3, length - 1); + int res = test3(); + if (res != i * 4 - 6) { + throw new RuntimeException("incorrect result: " + res + " for i = " + i); + } + } } diff --git a/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java b/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java index 87e87842af3..b31c1425728 100644 --- a/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java +++ b/test/hotspot/jtreg/compiler/rangechecks/TestArrayAccessAboveRCAfterRCCastIIEliminated.java @@ -44,7 +44,6 @@ public class TestArrayAccessAboveRCAfterRCCastIIEliminated { private static volatile int volatileField; public static void main(String[] args) { - int[] array = new int[100]; for (int i = 0; i < 20_000; i++) { test1(9, 10, 1, true); test1(9, 10, 1, false); @@ -72,6 +71,13 @@ public class TestArrayAccessAboveRCAfterRCCastIIEliminated { test12(9, 10, 1, false); test13(9, 10, 1, true); test13(9, 10, 1, false); + test14(8, 0, 1, true); + test14(8, 0, 1, false); + inlined14(0, 0); + test15(8, 0, 1, true); + test15(8, 0, 1, false); + inlined15(0, 0); + } try { test1(-1, 10, 1, true); @@ -125,6 +131,14 @@ public class TestArrayAccessAboveRCAfterRCCastIIEliminated { test13(-1, 10, 1, true); } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { } + try { + test14(Integer.MAX_VALUE, 10, 1, true); + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } + try { + test15(Integer.MAX_VALUE, 10, 1, true); + } catch (ArrayIndexOutOfBoundsException arrayIndexOutOfBoundsException) { + } } private static void test1(int i, int j, int flag, boolean flag2) { @@ -468,6 +482,72 @@ public class TestArrayAccessAboveRCAfterRCCastIIEliminated { } } + // Range check cast type widen after loop opts causes control dependency to be lost + private static void test14(int i, int j, int flag, boolean flag2) { + int l = 0; + for (; l < 10; l++); + j = inlined14(j, l); + int[] array = new int[10]; + notInlined(array); + if (flag == 0) { + } + if (flag2) { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } else { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } + } + + private static int inlined14(int j, int l) { + if (l == 10) { + j = 1; + } + return j; + } + + private static void test15(int i, int j, int flag, boolean flag2) { + i = Integer.max(i, Integer.MIN_VALUE + 1); + int l = 0; + for (; l < 10; l++); + j = inlined15(j, l); + int[] array = new int[10]; + notInlined(array); + if (flag == 0) { + } + if (flag2) { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } else { + float[] newArray = new float[10]; + newArray[i+j] = 42; // i+j in [0, 9] + float[] otherArray = new float[i+j]; // i+j in [0, max] + if (flag == 0) { + } + intField = array[otherArray.length]; + } + } + + private static int inlined15(int j, int l) { + if (l == 10) { + j = Integer.max(j, Integer.MIN_VALUE + 10); + } + return j; + } + private static void notInlined(int[] array) { } From b60ac710bebf195972436da324983e61b51484ef Mon Sep 17 00:00:00 2001 From: Anton Seoane Ampudia Date: Wed, 10 Dec 2025 08:53:30 +0000 Subject: [PATCH 042/211] 8364490: Fatal error on large SpecTrapLimitExtraEntries value Reviewed-by: chagedorn, roland --- src/hotspot/share/runtime/globals.hpp | 1 + .../TestSpecTrapLimitExtraEntries.java | 40 +++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/arguments/TestSpecTrapLimitExtraEntries.java diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 68b5d8254fd..b3e9edc0a80 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1369,6 +1369,7 @@ const int ObjectAlignmentInBytes = 8; \ product(int, SpecTrapLimitExtraEntries, 3, EXPERIMENTAL, \ "Extra method data trap entries for speculation") \ + range(0, 100) \ \ product(double, InlineFrequencyRatio, 0.25, DIAGNOSTIC, \ "Ratio of call site execution to caller method invocation") \ diff --git a/test/hotspot/jtreg/compiler/arguments/TestSpecTrapLimitExtraEntries.java b/test/hotspot/jtreg/compiler/arguments/TestSpecTrapLimitExtraEntries.java new file mode 100644 index 00000000000..83fd16ed0d9 --- /dev/null +++ b/test/hotspot/jtreg/compiler/arguments/TestSpecTrapLimitExtraEntries.java @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8364490 + * @summary "Hello world" sanity test for SpecTrapLimitExtraEntries + * + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:SpecTrapLimitExtraEntries=0 compiler.arguments.TestSpecTrapLimitExtraEntries + * @run main/othervm -XX:+UnlockExperimentalVMOptions -XX:SpecTrapLimitExtraEntries=100 compiler.arguments.TestSpecTrapLimitExtraEntries + */ + +package compiler.arguments; + +public class TestSpecTrapLimitExtraEntries { + + public static void main(String[] args) { + System.out.println("Passed"); + } +} From 8eaeb6990b85ac8717f4fc4ce883f674017b91f3 Mon Sep 17 00:00:00 2001 From: David Briemann Date: Wed, 10 Dec 2025 10:21:42 +0000 Subject: [PATCH 043/211] 8372589: VM crashes on init when NonNMethodCodeHeapSize is set too small and UseTransparentHugePages is enabled Reviewed-by: mdoerr, chagedorn --- src/hotspot/share/code/codeCache.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/code/codeCache.cpp b/src/hotspot/share/code/codeCache.cpp index beca3bcbcf5..95a2fb908de 100644 --- a/src/hotspot/share/code/codeCache.cpp +++ b/src/hotspot/share/code/codeCache.cpp @@ -227,11 +227,6 @@ void CodeCache::initialize_heaps() { if (!non_nmethod.set) { non_nmethod.size += compiler_buffer_size; - // Further down, just before FLAG_SET_ERGO(), all segment sizes are - // aligned down to the next lower multiple of min_size. For large page - // sizes, this may result in (non_nmethod.size == 0) which is not acceptable. - // Therefore, force non_nmethod.size to at least min_size. - non_nmethod.size = MAX2(non_nmethod.size, min_size); } if (!profiled.set && !non_profiled.set) { @@ -307,11 +302,10 @@ void CodeCache::initialize_heaps() { // Note: if large page support is enabled, min_size is at least the large // page size. This ensures that the code cache is covered by large pages. - non_profiled.size += non_nmethod.size & alignment_mask(min_size); - non_profiled.size += profiled.size & alignment_mask(min_size); - non_nmethod.size = align_down(non_nmethod.size, min_size); - profiled.size = align_down(profiled.size, min_size); - non_profiled.size = align_down(non_profiled.size, min_size); + non_nmethod.size = align_up(non_nmethod.size, min_size); + profiled.size = align_up(profiled.size, min_size); + non_profiled.size = align_up(non_profiled.size, min_size); + cache_size = non_nmethod.size + profiled.size + non_profiled.size; FLAG_SET_ERGO(NonNMethodCodeHeapSize, non_nmethod.size); FLAG_SET_ERGO(ProfiledCodeHeapSize, profiled.size); From b58e3b600bb14bf7133eda0c37a4be4c82919d79 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 10 Dec 2025 12:08:53 +0000 Subject: [PATCH 044/211] 8373227: Test java/net/httpclient/http2/StreamFlowControlTest.java failed: should sleep time be raised? Reviewed-by: djelinski --- .../http2/StreamFlowControlTest.java | 22 ++++++++++++++----- 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java index 3e4ee4864f5..32f96c7ed4b 100644 --- a/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java +++ b/test/jdk/java/net/httpclient/http2/StreamFlowControlTest.java @@ -82,6 +82,9 @@ public class StreamFlowControlTest { String http2URI; String https2URI; final AtomicInteger reqid = new AtomicInteger(); + final static int WINDOW = + Integer.getInteger("jdk.httpclient.windowsize", 2 * 16 * 1024); + @DataProvider(name = "variants") @@ -147,7 +150,11 @@ public class StreamFlowControlTest { // the window is exceeded... long wait = uri.startsWith("https://") ? 800 : 500; try (InputStream is = response.body()) { - sleep(wait); + byte[] discard = new byte[WINDOW/4]; + for (int j=0; j<2; j++) { + sleep(wait); + if (is.read(discard) < 0) break; + } is.readAllBytes(); } // we could fail here if we haven't waited long enough @@ -205,7 +212,11 @@ public class StreamFlowControlTest { sent.join(); long wait = uri.startsWith("https://") ? 800 : 350; try (InputStream is = response.body()) { - sleep(wait); + byte[] discard = new byte[WINDOW/4]; + for (int j=0; j<2; j++) { + sleep(wait); + if (is.read(discard) < 0) break; + } is.readAllBytes(); } // we could fail here if we haven't waited long enough @@ -316,17 +327,16 @@ public class StreamFlowControlTest { bytes = "no request body!" .repeat(100).getBytes(StandardCharsets.UTF_8); } - int window = Integer.getInteger("jdk.httpclient.windowsize", 2 * 16 * 1024); final int maxChunkSize; if (t instanceof FCHttp2TestExchange fct) { - maxChunkSize = Math.min(window, fct.conn.getMaxFrameSize()); + maxChunkSize = Math.min(WINDOW, fct.conn.getMaxFrameSize()); } else { - maxChunkSize = Math.min(window, SettingsFrame.MAX_FRAME_SIZE); + maxChunkSize = Math.min(WINDOW, SettingsFrame.MAX_FRAME_SIZE); } byte[] resp = bytes.length <= maxChunkSize ? bytes : Arrays.copyOfRange(bytes, 0, maxChunkSize); - int max = (window / resp.length) + 2; + int max = (WINDOW / resp.length) + 2; // send in chunks t.sendResponseHeaders(200, 0); for (int i = 0; i <= max; i++) { From 655e9cda3f6b1fa3a6f0553e7745aa088dde53e8 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 10 Dec 2025 13:08:12 +0000 Subject: [PATCH 045/211] 8373335: Serial: Clean up SerialHeap members by access specifies Reviewed-by: jsikstro --- src/hotspot/share/gc/serial/serialHeap.cpp | 6 ++-- src/hotspot/share/gc/serial/serialHeap.hpp | 39 +++++++++++----------- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/src/hotspot/share/gc/serial/serialHeap.cpp b/src/hotspot/share/gc/serial/serialHeap.cpp index 104924c1cad..08d730bf877 100644 --- a/src/hotspot/share/gc/serial/serialHeap.cpp +++ b/src/hotspot/share/gc/serial/serialHeap.cpp @@ -91,14 +91,16 @@ SerialHeap::SerialHeap() : CollectedHeap(), _young_gen(nullptr), _old_gen(nullptr), + _young_gen_saved_top(nullptr), + _old_gen_saved_top(nullptr), _rem_set(nullptr), _gc_policy_counters(new GCPolicyCounters("Copy:MSC", 2, 2)), _young_manager(nullptr), _old_manager(nullptr), - _is_heap_almost_full(false), _eden_pool(nullptr), _survivor_pool(nullptr), - _old_pool(nullptr) { + _old_pool(nullptr), + _is_heap_almost_full(false) { _young_manager = new GCMemoryManager("Copy"); _old_manager = new GCMemoryManager("MarkSweepCompact"); GCLocker::initialize(); diff --git a/src/hotspot/share/gc/serial/serialHeap.hpp b/src/hotspot/share/gc/serial/serialHeap.hpp index f5286179abf..36916c3f98e 100644 --- a/src/hotspot/share/gc/serial/serialHeap.hpp +++ b/src/hotspot/share/gc/serial/serialHeap.hpp @@ -76,6 +76,8 @@ class SerialHeap : public CollectedHeap { private: DefNewGeneration* _young_gen; TenuredGeneration* _old_gen; + + // Used during young-gc HeapWord* _young_gen_saved_top; HeapWord* _old_gen_saved_top; @@ -94,6 +96,10 @@ private: GCMemoryManager* _young_manager; GCMemoryManager* _old_manager; + MemoryPool* _eden_pool; + MemoryPool* _survivor_pool; + MemoryPool* _old_pool; + // Indicate whether heap is almost or approaching full. // Usually, there is some memory headroom for application/gc to run properly. // However, in extreme cases, e.g. young-gen is non-empty after a full gc, we @@ -113,6 +119,19 @@ private: static void verify_not_in_native_if_java_thread() NOT_DEBUG_RETURN; + // Try to allocate space by expanding the heap. + HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); + + HeapWord* mem_allocate_cas_noexpand(size_t size, bool is_tlab); + HeapWord* mem_allocate_work(size_t size, bool is_tlab); + + void initialize_serviceability() override; + + // Set the saved marks of generations, if that makes sense. + // In particular, if any generation might iterate over the oops + // in other generations, it should call this method. + void save_marks(); + public: // Returns JNI_OK on success jint initialize() override; @@ -211,26 +230,6 @@ public: // generations in a fully generational heap. CardTableRS* rem_set() { return _rem_set; } - public: - // Set the saved marks of generations, if that makes sense. - // In particular, if any generation might iterate over the oops - // in other generations, it should call this method. - void save_marks(); - -private: - // Try to allocate space by expanding the heap. - HeapWord* expand_heap_and_allocate(size_t size, bool is_tlab); - - HeapWord* mem_allocate_cas_noexpand(size_t size, bool is_tlab); - HeapWord* mem_allocate_work(size_t size, bool is_tlab); - - MemoryPool* _eden_pool; - MemoryPool* _survivor_pool; - MemoryPool* _old_pool; - - void initialize_serviceability() override; - -public: static SerialHeap* heap(); SerialHeap(); From 54430a87226096725b13f05326d08629420657ca Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 10 Dec 2025 15:14:46 +0000 Subject: [PATCH 046/211] 8373362: Http3TestServer should not log an exception stack trace when it is stopping normally Reviewed-by: jpai, djelinski --- .../test/lib/http3/Http3ServerExchange.java | 5 +++++ .../test/lib/http3/Http3TestServer.java | 19 ++++++++++++++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerExchange.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerExchange.java index 9a39ba4358d..c127abf3c0f 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerExchange.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3ServerExchange.java @@ -108,6 +108,11 @@ public final class Http3ServerExchange implements Http2TestExchange { rspheadersBuilder = new HttpHeadersBuilder(); } + Http3ServerConnection http3Connection() { + return serverConn; + } + + String connectionTag() { return serverConn.quicConnection().logTag(); } diff --git a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3TestServer.java b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3TestServer.java index ff76c67ed7e..6e81813cac3 100644 --- a/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3TestServer.java +++ b/test/jdk/java/net/httpclient/lib/jdk/httpclient/test/lib/http3/Http3TestServer.java @@ -55,6 +55,7 @@ import jdk.internal.net.http.http3.ConnectionSettings; import jdk.internal.net.http.http3.Http3Error; import jdk.internal.net.http.http3.frames.SettingsFrame; import jdk.internal.net.quic.QuicTLSContext; +import jdk.internal.net.quic.QuicTransportErrors; import jdk.internal.net.quic.QuicVersion; import static java.nio.charset.StandardCharsets.US_ASCII; @@ -261,7 +262,23 @@ public class Http3TestServer implements QuicServer.ConnectionAcceptor, AutoClose handler.handle(exchange); } catch (Throwable failure) { System.err.println("Failed to handle exchange: " + failure); - failure.printStackTrace(); + boolean noError = false; + if (exchange instanceof Http3ServerExchange http3ServerExchange) { + var quicConnection = http3ServerExchange.http3Connection().quicConnection(); + var cause = quicConnection.terminationCause(); + if (cause != null) { + var code = cause.getCloseCode(); + noError = cause.isAppLayer() + ? Http3Error.isNoError(code) + : code == QuicTransportErrors.NO_ERROR.code(); + } + } + // don't print the full stack trace if the connection + // is terminated with no error, in order to avoid + // cluttering the log. + if (!noError) { + failure.printStackTrace(); + } final var ioException = (failure instanceof IOException) ? (IOException) failure : new IOException(failure); From 11aa6e10c017a7257c60eb7395d728d32b2006d4 Mon Sep 17 00:00:00 2001 From: Fairoz Matte Date: Wed, 10 Dec 2025 18:15:32 +0000 Subject: [PATCH 047/211] 8373270: GCC 14.2.0 reports warning: '%s' directive output may be truncated Reviewed-by: kbarrett, dholmes, alanb --- .../unix/native/libjli/java_md_common.c | 25 +------------------ 1 file changed, 1 insertion(+), 24 deletions(-) diff --git a/src/java.base/unix/native/libjli/java_md_common.c b/src/java.base/unix/native/libjli/java_md_common.c index f67a50304d0..45509c7d25d 100644 --- a/src/java.base/unix/native/libjli/java_md_common.c +++ b/src/java.base/unix/native/libjli/java_md_common.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -259,29 +259,6 @@ JLI_ReportExceptionDescription(JNIEnv * env) { (*env)->ExceptionDescribe(env); } -/* - * Since using the file system as a registry is a bit risky, perform - * additional sanity checks on the identified directory to validate - * it as a valid JDK. - * - * Return 0 if the tests fail; otherwise return non-zero (true). - * - * Note that checking for anything more than the existence of an - * executable object at bin/java relative to the path being checked - * will break the regression tests. - */ -static int -CheckSanity(char *path, char *dir) -{ - char buffer[PATH_MAX]; - - if (JLI_StrLen(path) + JLI_StrLen(dir) + 11 > PATH_MAX) - return (0); /* Silently reject "impossibly" long paths */ - - JLI_Snprintf(buffer, sizeof(buffer), "%s/%s/bin/java", path, dir); - return ((access(buffer, X_OK) == 0) ? 1 : 0); -} - /* * "Borrowed" from Solaris 10 where the unsetenv() function is being added * to libc thanks to SUSv3 (Standard Unix Specification, version 3). As From 413f852bdb4767b2a1c29431144616668888138d Mon Sep 17 00:00:00 2001 From: Mat Carter Date: Wed, 10 Dec 2025 18:49:30 +0000 Subject: [PATCH 048/211] 8369736: Add management interface for AOT cache creation Reviewed-by: mr, iklam, kevinw --- src/hotspot/share/cds/aotMetaspace.cpp | 1 + src/hotspot/share/include/jvm.h | 3 + src/hotspot/share/prims/jvm.cpp | 13 ++ .../classes/sun/management/VMManagement.java | 5 +- .../sun/management/VMManagementImpl.java | 5 +- .../native/libmanagement/VMManagementImpl.c | 7 ++ .../internal/HotSpotAOTCacheImpl.java | 55 ++++++++ .../internal/PlatformMBeanProviderImpl.java | 38 +++++- .../jdk/management/HotSpotAOTCacheMXBean.java | 93 ++++++++++++++ .../aotCache/HotSpotAOTCacheMXBeanTest.java | 118 ++++++++++++++++++ 10 files changed, 335 insertions(+), 3 deletions(-) create mode 100644 src/jdk.management/share/classes/com/sun/management/internal/HotSpotAOTCacheImpl.java create mode 100644 src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/HotSpotAOTCacheMXBeanTest.java diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index f56050d4d31..3c87e3ef797 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -96,6 +96,7 @@ #include "runtime/vmOperations.hpp" #include "runtime/vmThread.hpp" #include "sanitizers/leak.hpp" +#include "services/management.hpp" #include "utilities/align.hpp" #include "utilities/bitMap.inline.hpp" #include "utilities/defaultStream.hpp" diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index dccdcacef71..7236679d8f3 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -87,6 +87,9 @@ JVM_InternString(JNIEnv *env, jstring str); /* * java.lang.System */ +JNIEXPORT jboolean JNICALL +JVM_AOTEndRecording(JNIEnv *env); + JNIEXPORT jlong JNICALL JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored); diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 16d9efde410..48d89235c98 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -229,6 +229,19 @@ extern void trace_class_resolution(Klass* to_class) { // java.lang.System ////////////////////////////////////////////////////////////////////// +JVM_ENTRY(jboolean, JVM_AOTEndRecording(JNIEnv *env)) +#if INCLUDE_CDS + if (CDSConfig::is_dumping_preimage_static_archive()) { + if (!AOTMetaspace::preimage_static_archive_dumped()) { + AOTMetaspace::dump_static_archive(THREAD); + return JNI_TRUE; + } + } + return JNI_FALSE; +#else + return JNI_FALSE; +#endif // INCLUDE_CDS +JVM_END JVM_LEAF(jlong, JVM_CurrentTimeMillis(JNIEnv *env, jclass ignored)) return os::javaTimeMillis(); diff --git a/src/java.management/share/classes/sun/management/VMManagement.java b/src/java.management/share/classes/sun/management/VMManagement.java index 3e227225ccd..29391cf53ba 100644 --- a/src/java.management/share/classes/sun/management/VMManagement.java +++ b/src/java.management/share/classes/sun/management/VMManagement.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -48,6 +48,9 @@ public interface VMManagement { public boolean isGcNotificationSupported(); public boolean isRemoteDiagnosticCommandsSupported(); + // AOT Subsystem + public boolean endAOTRecording(); + // Class Loading Subsystem public long getTotalClassCount(); public int getLoadedClassCount(); diff --git a/src/java.management/share/classes/sun/management/VMManagementImpl.java b/src/java.management/share/classes/sun/management/VMManagementImpl.java index b8c7a2921d4..0fd0d8ad562 100644 --- a/src/java.management/share/classes/sun/management/VMManagementImpl.java +++ b/src/java.management/share/classes/sun/management/VMManagementImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -117,6 +117,9 @@ class VMManagementImpl implements VMManagement { public native boolean isThreadCpuTimeEnabled(); public native boolean isThreadAllocatedMemoryEnabled(); + // AOT Subsystem + public native boolean endAOTRecording(); + // Class Loading Subsystem public int getLoadedClassCount() { long count = getTotalClassCount() - getUnloadedClassCount(); diff --git a/src/java.management/share/native/libmanagement/VMManagementImpl.c b/src/java.management/share/native/libmanagement/VMManagementImpl.c index d5141c71ee7..e6570d06bdd 100644 --- a/src/java.management/share/native/libmanagement/VMManagementImpl.c +++ b/src/java.management/share/native/libmanagement/VMManagementImpl.c @@ -101,6 +101,13 @@ Java_sun_management_VMManagementImpl_getVmArguments0 return JVM_GetVmArguments(env); } +JNIEXPORT jboolean JNICALL +Java_sun_management_VMManagementImpl_endAOTRecording + (JNIEnv *env, jobject dummy) +{ + return JVM_AOTEndRecording(env); +} + JNIEXPORT jlong JNICALL Java_sun_management_VMManagementImpl_getTotalClassCount (JNIEnv *env, jobject dummy) diff --git a/src/jdk.management/share/classes/com/sun/management/internal/HotSpotAOTCacheImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/HotSpotAOTCacheImpl.java new file mode 100644 index 00000000000..4bb556455ea --- /dev/null +++ b/src/jdk.management/share/classes/com/sun/management/internal/HotSpotAOTCacheImpl.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2025, Microsoft, Inc. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 com.sun.management.internal; + +import javax.management.ObjectName; +import jdk.management.HotSpotAOTCacheMXBean; +import sun.management.Util; +import sun.management.VMManagement; + +/** + * Implementation class for the AOT Cache subsystem. + * + * ManagementFactory.getRuntimeMXBean() returns an instance + * of this class. + */ +public class HotSpotAOTCacheImpl implements HotSpotAOTCacheMXBean { + + private final VMManagement jvm; + /** + * Constructor of HotSpotAOTCacheImpl class. + */ + HotSpotAOTCacheImpl(VMManagement vm) { + this.jvm = vm; + } + + public boolean endRecording() { + return jvm.endAOTRecording(); + } + + public ObjectName getObjectName() { + return Util.newObjectName("jdk.management:type=HotSpotAOTCache"); + } +} \ No newline at end of file diff --git a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java index 3a64fe6b858..b000516e626 100644 --- a/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java +++ b/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,6 +39,7 @@ import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; import javax.management.DynamicMBean; +import jdk.management.HotSpotAOTCacheMXBean; import jdk.management.VirtualThreadSchedulerMXBean; import sun.management.ManagementFactoryHelper; import sun.management.spi.PlatformMBeanProvider; @@ -159,6 +160,41 @@ public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { } }); + /** + * HotSpotAOTCacheMXBean. + */ + initMBeanList.add(new PlatformComponent() { + private final Set> mbeanInterfaces = + Set.of(HotSpotAOTCacheMXBean.class); + private final Set mbeanInterfaceNames = + Set.of(HotSpotAOTCacheMXBean.class.getName()); + private HotSpotAOTCacheMXBean impl; + + @Override + public Set> mbeanInterfaces() { + return mbeanInterfaces; + } + + @Override + public Set mbeanInterfaceNames() { + return mbeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return "jdk.management:type=HotSpotAOTCache"; + } + + @Override + public Map nameToMBeanMap() { + HotSpotAOTCacheMXBean impl = this.impl; + if (impl == null) { + this.impl = impl = new HotSpotAOTCacheImpl(ManagementFactoryHelper.getVMManagement()); + } + return Map.of("jdk.management:type=HotSpotAOTCache", impl); + } + }); + /** * VirtualThreadSchedulerMXBean. */ diff --git a/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java b/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java new file mode 100644 index 00000000000..2dc02f2bd73 --- /dev/null +++ b/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2025, Microsoft, Inc. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 jdk.management; + +import java.lang.management.ManagementFactory; +import java.lang.management.PlatformManagedObject; +import javax.management.MBeanServer; +import javax.management.ObjectName; + +/** + * Management interface for the JDK's Ahead of Time (AOT) Cache. + * + *

The management interface is registered with the platform {@link MBeanServer + * MBeanServer}. The {@link ObjectName ObjectName} that uniquely identifies the management + * interface within the {@code MBeanServer} is {@code jdk.management:type=HotSpotAOTCache}. + * + *

Direct access to the MXBean interface can be obtained with + * {@link ManagementFactory#getPlatformMXBean(Class)}. + * + * @since 26 + */ +public interface HotSpotAOTCacheMXBean extends PlatformManagedObject { + /** + * If an AOT recording is in progress, ends the recording. This method returns + * after the AOT artifacts have been completely written. + * + *

The JVM will start recording AOT artifacts upon start-up if appropriate JVM options are + * given in the command-line. The recording will stop when the JVM exits, or when + * the {@code endRecording} method is called. Examples: + * + *

${@code java -XX:AOTCacheOutput=app.aot ....} + * + *

+ * The JVM records optimization information for the current application in the AOT cache file + * {@code app.aot}. In a future run of the application, the option {@code -XX:AOTCache=app.aot} will + * cause the JVM to use the cache to improve the application's startup and warmup performance. + *
+ * + *

${@code java -XX:AOTMode=record -XX:AOTConfiguration=app.aotconfig ....} + * + *

+ * The JVM records optimization information for the current application in the AOT configuration + * file {@code app.aotconfig}. Subsequently, an AOT cache file can be created with the command: + * + *

${@code java -XX:AOTMode=create -XX:AOTConfiguration=app.aotconfig -XX:AOTCache=app.aot ...} + *

+ * + *

For more information about creating and using the AOT artifacts, and detailed + * specification of the corresponding JVM command-line options, please refer + * to JEP 483 and JEP 514. + * + *

Currently there are no APIs to start an AOT recording. AOT recordings must be + * started using JVM command-line options such as {@code -XX:AOTCacheOutput}. + * There are also no APIs to query whether an AOT recording is in progress, or what AOT + * artifacts are being recorded. + * + *

This method enables an application to end its own AOT recording + * programatically, but that is not necessarily the best approach. Doing so + * requires changing the application’s code, which might not be + * feasible. Even when it is feasible, injecting training-specific logic + * into the application reduces the similarity between training runs and + * production runs, potentially making the AOT cache less effective. It may + * be better to arrange for an external agent to end the training run, + * thereby creating an AOT cache without interfering with the application’s + * code. + * + * @return {@code true} if a recording was in progress and has been ended + * successfully; {@code false} otherwise. + */ + public boolean endRecording(); +} \ No newline at end of file diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HotSpotAOTCacheMXBeanTest.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HotSpotAOTCacheMXBeanTest.java new file mode 100644 index 00000000000..fba3589f5ce --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HotSpotAOTCacheMXBeanTest.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2025, Microsoft, Inc. 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 + * @summary Sanity test for HotSpotAOTCache MXBean + * @requires vm.cds.write.archived.java.heap + * @library /test/jdk/lib/testlibrary /test/lib + * @build HotSpotAOTCacheMXBeanTest + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar HotSpotAOTCacheMXBeanApp + * @run driver HotSpotAOTCacheMXBeanTest + */ + +import java.io.IOException; +import java.lang.management.ManagementFactory; +import javax.management.MBeanServer; +import jdk.management.HotSpotAOTCacheMXBean; +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.helpers.ClassFileInstaller; +import jdk.test.lib.process.OutputAnalyzer; + +public class HotSpotAOTCacheMXBeanTest { + static final String appJar = ClassFileInstaller.getJarPath("app.jar"); + static final String mainClass = "HotSpotAOTCacheMXBeanApp"; + public static void main(String[] args) throws Exception { + Tester tester = new Tester(); + tester.runAOTWorkflow(); + } + + static class Tester extends CDSAppTester { + public Tester() { + super(mainClass); + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] vmArgs(RunMode runMode) { + return new String[] { + "-Xlog:cds+class=trace", + "--add-modules=jdk.management" + }; + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] { + mainClass, runMode.name() + }; + } + + @Override + public void checkExecution(OutputAnalyzer out, RunMode runMode) { + var name = runMode.name(); + if (runMode.isApplicationExecuted()) { + if(runMode == RunMode.TRAINING) { + out.shouldContain("Hello Leyden " + name); + out.shouldContain("Successfully stopped recording"); + } else if (runMode == RunMode.ASSEMBLY) { + out.shouldNotContain("Hello Leyden "); + } else if (runMode == RunMode.PRODUCTION) { + out.shouldContain("Hello Leyden " + name); + out.shouldContain("Failed to stop recording"); + } + out.shouldNotContain("HotSpotAOTCacheMXBean is not available"); + out.shouldNotContain("IOException occurred!"); + } + } + } +} + +class HotSpotAOTCacheMXBeanApp { + public static void main(String[] args) { + System.out.println("Hello Leyden " + args[0]); + try { + MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + HotSpotAOTCacheMXBean aotBean = ManagementFactory.newPlatformMXBeanProxy(server, + "jdk.management:type=HotSpotAOTCache", + HotSpotAOTCacheMXBean.class); + if (aotBean == null) { + System.out.println("HotSpotAOTCacheMXBean is not available"); + return; + } + if (aotBean.endRecording()) { + System.out.println("Successfully stopped recording"); + } else { + System.out.println("Failed to stop recording"); + } + } catch (IOException e) { + System.out.println("IOException occurred!"); + } + } +} \ No newline at end of file From 52aa7fe1c970709fe387b70a5020ea0e77c4047f Mon Sep 17 00:00:00 2001 From: Phil Race Date: Wed, 10 Dec 2025 21:40:18 +0000 Subject: [PATCH 049/211] 8334549: [Sound] Test timed out: javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java Reviewed-by: aivanov, kizune --- .../sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java b/test/jdk/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java index b3198b8ab77..30f38f55acb 100644 --- a/test/jdk/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java +++ b/test/jdk/javax/sound/sampled/Clip/OpenNonIntegralNumberOfSampleframes.java @@ -32,6 +32,7 @@ import javax.sound.sampled.LineUnavailableException; /** * @test + * @key sound * @bug 8167435 */ public final class OpenNonIntegralNumberOfSampleframes { From 74dca863c2e61c13884c3454b8da7be125235970 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 10 Dec 2025 22:46:35 +0000 Subject: [PATCH 050/211] 8371718: (sc) Channels.new{Input,Output}Stream can allocate unbounded memory for a socket channel Reviewed-by: alanb --- .../sun/nio/ch/ChannelInputStream.java | 3 +- .../sun/nio/ch/ChannelOutputStream.java | 11 +++- .../classes/sun/nio/ch/NioSocketImpl.java | 12 ++-- .../classes/sun/nio/ch/SocketChannelImpl.java | 3 +- .../share/classes/sun/nio/ch/Streams.java | 6 +- .../Channels/SocketChannelStreams.java | 64 ++++++++++++++++++- 6 files changed, 83 insertions(+), 16 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java index 14b2058d28d..09f6d7b1d75 100644 --- a/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java +++ b/src/java.base/share/classes/sun/nio/ch/ChannelInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -109,6 +109,7 @@ class ChannelInputStream extends InputStream { if (len == 0) return 0; + len = Math.min(len, Streams.MAX_BUFFER_SIZE); ByteBuffer bb = ((this.bs == bs) ? this.bb : ByteBuffer.wrap(bs)); diff --git a/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java b/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java index dff8af9ebaf..b7207c9fd4b 100644 --- a/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java +++ b/src/java.base/share/classes/sun/nio/ch/ChannelOutputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -64,10 +64,15 @@ class ChannelOutputStream extends OutputStream { * If the channel is selectable then it must be configured blocking. */ private void writeFully(ByteBuffer bb) throws IOException { - while (bb.remaining() > 0) { + int pos = bb.position(); + int rem = bb.limit() - pos; + while (rem > 0) { + bb.limit(pos + Math.min(Streams.MAX_BUFFER_SIZE, rem)); int n = ch.write(bb); if (n <= 0) - throw new RuntimeException("no bytes written"); + throw new IOException("Write failed"); + pos += n; + rem -= n; } } diff --git a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java index 57935ff5b00..01f894be227 100644 --- a/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/NioSocketImpl.java @@ -78,10 +78,6 @@ import static jdk.internal.util.Exceptions.formatMsg; public final class NioSocketImpl extends SocketImpl implements PlatformSocketImpl { private static final NativeDispatcher nd = new SocketDispatcher(); - // The maximum number of bytes to read/write per syscall to avoid needing - // a huge buffer from the temporary buffer cache - private static final int MAX_BUFFER_SIZE = 128 * 1024; - // true if this is a SocketImpl for a ServerSocket private final boolean server; @@ -355,8 +351,8 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp // emulate legacy behavior to return -1, even if socket is closed if (readEOF) return -1; - // read up to MAX_BUFFER_SIZE bytes - int size = Math.min(len, MAX_BUFFER_SIZE); + // read up to Streams.MAX_BUFFER_SIZE bytes + int size = Math.min(len, Streams.MAX_BUFFER_SIZE); int n = implRead(b, off, size, remainingNanos); if (n == -1) readEOF = true; @@ -453,8 +449,8 @@ public final class NioSocketImpl extends SocketImpl implements PlatformSocketImp int pos = off; int end = off + len; while (pos < end) { - // write up to MAX_BUFFER_SIZE bytes - int size = Math.min((end - pos), MAX_BUFFER_SIZE); + // write up to Streams.MAX_BUFFER_SIZE bytes + int size = Math.min((end - pos), Streams.MAX_BUFFER_SIZE); int n = implWrite(b, pos, size); pos += n; } diff --git a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java index 6f3e8b443dc..868ed3b64bc 100644 --- a/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/SocketChannelImpl.java @@ -1373,6 +1373,7 @@ class SocketChannelImpl // nothing to do return 0; } + len = Math.min(len, Streams.MAX_BUFFER_SIZE); readLock.lock(); try { @@ -1469,7 +1470,7 @@ class SocketChannelImpl beginWrite(true); configureSocketNonBlockingIfVirtualThread(); while (pos < end && isOpen()) { - int size = end - pos; + int size = Math.min(end - pos, Streams.MAX_BUFFER_SIZE); int n = tryWrite(b, pos, size); while (IOStatus.okayToRetry(n) && isOpen()) { park(Net.POLLOUT); diff --git a/src/java.base/share/classes/sun/nio/ch/Streams.java b/src/java.base/share/classes/sun/nio/ch/Streams.java index 4326c9e2e0b..847fa8333e8 100644 --- a/src/java.base/share/classes/sun/nio/ch/Streams.java +++ b/src/java.base/share/classes/sun/nio/ch/Streams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -33,6 +33,10 @@ import java.nio.channels.WritableByteChannel; * Factory methods for input/output streams based on channels. */ public class Streams { + // The maximum number of bytes to read/write per syscall to avoid needing + // a huge buffer from the temporary buffer cache + static final int MAX_BUFFER_SIZE = 128 * 1024; + private Streams() { } /** diff --git a/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java index 72c07392d7c..519de1e725f 100644 --- a/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java +++ b/test/jdk/java/nio/channels/Channels/SocketChannelStreams.java @@ -22,10 +22,10 @@ */ /* @test - * @bug 8279339 - * @run testng SocketChannelStreams + * @bug 8279339 8371718 * @summary Exercise InputStream/OutputStream returned by Channels.newXXXStream * when channel is a SocketChannel + * @run testng SocketChannelStreams */ import java.io.Closeable; @@ -35,6 +35,8 @@ import java.io.OutputStream; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; +import java.nio.ByteBuffer; +import java.nio.channels.ByteChannel; import java.nio.channels.Channels; import java.nio.channels.IllegalBlockingModeException; import java.nio.channels.ServerSocketChannel; @@ -51,6 +53,9 @@ import static org.testng.Assert.*; @Test public class SocketChannelStreams { + // Maximum size of internal temporary buffer + private static final int MAX_BUFFER_SIZE = 128*1024; + private ScheduledExecutorService executor; @BeforeClass() @@ -379,6 +384,25 @@ public class SocketChannelStreams { }); } + /** + * Test that internal buffers have at most MAX_BUFFER_SIZE bytes remaining. + */ + public void testReadLimit() throws IOException { + InputStream in = Channels.newInputStream(new TestChannel()); + byte[] b = new byte[3*MAX_BUFFER_SIZE]; + int n = in.read(b, 0, b.length); + assertEquals(n, MAX_BUFFER_SIZE); + } + + /** + * Test that internal buffers have at most MAX_BUFFER_SIZE bytes remaining. + */ + public void testWriteLimit() throws IOException { + OutputStream out = Channels.newOutputStream(new TestChannel()); + byte[] b = new byte[3*MAX_BUFFER_SIZE]; + out.write(b, 0, b.length); + } + // -- test infrastructure -- private interface ThrowingTask { @@ -477,4 +501,40 @@ public class SocketChannelStreams { private Future schedule(Runnable task, long delay) { return executor.schedule(task, delay, TimeUnit.MILLISECONDS); } + + /** + * ByteChannel that throws if more than 128k bytes remain + * in the buffer supplied for reading or writing. + */ + private static class TestChannel implements ByteChannel { + @Override + public int read(ByteBuffer bb) throws IOException { + int rem = bb.remaining(); + if (rem > MAX_BUFFER_SIZE) { + throw new IOException("too big"); + } + bb.position(bb.limit()); + return rem; + } + + @Override + public int write(ByteBuffer bb) throws IOException { + int rem = bb.remaining(); + if (rem > MAX_BUFFER_SIZE) { + throw new IOException("too big"); + } + bb.position(bb.limit()); + return rem; + } + + @Override + public boolean isOpen() { + return true; + } + + @Override + public void close() { + throw new UnsupportedOperationException(); + } + } } From 920a99faeb6e0aee445df39cf8ddd43df18345d6 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 11 Dec 2025 07:44:10 +0000 Subject: [PATCH 051/211] 8370731: Tests in vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/ failed: OutOfMemoryError Reviewed-by: sspitsyn --- .../CollectionCounters001.java | 53 +++++++++---------- .../TestDescription.java | 5 +- .../TestDescription.java | 5 +- .../TestDescription.java | 5 +- .../TestDescription.java | 5 +- 5 files changed, 38 insertions(+), 35 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters001/CollectionCounters001.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters001/CollectionCounters001.java index f256a5649e5..aac6ab88246 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters001/CollectionCounters001.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters001/CollectionCounters001.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2025, 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 @@ -29,9 +29,10 @@ * @summary converted from VM Testbase nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters001. * VM Testbase keywords: [monitoring] * + * @requires vm.opt.DisableExplicitGC != "true" * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm -XX:-UseGCOverheadLimit * nsk.monitoring.GarbageCollectorMXBean.CollectionCounters.CollectionCounters001.CollectionCounters001 * -testMode=directly */ @@ -60,6 +61,7 @@ import nsk.share.runner.RunParamsAware; * time. It may be false with -XX:+DisableExplicitGC. */ public class CollectionCounters001 extends MonitoringTestBase implements RunParamsAware, Initializable { + private List gcBeans; private MemoryMXBean memory; Stresser stresser; @@ -76,18 +78,21 @@ public class CollectionCounters001 extends MonitoringTestBase implements RunPara private void runOne(ExecutionController stresser) { updateCounters(); - validate(); - Algorithms.eatMemory(stresser); - if(stresser.continueExecution()) { + validate(false /* don't check gc count increases */); + int iteration = 0; + do { + System.out.println("=========== stresser iter: " + (stresser.getIteration()) + + " runOne iter: " + (++iteration) + " ==========="); + Algorithms.eatMemory(stresser); updateCounters(); - validateNonTrivial(); + validate(true); System.gc(); updateCounters(); - validateNonTrivial(); + validate(true); memory.gc(); updateCounters(); - validateNonTrivial(); - } + validate(true); + } while (stresser.continueExecution()); } public void run() { @@ -98,26 +103,20 @@ public class CollectionCounters001 extends MonitoringTestBase implements RunPara } } - private void validate() { + private void validate(boolean gcCountMustIncrease) { if (collectionCount < 0) - throw new TestFailure("collectionCount negative: " + collectionCount); + throw new TestFailure("collectionCount negative: " + collectionCount); if (collectionTime < 0) - throw new TestFailure("collectionTime negative: " + collectionTime); - if (collectionCount < collectionCountOld) + throw new TestFailure("collectionTime negative: " + collectionTime); + if (collectionTime < collectionTimeOld) + throw new TestFailure("collectionTime decreased: " + collectionTime + " -> " + collectionTimeOld); + if (!gcCountMustIncrease) { + if (collectionCount < collectionCountOld) throw new TestFailure("collectionCount decreased: " + collectionCount + " -> " + collectionCountOld); - if (collectionTime < collectionTimeOld) - throw new TestFailure("collectionTime decreased: " + collectionTime + " -> " + collectionTimeOld); - } - - private void validateNonTrivial() { - if (collectionCount < 0) - throw new TestFailure("collectionCount negative: " + collectionCount); - if (collectionTime < 0) - throw new TestFailure("collectionTime negative: " + collectionTime); - if (collectionCount <= collectionCountOld) + } else { + if (collectionCount <= collectionCountOld) throw new TestFailure("collectionCount not increased: " + collectionCount + " -> " + collectionCountOld); - if (collectionTime < collectionTimeOld) - throw new TestFailure("collection time became smaller: " + collectionTime + " -> " + collectionTimeOld); + } } private void updateCounters() { @@ -126,8 +125,8 @@ public class CollectionCounters001 extends MonitoringTestBase implements RunPara collectionCount = 0; collectionTime = 0; for (GarbageCollectorMXBean gcBean : gcBeans) { - collectionCount += gcBean.getCollectionCount(); - collectionTime += gcBean.getCollectionTime(); + collectionCount += gcBean.getCollectionCount(); + collectionTime += gcBean.getCollectionTime(); } } diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters002/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters002/TestDescription.java index 9bfbf141d31..c331991cd68 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters002/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters002/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -29,9 +29,10 @@ * @summary converted from VM Testbase nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters002. * VM Testbase keywords: [monitoring] * + * @requires vm.opt.DisableExplicitGC != "true" * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm -XX:-UseGCOverheadLimit * nsk.monitoring.GarbageCollectorMXBean.CollectionCounters.CollectionCounters001.CollectionCounters001 * -testMode=server * -MBeanServer=default diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters003/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters003/TestDescription.java index 3524cfd66db..024c8d363a5 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters003/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters003/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -29,9 +29,10 @@ * @summary converted from VM Testbase nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters003. * VM Testbase keywords: [monitoring] * + * @requires vm.opt.DisableExplicitGC != "true" * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm -XX:-UseGCOverheadLimit * nsk.monitoring.GarbageCollectorMXBean.CollectionCounters.CollectionCounters001.CollectionCounters001 * -testMode=server * -MBeanServer=custom diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters004/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters004/TestDescription.java index b215e633464..09cde45ac4f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters004/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters004/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -29,9 +29,10 @@ * @summary converted from VM Testbase nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters004. * VM Testbase keywords: [monitoring] * + * @requires vm.opt.DisableExplicitGC != "true" * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm -XX:-UseGCOverheadLimit * nsk.monitoring.GarbageCollectorMXBean.CollectionCounters.CollectionCounters001.CollectionCounters001 * -testMode=proxy * -MBeanServer=default diff --git a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters005/TestDescription.java b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters005/TestDescription.java index 63cccf1c268..f70f680498b 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters005/TestDescription.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters005/TestDescription.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -29,9 +29,10 @@ * @summary converted from VM Testbase nsk/monitoring/GarbageCollectorMXBean/CollectionCounters/CollectionCounters005. * VM Testbase keywords: [monitoring] * + * @requires vm.opt.DisableExplicitGC != "true" * @library /vmTestbase * /test/lib - * @run main/othervm + * @run main/othervm -XX:-UseGCOverheadLimit * nsk.monitoring.GarbageCollectorMXBean.CollectionCounters.CollectionCounters001.CollectionCounters001 * -testMode=proxy * -MBeanServer=custom From b46aef88b333db8866c60c18cbf842b6cb89dacf Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 11 Dec 2025 08:17:25 +0000 Subject: [PATCH 052/211] 8371871: libSharedCloseAgent.cpp crashes VS2019 and older VS2022 compiler Reviewed-by: jvernee, mdoerr --- test/jdk/java/foreign/sharedclosejvmti/libSharedCloseAgent.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/foreign/sharedclosejvmti/libSharedCloseAgent.cpp b/test/jdk/java/foreign/sharedclosejvmti/libSharedCloseAgent.cpp index a82818e0280..3e7fc2e10da 100644 --- a/test/jdk/java/foreign/sharedclosejvmti/libSharedCloseAgent.cpp +++ b/test/jdk/java/foreign/sharedclosejvmti/libSharedCloseAgent.cpp @@ -102,7 +102,8 @@ Agent_OnLoad(JavaVM *vm, char *options, void *reserved) { return jni_err; } - jvmtiCapabilities capabilities{}; + jvmtiCapabilities capabilities; + memset(&capabilities, 0, sizeof(jvmtiCapabilities)); capabilities.can_generate_method_exit_events = 1; jvmtiError err = env->AddCapabilities(&capabilities); From 4b774cb46d9355015a6bfcf53b47233d6f235239 Mon Sep 17 00:00:00 2001 From: Saranya Natarajan Date: Thu, 11 Dec 2025 08:43:31 +0000 Subject: [PATCH 053/211] 8370489: Some compiler tests miss the @key randomness Reviewed-by: dfenacci, epeter, chagedorn --- .../jtreg/compiler/c2/TestMergeStores.java | 3 ++ .../c2/TestMergeStoresMemorySegment.java | 12 ++++++- .../jtreg/compiler/c2/TestMinMaxSubword.java | 1 + .../c2/aarch64/TestFloat16Replicate.java | 1 + .../compiler/c2/irTests/ModDNodeTests.java | 1 + .../compiler/c2/irTests/ModFNodeTests.java | 1 + .../c2/irTests/ModINodeIdealizationTests.java | 1 + .../c2/irTests/ModLNodeIdealizationTests.java | 1 + .../c2/irTests/TestMulNodeIdealization.java | 3 +- .../compiler/c2/irTests/TestShiftAndMask.java | 1 + .../irTests/UDivINodeIdealizationTests.java | 3 +- .../irTests/UDivLNodeIdealizationTests.java | 3 +- .../irTests/UModINodeIdealizationTests.java | 3 +- .../irTests/UModLNodeIdealizationTests.java | 3 +- .../TestDivDependentOnMainLoopGuard.java | 1 + .../jtreg/compiler/igvn/ExpressionFuzzer.java | 1 + .../TestFloat16MaxMinSpecialValues.java | 1 + .../InvariantCodeMotionReassociateAddSub.java | 1 + .../InvariantCodeMotionReassociateCmp.java | 1 + .../TestParallelIvInIntCountedLoop.java | 1 + .../loopopts/superword/MinMaxRed_Int.java | 1 + .../loopopts/superword/ReductionPerf.java | 3 +- .../loopopts/superword/TestAliasing.java | 1 + .../loopopts/superword/TestAlignVector.java | 1 + .../TestCompatibleUseDefTypeSize.java | 3 +- .../superword/TestDependencyOffsets.java | 33 +++++++++++++++++++ .../superword/TestEquivalentInvariants.java | 1 + .../loopopts/superword/TestMemorySegment.java | 1 + .../TestMemorySegmentUnalignedAddress.java | 1 + .../loopopts/superword/TestSplitPacks.java | 1 + .../jtreg/compiler/vectorapi/Test8278948.java | 3 +- .../vectorapi/TestVectorAddMulReduction.java | 1 + .../TestVectorCompressExpandBits.java | 1 + .../vectorapi/VectorMaskCastIdentityTest.java | 1 + .../compiler/vectorapi/VectorMultiplyOpt.java | 3 +- .../VectorSaturatedOperationsTest.java | 1 + .../vectorization/TestAutoVecIntMinMax.java | 1 + .../vectorization/TestEor3AArch64.java | 1 + .../vectorization/TestMacroLogicVector.java | 3 +- .../vectorization/TestVectorZeroCount.java | 12 +++---- 40 files changed, 99 insertions(+), 17 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java index 84329c4a9c8..5e6a757dd5f 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStores.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStores.java @@ -34,6 +34,7 @@ import java.util.Random; /* * @test * @bug 8318446 8331054 8331311 8335392 8347405 + * @key randomness * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -43,6 +44,7 @@ import java.util.Random; /* * @test * @bug 8318446 8331054 8331311 8335392 8347405 + * @key randomness * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / @@ -52,6 +54,7 @@ import java.util.Random; /* * @test * @bug 8318446 8331054 8331311 8335392 8348959 8351414 + * @key randomness * @summary Test merging of consecutive stores * @modules java.base/jdk.internal.misc * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java b/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java index a5302d1b515..a275570747b 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java +++ b/test/hotspot/jtreg/compiler/c2/TestMergeStoresMemorySegment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,6 +34,7 @@ import java.lang.foreign.*; /* * @test id=byte-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment ByteArray @@ -42,6 +43,7 @@ import java.lang.foreign.*; /* * @test id=char-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment CharArray @@ -50,6 +52,7 @@ import java.lang.foreign.*; /* * @test id=short-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment ShortArray @@ -58,6 +61,7 @@ import java.lang.foreign.*; /* * @test id=int-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment IntArray @@ -66,6 +70,7 @@ import java.lang.foreign.*; /* * @test id=long-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment LongArray @@ -74,6 +79,7 @@ import java.lang.foreign.*; /* * @test id=float-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment FloatArray @@ -82,6 +88,7 @@ import java.lang.foreign.*; /* * @test id=double-array * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment DoubleArray @@ -90,6 +97,7 @@ import java.lang.foreign.*; /* * @test id=byte-buffer * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment ByteBuffer @@ -98,6 +106,7 @@ import java.lang.foreign.*; /* * @test id=byte-buffer-direct * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment ByteBufferDirect @@ -106,6 +115,7 @@ import java.lang.foreign.*; /* * @test id=native * @bug 8335392 + * @key randomness * @summary Test MergeStores optimization for MemorySegment * @library /test/lib / * @run driver compiler.c2.TestMergeStoresMemorySegment Native diff --git a/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java b/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java index 955aa4058f0..a7e90353f90 100644 --- a/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java +++ b/test/hotspot/jtreg/compiler/c2/TestMinMaxSubword.java @@ -31,6 +31,7 @@ import java.util.Random; /* * @test * @bug 8294816 + * @key randomness * @summary Test Math.min/max vectorization miscompilation for integer subwords * @library /test/lib / * @requires vm.compiler2.enabled diff --git a/test/hotspot/jtreg/compiler/c2/aarch64/TestFloat16Replicate.java b/test/hotspot/jtreg/compiler/c2/aarch64/TestFloat16Replicate.java index ab7808a0401..6be4286d2a0 100644 --- a/test/hotspot/jtreg/compiler/c2/aarch64/TestFloat16Replicate.java +++ b/test/hotspot/jtreg/compiler/c2/aarch64/TestFloat16Replicate.java @@ -23,6 +23,7 @@ /** * @test * @bug 8361582 +* @key randomness * @summary Ensure the correct backend replicate node is being generated for * half precision float constants on >16B SVE machines * @modules jdk.incubator.vector diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java index 3c28c936d31..7eed798871e 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java @@ -30,6 +30,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8345766 + * @key randomness * @summary Test that Ideal transformations of ModDNode are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.ModDNodeTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java index 1b5e14b4835..886efe57124 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java @@ -30,6 +30,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8345766 + * @key randomness * @summary Test that Ideal transformations of ModFNode are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.ModFNodeTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java index d19e2562779..1ba71584031 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModINodeIdealizationTests.java @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8332268 + * @key randomness * @summary Test that Ideal transformations of ModINode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.ModINodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java index fc08ef60603..719cc596215 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModLNodeIdealizationTests.java @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8267265 + * @key randomness * @summary Test that Ideal transformations of ModLNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.ModLNodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestMulNodeIdealization.java b/test/hotspot/jtreg/compiler/c2/irTests/TestMulNodeIdealization.java index ca6d5fbe118..e0307f2eb98 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestMulNodeIdealization.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestMulNodeIdealization.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -31,6 +31,7 @@ import jdk.test.lib.Utils; /* * @test * @bug 8291336 + * @key randomness * @summary Test that transformation of multiply-by-2 is appropriately turned into additions. * @library /test/lib / * @requires vm.compiler2.enabled diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java index 2cdc6414685..1413ee0cafa 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestShiftAndMask.java @@ -31,6 +31,7 @@ import java.util.Objects; /* * @test * @bug 8277850 8278949 8285793 8346664 + * @key randomness * @summary C2: optimize mask checks in counted loops * @library /test/lib / * @run driver compiler.c2.irTests.TestShiftAndMask diff --git a/test/hotspot/jtreg/compiler/c2/irTests/UDivINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/UDivINodeIdealizationTests.java index 7183e0b311a..dd135c93e0d 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/UDivINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/UDivINodeIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8332268 + * @key randomness * @summary Test that Ideal transformations of UDivINode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.UDivINodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/UDivLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/UDivLNodeIdealizationTests.java index a5cfc2cddc5..bc80805cabd 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/UDivLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/UDivLNodeIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8332268 + * @key randomness * @summary Test that Ideal transformations of UDivLNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.UDivLNodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/UModINodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/UModINodeIdealizationTests.java index fa24033ab46..99982c70b6e 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/UModINodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/UModINodeIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8332268 + * @key randomness * @summary Test that Ideal transformations of UModINode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.UModINodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/c2/irTests/UModLNodeIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/UModLNodeIdealizationTests.java index 93ae861cfaa..9bbded327e0 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/UModLNodeIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/UModLNodeIdealizationTests.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -32,6 +32,7 @@ import compiler.lib.ir_framework.*; /* * @test * @bug 8332268 + * @key randomness * @summary Test that Ideal transformations of UModLNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.UModLNodeIdealizationTests diff --git a/test/hotspot/jtreg/compiler/controldependency/TestDivDependentOnMainLoopGuard.java b/test/hotspot/jtreg/compiler/controldependency/TestDivDependentOnMainLoopGuard.java index a6b7a462743..27fdc6b9e34 100644 --- a/test/hotspot/jtreg/compiler/controldependency/TestDivDependentOnMainLoopGuard.java +++ b/test/hotspot/jtreg/compiler/controldependency/TestDivDependentOnMainLoopGuard.java @@ -24,6 +24,7 @@ /* * @test * @bug 8349139 + * @key randomness * @summary C2: Div looses dependency on condition that guarantees divisor not null in counted loop * @library /test/lib / * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:CompileOnly=TestDivDependentOnMainLoopGuard::* diff --git a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java index 40bfb2e4319..570c59f0da2 100644 --- a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java +++ b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java @@ -24,6 +24,7 @@ /* * @test * @bug 8359412 + * @key randomness * @summary Use the template framework library to generate random expressions. * @modules java.base/jdk.internal.misc * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/intrinsics/float16/TestFloat16MaxMinSpecialValues.java b/test/hotspot/jtreg/compiler/intrinsics/float16/TestFloat16MaxMinSpecialValues.java index f83ca307d84..f85297859f3 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/float16/TestFloat16MaxMinSpecialValues.java +++ b/test/hotspot/jtreg/compiler/intrinsics/float16/TestFloat16MaxMinSpecialValues.java @@ -30,6 +30,7 @@ import jdk.test.lib.*; /** * @test * @bug 8352585 + * @key randomness * @library /test/lib / * @summary Add special case handling for Float16.max/min x86 backend * @modules jdk.incubator.vector diff --git a/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateAddSub.java b/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateAddSub.java index 11f37c1f7e7..e05cef8335b 100644 --- a/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateAddSub.java +++ b/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateAddSub.java @@ -31,6 +31,7 @@ import java.util.Random; /* * @test * @bug 8323220 + * @key randomness * @summary Test loop invariant code motion of add/sub through reassociation * @library /test/lib / * @run driver compiler.c2.loopopts.InvariantCodeMotionReassociateAddSub diff --git a/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateCmp.java b/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateCmp.java index 566e294b4bf..bf139befc98 100644 --- a/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateCmp.java +++ b/test/hotspot/jtreg/compiler/loopopts/InvariantCodeMotionReassociateCmp.java @@ -31,6 +31,7 @@ import java.util.Random; /* * @test * @bug 8323220 + * @key randomness * @summary Test loop invariant code motion for cmp nodes through reassociation * @library /test/lib / * @run driver compiler.c2.loopopts.InvariantCodeMotionReassociateCmp diff --git a/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java b/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java index 95ba9e6e795..f8abb716e42 100644 --- a/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java +++ b/test/hotspot/jtreg/compiler/loopopts/parallel_iv/TestParallelIvInIntCountedLoop.java @@ -32,6 +32,7 @@ import java.util.Random; /** * @test * @bug 8328528 + * @key randomness * @summary test the long typed parallel iv replacing transformation for int counted loop * @library /test/lib / * @requires vm.compiler2.enabled diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Int.java b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Int.java index 4e15c0de6e9..08f5e200aa0 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Int.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/MinMaxRed_Int.java @@ -24,6 +24,7 @@ /** * @test * @bug 8302673 + * @key randomness * @summary [SuperWord] MaxReduction and MinReduction should vectorize for int * @library /test/lib / * @run driver compiler.loopopts.superword.MinMaxRed_Int diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java b/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java index 56acdd349f8..10181ab3da2 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/ReductionPerf.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,6 +24,7 @@ /* * @test * @bug 8074981 8302652 + * @key randomness * @summary Test SuperWord Reduction Perf. * @library /test/lib / * @run main/othervm -Xbatch diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasing.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasing.java index 33cef6e5e6b..f5ad14871f9 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasing.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasing.java @@ -24,6 +24,7 @@ /* * @test * @bug 8324751 + * @key randomness * @summary Test Speculative Aliasing checks in SuperWord * @library /test/lib / * @run driver compiler.loopopts.superword.TestAliasing nCOH_nAV_ySAC diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java index 322c36c39e1..5a2d11ef2e1 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAlignVector.java @@ -36,6 +36,7 @@ import java.nio.ByteOrder; /* * @test id=NoAlignVector * @bug 8310190 + * @key randomness * @summary Test AlignVector with various loop init, stride, scale, invar, etc. * @modules java.base/jdk.internal.misc * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java index e6c373c4c87..0e17489e1c8 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestCompatibleUseDefTypeSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -35,6 +35,7 @@ import java.nio.ByteOrder; /* * @test * @bug 8325155 + * @key randomness * @summary Test some cases that vectorize after the removal of the alignment boundaries code. * Now, we instead check if use-def connections have compatible type size. * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java index e2aca036474..2678aab9c40 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestDependencyOffsets.java @@ -24,6 +24,7 @@ /* * @test id=vanilla-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @library /test/lib / * @compile ../../lib/ir_framework/TestFramework.java @@ -33,6 +34,7 @@ /* * @test id=vanilla-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @library /test/lib / * @compile ../../lib/ir_framework/TestFramework.java @@ -42,6 +44,7 @@ /* * @test id=sse4-v016-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -54,6 +57,7 @@ /* * @test id=sse4-v016-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -66,6 +70,7 @@ /* * @test id=sse4-v008-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -78,6 +83,7 @@ /* * @test id=sse4-v008-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -102,6 +108,7 @@ /* * @test id=sse4-v004-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -114,6 +121,7 @@ /* * @test id=avx1-v032-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -126,6 +134,7 @@ /* * @test id=avx1-v032-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -138,6 +147,7 @@ /* * @test id=avx1-v016-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -150,6 +160,7 @@ /* * @test id=avx1-v016-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -162,6 +173,7 @@ /* * @test id=avx2-v032-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -174,6 +186,7 @@ /* * @test id=avx2-v032-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -186,6 +199,7 @@ /* * @test id=avx2-v016-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -198,6 +212,7 @@ /* * @test id=avx2-v016-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -210,6 +225,7 @@ /* * @test id=avx512-v064-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -222,6 +238,7 @@ /* * @test id=avx512-v064-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -234,6 +251,7 @@ /* * @test id=avx512-v032-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -246,6 +264,7 @@ /* * @test id=avx512-v032-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -258,6 +277,7 @@ /* * @test id=avx512bw-v064-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -270,6 +290,7 @@ /* * @test id=avx512bw-v064-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -282,6 +303,7 @@ /* * @test id=avx512bw-v032-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -294,6 +316,7 @@ /* * @test id=avx512bw-v032-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") @@ -306,6 +329,7 @@ /* * @test id=vec-v064-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -317,6 +341,7 @@ /* * @test id=vec-v064-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -328,6 +353,7 @@ /* * @test id=vec-v032-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -339,6 +365,7 @@ /* * @test id=vec-v032-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -350,6 +377,7 @@ /* * @test id=vec-v016-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -361,6 +389,7 @@ /* * @test id=vec-v016-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -372,6 +401,7 @@ /* * @test id=vec-v008-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -383,6 +413,7 @@ /* * @test id=vec-v008-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -394,6 +425,7 @@ /* * @test id=vec-v004-A * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") @@ -405,6 +437,7 @@ /* * @test id=vec-v004-U * @bug 8298935 8308606 8310308 8312570 8310190 + * @key randomness * @summary Test SuperWord: vector size, offsets, dependencies, alignment. * @requires vm.compiler2.enabled * @requires (os.arch!="x86" & os.arch!="i386" & os.arch!="amd64" & os.arch!="x86_64") diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java index 91d1ee9666a..8677ae851cf 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestEquivalentInvariants.java @@ -35,6 +35,7 @@ import java.lang.foreign.*; /* * @test * @bug 8343685 8331659 + * @key randomness * @summary Test vectorization with various invariants that are equivalent, but not trivially so, * i.e. where the invariants have the same summands, but in a different order. * @modules java.base/jdk.internal.misc diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment.java index a2b5434a5a2..20ba2638fc1 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegment.java @@ -34,6 +34,7 @@ import java.lang.foreign.*; /* * @test id=byte-array * @bug 8329273 + * @key randomness * @summary Test vectorization of loops over MemorySegment * @library /test/lib / * @run driver compiler.loopopts.superword.TestMemorySegment ByteArray diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java index 969014e2293..7354ba896d0 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestMemorySegmentUnalignedAddress.java @@ -35,6 +35,7 @@ import java.lang.foreign.*; /* * @test id=byte-buffer-direct * @bug 8323582 + * @key randomness * @summary Test vectorization of loops over MemorySegment, with native memory where the address is not always aligned. * @library /test/lib / * @run driver compiler.loopopts.superword.TestMemorySegmentUnalignedAddress ByteBufferDirect diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java index 631b55fc65f..9a2e23e4530 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestSplitPacks.java @@ -35,6 +35,7 @@ import java.nio.ByteOrder; /* * @test * @bug 8326139 8348659 + * @key randomness * @summary Test splitting packs in SuperWord * @library /test/lib / * @run driver compiler.loopopts.superword.TestSplitPacks nCOH_nAV_ySAC diff --git a/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java index 5218e10c4af..5170c188133 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java +++ b/test/hotspot/jtreg/compiler/vectorapi/Test8278948.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -33,6 +33,7 @@ import jdk.test.lib.Utils; /* * @test * @bug 8278948 + * @key randomness * @summary Intermediate integer promotion vector length encoding is calculated incorrectly on x86 * @modules jdk.incubator.vector * @library /test/lib diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java index 38a2753a7ed..ddf16ce185f 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorAddMulReduction.java @@ -38,6 +38,7 @@ import jdk.test.lib.Utils; /** * @test * @bug 8320725 + * @key randomness * @library /test/lib / * @summary Verify non-strictly ordered AddReductionVF/VD and MulReductionVF/VD * nodes are generated in VectorAPI diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorCompressExpandBits.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorCompressExpandBits.java index f5174b7e6dc..8889ccd0d26 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/TestVectorCompressExpandBits.java +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorCompressExpandBits.java @@ -38,6 +38,7 @@ import jdk.test.lib.Utils; /** * @test * @bug 8301012 + * @key randomness * @library /test/lib / * @requires os.arch == "aarch64" & vm.cpu.features ~= ".*sve2.*" & vm.cpu.features ~= ".*svebitperm.*" * @summary [vectorapi]: Intrinsify CompressBitsV/ExpandBitsV and add the AArch64 SVE backend implementation diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCastIdentityTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCastIdentityTest.java index e66b16f053b..be9d8e6390c 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCastIdentityTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMaskCastIdentityTest.java @@ -24,6 +24,7 @@ /* * @test * @bug 8356760 +* @key randomness * @library /test/lib / * @summary Optimize VectorMask.fromLong for all-true/all-false cases * @modules jdk.incubator.vector diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorMultiplyOpt.java b/test/hotspot/jtreg/compiler/vectorapi/VectorMultiplyOpt.java index a48cd25e47f..a8394f41f8a 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorMultiplyOpt.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorMultiplyOpt.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -32,6 +32,7 @@ import java.lang.reflect.Array; /** * @test * @bug 8341137 + * @key randomness * @summary Optimize long vector multiplication using x86 VPMUL[U]DQ instruction. * @modules jdk.incubator.vector * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java index 887c41efd48..e51e6d31cb5 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorSaturatedOperationsTest.java @@ -24,6 +24,7 @@ /** * @test * @bug 8338021 8342677 8349522 +* @key randomness * @summary Add IR validation tests for newly added saturated vector add / sub operations * @modules jdk.incubator.vector * @library /test/lib / diff --git a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java index 6d868b48dd7..917d69876ce 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java @@ -30,6 +30,7 @@ import jdk.test.lib.Utils; /* * @test * @bug 8288107 + * @key randomness * @summary Auto-vectorization enhancement for integer Math.max/Math.min operations * @library /test/lib / * @requires vm.compiler2.enabled diff --git a/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java b/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java index d5a3de09123..3fed3eda124 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestEor3AArch64.java @@ -33,6 +33,7 @@ import jdk.test.lib.Utils; /* * @test * @bug 8293488 + * @key randomness * @summary Test EOR3 Neon/SVE2 instruction for aarch64 SHA3 extension * @library /test/lib / * @requires os.arch == "aarch64" diff --git a/test/hotspot/jtreg/compiler/vectorization/TestMacroLogicVector.java b/test/hotspot/jtreg/compiler/vectorization/TestMacroLogicVector.java index d2486f0ed77..9ab5994f566 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestMacroLogicVector.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestMacroLogicVector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,6 +24,7 @@ /** * @test * @bug 8241040 + * @key randomness * @library /test/lib * * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions diff --git a/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java b/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java index c30a28c46f9..7d03bb52071 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestVectorZeroCount.java @@ -21,20 +21,20 @@ * questions. */ +package compiler.vectorization; + +import java.util.Random; +import jdk.test.lib.Utils; + /* @test * @bug 8349637 + * @key randomness * @requires vm.flavor == "server" & (vm.opt.TieredStopAtLevel == null | vm.opt.TieredStopAtLevel == 4) * @summary Ensure that vectorization of numberOfLeadingZeros and numberOfTrailingZeros outputs correct values * @library /test/lib / * @run main/othervm/timeout=480 compiler.vectorization.TestVectorZeroCount */ -package compiler.vectorization; - -import java.util.Random; - -import jdk.test.lib.Utils; - public class TestVectorZeroCount { private static final int SIZE = 1024; private static final Random RANDOM = Utils.getRandomInstance(); From 6a6ff876c515eba6cc89320e02dc5739d4540316 Mon Sep 17 00:00:00 2001 From: Roman Marchenko Date: Thu, 11 Dec 2025 08:48:26 +0000 Subject: [PATCH 054/211] 8372860: TestCodeCacheUnloadDuringConcCycle fails on ARM32 Reviewed-by: tschatzl, shade --- .../hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java index a4fadc185d2..af746ad206d 100644 --- a/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java +++ b/test/hotspot/jtreg/gc/g1/TestCodeCacheUnloadDuringConcCycle.java @@ -140,7 +140,7 @@ class TestCodeCacheUnloadDuringConcCycleRunner { System.out.println("Compiled " + i + " classes"); } i++; - } while (i < 200); + } while (i < 1000); System.out.println("Compilation done, compiled " + i + " classes"); } catch (Throwable t) { } From aa986be7529b7a2950202dbe6885e5224d331078 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Thu, 11 Dec 2025 10:56:20 +0000 Subject: [PATCH 055/211] 8373421: Parallel: Rename young generation eden and survivor space pool Reviewed-by: tschatzl, jsikstro --- .../gc/parallel/parallelScavengeHeap.cpp | 14 ++++++------ .../share/gc/parallel/psMemoryPool.cpp | 22 +++++++++---------- .../share/gc/parallel/psMemoryPool.hpp | 18 +++++++-------- 3 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp index cff53e84059..0d8a3166f79 100644 --- a/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp +++ b/src/hotspot/share/gc/parallel/parallelScavengeHeap.cpp @@ -132,14 +132,14 @@ jint ParallelScavengeHeap::initialize() { void ParallelScavengeHeap::initialize_serviceability() { - _eden_pool = new EdenMutableSpacePool(_young_gen, - _young_gen->eden_space(), - "PS Eden Space", - false /* support_usage_threshold */); + _eden_pool = new PSEdenSpacePool(_young_gen, + _young_gen->eden_space(), + "PS Eden Space", + false /* support_usage_threshold */); - _survivor_pool = new SurvivorMutableSpacePool(_young_gen, - "PS Survivor Space", - false /* support_usage_threshold */); + _survivor_pool = new PSSurvivorSpacePool(_young_gen, + "PS Survivor Space", + false /* support_usage_threshold */); _old_pool = new PSOldGenerationPool(_old_gen, "PS Old Gen", diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.cpp b/src/hotspot/share/gc/parallel/psMemoryPool.cpp index 81c7b17a1ef..40170f62f06 100644 --- a/src/hotspot/share/gc/parallel/psMemoryPool.cpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.cpp @@ -39,16 +39,16 @@ MemoryUsage PSOldGenerationPool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -// The max size of EdenMutableSpacePool = +// The max size of PSEdenSpacePool = // max size of the PSYoungGen - capacity of two survivor spaces // // Max size of PS eden space is changing due to ergonomic. // PSYoungGen, PSOldGen, Eden, Survivor spaces are all resizable. // -EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen, - MutableSpace* space, - const char* name, - bool support_usage_threshold) : +PSEdenSpacePool::PSEdenSpacePool(PSYoungGen* young_gen, + MutableSpace* space, + const char* name, + bool support_usage_threshold) : CollectedMemoryPool(name, space->capacity_in_bytes(), (young_gen->max_gen_size() - young_gen->from_space()->capacity_in_bytes() - @@ -58,7 +58,7 @@ EdenMutableSpacePool::EdenMutableSpacePool(PSYoungGen* young_gen, _space(space) { } -MemoryUsage EdenMutableSpacePool::get_memory_usage() { +MemoryUsage PSEdenSpacePool::get_memory_usage() { size_t maxSize = (available_for_allocation() ? max_size() : 0); size_t used = used_in_bytes(); size_t committed = _space->capacity_in_bytes(); @@ -66,20 +66,20 @@ MemoryUsage EdenMutableSpacePool::get_memory_usage() { return MemoryUsage(initial_size(), used, committed, maxSize); } -// The max size of SurvivorMutableSpacePool = +// The max size of PSSurvivorSpacePool = // current capacity of the from-space // // PS from and to survivor spaces could have different sizes. // -SurvivorMutableSpacePool::SurvivorMutableSpacePool(PSYoungGen* young_gen, - const char* name, - bool support_usage_threshold) : +PSSurvivorSpacePool::PSSurvivorSpacePool(PSYoungGen* young_gen, + const char* name, + bool support_usage_threshold) : CollectedMemoryPool(name, young_gen->from_space()->capacity_in_bytes(), young_gen->from_space()->capacity_in_bytes(), support_usage_threshold), _young_gen(young_gen) { } -MemoryUsage SurvivorMutableSpacePool::get_memory_usage() { +MemoryUsage PSSurvivorSpacePool::get_memory_usage() { size_t maxSize = (available_for_allocation() ? max_size() : 0); size_t used = used_in_bytes(); size_t committed = committed_in_bytes(); diff --git a/src/hotspot/share/gc/parallel/psMemoryPool.hpp b/src/hotspot/share/gc/parallel/psMemoryPool.hpp index 0da47e5a8ef..ed9793203d4 100644 --- a/src/hotspot/share/gc/parallel/psMemoryPool.hpp +++ b/src/hotspot/share/gc/parallel/psMemoryPool.hpp @@ -43,16 +43,16 @@ public: size_t max_size() const { return _old_gen->reserved().byte_size(); } }; -class EdenMutableSpacePool : public CollectedMemoryPool { +class PSEdenSpacePool : public CollectedMemoryPool { private: PSYoungGen* _young_gen; MutableSpace* _space; public: - EdenMutableSpacePool(PSYoungGen* young_gen, - MutableSpace* space, - const char* name, - bool support_usage_threshold); + PSEdenSpacePool(PSYoungGen* young_gen, + MutableSpace* space, + const char* name, + bool support_usage_threshold); MutableSpace* space() { return _space; } MemoryUsage get_memory_usage(); @@ -65,14 +65,14 @@ public: } }; -class SurvivorMutableSpacePool : public CollectedMemoryPool { +class PSSurvivorSpacePool : public CollectedMemoryPool { private: PSYoungGen* _young_gen; public: - SurvivorMutableSpacePool(PSYoungGen* young_gen, - const char* name, - bool support_usage_threshold); + PSSurvivorSpacePool(PSYoungGen* young_gen, + const char* name, + bool support_usage_threshold); MemoryUsage get_memory_usage(); From e1d1d53cd1211b64d1fef03583a23056908b3482 Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Thu, 11 Dec 2025 13:53:01 +0000 Subject: [PATCH 056/211] 8167268: StandardGlyphVector.getGlyphMetrics creates metrics with erroneous bounds for characters with no outline (e.g., the space character ' ') Reviewed-by: serb, prr --- .../classes/sun/font/StandardGlyphVector.java | 14 ++-- .../font/GlyphVector/GlyphMetricsTest.java | 72 +++++++++++++++++++ 2 files changed, 80 insertions(+), 6 deletions(-) create mode 100644 test/jdk/java/awt/font/GlyphVector/GlyphMetricsTest.java diff --git a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java index e333a9de291..d44bd9a00e5 100644 --- a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java +++ b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, 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 @@ -608,11 +608,13 @@ public class StandardGlyphVector extends GlyphVector { } Rectangle2D vb = getGlyphVisualBounds(ix).getBounds2D(); - Point2D pt = getGlyphPosition(ix); - vb.setRect(vb.getMinX() - pt.getX(), - vb.getMinY() - pt.getY(), - vb.getWidth(), - vb.getHeight()); + if (!vb.isEmpty()) { + Point2D pt = getGlyphPosition(ix); + vb.setRect(vb.getMinX() - pt.getX(), + vb.getMinY() - pt.getY(), + vb.getWidth(), + vb.getHeight()); + } Point2D.Float adv = getGlyphStrike(ix).strike.getGlyphMetrics(glyphs[ix]); GlyphMetrics gm = new GlyphMetrics(true, adv.x, adv.y, diff --git a/test/jdk/java/awt/font/GlyphVector/GlyphMetricsTest.java b/test/jdk/java/awt/font/GlyphVector/GlyphMetricsTest.java new file mode 100644 index 00000000000..415b840671c --- /dev/null +++ b/test/jdk/java/awt/font/GlyphVector/GlyphMetricsTest.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8167268 + * @summary Checks behavior of GlyphVector.getGlyphMetrics(int). + */ + +import java.awt.Font; +import java.awt.Rectangle; +import java.awt.font.FontRenderContext; +import java.awt.font.GlyphMetrics; +import java.awt.font.GlyphVector; +import java.awt.font.TextLayout; +import java.awt.geom.Rectangle2D; + +public class GlyphMetricsTest { + + public static void main(String[] args) { + + String text = "The quick brown \r\n fox JUMPS over \t the lazy dog."; + Font font = new Font(Font.DIALOG, Font.PLAIN, 60); + FontRenderContext frc = new FontRenderContext(null, true, true); + GlyphVector gv = font.createGlyphVector(frc, text); + + for (int i = 0; i < gv.getNumGlyphs(); i++) { + + GlyphMetrics gm = gv.getGlyphMetrics(i); + Rectangle2D bounds = gm.getBounds2D(); + assertEqual(gm.getAdvance(), gm.getAdvanceX(), 0, "advance x", i); + assertEqual(0, gm.getAdvanceY(), 0, "advance y", i); + + // assumes one glyph per char in the test text + String character = text.substring(i, i + 1); + TextLayout layout = new TextLayout(character, font, frc); + Rectangle pixelBounds = layout.getPixelBounds(frc, 0, 0); + assertEqual(pixelBounds.getWidth(), bounds.getWidth(), 2, "width", i); + assertEqual(pixelBounds.getHeight(), bounds.getHeight(), 2, "height", i); + assertEqual(pixelBounds.getX(), bounds.getX(), 2, "x", i); + assertEqual(pixelBounds.getY(), bounds.getY(), 2, "y", i); + } + } + + private static void assertEqual(double d1, double d2, double variance, + String scenario, int index) { + if (Math.abs(d1 - d2) > variance) { + String msg = String.format("%s for index %d: %f != %f", scenario, index, d1, d2); + throw new RuntimeException(msg); + } + } +} From b0bd0c398ee0e0fd625eba1e7d9802a4e420a2c5 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 11 Dec 2025 14:13:32 +0000 Subject: [PATCH 057/211] 8372759: Test build/AbsPathsInImage.java fails after JDK-8370438 Reviewed-by: erikj --- make/autoconf/flags-ldflags.m4 | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/make/autoconf/flags-ldflags.m4 b/make/autoconf/flags-ldflags.m4 index b0dc565b39f..466ff1beaf4 100644 --- a/make/autoconf/flags-ldflags.m4 +++ b/make/autoconf/flags-ldflags.m4 @@ -63,7 +63,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], fi BASIC_LDFLAGS_JVM_ONLY="" - LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing" + LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing $DEBUG_PREFIX_CFLAGS" LDFLAGS_CXX_PARTIAL_LINKING="$MACHINE_FLAG -r" @@ -71,7 +71,7 @@ AC_DEFUN([FLAGS_SETUP_LDFLAGS_HELPER], BASIC_LDFLAGS_JVM_ONLY="-mno-omit-leaf-frame-pointer -mstack-alignment=16 \ -fPIC" - LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing" + LDFLAGS_LTO="-flto=auto -fuse-linker-plugin -fno-strict-aliasing $DEBUG_PREFIX_CFLAGS" LDFLAGS_CXX_PARTIAL_LINKING="$MACHINE_FLAG -r" if test "x$OPENJDK_TARGET_OS" = xlinux; then From 2a1c676e0a1a357f75ea008e8e12c7ae9340b9b1 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Thu, 11 Dec 2025 14:33:44 +0000 Subject: [PATCH 058/211] 8373464: Test JdkManagementCheckSince.java fails after JDK-8369736 Reviewed-by: dholmes, shade, kevinw --- .../share/classes/jdk/management/HotSpotAOTCacheMXBean.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java b/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java index 2dc02f2bd73..4a921c348d0 100644 --- a/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java +++ b/src/jdk.management/share/classes/jdk/management/HotSpotAOTCacheMXBean.java @@ -39,7 +39,7 @@ import javax.management.ObjectName; *

Direct access to the MXBean interface can be obtained with * {@link ManagementFactory#getPlatformMXBean(Class)}. * - * @since 26 + * @since 27 */ public interface HotSpotAOTCacheMXBean extends PlatformManagedObject { /** @@ -90,4 +90,4 @@ public interface HotSpotAOTCacheMXBean extends PlatformManagedObject { * successfully; {@code false} otherwise. */ public boolean endRecording(); -} \ No newline at end of file +} From 692edc4879489d44a477a03028eb3e7ef9dff388 Mon Sep 17 00:00:00 2001 From: Nizar Benalla Date: Thu, 11 Dec 2025 15:30:21 +0000 Subject: [PATCH 059/211] 8373443: Update --release 26 symbol information for JDK 26 build 27 Reviewed-by: jlahoda, iris, darcy --- .../share/data/symbols/java.base-Q.sym.txt | 44 +++++++++++++ .../share/data/symbols/java.sql-Q.sym.txt | 64 +++++++++++++++++++ .../symbols/jdk.incubator.foreign-Q.sym.txt | 43 +++++++++++++ .../share/data/symbols/jdk.jpackage-Q.sym.txt | 31 +++++++++ src/jdk.compiler/share/data/symbols/symbols | 2 +- 5 files changed, 183 insertions(+), 1 deletion(-) create mode 100644 src/jdk.compiler/share/data/symbols/java.sql-Q.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-Q.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jpackage-Q.sym.txt diff --git a/src/jdk.compiler/share/data/symbols/java.base-Q.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-Q.sym.txt index fb1ec6ec7bb..29ecd9f0304 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-Q.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-Q.sym.txt @@ -83,6 +83,11 @@ method name close descriptor ()V thrownTypes java/io/IOException flags 1 -class name java/lang/StableValue +class name java/lang/String +field name UNICODE_CASEFOLD_ORDER descriptor Ljava/util/Comparator; flags 19 signature Ljava/util/Comparator; +method name equalsFoldCase descriptor (Ljava/lang/String;)Z flags 1 +method name compareToFoldCase descriptor (Ljava/lang/String;)I flags 1 + class name java/lang/Thread -method name stop descriptor ()V @@ -464,6 +469,16 @@ innerclass innerClass java/lang/Thread$State outerClass java/lang/Thread innerCl innerclass innerClass java/util/concurrent/StructuredTaskScope$Subtask outerClass java/util/concurrent/StructuredTaskScope innerClassName Subtask flags 609 innerclass innerClass java/util/concurrent/StructuredTaskScope$Subtask$State outerClass java/util/concurrent/StructuredTaskScope$Subtask innerClassName State flags 4019 +class name java/util/concurrent/ThreadLocalRandom +method name nextGaussian descriptor ()D flags 1 + +class name java/util/jar/JarFile +header extends java/util/zip/ZipFile flags 21 +innerclass innerClass java/lang/Runtime$Version outerClass java/lang/Runtime innerClassName Version flags 19 +innerclass innerClass java/util/jar/Attributes$Name outerClass java/util/jar/Attributes innerClassName Name flags 9 +innerclass innerClass java/lang/ScopedValue$Carrier outerClass java/lang/ScopedValue innerClassName Carrier flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name java/util/stream/Collectors header extends java/lang/Object flags 31 runtimeAnnotations @Ljdk/internal/vm/annotation/AOTSafeClassInitializer; innerclass innerClass java/util/stream/Collector$Characteristics outerClass java/util/stream/Collector innerClassName Characteristics flags 4019 @@ -486,6 +501,35 @@ method name getKey descriptor (Ljava/security/Key;Ljava/security/Provider;)Ljava method name getKeyPair descriptor ([C)Ljava/security/KeyPair; thrownTypes java/security/NoSuchAlgorithmException,java/security/InvalidKeyException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) method name getKeyPair descriptor (Ljava/security/Key;Ljava/security/Provider;)Ljava/security/KeyPair; thrownTypes java/security/NoSuchAlgorithmException,java/security/InvalidKeyException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;PEM_API;) +class name javax/crypto/spec/HPKEParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 31 +field name KEM_DHKEM_P_256_HKDF_SHA256 descriptor I constantValue 16 flags 19 +field name KEM_DHKEM_P_384_HKDF_SHA384 descriptor I constantValue 17 flags 19 +field name KEM_DHKEM_P_521_HKDF_SHA512 descriptor I constantValue 18 flags 19 +field name KEM_DHKEM_X25519_HKDF_SHA256 descriptor I constantValue 32 flags 19 +field name KEM_DHKEM_X448_HKDF_SHA512 descriptor I constantValue 33 flags 19 +field name KDF_HKDF_SHA256 descriptor I constantValue 1 flags 19 +field name KDF_HKDF_SHA384 descriptor I constantValue 2 flags 19 +field name KDF_HKDF_SHA512 descriptor I constantValue 3 flags 19 +field name AEAD_AES_128_GCM descriptor I constantValue 1 flags 19 +field name AEAD_AES_256_GCM descriptor I constantValue 2 flags 19 +field name AEAD_CHACHA20_POLY1305 descriptor I constantValue 3 flags 19 +field name EXPORT_ONLY descriptor I constantValue 65535 flags 19 +method name of descriptor (III)Ljavax/crypto/spec/HPKEParameterSpec; flags 9 +method name withInfo descriptor ([B)Ljavax/crypto/spec/HPKEParameterSpec; flags 1 +method name withPsk descriptor (Ljavax/crypto/SecretKey;[B)Ljavax/crypto/spec/HPKEParameterSpec; flags 1 +method name withEncapsulation descriptor ([B)Ljavax/crypto/spec/HPKEParameterSpec; flags 1 +method name withAuthKey descriptor (Ljava/security/AsymmetricKey;)Ljavax/crypto/spec/HPKEParameterSpec; flags 1 +method name kem_id descriptor ()I flags 1 +method name kdf_id descriptor ()I flags 1 +method name aead_id descriptor ()I flags 1 +method name info descriptor ()[B flags 1 +method name psk descriptor ()Ljavax/crypto/SecretKey; flags 1 +method name psk_id descriptor ()[B flags 1 +method name authKey descriptor ()Ljava/security/AsymmetricKey; flags 1 +method name encapsulation descriptor ()[B flags 1 +method name toString descriptor ()Ljava/lang/String; flags 1 + class name jdk/internal/classfile/impl/DirectCodeBuilder header extends jdk/internal/classfile/impl/AbstractDirectBuilder implements jdk/internal/classfile/impl/TerminalCodeBuilder flags 31 signature Ljdk/internal/classfile/impl/AbstractDirectBuilder;Ljdk/internal/classfile/impl/TerminalCodeBuilder; innerclass innerClass jdk/internal/classfile/impl/AbstractPseudoInstruction$ExceptionCatchImpl outerClass jdk/internal/classfile/impl/AbstractPseudoInstruction innerClassName ExceptionCatchImpl flags 19 diff --git a/src/jdk.compiler/share/data/symbols/java.sql-Q.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-Q.sym.txt new file mode 100644 index 00000000000..a8f41a27db0 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.sql-Q.sym.txt @@ -0,0 +1,64 @@ +# +# Copyright (c) 2025, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name java/sql/Array +header extends java/lang/Object implements java/lang/AutoCloseable flags 601 +method name close descriptor ()V thrownTypes java/sql/SQLException flags 1 + +class name java/sql/Blob +header extends java/lang/Object implements java/lang/AutoCloseable flags 601 +method name close descriptor ()V thrownTypes java/sql/SQLException flags 1 + +class name java/sql/Clob +header extends java/lang/Object implements java/lang/AutoCloseable flags 601 +method name close descriptor ()V thrownTypes java/sql/SQLException flags 1 + +class name java/sql/Connection +method name enquoteLiteral descriptor (Ljava/lang/String;)Ljava/lang/String; thrownTypes java/sql/SQLException flags 1 +method name enquoteIdentifier descriptor (Ljava/lang/String;Z)Ljava/lang/String; thrownTypes java/sql/SQLException flags 1 +method name isSimpleIdentifier descriptor (Ljava/lang/String;)Z thrownTypes java/sql/SQLException flags 1 +method name enquoteNCharLiteral descriptor (Ljava/lang/String;)Ljava/lang/String; thrownTypes java/sql/SQLException flags 1 + +class name java/sql/JDBCType +field name DECFLOAT descriptor Ljava/sql/JDBCType; flags 4019 +field name JSON descriptor Ljava/sql/JDBCType; flags 4019 + +class name java/sql/SQLPermission +header extends java/security/BasicPermission flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="26") + +class name java/sql/SQLXML +header extends java/lang/Object implements java/lang/AutoCloseable flags 601 +method name close descriptor ()V thrownTypes java/sql/SQLException flags 1 + +class name java/sql/Statement +header extends java/lang/Object implements java/sql/Wrapper,java/lang/AutoCloseable flags 601 classAnnotations @Ljdk/Profile+Annotation;(value=I2) + +class name java/sql/Types +field name DECFLOAT descriptor I constantValue 2015 flags 19 +field name JSON descriptor I constantValue 2016 flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-Q.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-Q.sym.txt new file mode 100644 index 00000000000..2d774f83cf1 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.foreign-Q.sym.txt @@ -0,0 +1,43 @@ +# +# Copyright (c) 2025, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +class name jdk/internal/foreign/AbstractMemorySegmentImpl +header extends java/lang/Object implements java/lang/foreign/MemorySegment,java/lang/foreign/SegmentAllocator sealed true permittedSubclasses jdk/internal/foreign/HeapMemorySegmentImpl,jdk/internal/foreign/NativeMemorySegmentImpl flags 421 +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 609 +innerclass innerClass java/lang/foreign/MemorySegment$Scope outerClass java/lang/foreign/MemorySegment innerClassName Scope flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name apply descriptor (Ljava/lang/String;Ljava/util/List;)Ljava/lang/RuntimeException; +-method name apply descriptor (Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jpackage-Q.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jpackage-Q.sym.txt new file mode 100644 index 00000000000..27fd9e69203 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jpackage-Q.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2025, 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. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# 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. +# +# ########################################################## +# ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### +# ########################################################## +# +module name jdk.jpackage +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;jdk.jlink\u0020;flags\u0020;0,name\u0020;java.naming\u0020;flags\u0020;0,name\u0020;java.desktop\u0020;flags\u0020;0 uses jdk/jpackage/internal/cli/CliBundlingEnvironment provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/jpackage/internal/cli/Main$Provider,interface\u0020;jdk/jpackage/internal/cli/CliBundlingEnvironment\u0020;impls\u0020;jdk/jpackage/internal/MacBundlingEnvironment target macos-aarch64 moduleMainClass jdk/jpackage/main/Main flags 8000 + diff --git a/src/jdk.compiler/share/data/symbols/symbols b/src/jdk.compiler/share/data/symbols/symbols index 4bc5127310f..8fdcac5c652 100644 --- a/src/jdk.compiler/share/data/symbols/symbols +++ b/src/jdk.compiler/share/data/symbols/symbols @@ -48,4 +48,4 @@ platform version M base L files java.base-M.sym.txt:java.compiler-M.sym.txt:java platform version N base M files java.base-N.sym.txt:java.compiler-N.sym.txt:java.desktop-N.sym.txt:java.management-N.sym.txt:java.management.rmi-N.sym.txt:jdk.compiler-N.sym.txt:jdk.httpserver-N.sym.txt:jdk.incubator.foreign-N.sym.txt:jdk.javadoc-N.sym.txt:jdk.jshell-N.sym.txt:jdk.localedata-N.sym.txt:jdk.unsupported-N.sym.txt platform version O base N files java.base-O.sym.txt:java.compiler-O.sym.txt:java.datatransfer-O.sym.txt:java.desktop-O.sym.txt:java.instrument-O.sym.txt:java.logging-O.sym.txt:java.management-O.sym.txt:java.management.rmi-O.sym.txt:java.naming-O.sym.txt:java.net.http-O.sym.txt:java.prefs-O.sym.txt:java.rmi-O.sym.txt:java.scripting-O.sym.txt:java.se-O.sym.txt:java.security.jgss-O.sym.txt:java.security.sasl-O.sym.txt:java.smartcardio-O.sym.txt:java.sql-O.sym.txt:java.sql.rowset-O.sym.txt:java.transaction.xa-O.sym.txt:java.xml-O.sym.txt:java.xml.crypto-O.sym.txt:jdk.accessibility-O.sym.txt:jdk.attach-O.sym.txt:jdk.charsets-O.sym.txt:jdk.compiler-O.sym.txt:jdk.crypto.cryptoki-O.sym.txt:jdk.dynalink-O.sym.txt:jdk.editpad-O.sym.txt:jdk.hotspot.agent-O.sym.txt:jdk.httpserver-O.sym.txt:jdk.incubator.foreign-O.sym.txt:jdk.incubator.vector-O.sym.txt:jdk.jartool-O.sym.txt:jdk.javadoc-O.sym.txt:jdk.jcmd-O.sym.txt:jdk.jconsole-O.sym.txt:jdk.jdeps-O.sym.txt:jdk.jdi-O.sym.txt:jdk.jdwp.agent-O.sym.txt:jdk.jfr-O.sym.txt:jdk.jlink-O.sym.txt:jdk.jpackage-O.sym.txt:jdk.jshell-O.sym.txt:jdk.jsobject-O.sym.txt:jdk.jstatd-O.sym.txt:jdk.localedata-O.sym.txt:jdk.management-O.sym.txt:jdk.management.agent-O.sym.txt:jdk.management.jfr-O.sym.txt:jdk.naming.dns-O.sym.txt:jdk.naming.rmi-O.sym.txt:jdk.net-O.sym.txt:jdk.nio.mapmode-O.sym.txt:jdk.sctp-O.sym.txt:jdk.security.auth-O.sym.txt:jdk.security.jgss-O.sym.txt:jdk.unsupported-O.sym.txt:jdk.xml.dom-O.sym.txt:jdk.zipfs-O.sym.txt platform version P base O files java.base-P.sym.txt:java.compiler-P.sym.txt:java.desktop-P.sym.txt:java.logging-P.sym.txt:java.management-P.sym.txt:java.net.http-P.sym.txt:java.security.jgss-P.sym.txt:java.xml.crypto-P.sym.txt:jdk.attach-P.sym.txt:jdk.compiler-P.sym.txt:jdk.incubator.foreign-P.sym.txt:jdk.incubator.vector-P.sym.txt:jdk.jdi-P.sym.txt:jdk.jfr-P.sym.txt:jdk.jpackage-P.sym.txt:jdk.jshell-P.sym.txt:jdk.net-P.sym.txt:jdk.security.jgss-P.sym.txt -platform version Q base P files java.base-Q.sym.txt:java.compiler-Q.sym.txt:java.desktop-Q.sym.txt:java.management-Q.sym.txt:java.net.http-Q.sym.txt:jdk.httpserver-Q.sym.txt:jdk.incubator.vector-Q.sym.txt:jdk.jartool-Q.sym.txt:jdk.jdeps-Q.sym.txt:jdk.jfr-Q.sym.txt:jdk.jlink-Q.sym.txt:jdk.jshell-Q.sym.txt:jdk.jsobject-Q.sym.txt:jdk.localedata-Q.sym.txt +platform version Q base P files java.base-Q.sym.txt:java.compiler-Q.sym.txt:java.desktop-Q.sym.txt:java.management-Q.sym.txt:java.net.http-Q.sym.txt:java.sql-Q.sym.txt:jdk.httpserver-Q.sym.txt:jdk.incubator.foreign-Q.sym.txt:jdk.incubator.vector-Q.sym.txt:jdk.jartool-Q.sym.txt:jdk.jdeps-Q.sym.txt:jdk.jfr-Q.sym.txt:jdk.jlink-Q.sym.txt:jdk.jpackage-Q.sym.txt:jdk.jshell-Q.sym.txt:jdk.jsobject-Q.sym.txt:jdk.localedata-Q.sym.txt From 431dcf84e9754c743105380ca69af647b57193bc Mon Sep 17 00:00:00 2001 From: Daniel Gredler Date: Thu, 11 Dec 2025 20:15:45 +0000 Subject: [PATCH 060/211] 8368702: [macosx] Printing text with composite fonts loses font transform Reviewed-by: psadhukhan, prr --- .../macosx/classes/sun/lwawt/macosx/CTextPipe.java | 12 +++++++++--- .../jdk/java/awt/print/PrinterJob/PrintTextTest.java | 2 +- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java index 6fdda409ce5..cf4a6e72136 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/macosx/CTextPipe.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, 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 @@ -97,8 +97,14 @@ public class CTextPipe implements TextPipe { if (f2d instanceof CFont) { CompositeFont cf = ((CFont)f2d).getCompositeFont2D(); PhysicalFont pf = cf.getSlotFont(slot); - Font f = new Font(pf.getFontName(null), - font.getStyle(), font.getSize()); + String name = pf.getFontName(null); + Font f = new Font(name, font.getStyle(), font.getSize()); + if (font.isTransformed()) { + f = f.deriveFont(font.getTransform()); + } + if (font.hasLayoutAttributes()) { + f = f.deriveFont(font.getAttributes()); + } return f; } return null; diff --git a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java index 06e71c4067f..defca807fc0 100644 --- a/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java +++ b/test/jdk/java/awt/print/PrinterJob/PrintTextTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 6425068 7156751 7157659 8029204 8132890 8148334 8344637 + * @bug 6425068 7156751 7157659 8029204 8132890 8148334 8344637 8368702 * @key printer * @summary Confirm that text prints where we expect to the length we expect. * @library /java/awt/regtesthelpers From 66d7b0ce8f8414c3d5fd3476b65152b9f2a9a587 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 11 Dec 2025 20:32:58 +0000 Subject: [PATCH 061/211] 8371657: [macosx] Programmatically selecting/deselecting List item triggers an ItemEvent Reviewed-by: aivanov, azvegint, dnguyen, tr --- .../macosx/classes/sun/lwawt/LWListPeer.java | 51 +++-- test/jdk/ProblemList.txt | 1 + .../awt/List/NoEvents/ProgrammaticChange.java | 176 ++++++++++++++++++ 3 files changed, 215 insertions(+), 13 deletions(-) create mode 100644 test/jdk/java/awt/List/NoEvents/ProgrammaticChange.java diff --git a/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java b/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java index 905a66b3212..84258b454a2 100644 --- a/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java +++ b/src/java.desktop/macosx/classes/sun/lwawt/LWListPeer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2025, 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 @@ -86,8 +86,11 @@ final class LWListPeer extends LWComponentPeer final int[] selectedIndices = getTarget().getSelectedIndexes(); synchronized (getDelegateLock()) { getDelegate().setSkipStateChangedEvent(true); - getDelegate().getView().setSelectedIndices(selectedIndices); - getDelegate().setSkipStateChangedEvent(false); + try { + getDelegate().getView().setSelectedIndices(selectedIndices); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } @@ -111,24 +114,39 @@ final class LWListPeer extends LWComponentPeer @Override public void add(final String item, final int index) { synchronized (getDelegateLock()) { - getDelegate().getModel().add(index, item); - revalidate(); + getDelegate().setSkipStateChangedEvent(true); + try { + getDelegate().getModel().add(index, item); + revalidate(); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } @Override public void delItems(final int start, final int end) { synchronized (getDelegateLock()) { - getDelegate().getModel().removeRange(start, end); - revalidate(); + getDelegate().setSkipStateChangedEvent(true); + try { + getDelegate().getModel().removeRange(start, end); + revalidate(); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } @Override public void removeAll() { synchronized (getDelegateLock()) { - getDelegate().getModel().removeAllElements(); - revalidate(); + getDelegate().setSkipStateChangedEvent(true); + try { + getDelegate().getModel().removeAllElements(); + revalidate(); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } @@ -136,16 +154,23 @@ final class LWListPeer extends LWComponentPeer public void select(final int index) { synchronized (getDelegateLock()) { getDelegate().setSkipStateChangedEvent(true); - getDelegate().getView().setSelectedIndex(index); - getDelegate().setSkipStateChangedEvent(false); + try { + getDelegate().getView().setSelectedIndex(index); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } @Override public void deselect(final int index) { synchronized (getDelegateLock()) { - getDelegate().getView().getSelectionModel(). - removeSelectionInterval(index, index); + getDelegate().setSkipStateChangedEvent(true); + try { + getDelegate().getView().removeSelectionInterval(index, index); + } finally { + getDelegate().setSkipStateChangedEvent(false); + } } } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 0076b1cf891..757d9c0ba63 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -150,6 +150,7 @@ java/awt/EventQueue/PushPopDeadlock/PushPopDeadlock.java 8024034 generic-all java/awt/grab/EmbeddedFrameTest1/EmbeddedFrameTest1.java 7080150 macosx-all java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all java/awt/List/KeyEventsTest/KeyEventsTest.java 8201307 linux-all +java/awt/List/NoEvents/ProgrammaticChange.java 8201307 linux-all java/awt/Paint/ListRepaint.java 8201307 linux-all java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8370584 windows-x64 diff --git a/test/jdk/java/awt/List/NoEvents/ProgrammaticChange.java b/test/jdk/java/awt/List/NoEvents/ProgrammaticChange.java new file mode 100644 index 00000000000..07b4bd2ac70 --- /dev/null +++ b/test/jdk/java/awt/List/NoEvents/ProgrammaticChange.java @@ -0,0 +1,176 @@ +/* + * Copyright Amazon.com Inc. 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. + */ + +import java.awt.Frame; +import java.awt.List; +import java.awt.Robot; +import java.util.Arrays; +import java.util.function.Supplier; + +/** + * @test + * @bug 8371657 + * @key headful + * @summary Checks that programmatic changes to a List do not fire events + */ +public final class ProgrammaticChange { + + private static Robot robot; + private static volatile boolean itemEvent; + private static volatile boolean actionEvent; + + public static void main(String[] args) throws Exception { + robot = new Robot(); + robot.mouseMove(0, 0); // Just in case, the mouse may affect selection + + var creators = Arrays.>asList( + List::new, () -> createList(false), () -> createList(true) + ); + for (Supplier creator : creators) { + test(creator, true); // Test displayable list + test(creator, false); // Test non-displayable list + } + } + + private static void test(Supplier creator, boolean displayable) { + List list = creator.get(); + list.addItemListener(event -> { + System.err.println("event = " + event); + itemEvent = true; + }); + list.addActionListener(event -> { + System.err.println("event = " + event); + actionEvent = true; + }); + + Frame frame = null; + try { + if (displayable) { + frame = new Frame(); + frame.setSize(300, 200); + frame.setLocationRelativeTo(null); + frame.add(list); + frame.setVisible(true); + } + tryTriggerEvents(list); + } finally { + if (frame != null) { + frame.dispose(); + } + } + } + + private static void tryTriggerEvents(List list) { + // Only "select" and "deselect" should not fire events per the spec, + // but we also check other methods to prevent accidental changes + selectAll(list); + verify(); + deselectAll(list); + verify(); + + // "add" may change the current selection + selectAll(list); + list.add("newItemStart", 0); + list.add("newItemMid", 1); + list.add("newItemEnd"); + verify(); + + // "remove" may change the current selection + selectAll(list); + list.remove(0); + verify(); + + // "makeVisible" may change the current selection + for (int i = 0; i < 100; i++){ + list.add("newItem_" + i, 0); + } + selectAll(list); + list.makeVisible(1); + list.makeVisible(99); + verify(); + + // "setMultipleMode" may change the current selection + selectAll(list); + list.setMultipleMode(!list.isMultipleMode()); + selectAll(list); + list.setMultipleSelections(!list.allowsMultipleSelections()); + verify(); + + // "removeAll" may change the current selection + selectAll(list); + list.removeAll(); + verify(); + + // No extra logic; just calling methods to touch all code paths + list.add("newItem1"); + list.getSelectedIndex(); + list.getSelectedIndexes(); + list.getSelectedItem(); + list.getSelectedItems(); + list.getSelectedObjects(); + list.getVisibleIndex(); + list.isIndexSelected(0); + list.isSelected(0); + + list.add("newItem2"); + list.delItems(0, 0); + list.addItem("newItem4"); + list.delItem(0); + list.addItem("newItem6", 0); + list.replaceItem("newItem7", 0); + list.remove("newItem7"); + list.add("newItem8"); + list.clear(); + verify(); + } + + private static void selectAll(List list) { + for (int index = 0; index < list.getItemCount(); index++) { + list.select(index); + } + } + + private static void deselectAll(List list) { + for (int index = 0; index < list.countItems(); index++) { + list.deselect(index); + } + } + + private static List createList(boolean multipleMode) { + List list = new List(4, multipleMode); + for (String item : new String[]{"item1", "item2", "item3"}) { + list.add(item); + } + return list; + } + + private static void verify() { + robot.waitForIdle(); + robot.delay(700); // Large delay, we are waiting for unexpected events + if (actionEvent || itemEvent) { + System.err.println("itemEvent: " + itemEvent); + System.err.println("actionEvent: " + actionEvent); + throw new RuntimeException("Unexpected event"); + } + } +} From ae85d899d074c531371dece30319ace701517528 Mon Sep 17 00:00:00 2001 From: Xueming Shen Date: Thu, 11 Dec 2025 20:47:32 +0000 Subject: [PATCH 062/211] 8373389: Two jdk/incubator/vector/ tests fails after JDK-8371446 Reviewed-by: psandoz --- test/jdk/jdk/incubator/vector/AbstractVectorTest.java | 5 +---- test/jdk/jdk/incubator/vector/Byte128VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Byte256VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Byte512VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Byte64VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java | 10 ++++++++-- .../jdk/jdk/incubator/vector/Double128VectorTests.java | 6 ++++++ .../jdk/jdk/incubator/vector/Double256VectorTests.java | 6 ++++++ .../jdk/jdk/incubator/vector/Double512VectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Double64VectorTests.java | 6 ++++++ .../jdk/jdk/incubator/vector/DoubleMaxVectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Float128VectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Float256VectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Float512VectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Float64VectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java | 6 ++++++ test/jdk/jdk/incubator/vector/Int128VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Int256VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Int512VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Int64VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/IntMaxVectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Long128VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Long256VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Long512VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Long64VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/LongMaxVectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Short128VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Short256VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Short512VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/Short64VectorTests.java | 10 ++++++++-- test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java | 10 ++++++++-- 31 files changed, 221 insertions(+), 44 deletions(-) diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorTest.java index b334e64ab80..99824d6e693 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorTest.java @@ -119,10 +119,7 @@ public class AbstractVectorTest { Arrays.fill(a, true); return a; }), - withToString("mask[false]", boolean[]::new), - withToString("mask[random]", (int s) -> { - return fill_boolean(s,_i -> RAND.nextBoolean()); - }) + withToString("mask[false]", boolean[]::new) ); static final List>> diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java index 4980c66c02a..c33678bee1f 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorTests.java @@ -1125,6 +1125,12 @@ public class Byte128VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -4503,7 +4509,7 @@ public class Byte128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueByte128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4527,7 +4533,7 @@ public class Byte128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueByte128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java index b3cad54e101..837febfe0ed 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorTests.java @@ -1125,6 +1125,12 @@ public class Byte256VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -4503,7 +4509,7 @@ public class Byte256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueByte256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4527,7 +4533,7 @@ public class Byte256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueByte256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java index 83e48cd2fdc..1dd979f44bf 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorTests.java @@ -1125,6 +1125,12 @@ public class Byte512VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -4503,7 +4509,7 @@ public class Byte512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueByte512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4527,7 +4533,7 @@ public class Byte512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueByte512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java index 0088b3fbf8e..43d180db0a5 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorTests.java @@ -1125,6 +1125,12 @@ public class Byte64VectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -4503,7 +4509,7 @@ public class Byte64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueByte64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4527,7 +4533,7 @@ public class Byte64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueByte64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java index 6df01fb48e3..cb7b00d8ebf 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorTests.java @@ -1130,6 +1130,12 @@ public class ByteMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> BYTE_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> BYTE_GENERATOR_TRIPLES = BYTE_GENERATOR_PAIRS.stream(). @@ -4508,7 +4514,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueByteMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4532,7 +4538,7 @@ public class ByteMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueByteMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Double128VectorTests.java b/test/jdk/jdk/incubator/vector/Double128VectorTests.java index 879dac4c966..716d7b1f1f7 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorTests.java @@ -1217,6 +1217,12 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Double256VectorTests.java b/test/jdk/jdk/incubator/vector/Double256VectorTests.java index 87230330642..298d5591b1c 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorTests.java @@ -1217,6 +1217,12 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Double512VectorTests.java b/test/jdk/jdk/incubator/vector/Double512VectorTests.java index af8fbf5f51f..34723b27ec9 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorTests.java @@ -1217,6 +1217,12 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Double64VectorTests.java b/test/jdk/jdk/incubator/vector/Double64VectorTests.java index 67822ae5353..f8ccd2ea8b4 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorTests.java @@ -1217,6 +1217,12 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java index 5d7ae07c55a..1992f80eb2d 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorTests.java @@ -1222,6 +1222,12 @@ relativeError)); flatMap(fa -> DOUBLE_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> DOUBLE_GENERATOR_TRIPLES = DOUBLE_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Float128VectorTests.java b/test/jdk/jdk/incubator/vector/Float128VectorTests.java index 0d3ce311a90..d605fa7c61f 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorTests.java @@ -1228,6 +1228,12 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Float256VectorTests.java b/test/jdk/jdk/incubator/vector/Float256VectorTests.java index 88ea856f17b..f72e81cd030 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorTests.java @@ -1228,6 +1228,12 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Float512VectorTests.java b/test/jdk/jdk/incubator/vector/Float512VectorTests.java index cdccbfdd319..68e182a602a 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorTests.java @@ -1228,6 +1228,12 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Float64VectorTests.java b/test/jdk/jdk/incubator/vector/Float64VectorTests.java index 056eae1974f..c5bc801bc03 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorTests.java @@ -1228,6 +1228,12 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java index 19bd385ca1f..5fccb85dc40 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorTests.java @@ -1233,6 +1233,12 @@ relativeError)); flatMap(fa -> FLOAT_GENERATORS.stream().skip(1).map(fb -> List.of(fa, fb))). collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> FLOAT_GENERATOR_TRIPLES = FLOAT_GENERATOR_PAIRS.stream(). diff --git a/test/jdk/jdk/incubator/vector/Int128VectorTests.java b/test/jdk/jdk/incubator/vector/Int128VectorTests.java index 1bf3203790c..c0834d7710f 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorTests.java @@ -1115,6 +1115,12 @@ public class Int128VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -4547,7 +4553,7 @@ public class Int128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueInt128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4571,7 +4577,7 @@ public class Int128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueInt128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Int256VectorTests.java b/test/jdk/jdk/incubator/vector/Int256VectorTests.java index 5973fec7e57..cb8d306156a 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorTests.java @@ -1115,6 +1115,12 @@ public class Int256VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -4547,7 +4553,7 @@ public class Int256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueInt256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4571,7 +4577,7 @@ public class Int256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueInt256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Int512VectorTests.java b/test/jdk/jdk/incubator/vector/Int512VectorTests.java index a1e969fc852..d35d680c0c8 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorTests.java @@ -1115,6 +1115,12 @@ public class Int512VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -4547,7 +4553,7 @@ public class Int512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueInt512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4571,7 +4577,7 @@ public class Int512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueInt512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Int64VectorTests.java b/test/jdk/jdk/incubator/vector/Int64VectorTests.java index 15b3b68820e..9c35785e298 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorTests.java @@ -1115,6 +1115,12 @@ public class Int64VectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -4547,7 +4553,7 @@ public class Int64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueInt64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4571,7 +4577,7 @@ public class Int64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueInt64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java index 67368e0f70e..0f5e0d1cdc0 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorTests.java @@ -1120,6 +1120,12 @@ public class IntMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> INT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> INT_GENERATOR_TRIPLES = INT_GENERATOR_PAIRS.stream(). @@ -4552,7 +4558,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueIntMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4576,7 +4582,7 @@ public class IntMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueIntMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Long128VectorTests.java b/test/jdk/jdk/incubator/vector/Long128VectorTests.java index 6f91fb9ffbf..832329a0a8b 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorTests.java @@ -1105,6 +1105,12 @@ public class Long128VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -4569,7 +4575,7 @@ public class Long128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueLong128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4593,7 +4599,7 @@ public class Long128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueLong128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Long256VectorTests.java b/test/jdk/jdk/incubator/vector/Long256VectorTests.java index 118c955ad24..ff9d063ad0a 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorTests.java @@ -1105,6 +1105,12 @@ public class Long256VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -4569,7 +4575,7 @@ public class Long256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueLong256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4593,7 +4599,7 @@ public class Long256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueLong256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Long512VectorTests.java b/test/jdk/jdk/incubator/vector/Long512VectorTests.java index 1bca0ef0ebd..fac87be8e22 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorTests.java @@ -1105,6 +1105,12 @@ public class Long512VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -4569,7 +4575,7 @@ public class Long512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueLong512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4593,7 +4599,7 @@ public class Long512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueLong512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Long64VectorTests.java b/test/jdk/jdk/incubator/vector/Long64VectorTests.java index 212bbb5047c..7c283b972dc 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorTests.java @@ -1105,6 +1105,12 @@ public class Long64VectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -4569,7 +4575,7 @@ public class Long64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueLong64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4593,7 +4599,7 @@ public class Long64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueLong64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java index 3eba905e4f8..c76a2a2affd 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorTests.java @@ -1110,6 +1110,12 @@ public class LongMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> LONG_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> LONG_GENERATOR_TRIPLES = LONG_GENERATOR_PAIRS.stream(). @@ -4574,7 +4580,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueLongMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4598,7 +4604,7 @@ public class LongMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueLongMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Short128VectorTests.java b/test/jdk/jdk/incubator/vector/Short128VectorTests.java index 50be26b163a..8300c64e574 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorTests.java @@ -1115,6 +1115,12 @@ public class Short128VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -4494,7 +4500,7 @@ public class Short128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueShort128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4518,7 +4524,7 @@ public class Short128VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueShort128VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Short256VectorTests.java b/test/jdk/jdk/incubator/vector/Short256VectorTests.java index 5f63164755b..f208905b203 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorTests.java @@ -1115,6 +1115,12 @@ public class Short256VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -4494,7 +4500,7 @@ public class Short256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueShort256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4518,7 +4524,7 @@ public class Short256VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueShort256VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Short512VectorTests.java b/test/jdk/jdk/incubator/vector/Short512VectorTests.java index 5044f8db482..776ba2115b8 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorTests.java @@ -1115,6 +1115,12 @@ public class Short512VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -4494,7 +4500,7 @@ public class Short512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueShort512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4518,7 +4524,7 @@ public class Short512VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueShort512VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/Short64VectorTests.java b/test/jdk/jdk/incubator/vector/Short64VectorTests.java index bc12c3f0938..9903759f8f3 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorTests.java @@ -1115,6 +1115,12 @@ public class Short64VectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -4494,7 +4500,7 @@ public class Short64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueShort64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4518,7 +4524,7 @@ public class Short64VectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueShort64VectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java index ec2df02b171..2e5c37d8cc6 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorTests.java @@ -1120,6 +1120,12 @@ public class ShortMaxVectorTests extends AbstractVectorTest { .flatMap(pair -> SHORT_SATURATING_GENERATORS_ASSOC.stream().map(f -> List.of(pair.get(0), pair.get(1), f))) .collect(Collectors.toList()); + @DataProvider + public Object[][] boolUnaryOpProvider() { + return BOOL_ARRAY_GENERATORS.stream(). + map(f -> new Object[]{f}). + toArray(Object[][]::new); + } static final List>> SHORT_GENERATOR_TRIPLES = SHORT_GENERATOR_PAIRS.stream(). @@ -4499,7 +4505,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void anyTrueShortMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); @@ -4523,7 +4529,7 @@ public class ShortMaxVectorTests extends AbstractVectorTest { return res; } - @Test(dataProvider = "boolMaskUnaryOpProvider") + @Test(dataProvider = "boolUnaryOpProvider") static void allTrueShortMaxVectorTests(IntFunction fm) { boolean[] mask = fm.apply(SPECIES.length()); boolean[] r = fmr.apply(SPECIES.length()); From c46bed7292aad21b8cf9defcccac43c010a1f116 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Fri, 12 Dec 2025 04:03:33 +0000 Subject: [PATCH 063/211] 8371502: serviceability/jvmti/vthread/ThreadListStackTracesTest/ThreadListStackTracesTest.java failing Reviewed-by: lmesnik, amenkov --- .../ThreadListStackTracesTest.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadListStackTracesTest/ThreadListStackTracesTest.java b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadListStackTracesTest/ThreadListStackTracesTest.java index 98695390ef7..079f65620d8 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadListStackTracesTest/ThreadListStackTracesTest.java +++ b/test/hotspot/jtreg/serviceability/jvmti/vthread/ThreadListStackTracesTest/ThreadListStackTracesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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 @@ -44,6 +44,13 @@ abstract class TestTask implements Runnable { } } + public void ensureReadyAndWaiting(Thread vt, Thread.State expState, ReentrantLock rlock) { + // wait while the thread is not ready or thread state is unexpected + while (!threadReady || (vt.getState() != expState) || !rlock.hasQueuedThreads()) { + sleep(1); + } + } + public void ensureReady(Thread vt, Thread.State expState) { // wait while the thread is not ready or thread state is unexpected while (!threadReady || (vt.getState() != expState)) { @@ -97,7 +104,7 @@ public class ThreadListStackTracesTest { String name = "ReentrantLockTestTask"; TestTask task = new ReentrantLockTestTask(); Thread vt = Thread.ofVirtual().name(name).start(task); - task.ensureReady(vt, expState); + task.ensureReadyAndWaiting(vt, expState, reentrantLock); checkStates(vt, expState); } From 325cdb7fc5cd2ce1d2c2bf08ca064fb0f7e5a0b8 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Fri, 12 Dec 2025 05:46:33 +0000 Subject: [PATCH 064/211] 8373517: Revert the macos Tahoe specific change done in JDK-8359830 Reviewed-by: rriggs, bpb --- .../macosx/native/libjava/java_props_macosx.c | 50 ++++++------------- 1 file changed, 16 insertions(+), 34 deletions(-) diff --git a/src/java.base/macosx/native/libjava/java_props_macosx.c b/src/java.base/macosx/native/libjava/java_props_macosx.c index 6656bf04efc..94749ee3efe 100644 --- a/src/java.base/macosx/native/libjava/java_props_macosx.c +++ b/src/java.base/macosx/native/libjava/java_props_macosx.c @@ -23,7 +23,6 @@ * questions. */ -#include #include #include #include @@ -230,50 +229,33 @@ void setOSNameAndVersion(java_props_t *sprops) { NSString *nsVerStr = NULL; char* osVersionCStr = NULL; NSOperatingSystemVersion osVer = [[NSProcessInfo processInfo] operatingSystemVersion]; - // Some macOS versions require special handling. For example, - // when the NSOperatingSystemVersion reports 10.16 as the version - // then it should be treated as 11. Similarly, when it reports 16.0 - // as the version then it should be treated as 26. - // If the SYSTEM_VERSION_COMPAT environment variable (a macOS construct) - // is set to 1, then we don't do any special handling for any versions - // and just literally use the value that NSOperatingSystemVersion reports. - const char* envVal = getenv("SYSTEM_VERSION_COMPAT"); - const bool versionCompatEnabled = envVal != NULL - && strncmp(envVal, "1", 1) == 0; - const bool requiresSpecialHandling = - ((long) osVer.majorVersion == 10 && (long) osVer.minorVersion >= 16) - || ((long) osVer.majorVersion == 16 && (long) osVer.minorVersion >= 0); - if (!requiresSpecialHandling || versionCompatEnabled) { - // no special handling - just use the version reported - // by NSOperatingSystemVersion - if (osVer.patchVersion == 0) { - // Omit trailing ".0" + // Copy out the char* if running on version other than 10.16 Mac OS (10.16 == 11.x) + // or explicitly requesting version compatibility + if (!((long)osVer.majorVersion == 10 && (long)osVer.minorVersion >= 16) || + (getenv("SYSTEM_VERSION_COMPAT") != NULL)) { + if (osVer.patchVersion == 0) { // Omit trailing ".0" nsVerStr = [NSString stringWithFormat:@"%ld.%ld", (long)osVer.majorVersion, (long)osVer.minorVersion]; } else { nsVerStr = [NSString stringWithFormat:@"%ld.%ld.%ld", - (long)osVer.majorVersion, (long)osVer.minorVersion, - (long)osVer.patchVersion]; + (long)osVer.majorVersion, (long)osVer.minorVersion, (long)osVer.patchVersion]; } } else { - // Requires special handling. We ignore the version reported - // by the NSOperatingSystemVersion API and instead read the - // *real* ProductVersion from - // /System/Library/CoreServices/.SystemVersionPlatform.plist. - // If not found there, then as a last resort we fallback to - // /System/Library/CoreServices/SystemVersion.plist - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: - @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; + // Version 10.16, without explicit env setting of SYSTEM_VERSION_COMPAT + // AKA 11+ Read the *real* ProductVersion from the hidden link to avoid SYSTEM_VERSION_COMPAT + // If not found, fallback below to the SystemVersion.plist + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : + @"/System/Library/CoreServices/.SystemVersionPlatform.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey: @"ProductVersion"]; + nsVerStr = [version objectForKey : @"ProductVersion"]; } } - // Last resort - fallback to reading the SystemVersion.plist + // Fallback to reading the SystemVersion.plist if (nsVerStr == NULL) { - NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile: - @"/System/Library/CoreServices/SystemVersion.plist"]; + NSDictionary *version = [NSDictionary dictionaryWithContentsOfFile : + @"/System/Library/CoreServices/SystemVersion.plist"]; if (version != NULL) { - nsVerStr = [version objectForKey: @"ProductVersion"]; + nsVerStr = [version objectForKey : @"ProductVersion"]; } } From 650de99fc662a3e8473391627df9e523b6b80727 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 12 Dec 2025 07:17:17 +0000 Subject: [PATCH 065/211] 8367158: C2: create better fill and copy benchmarks, taking alignment into account Reviewed-by: qamai, kvn --- .../compiler/VectorBulkOperationsArray.java | 774 ++++++++++++++++++ .../VectorBulkOperationsMemorySegment.java | 374 +++++++++ 2 files changed, 1148 insertions(+) create mode 100644 test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsArray.java create mode 100644 test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsMemorySegment.java diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsArray.java b/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsArray.java new file mode 100644 index 00000000000..2b055779ff6 --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsArray.java @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2025, 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 org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import java.util.concurrent.TimeUnit; +import java.util.Random; +import java.util.Arrays; + +/** + * This benchmark is here to measure vectorized peformance for some simple bulk operations: + * - fill + * - copy + * + * We may add more in the future, for example: + * - comparison + * - find index + * - filter + * - ... + * + * One important feature of this benchmark, is that we control for alignment and 4k-aliasing, + * something almost no benchmarks have considered up to now. But it is important to get more + * precise, clean and reliable results. + * + * Note, you may want to play with "-XX:-OptimizeFill" for the fill benchmarks, so that we do + * not use the fill-intrinsic, but auto-vectorize. Though I'm currently not seeing a difference, + * maybe the loop is not recognized properly? Maybe the alignment "randomization" prevents it. + * + * Please also look at the companion benchmark: + * VectorBulkOperationsMemorySegment.java + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 3, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Fork(value = 1) +public class VectorBulkOperationsArray { + @Param({ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", + "100","101","102","103","104","105","106","107","108","109", + "110","111","112","113","114","115","116","117","118","119", + "120","121","122","123","124","125","126","127","128","129", + "130","131","132","133","134","135","136","137","138","139", + "140","141","142","143","144","145","146","147","148","149", + "150","151","152","153","154","155","156","157","158","159", + "160","161","162","163","164","165","166","167","168","169", + "170","171","172","173","174","175","176","177","178","179", + "180","181","182","183","184","185","186","187","188","189", + "190","191","192","193","194","195","196","197","198","199", + "200","201","202","203","204","205","206","207","208","209", + "210","211","212","213","214","215","216","217","218","219", + "220","221","222","223","224","225","226","227","228","229", + "230","231","232","233","234","235","236","237","238","239", + "240","241","242","243","244","245","246","247","248","249", + "250","251","252","253","254","255","256","257","258","259", + "260","261","262","263","264","265","266","267","268","269", + "270","271","272","273","274","275","276","277","278","279", + "280","281","282","283","284","285","286","287","288","289", + "290","291","292","293","294","295","296","297","298","299", + "300"}) + public static int NUM_ACCESS_ELEMENTS; + // This is just a default to investigate small iteration loops. + + // Every array has two regions: + // - read region + // - write region + // We should make sure that the region is a multiple of 4k, so that the + // 4k-aliasing prevention trick can work. If we used two arrays, then + // we would not know what the relative offset is between them, so we could + // not do anything about the 4k-aliasing effects. + // Background on 4k-aliasing: many modern CPUs have a store-to-load-forwarding + // mechanism that speeds up loads if the memory locations that were recently + // stored to. For this, the CPU needs to check if there is a store in the store + // buffer with the same address and size. There are various implementations + // with different performance characteristics on various CPUs. For x86, there + // is a special mechanism that quickly checks the lowest 12bits of the address, + // to see if there is a match. If there is a match on the 12bits, we then + // have to eventually check the rest of the bits. There seems to be something + // speculative going on, and so if we eventually find that there is a match + // things are really fast. But if we eventually find that the rest of the + // bits do not match, we have to abort and redo the load from memory/cache, + // and that can be slower than if we had gone to memory/cache directly. Hence, + // if we regularly have matches on the 12bits, but mismatches on the other + // bits, we can be slower than expected. 12bits of address gives us a cyclic + // patterns every 4k bytes. So if you load/store with a distance of 4k or + // a multiple, you can see slower performance than expected, you get a dip/ + // spike in the curve that is a strange artifact. We would like to avoid this + // in our benchmark. That is why we make sure to have k * 4k + 2k offset + // between load and store. + // + // It would be ince to set REGION_SIZE statically, but we want to keep it rather small if possible, + // to avoid running out of cache. But it might be quite large if NUM_ACCESS_ELEMENTS is large. + public static int REGION_SIZE = -1024; + public static final int REGION_2_BYTE_OFFSET = 1024 * 2; // prevent 4k-aliasing + public static final int REGION_2_SHORT_OFFSET = REGION_2_BYTE_OFFSET / 2; + public static final int REGION_2_CHAR_OFFSET = REGION_2_BYTE_OFFSET / 2; + public static final int REGION_2_INT_OFFSET = REGION_2_BYTE_OFFSET / 4; + public static final int REGION_2_LONG_OFFSET = REGION_2_BYTE_OFFSET / 8; + public static final int REGION_2_FLOAT_OFFSET = REGION_2_BYTE_OFFSET / 4; + public static final int REGION_2_DOUBLE_OFFSET = REGION_2_BYTE_OFFSET / 8; + // For Objects, it could be 4 or 8 bytes. Dividing by 8 gives us something + // reasonable for both cases. + public static final int REGION_2_OBJECT_OFFSET = REGION_2_BYTE_OFFSET / 8; + + // The arrays with the two regions each + private byte[] aB; + private short[] aS; + private char[] aC; + private int[] aI; + private long[] aL; + private float[] aF; + private double[] aD; + + // Used when we need variable values in fill. + private byte varB = 42; + private short varS = 42; + private char varC = 42; + private int varI = 42; + private long varL = 42; + private float varF = 42; + private double varD = 42; + + // Classes for Object arrays. + static class A { + int x; + A(int x) { + this.x = x; + } + } + static class B extends A { + int y; + B(int x, int y) { + super(x); + this.y = y; + } + } + private A[] aOA; + private B[] aOB; + private A varOA = new A(-1); + private B varOB = new B(-1, -1); + + // Number of repetitions, to randomize the offsets. + public static final int REPETITIONS = 64 * 64; + + @CompilerControl(CompilerControl.Mode.INLINE) + public static int offsetLoad(int i) { return i & 63; } // bits 0-7, value from 0-63 + + @CompilerControl(CompilerControl.Mode.INLINE) + public static int offsetStore(int i) { return (i >> 8) & 63; } // bits 8-15, value from 0-63 + + @Param("42") + private int seed; + private Random r = new Random(seed); + + public static int roundUp4k(int i) { + return (i + 4*1024-1) & (-4*1024); + } + + @Setup + public void init() { + // Make sure we can fit the longs, and then some whiggle room for alignment. + REGION_SIZE = roundUp4k(NUM_ACCESS_ELEMENTS * 8 + 1024 + REGION_2_BYTE_OFFSET); + aB = new byte[2 * REGION_SIZE]; + aC = new char[2 * REGION_SIZE]; + aS = new short[2 * REGION_SIZE]; + aI = new int[2 * REGION_SIZE]; + aL = new long[2 * REGION_SIZE]; + aF = new float[2 * REGION_SIZE]; + aD = new double[2 * REGION_SIZE]; + aOA = new A[2 * REGION_SIZE]; + aOB = new B[2 * REGION_SIZE]; + + for (int i = 0; i < 2 * REGION_SIZE; i++) { + aB[i] = (byte) r.nextInt(); + aS[i] = (short) r.nextInt(); + aC[i] = (char) r.nextInt(); + aI[i] = r.nextInt(); + aL[i] = r.nextLong(); + aF[i] = r.nextFloat(); + aD[i] = r.nextDouble(); + aOA[i] = switch (i % 4) { + case 0, 1 -> new A(i); + case 2 -> new B(i, i); + default -> null; + }; + aOB[i] = (i % 3 != 0) ? new B(i, i) : null; + } + } + + // -------------------------------- BYTE ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aB[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aB[i + offset_store] = varB; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_byte_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + Arrays.fill(aB, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (byte)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_byte_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + Arrays.fill(aB, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varB); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aB[i + offset_store] = aB[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_byte_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + System.arraycopy(aB, offset_load, aB, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- CHAR ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_char_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aC[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_char_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aC[i + offset_store] = varC; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_char_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + Arrays.fill(aC, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (char)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_char_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + Arrays.fill(aC, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varC); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_char_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aC[i + offset_store] = aC[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_char_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_CHAR_OFFSET; + System.arraycopy(aC, offset_load, aC, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- SHORT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_short_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aS[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_short_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aS[i + offset_store] = varS; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_short_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + Arrays.fill(aS, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (short)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_short_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + Arrays.fill(aS, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varS); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_short_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aS[i + offset_store] = aS[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_short_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_SHORT_OFFSET; + System.arraycopy(aS, offset_load, aS, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- INT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_int_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aI[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_int_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aI[i + offset_store] = varI; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_int_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + Arrays.fill(aI, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (int)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_int_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + Arrays.fill(aI, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varI); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_int_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aI[i + offset_store] = aI[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_int_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_INT_OFFSET; + System.arraycopy(aI, offset_load, aI, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- LONG ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_long_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aL[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_long_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aL[i + offset_store] = varL; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_long_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + Arrays.fill(aL, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (long)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_long_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + Arrays.fill(aL, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varL); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_long_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aL[i + offset_store] = aL[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_long_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_LONG_OFFSET; + System.arraycopy(aL, offset_load, aL, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- FLOAT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_float_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aF[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_float_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aF[i + offset_store] = varF; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_float_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + Arrays.fill(aF, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (float)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_float_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + Arrays.fill(aF, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varF); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_float_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aF[i + offset_store] = aF[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_float_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_FLOAT_OFFSET; + System.arraycopy(aF, offset_load, aF, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- DOUBLE ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_double_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aD[i + offset_store] = 0; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_double_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aD[i + offset_store] = varD; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_double_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + Arrays.fill(aD, offset_store, offset_store + NUM_ACCESS_ELEMENTS, (double)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_double_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + Arrays.fill(aD, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varD); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_double_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aD[i + offset_store] = aD[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_double_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_DOUBLE_OFFSET; + System.arraycopy(aD, offset_load, aD, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- OBJECT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_null_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aOA[i + offset_store] = null; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_A2A_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aOA[i + offset_store] = varOA; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_B2A_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aOA[i + offset_store] = varOB; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_null_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + Arrays.fill(aOA, offset_store, offset_store + NUM_ACCESS_ELEMENTS, null); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_A2A_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + Arrays.fill(aOA, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varOA); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_B2A_arrays_fill() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + Arrays.fill(aOA, offset_store, offset_store + NUM_ACCESS_ELEMENTS, varOB); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_A2A_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aOA[i + offset_store] = aOA[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_B2A_loop() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + for (int i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + aOA[i + offset_store] = aOB[i + offset_load]; + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_A2A_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + System.arraycopy(aOA, offset_load, aOA, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_B2A_system_arraycopy() { + for (int r = 0; r < REPETITIONS; r++) { + int offset_load = offsetLoad(r); + int offset_store = offsetStore(r) + REGION_SIZE + REGION_2_OBJECT_OFFSET; + System.arraycopy(aOB, offset_load, aOA, offset_store, NUM_ACCESS_ELEMENTS); + } + } +} diff --git a/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsMemorySegment.java b/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsMemorySegment.java new file mode 100644 index 00000000000..fae12a4ac9d --- /dev/null +++ b/test/micro/org/openjdk/bench/vm/compiler/VectorBulkOperationsMemorySegment.java @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2025, 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 org.openjdk.bench.vm.compiler; + +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.*; + +import java.lang.foreign.*; +import java.util.concurrent.TimeUnit; +import java.util.Random; +import java.util.Arrays; + +/** + * This benchmark is here to measure vectorized peformance for some simple bulk operations: + * - fill + * - copy + * + * We may add more in the future, for example: + * - comparison + * - find index + * - filter + * - ... + * + * One important feature of this benchmark, is that we control for alignment and 4k-aliasing, + * something almost no benchmarks have considered up to now. But it is important to get more + * precise, clean and reliable results. + * + * Please also look at the companion benchmark: + * VectorBulkOperationsArray.java + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +@State(Scope.Thread) +@Warmup(iterations = 3, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 5, time = 1000, timeUnit = TimeUnit.MILLISECONDS) +@Fork(value = 1) +public class VectorBulkOperationsMemorySegment { + @Param({ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", + "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", + "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", + "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", + "40", "41", "42", "43", "44", "45", "46", "47", "48", "49", + "50", "51", "52", "53", "54", "55", "56", "57", "58", "59", + "60", "61", "62", "63", "64", "65", "66", "67", "68", "69", + "70", "71", "72", "73", "74", "75", "76", "77", "78", "79", + "80", "81", "82", "83", "84", "85", "86", "87", "88", "89", + "90", "91", "92", "93", "94", "95", "96", "97", "98", "99", + "100","101","102","103","104","105","106","107","108","109", + "110","111","112","113","114","115","116","117","118","119", + "120","121","122","123","124","125","126","127","128","129", + "130","131","132","133","134","135","136","137","138","139", + "140","141","142","143","144","145","146","147","148","149", + "150","151","152","153","154","155","156","157","158","159", + "160","161","162","163","164","165","166","167","168","169", + "170","171","172","173","174","175","176","177","178","179", + "180","181","182","183","184","185","186","187","188","189", + "190","191","192","193","194","195","196","197","198","199", + "200","201","202","203","204","205","206","207","208","209", + "210","211","212","213","214","215","216","217","218","219", + "220","221","222","223","224","225","226","227","228","229", + "230","231","232","233","234","235","236","237","238","239", + "240","241","242","243","244","245","246","247","248","249", + "250","251","252","253","254","255","256","257","258","259", + "260","261","262","263","264","265","266","267","268","269", + "270","271","272","273","274","275","276","277","278","279", + "280","281","282","283","284","285","286","287","288","289", + "290","291","292","293","294","295","296","297","298","299", + "300"}) + public static long NUM_ACCESS_ELEMENTS; + + @Param({"native", "array_byte", "array_int", "array_long"}) + public static String BACKING_TYPE; + + // Every array has two regions: + // - read region + // - write region + // We should make sure that the region is a multiple of 4k, so that the + // 4k-aliasing prevention trick can work. + // See VectorBulkOperationsArray.java for a deeper explanation. + // + // It would be ince to set REGION_SIZE statically, but we want to keep it rather small if possible, + // to avoid running out of cache. But it might be quite large if NUM_ACCESS_ELEMENTS is large. + public static long REGION_SIZE = -1024; + public static final long REGION_2_BYTE_OFFSET = 1024 * 2; // prevent 4k-aliasing + + // TDOO: see what is still actie up here. + + // Just one MemorySegment for all cases, backed by whatever BACKING_TYPE. + MemorySegment ms; + + // Used when we need variable values in fill. + private byte varB = 42; + private short varS = 42; + private char varC = 42; + private int varI = 42; + private long varL = 42; + private float varF = 42; + private double varD = 42; + + // Number of repetitions, to randomize the offsets. + public static final int REPETITIONS = 64 * 64; + + @CompilerControl(CompilerControl.Mode.INLINE) + public static long offsetLoad(long i) { return i & 63; } // bits 0-7, value from 0-63 + + @CompilerControl(CompilerControl.Mode.INLINE) + public static long offsetStore(long i) { return (i >> 8) & 63; } // bits 8-15, value from 0-63 + + @Param("42") + private int seed; + private Random r = new Random(seed); + + public static long roundUp4k(long i) { + return (i + 4*1024-1) & (-4*1024L); + } + + @Setup + public void init() { + // Make sure we can fit the longs, and then some whiggle room for alignment. + REGION_SIZE = roundUp4k(NUM_ACCESS_ELEMENTS * 8 + 1024 + REGION_2_BYTE_OFFSET); + ms = switch(BACKING_TYPE) { + case "native" -> Arena.ofAuto().allocate(2 * REGION_SIZE, 4 * 1024); + case "array_byte" -> MemorySegment.ofArray(new byte[(int)(2 * REGION_SIZE)]); + case "array_int" -> MemorySegment.ofArray(new int[(int)(2 * REGION_SIZE / 4)]); + case "array_long" -> MemorySegment.ofArray(new long[(int)(2 * REGION_SIZE / 8)]); + default -> throw new RuntimeException("not implemented: " + BACKING_TYPE); + }; + } + + // -------------------------------- BYTE ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_BYTE, i + offset_store, (byte)0); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_BYTE, i + offset_store, varB); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_zero_byte_MS_fill() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + // The API does not allow us to fill a sub-segment directly, so we have to slice. + MemorySegment slice = ms.asSlice(offset_store, NUM_ACCESS_ELEMENTS); + slice.fill((byte)0); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_byte_MS_fill() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + // The API does not allow us to fill a sub-segment directly, so we have to slice. + MemorySegment slice = ms.asSlice(offset_store, NUM_ACCESS_ELEMENTS); + slice.fill(varB); + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_byte_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = offsetLoad(r); + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + byte v = ms.get(ValueLayout.JAVA_BYTE, i + offset_load); + ms.set(ValueLayout.JAVA_BYTE, i + offset_store, v); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_byte_MemorySegment_copy() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = offsetLoad(r); + long offset_store = offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + MemorySegment.copy(ms, offset_load, ms, offset_store, NUM_ACCESS_ELEMENTS); + } + } + + // -------------------------------- CHAR ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_char_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 2L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_CHAR_UNALIGNED, 2L * i + offset_store, varC); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_char_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 2L * offsetLoad(r); + long offset_store = 2L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + char v = ms.get(ValueLayout.JAVA_CHAR_UNALIGNED, 2L * i + offset_load); + ms.set(ValueLayout.JAVA_CHAR_UNALIGNED, 2L * i + offset_store, v); + } + } + } + + // -------------------------------- SHORT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_short_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 2L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_SHORT_UNALIGNED, 2L * i + offset_store, varS); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_short_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 2L * offsetLoad(r); + long offset_store = 2L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + short v = ms.get(ValueLayout.JAVA_SHORT_UNALIGNED, 2L * i + offset_load); + ms.set(ValueLayout.JAVA_SHORT_UNALIGNED, 2L * i + offset_store, v); + } + } + } + + // -------------------------------- INT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_int_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 4L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_INT_UNALIGNED, 4L * i + offset_store, varI); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_int_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 4L * offsetLoad(r); + long offset_store = 4L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + int v = ms.get(ValueLayout.JAVA_INT_UNALIGNED, 4L * i + offset_load); + ms.set(ValueLayout.JAVA_INT_UNALIGNED, 4L * i + offset_store, v); + } + } + } + + // -------------------------------- LONG ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_long_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 8L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_LONG_UNALIGNED, 8L * i + offset_store, varL); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_long_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 8L * offsetLoad(r); + long offset_store = 8L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + long v = ms.get(ValueLayout.JAVA_LONG_UNALIGNED, 8L * i + offset_load); + ms.set(ValueLayout.JAVA_LONG_UNALIGNED, 8L * i + offset_store, v); + } + } + } + + // -------------------------------- FLOAT ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_float_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 4L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_FLOAT_UNALIGNED, 4L * i + offset_store, varS); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_float_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 4L * offsetLoad(r); + long offset_store = 4L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + float v = ms.get(ValueLayout.JAVA_FLOAT_UNALIGNED, 4L * i + offset_load); + ms.set(ValueLayout.JAVA_FLOAT_UNALIGNED, 4L * i + offset_store, v); + } + } + } + + // -------------------------------- DOUBLE ------------------------------ + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void fill_var_double_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_store = 8L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + ms.set(ValueLayout.JAVA_DOUBLE_UNALIGNED, 8L * i + offset_store, varS); + } + } + } + + @Benchmark + @OperationsPerInvocation(REPETITIONS) + public void copy_double_loop() { + for (int r = 0; r < REPETITIONS; r++) { + long offset_load = 8L * offsetLoad(r); + long offset_store = 8L * offsetStore(r) + REGION_SIZE + REGION_2_BYTE_OFFSET; + for (long i = 0; i < NUM_ACCESS_ELEMENTS; i++) { + double v = ms.get(ValueLayout.JAVA_DOUBLE_UNALIGNED, 8L * i + offset_load); + ms.set(ValueLayout.JAVA_DOUBLE_UNALIGNED, 8L * i + offset_store, v); + } + } + } +} From dc6255261f34c65d0e87814638817c97a880eb7f Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Fri, 12 Dec 2025 09:59:33 +0000 Subject: [PATCH 066/211] 8371920: [TEST] Enable CMove tests on other platforms Reviewed-by: fyang, epeter --- .../TestConditionalMove.java | 170 +++++++------- .../{irTests => cmove}/TestFPComparison2.java | 219 ++++++++++++------ .../TestScalarConditionalMoveCmpObj.java | 3 +- 3 files changed, 231 insertions(+), 161 deletions(-) rename test/hotspot/jtreg/compiler/c2/{irTests => cmove}/TestConditionalMove.java (95%) rename test/hotspot/jtreg/compiler/c2/{irTests => cmove}/TestFPComparison2.java (91%) rename test/hotspot/jtreg/compiler/c2/{irTests => cmove}/TestScalarConditionalMoveCmpObj.java (99%) diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java b/test/hotspot/jtreg/compiler/c2/cmove/TestConditionalMove.java similarity index 95% rename from test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java rename to test/hotspot/jtreg/compiler/c2/cmove/TestConditionalMove.java index c531f73b71d..91197322319 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestConditionalMove.java +++ b/test/hotspot/jtreg/compiler/c2/cmove/TestConditionalMove.java @@ -36,7 +36,7 @@ import jdk.test.lib.Utils; * @key randomness * @summary Auto-vectorization enhancement to support vector conditional move. * @library /test/lib / - * @run driver compiler.c2.irTests.TestConditionalMove + * @run driver ${test.main.class} */ public class TestConditionalMove { @@ -601,7 +601,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVFGT(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? a[i] : b[i]; @@ -619,7 +619,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVFGTSwap(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] > a[i]) ? a[i] : b[i]; @@ -637,7 +637,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVFLT(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? a[i] : b[i]; @@ -655,7 +655,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVFLTSwap(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] < a[i]) ? a[i] : b[i]; @@ -673,7 +673,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVFEQ(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? a[i] : b[i]; @@ -691,7 +691,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVDLE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? a[i] : b[i]; @@ -709,7 +709,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVDLESwap(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] <= a[i]) ? a[i] : b[i]; @@ -727,7 +727,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVDGE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? a[i] : b[i]; @@ -745,7 +745,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVDGESwap(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (b[i] >= a[i]) ? a[i] : b[i]; @@ -763,7 +763,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveVDNE(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? a[i] : b[i]; @@ -782,7 +782,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGTforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? 0.1f : -0.1f; @@ -800,7 +800,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGEforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? 0.1f : -0.1f; @@ -818,7 +818,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFLTforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? 0.1f : -0.1f; @@ -836,7 +836,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFLEforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? 0.1f : -0.1f; @@ -854,7 +854,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFEQforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? 0.1f : -0.1f; @@ -872,7 +872,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFNEQforFConst(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? 0.1f : -0.1f; @@ -896,7 +896,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFLTforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; @@ -925,7 +925,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFLEforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; @@ -948,7 +948,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFYYforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1f : -0.1f; @@ -967,7 +967,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFXXforFConstH2(float[] a, float[] b, float[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1f : -0.1f; @@ -986,7 +986,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDGTforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] > b[i]) ? 0.1 : -0.1; @@ -1004,7 +1004,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDGEforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] >= b[i]) ? 0.1 : -0.1; @@ -1022,7 +1022,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDLTforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] < b[i]) ? 0.1 : -0.1; @@ -1040,7 +1040,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDLEforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] <= b[i]) ? 0.1 : -0.1; @@ -1058,7 +1058,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDEQforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] == b[i]) ? 0.1 : -0.1; @@ -1076,7 +1076,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDNEQforDConst(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i++) { c[i] = (a[i] != b[i]) ? 0.1 : -0.1; @@ -1094,7 +1094,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDLTforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; @@ -1113,7 +1113,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDLEforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; @@ -1132,7 +1132,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDYYforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] <= b[i+0]) ? 0.1 : -0.1; @@ -1151,7 +1151,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDXXforDConstH2(double[] a, double[] b, double[] c) { for (int i = 0; i < a.length; i+=2) { c[i+0] = (a[i+0] < b[i+0]) ? 0.1 : -0.1; @@ -1351,7 +1351,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIEQforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1373,7 +1373,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveINEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1395,7 +1395,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1417,7 +1417,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIGEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1439,7 +1439,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveILTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1461,7 +1461,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveILEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1476,7 +1476,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIEQforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1490,7 +1490,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveINEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1504,7 +1504,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1518,7 +1518,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveIGEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1532,7 +1532,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveILTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1546,7 +1546,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_I, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveILEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -1731,7 +1731,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLEQforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1745,7 +1745,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLNEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1759,7 +1759,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1773,7 +1773,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLGEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1787,7 +1787,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLLTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1801,7 +1801,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveLLEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -1824,7 +1824,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLEQforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1847,7 +1847,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLNEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1870,7 +1870,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1893,7 +1893,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLGEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1916,7 +1916,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLLTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -1939,7 +1939,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_L, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveLLEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2134,7 +2134,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIEQforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2156,7 +2156,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUINEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2178,7 +2178,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIGTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2200,7 +2200,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIGEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2222,7 +2222,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUILTforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2244,7 +2244,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUILEforF(int[] a, int[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2259,7 +2259,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIEQforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2273,7 +2273,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUINEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2287,7 +2287,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIGTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2301,7 +2301,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUIGEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2315,7 +2315,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUILTforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2329,7 +2329,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_U, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveUILEforD(int[] a, int[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2514,7 +2514,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULEQforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2528,7 +2528,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULNEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2542,7 +2542,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULGTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2556,7 +2556,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULGEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2570,7 +2570,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULLTforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2584,7 +2584,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveULLEforF(long[] a, long[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2607,7 +2607,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULEQforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2630,7 +2630,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULNEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2653,7 +2653,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULGTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2676,7 +2676,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULGEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2699,7 +2699,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULLTforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2722,7 +2722,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_UL, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) // Requires avx2, else L is restricted to 16 byte, and D has 32. That leads to a vector elements mismatch of 2 to 4. private static void testCMoveULLEforD(long[] a, long[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { @@ -2772,7 +2772,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGTforF(float[] a, float[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2786,7 +2786,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGTforD(float[] a, float[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2828,7 +2828,7 @@ public class TestConditionalMove { @IR(failOn = {IRNode.STORE_VECTOR}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDGTforF(double[] a, double[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; @@ -2849,7 +2849,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_D, ">0", IRNode.CMP_D, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveDGTforD(double[] a, double[] b, double[] c, double[] d, double[] r, double[] r2) { for (int i = 0; i < a.length; i++) { double cc = c[i]; @@ -2871,7 +2871,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGTforFCmpCon1(float a, float[] b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < b.length; i++) { float cc = c[i]; @@ -2892,7 +2892,7 @@ public class TestConditionalMove { applyIf = {"UseVectorCmov", "false"}) @IR(counts = {IRNode.CMOVE_F, ">0", IRNode.CMP_F, ">0"}, applyIf = {"UseVectorCmov", "false"}, - applyIfPlatform = {"riscv64", "true"}) + applyIfPlatformOr = {"riscv64", "true", "x64", "true", "aarch64", "true"}) private static void testCMoveFGTforFCmpCon2(float[] a, float b, float[] c, float[] d, float[] r, float[] r2) { for (int i = 0; i < a.length; i++) { float cc = c[i]; diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java b/test/hotspot/jtreg/compiler/c2/cmove/TestFPComparison2.java similarity index 91% rename from test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java rename to test/hotspot/jtreg/compiler/c2/cmove/TestFPComparison2.java index 8cf3f728666..dca1f964231 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison2.java +++ b/test/hotspot/jtreg/compiler/c2/cmove/TestFPComparison2.java @@ -30,10 +30,9 @@ import java.util.List; * @test * @bug 8358892 8357551 * @summary The test is to trigger code path of BoolTest::ge/gt in C2_MacroAssembler::enc_cmove_cmp_fp - * @requires os.arch == "riscv64" * @requires vm.debug * @library /test/lib / - * @run driver compiler.c2.irTests.TestFPComparison2 + * @run driver ${test.main.class} */ public class TestFPComparison2 { static final double[] DOUBLES = new double[] { @@ -109,7 +108,8 @@ public class TestFPComparison2 { class Test_ge_1 { @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -124,7 +124,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -139,7 +140,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_0_1(float x, float y) { return !(x <= y) ? 0 : 1; } @@ -149,7 +151,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_0_1(double x, double y) { return !(x <= y) ? 0 : 1; } @@ -159,7 +162,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_10_20(float x, float y) { return !(x <= y) ? 10 : 20; } @@ -169,7 +173,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_10_20(double x, double y) { return !(x <= y) ? 10 : 20; } @@ -179,7 +184,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { return !(x <= y) ? a : b; } @@ -189,7 +195,8 @@ class Test_ge_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { return !(x <= y) ? a : b; } @@ -338,7 +345,8 @@ class Test_ge_1 { class Test_ge_cmove_fp_1 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -353,7 +361,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -368,7 +377,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_0_1(float x, float y) { return !(x <= y) ? 0.0f : 1.0f; } @@ -378,7 +388,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_0_1(double x, double y) { return !(x <= y) ? 0.0f : 1.0f; } @@ -388,7 +399,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_10_20(float x, float y) { return !(x <= y) ? 10.0f : 20.0f; } @@ -398,7 +410,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_10_20(double x, double y) { return !(x <= y) ? 10.0f : 20.0f; } @@ -408,7 +421,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { return !(x <= y) ? a : b; } @@ -418,7 +432,8 @@ class Test_ge_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { return !(x <= y) ? a : b; } @@ -566,7 +581,8 @@ class Test_ge_cmove_fp_1 { class Test_ge_2 { @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -581,7 +597,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -596,7 +613,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_0_1(float x, float y) { return !(x >= y) ? 0 : 1; } @@ -606,7 +624,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_0_1(double x, double y) { return !(x >= y) ? 0 : 1; } @@ -616,7 +635,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_fixed_10_20(float x, float y) { return !(x >= y) ? 10 : 20; } @@ -626,7 +646,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_fixed_10_20(double x, double y) { return !(x >= y) ? 10 : 20; } @@ -636,7 +657,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_ge_variable_results(float x, float y, int a, int b) { return !(x >= y) ? a : b; } @@ -646,7 +668,8 @@ class Test_ge_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_ge_variable_results(double x, double y, int a, int b) { return !(x >= y) ? a : b; } @@ -794,7 +817,8 @@ class Test_ge_2 { class Test_ge_cmove_fp_2 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -809,7 +833,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -824,7 +849,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_0_1(float x, float y) { return !(x >= y) ? 0.0f : 1.0f; } @@ -834,7 +860,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_0_1(double x, double y) { return !(x >= y) ? 0.0f : 1.0f; } @@ -844,7 +871,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_fixed_10_20(float x, float y) { return !(x >= y) ? 10.0f : 20.0f; } @@ -854,7 +882,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_fixed_10_20(double x, double y) { return !(x >= y) ? 10.0f : 20.0f; } @@ -864,7 +893,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_variable_results(float x, float y, float a, float b) { return !(x >= y) ? a : b; } @@ -874,7 +904,8 @@ class Test_ge_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_ge_variable_results(double x, double y, float a, float b) { return !(x >= y) ? a : b; } @@ -1022,7 +1053,8 @@ class Test_ge_cmove_fp_2 { class Test_gt_1 { @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -1037,7 +1069,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -1052,7 +1085,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_0_1(float x, float y) { return !(x < y) ? 0 : 1; } @@ -1062,7 +1096,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_0_1(double x, double y) { return !(x < y) ? 0 : 1; } @@ -1072,7 +1107,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_10_20(float x, float y) { return !(x < y) ? 10 : 20; } @@ -1082,7 +1118,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_10_20(double x, double y) { return !(x < y) ? 10 : 20; } @@ -1092,7 +1129,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { return !(x < y) ? a : b; } @@ -1102,7 +1140,8 @@ class Test_gt_1 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { return !(x < y) ? a : b; } @@ -1250,7 +1289,8 @@ class Test_gt_1 { class Test_gt_cmove_fp_1 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -1265,7 +1305,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -1280,7 +1321,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_0_1(float x, float y) { return !(x < y) ? 0.0f : 1.0f; } @@ -1290,7 +1332,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_0_1(double x, double y) { return !(x < y) ? 0.0f : 1.0f; } @@ -1300,7 +1343,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_10_20(float x, float y) { return !(x < y) ? 10.0f : 20.0f; } @@ -1310,7 +1354,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_10_20(double x, double y) { return !(x < y) ? 10.0f : 20.0f; } @@ -1320,7 +1365,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { return !(x < y) ? a : b; } @@ -1330,7 +1376,8 @@ class Test_gt_cmove_fp_1 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { return !(x < y) ? a : b; } @@ -1478,7 +1525,8 @@ class Test_gt_cmove_fp_1 { class Test_gt_2 { @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -1493,7 +1541,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -1508,7 +1557,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_0_1(float x, float y) { return !(x > y) ? 0 : 1; } @@ -1518,7 +1568,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_0_1(double x, double y) { return !(x > y) ? 0 : 1; } @@ -1528,7 +1579,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_fixed_10_20(float x, float y) { return !(x > y) ? 10 : 20; } @@ -1538,7 +1590,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_fixed_10_20(double x, double y) { return !(x > y) ? 10 : 20; } @@ -1548,7 +1601,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_float_BoolTest_gt_variable_results(float x, float y, int a, int b) { return !(x > y) ? a : b; } @@ -1558,7 +1612,8 @@ class Test_gt_2 { } @Test - @IR(counts = {IRNode.CMOVE_I, "1"}) + @IR(counts = {IRNode.CMOVE_I, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static int test_double_BoolTest_gt_variable_results(double x, double y, int a, int b) { return !(x > y) ? a : b; } @@ -1706,7 +1761,8 @@ class Test_gt_2 { class Test_gt_cmove_fp_2 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_1_0(float x, float y) { // return 1 // when either x or y is NaN @@ -1721,7 +1777,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_1_0(double x, double y) { // return 1 // when either x or y is NaN @@ -1736,7 +1793,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_0_1(float x, float y) { return !(x > y) ? 0.0f : 1.0f; } @@ -1746,7 +1804,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_0_1(double x, double y) { return !(x > y) ? 0.0f : 1.0f; } @@ -1756,7 +1815,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_fixed_10_20(float x, float y) { return !(x > y) ? 10.0f : 20.0f; } @@ -1766,7 +1826,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_fixed_10_20(double x, double y) { return !(x > y) ? 10.0f : 20.0f; } @@ -1776,7 +1837,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_variable_results(float x, float y, float a, float b) { return !(x > y) ? a : b; } @@ -1786,7 +1848,8 @@ class Test_gt_cmove_fp_2 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_double_BoolTest_gt_variable_results(double x, double y, float a, float b) { return !(x > y) ? a : b; } @@ -1934,7 +1997,8 @@ class Test_gt_cmove_fp_2 { class Test_cmov_fp_cmp_fp_ge_3 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_x_lt_0(float x) { return x < 0 ? 0 : x; } @@ -1944,7 +2008,8 @@ class Test_cmov_fp_cmp_fp_ge_3 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_x_gt_0(float x) { return x > 0 ? 0 : x; } @@ -1954,7 +2019,8 @@ class Test_cmov_fp_cmp_fp_ge_3 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_neg_x_lt_0(float x) { return !(x < 0) ? 0 : x; } @@ -1964,7 +2030,8 @@ class Test_cmov_fp_cmp_fp_ge_3 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_gt_neg_x_gt_0(float x) { return !(x > 0) ? 0 : x; } @@ -2038,7 +2105,8 @@ class Test_cmov_fp_cmp_fp_ge_3 { class Test_cmov_fp_cmp_fp_ge_4 { @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_x_le_0(float x) { return x <= 0 ? 0 : x; } @@ -2048,7 +2116,8 @@ class Test_cmov_fp_cmp_fp_ge_4 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_x_ge_0(float x) { return x >= 0 ? 0 : x; } @@ -2058,7 +2127,8 @@ class Test_cmov_fp_cmp_fp_ge_4 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_neg_x_le_0(float x) { return !(x <= 0) ? 0 : x; } @@ -2068,7 +2138,8 @@ class Test_cmov_fp_cmp_fp_ge_4 { } @Test - @IR(counts = {IRNode.CMOVE_F, "1"}) + @IR(counts = {IRNode.CMOVE_F, "1"}, + applyIfPlatformOr = {"riscv64", "true", "aarch64", "true"}) public static float test_float_BoolTest_ge_neg_x_ge_0(float x) { return !(x >= 0) ? 0 : x; } diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java b/test/hotspot/jtreg/compiler/c2/cmove/TestScalarConditionalMoveCmpObj.java similarity index 99% rename from test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java rename to test/hotspot/jtreg/compiler/c2/cmove/TestScalarConditionalMoveCmpObj.java index e332ac9e293..63d6f6fba7f 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestScalarConditionalMoveCmpObj.java +++ b/test/hotspot/jtreg/compiler/c2/cmove/TestScalarConditionalMoveCmpObj.java @@ -31,9 +31,8 @@ import jdk.test.lib.Utils; /* * @test * @summary Test conditional move + compare object. - * @requires vm.simpleArch == "riscv64" * @library /test/lib / - * @run driver compiler.c2.irTests.TestScalarConditionalMoveCmpObj + * @run driver ${test.main.class} */ public class TestScalarConditionalMoveCmpObj { From 180d8c1b57efb29f8f016843d66daca59bb5934f Mon Sep 17 00:00:00 2001 From: Daisuke Yamazaki Date: Fri, 12 Dec 2025 12:04:20 +0000 Subject: [PATCH 067/211] 8372746: Some httpserver files could benefit from some formatting cleanup Reviewed-by: jpai, mikael, michaelm, djelinski, dfuchs --- .../com/sun/net/httpserver/Authenticator.java | 14 +- .../net/httpserver/BasicAuthenticator.java | 34 +- .../com/sun/net/httpserver/Filter.java | 16 +- .../com/sun/net/httpserver/Headers.java | 14 +- .../com/sun/net/httpserver/HttpContext.java | 4 +- .../com/sun/net/httpserver/HttpExchange.java | 6 +- .../com/sun/net/httpserver/HttpHandler.java | 4 +- .../com/sun/net/httpserver/HttpServer.java | 10 +- .../sun/net/httpserver/HttpsConfigurator.java | 14 +- .../com/sun/net/httpserver/HttpsServer.java | 6 +- .../sun/net/httpserver/SimpleFileServer.java | 4 +- .../com/sun/net/httpserver/package-info.java | 33 +- .../httpserver/spi/HttpServerProvider.java | 4 +- .../sun/net/httpserver/AuthFilter.java | 32 +- .../net/httpserver/ChunkedInputStream.java | 40 +- .../net/httpserver/ChunkedOutputStream.java | 32 +- .../classes/sun/net/httpserver/Code.java | 4 +- .../sun/net/httpserver/ContextList.java | 34 +- .../httpserver/DefaultHttpServerProvider.java | 10 +- .../sun/net/httpserver/ExchangeImpl.java | 136 +++---- .../httpserver/FixedLengthInputStream.java | 20 +- .../httpserver/FixedLengthOutputStream.java | 18 +- .../sun/net/httpserver/HttpConnection.java | 46 +-- .../sun/net/httpserver/HttpContextImpl.java | 42 +-- .../classes/sun/net/httpserver/HttpError.java | 6 +- .../sun/net/httpserver/HttpExchangeImpl.java | 48 +-- .../sun/net/httpserver/HttpServerImpl.java | 40 +- .../sun/net/httpserver/HttpsExchangeImpl.java | 52 +-- .../sun/net/httpserver/HttpsServerImpl.java | 46 +-- .../net/httpserver/LeftOverInputStream.java | 34 +- .../classes/sun/net/httpserver/Request.java | 106 +++--- .../sun/net/httpserver/SSLStreams.java | 168 ++++----- .../sun/net/httpserver/ServerImpl.java | 342 +++++++++--------- .../httpserver/UndefLengthOutputStream.java | 16 +- .../net/httpserver/UnmodifiableHeaders.java | 22 +- .../simpleserver/FileServerHandler.java | 2 +- 36 files changed, 729 insertions(+), 730 deletions(-) diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Authenticator.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Authenticator.java index ddef30f0c5c..6bb97e0799a 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Authenticator.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Authenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, 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,7 @@ public abstract class Authenticator { /** * Constructor for subclasses to call. */ - protected Authenticator () { } + protected Authenticator() { } /** * Base class for return type from {@link #authenticate(HttpExchange)} method. @@ -50,7 +50,7 @@ public abstract class Authenticator { /** * Constructor for subclasses to call. */ - protected Result () {} + protected Result() {} } /** @@ -67,7 +67,7 @@ public abstract class Authenticator { * @param responseCode the response code to associate with this * {@code Failure} instance */ - public Failure (int responseCode) { + public Failure(int responseCode) { this.responseCode = responseCode; } @@ -94,7 +94,7 @@ public abstract class Authenticator { * * @param p the authenticated user you wish to set as {@code Principal} */ - public Success (HttpPrincipal p) { + public Success(HttpPrincipal p) { principal = p; } @@ -126,7 +126,7 @@ public abstract class Authenticator { * @param responseCode the response code to associate with this * {@code Retry} instance */ - public Retry (int responseCode) { + public Retry(int responseCode) { this.responseCode = responseCode; } @@ -158,5 +158,5 @@ public abstract class Authenticator { * @param exch the {@code HttpExchange} upon which authenticate is called * @return the result */ - public abstract Result authenticate (HttpExchange exch); + public abstract Result authenticate(HttpExchange exch); } diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java index b2cf78dd992..8c306888370 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/BasicAuthenticator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, 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 @@ -35,7 +35,7 @@ import static java.nio.charset.StandardCharsets.UTF_8; /** * BasicAuthenticator provides an implementation of HTTP Basic * authentication. It is an abstract class and must be extended - * to provide an implementation of {@link #checkCredentials(String,String)} + * to provide an implementation of {@link #checkCredentials(String, String)} * which is called to verify each incoming request. * * @since 1.6 @@ -104,34 +104,34 @@ public abstract class BasicAuthenticator extends Authenticator { * * @return the authenticator's realm string */ - public String getRealm () { + public String getRealm() { return realm; } - public Result authenticate (HttpExchange t) + public Result authenticate(HttpExchange t) { Headers rmap = t.getRequestHeaders(); /* * look for auth token */ - String auth = rmap.getFirst ("Authorization"); + String auth = rmap.getFirst("Authorization"); if (auth == null) { setAuthHeader(t); - return new Authenticator.Retry (401); + return new Authenticator.Retry(401); } - int sp = auth.indexOf (' '); + int sp = auth.indexOf(' '); if (sp == -1 || !auth.substring(0, sp).equalsIgnoreCase("Basic")) { - return new Authenticator.Failure (401); + return new Authenticator.Failure(401); } byte[] b = Base64.getDecoder().decode(auth.substring(sp+1)); - String userpass = new String (b, charset); - int colon = userpass.indexOf (':'); - String uname = userpass.substring (0, colon); - String pass = userpass.substring (colon+1); + String userpass = new String(b, charset); + int colon = userpass.indexOf(':'); + String uname = userpass.substring(0, colon); + String pass = userpass.substring(colon+1); - if (checkCredentials (uname, pass)) { - return new Authenticator.Success ( - new HttpPrincipal ( + if (checkCredentials(uname, pass)) { + return new Authenticator.Success( + new HttpPrincipal( uname, realm ) ); @@ -146,7 +146,7 @@ public abstract class BasicAuthenticator extends Authenticator { Headers map = t.getResponseHeaders(); var authString = "Basic realm=" + "\"" + realm + "\"" + (isUTF8 ? ", charset=\"UTF-8\"" : ""); - map.set ("WWW-Authenticate", authString); + map.set("WWW-Authenticate", authString); } /** @@ -159,6 +159,6 @@ public abstract class BasicAuthenticator extends Authenticator { * @param password the password from the request * @return {@code true} if the credentials are valid, {@code false} otherwise */ - public abstract boolean checkCredentials (String username, String password); + public abstract boolean checkCredentials(String username, String password); } diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Filter.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Filter.java index 7dacefcb59b..906e8448c54 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Filter.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Filter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -53,7 +53,7 @@ public abstract class Filter { /** * Constructor for subclasses to call. */ - protected Filter () {} + protected Filter() {} /** * A chain of filters associated with a {@link HttpServer}. @@ -76,7 +76,7 @@ public abstract class Filter { * @param handler the {@link HttpHandler} that will be invoked after * the final {@code Filter} has finished */ - public Chain (List filters, HttpHandler handler) { + public Chain(List filters, HttpHandler handler) { iter = filters.listIterator(); this.handler = handler; } @@ -93,12 +93,12 @@ public abstract class Filter { * @throws IOException if an I/O error occurs * @throws NullPointerException if exchange is {@code null} */ - public void doFilter (HttpExchange exchange) throws IOException { + public void doFilter(HttpExchange exchange) throws IOException { if (!iter.hasNext()) { - handler.handle (exchange); + handler.handle(exchange); } else { Filter f = iter.next(); - f.doFilter (exchange, this); + f.doFilter(exchange, this); } } } @@ -135,14 +135,14 @@ public abstract class Filter { * must be rethrown again * @throws NullPointerException if either exchange or chain are {@code null} */ - public abstract void doFilter (HttpExchange exchange, Chain chain) + public abstract void doFilter(HttpExchange exchange, Chain chain) throws IOException; /** * Returns a short description of this {@code Filter}. * * @return a {@code String} describing the {@code Filter} */ - public abstract String description (); + public abstract String description(); /** * Returns a pre-processing {@code Filter} with the given description and diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java index 7d11bd42c94..2decd48c806 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/Headers.java @@ -62,9 +62,9 @@ import sun.net.httpserver.UnmodifiableHeaders; *

    *
  • {@link #getFirst(String)} returns a single valued header or the first * value of a multi-valued header. - *
  • {@link #add(String,String)} adds the given header value to the list + *
  • {@link #add(String, String)} adds the given header value to the list * for the given key. - *
  • {@link #set(String,String)} sets the given header field to the single + *
  • {@link #set(String, String)} sets the given header field to the single * value given overwriting any existing values in the value list. *
* @@ -80,9 +80,9 @@ import sun.net.httpserver.UnmodifiableHeaders; * {@code null} keys will never be present in HTTP request or response headers. * @since 1.6 */ -public class Headers implements Map> { +public class Headers implements Map> { - HashMap> map; + HashMap> map; /** * Creates an empty instance of {@code Headers}. @@ -99,7 +99,7 @@ public class Headers implements Map> { * null. * @since 18 */ - public Headers(Map> headers) { + public Headers(Map> headers) { Objects.requireNonNull(headers); var h = headers.entrySet().stream() .collect(Collectors.toUnmodifiableMap( @@ -234,7 +234,7 @@ public class Headers implements Map> { List l = map.get(k); if (l == null) { l = new LinkedList<>(); - map.put(k,l); + map.put(k, l); } l.add(value); } @@ -372,7 +372,7 @@ public class Headers implements Map> { * null. * @since 18 */ - public static Headers of(Map> headers) { + public static Headers of(Map> headers) { return new UnmodifiableHeaders(new Headers(headers)); } } diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpContext.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpContext.java index 12529d88385..1c9e41e866c 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpContext.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpContext.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -90,7 +90,7 @@ public abstract class HttpContext { * * @return a {@code Map} containing the attributes of this context */ - public abstract Map getAttributes() ; + public abstract Map getAttributes() ; /** * Returns this context's {@link List} of {@linkplain Filter filters}. This diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java index 7ea43c0418e..a56c20b53af 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpExchange.java @@ -48,7 +48,7 @@ import java.net.URI; * should be closed. *
  • {@link #getResponseHeaders()} to set any response headers, except * content-length. - *
  • {@link #sendResponseHeaders(int,long)} to send the response headers. + *
  • {@link #sendResponseHeaders(int, long)} to send the response headers. * Must be called before next step. *
  • {@link #getResponseBody()} to get a {@link OutputStream} to * send the response body. When the response body has been written, the @@ -73,7 +73,7 @@ public abstract class HttpExchange implements AutoCloseable, Request { /* * Symbolic values for the responseLength parameter of - * sendResponseHeaders(int,long) + * sendResponseHeaders(int, long) */ /** @@ -163,7 +163,7 @@ public abstract class HttpExchange implements AutoCloseable, Request { /** * Returns a stream to which the response body must be - * written. {@link #sendResponseHeaders(int,long)}) must be called prior to + * written. {@link #sendResponseHeaders(int, long)}) must be called prior to * calling this method. Multiple calls to this method (for the same exchange) * will return the same stream. In order to correctly terminate each exchange, * the output stream must be closed, even if no response body is being sent. diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandler.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandler.java index 1f1fc129c9d..447001a4f53 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandler.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpHandler.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -44,5 +44,5 @@ public interface HttpHandler { * @throws NullPointerException if exchange is {@code null} * @throws IOException if an I/O error occurs */ - public abstract void handle (HttpExchange exchange) throws IOException; + public abstract void handle(HttpExchange exchange) throws IOException; } diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java index 8ed0172690f..a0271fed146 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpServer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -44,7 +44,7 @@ import java.util.concurrent.Executor; * a root URI path which represents the location of the application or service * on this server. The mapping of a handler to a {@code HttpServer} is * encapsulated by a {@link HttpContext} object. HttpContexts are created by - * calling {@link #createContext(String,HttpHandler)}. + * calling {@link #createContext(String, HttpHandler)}. * Any request for which no handler can be found is rejected with a 404 response. * Management of threads can be done external to this object by providing a * {@link java.util.concurrent.Executor} object. If none is provided a default @@ -117,13 +117,13 @@ public abstract class HttpServer { * Creates a {@code HttpServer} instance which is initially not bound to any * local address/port. The {@code HttpServer} is acquired from the currently * installed {@link HttpServerProvider}. The server must be bound using - * {@link #bind(InetSocketAddress,int)} before it can be used. + * {@link #bind(InetSocketAddress, int)} before it can be used. * * @throws IOException if an I/O error occurs * @return an instance of {@code HttpServer} */ public static HttpServer create() throws IOException { - return create (null, 0); + return create(null, 0); } /** @@ -149,7 +149,7 @@ public abstract class HttpServer { public static HttpServer create(InetSocketAddress addr, int backlog) throws IOException { HttpServerProvider provider = HttpServerProvider.provider(); - return provider.createHttpServer (addr, backlog); + return provider.createHttpServer(addr, backlog); } /** diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsConfigurator.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsConfigurator.java index 8cd9e3affa2..7f329e02f47 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsConfigurator.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsConfigurator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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,11 +38,11 @@ import javax.net.ssl.SSLParameters; *

    The following example shows how this may be done: * *

    - * SSLContext sslContext = SSLContext.getInstance (....);
    + * SSLContext sslContext = SSLContext.getInstance(....);
      * HttpsServer server = HttpsServer.create();
      *
    - * server.setHttpsConfigurator (new HttpsConfigurator(sslContext) {
    - *     public void configure (HttpsParameters params) {
    + * server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
    + *     public void configure(HttpsParameters params) {
      *
      *         // get the remote address if needed
      *         InetSocketAddress remote = params.getClientAddress();
    @@ -51,7 +51,7 @@ import javax.net.ssl.SSLParameters;
      *
      *         // get the default parameters
      *         SSLParameters sslparams = c.getDefaultSSLParameters();
    - *         if (remote.equals (...) ) {
    + *         if (remote.equals(...)) {
      *             // modify the default set for client x
      *         }
      *
    @@ -74,7 +74,7 @@ public class HttpsConfigurator {
          */
         public HttpsConfigurator(SSLContext context) {
             if (context == null) {
    -            throw new NullPointerException ("null SSLContext");
    +            throw new NullPointerException("null SSLContext");
             }
             this.context = context;
         }
    @@ -107,6 +107,6 @@ public class HttpsConfigurator {
         * @since 1.6
         */
         public void configure(HttpsParameters params) {
    -        params.setSSLParameters (getSSLContext().getDefaultSSLParameters());
    +        params.setSSLParameters(getSSLContext().getDefaultSSLParameters());
         }
     }
    diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsServer.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsServer.java
    index 7b3dafd5582..192b8c3d697 100644
    --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsServer.java
    +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/HttpsServer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2005, 2025, 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
    @@ -57,7 +57,7 @@ public abstract class HttpsServer extends HttpServer {
          * Creates a {@code HttpsServer} instance which is initially not bound to any
          * local address/port. The {@code HttpsServer} is acquired from the currently
          * installed {@link HttpServerProvider}. The server must be bound using
    -     * {@link #bind(InetSocketAddress,int)} before it can be used. The server
    +     * {@link #bind(InetSocketAddress, int)} before it can be used. The server
          * must also have a {@code HttpsConfigurator} established with
          * {@link #setHttpsConfigurator(HttpsConfigurator)}.
          *
    @@ -80,7 +80,7 @@ public abstract class HttpsServer extends HttpServer {
          * established with {@link #setHttpsConfigurator(HttpsConfigurator)}.
          *
          * @param addr the address to listen on, if {@code null} then
    -     *             {@link #bind(InetSocketAddress,int)} must be called to set
    +     *             {@link #bind(InetSocketAddress, int)} must be called to set
          *             the address
          * @param backlog the socket backlog. If this value is less than or equal to
          *               zero, then a system default value is used.
    diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java
    index 551f24d3cf0..ba93b81db5a 100644
    --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java
    +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/SimpleFileServer.java
    @@ -1,5 +1,5 @@
     /*
    - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved.
    + * Copyright (c) 2021, 2025, 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
    @@ -55,7 +55,7 @@ import sun.net.httpserver.simpleserver.OutputFilter;
      *
      * 

    Simple file server

    * - *

    The {@link #createFileServer(InetSocketAddress,Path,OutputLevel) createFileServer} + *

    The {@link #createFileServer(InetSocketAddress, Path, OutputLevel) createFileServer} * static factory method returns an {@link HttpServer HttpServer} that is a * simple out-of-the-box file server. The server comes with an initial handler * that serves files from a given directory path (and its subdirectories). diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java index 3b9de3520fb..466b76a6c4a 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/package-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -117,26 +117,25 @@ The following code shows how the SSLContext is then used in a HttpsConfigurator and how the SSLContext and HttpsConfigurator are linked to the HttpsServer.

    -    server.setHttpsConfigurator (new HttpsConfigurator(sslContext) {
    -        public void configure (HttpsParameters params) {
    +   server.setHttpsConfigurator(new HttpsConfigurator(sslContext) {
    +       public void configure(HttpsParameters params) {
     
    -        // get the remote address if needed
    -        InetSocketAddress remote = params.getClientAddress();
    +           // get the remote address if needed
    +           InetSocketAddress remote = params.getClientAddress();
     
    -        SSLContext c = getSSLContext();
    +           SSLContext c = getSSLContext();
     
    -        // get the default parameters
    -        SSLParameters sslparams = c.getDefaultSSLParameters();
    -        if (remote.equals (...) ) {
    -            // modify the default set for client x
    -        }
    +           // get the default parameters
    +           SSLParameters sslparams = c.getDefaultSSLParameters();
    +           if (remote.equals(...)) {
    +               // modify the default set for client x
    +           }
     
    -        params.setSSLParameters(sslparams);
    -        // statement above could throw IAE if any params invalid.
    -        // eg. if app has a UI and parameters supplied by a user.
    -
    -        }
    -    });
    +           params.setSSLParameters(sslparams);
    +           // statement above could throw IAE if any params invalid.
    +           // eg. if app has a UI and parameters supplied by a user.
    +       }
    +   });
        
    @since 1.6 */ diff --git a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java index d025e90cf87..9d73f0e7340 100644 --- a/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java +++ b/src/jdk.httpserver/share/classes/com/sun/net/httpserver/spi/HttpServerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -152,7 +152,7 @@ public abstract class HttpServerProvider { * * @return The system-wide default HttpServerProvider */ - public static HttpServerProvider provider () { + public static HttpServerProvider provider() { synchronized (lock) { if (provider != null) return provider; diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/AuthFilter.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/AuthFilter.java index 468fa19fe16..4641325af92 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/AuthFilter.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/AuthFilter.java @@ -33,48 +33,48 @@ public class AuthFilter extends Filter { private Authenticator authenticator; - public AuthFilter (Authenticator authenticator) { + public AuthFilter(Authenticator authenticator) { this.authenticator = authenticator; } - public String description () { + public String description() { return "Authentication filter"; } - public void setAuthenticator (Authenticator a) { + public void setAuthenticator(Authenticator a) { authenticator = a; } - public void consumeInput (HttpExchange t) throws IOException { + public void consumeInput(HttpExchange t) throws IOException { InputStream i = t.getRequestBody(); byte[] b = new byte [4096]; - while (i.read (b) != -1); - i.close (); + while (i.read(b) != -1); + i.close(); } /** * The filter's implementation, which is invoked by the server */ - public void doFilter (HttpExchange t, Filter.Chain chain) throws IOException + public void doFilter(HttpExchange t, Filter.Chain chain) throws IOException { if (authenticator != null) { - Authenticator.Result r = authenticator.authenticate (t); + Authenticator.Result r = authenticator.authenticate(t); if (r instanceof Authenticator.Success) { Authenticator.Success s = (Authenticator.Success)r; - ExchangeImpl e = ExchangeImpl.get (t); - e.setPrincipal (s.getPrincipal()); - chain.doFilter (t); + ExchangeImpl e = ExchangeImpl.get(t); + e.setPrincipal(s.getPrincipal()); + chain.doFilter(t); } else if (r instanceof Authenticator.Retry) { Authenticator.Retry ry = (Authenticator.Retry)r; - consumeInput (t); - t.sendResponseHeaders (ry.getResponseCode(), RSPBODY_EMPTY); + consumeInput(t); + t.sendResponseHeaders(ry.getResponseCode(), RSPBODY_EMPTY); } else if (r instanceof Authenticator.Failure) { Authenticator.Failure f = (Authenticator.Failure)r; - consumeInput (t); - t.sendResponseHeaders (f.getResponseCode(), RSPBODY_EMPTY); + consumeInput(t); + t.sendResponseHeaders(f.getResponseCode(), RSPBODY_EMPTY); } } else { - chain.doFilter (t); + chain.doFilter(t); } } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedInputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedInputStream.java index 34ac72e1fee..0c003378d77 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedInputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -31,7 +31,7 @@ import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; class ChunkedInputStream extends LeftOverInputStream { - ChunkedInputStream (ExchangeImpl t, InputStream src) { + ChunkedInputStream(ExchangeImpl t, InputStream src) { super (t, src); } @@ -48,7 +48,7 @@ class ChunkedInputStream extends LeftOverInputStream { */ private static final int MAX_CHUNK_HEADER_SIZE = 2050; - private int numeric (char[] arr, int nchars) throws IOException { + private int numeric(char[] arr, int nchars) throws IOException { assert arr.length >= nchars; int len = 0; for (int i=0; i='A' && c<= 'F') { val = c - 'A' + 10; } else { - throw new IOException ("invalid chunk length"); + throw new IOException("invalid chunk length"); } len = len * 16 + val; } @@ -71,10 +71,10 @@ class ChunkedInputStream extends LeftOverInputStream { /* read the chunk header line and return the chunk length * any chunk extensions are ignored */ - private int readChunkHeader () throws IOException { + private int readChunkHeader() throws IOException { boolean gotCR = false; int c; - char[] len_arr = new char [16]; + char[] len_arr = new char[16]; int len_size = 0; boolean end_of_len = false; int read = 0; @@ -85,11 +85,11 @@ class ChunkedInputStream extends LeftOverInputStream { if ((len_size == len_arr.length -1) || (read > MAX_CHUNK_HEADER_SIZE)) { - throw new IOException ("invalid chunk header"); + throw new IOException("invalid chunk header"); } if (gotCR) { if (ch == LF) { - int l = numeric (len_arr, len_size); + int l = numeric(len_arr, len_size); return l; } else { gotCR = false; @@ -107,10 +107,10 @@ class ChunkedInputStream extends LeftOverInputStream { } } } - throw new IOException ("end of stream reading chunk header"); + throw new IOException("end of stream reading chunk header"); } - protected int readImpl (byte[]b, int off, int len) throws IOException { + protected int readImpl(byte[] b, int off, int len) throws IOException { if (eof) { return -1; } @@ -119,7 +119,7 @@ class ChunkedInputStream extends LeftOverInputStream { if (remaining == 0) { eof = true; consumeCRLF(); - t.getServerImpl().requestCompleted (t.getConnection()); + t.getServerImpl().requestCompleted(t.getConnection()); return -1; } needToReadHeader = false; @@ -140,15 +140,15 @@ class ChunkedInputStream extends LeftOverInputStream { return n; } - private void consumeCRLF () throws IOException { + private void consumeCRLF() throws IOException { char c; c = (char)in.read(); /* CR */ if (c != CR) { - throw new IOException ("invalid chunk end"); + throw new IOException("invalid chunk end"); } c = (char)in.read(); /* LF */ if (c != LF) { - throw new IOException ("invalid chunk end"); + throw new IOException("invalid chunk end"); } } @@ -158,7 +158,7 @@ class ChunkedInputStream extends LeftOverInputStream { * limitation for the moment. It only affects potential efficiency * rather than correctness. */ - public int available () throws IOException { + public int available() throws IOException { if (eof || closed) { return 0; } @@ -170,17 +170,17 @@ class ChunkedInputStream extends LeftOverInputStream { * have been read from the underlying channel * and buffered internally */ - public boolean isDataBuffered () throws IOException { + public boolean isDataBuffered() throws IOException { assert eof; return in.available() > 0; } - public boolean markSupported () {return false;} + public boolean markSupported() {return false;} - public void mark (int l) { + public void mark(int l) { } - public void reset () throws IOException { - throw new IOException ("mark/reset not supported"); + public void reset() throws IOException { + throw new IOException("mark/reset not supported"); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java index e8e84eb8edd..fd1a940c0a5 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ChunkedOutputStream.java @@ -57,14 +57,14 @@ class ChunkedOutputStream extends FilterOutputStream private byte[] buf = new byte [CHUNK_SIZE+OFFSET+2]; ExchangeImpl t; - ChunkedOutputStream (ExchangeImpl t, OutputStream src) { - super (src); + ChunkedOutputStream(ExchangeImpl t, OutputStream src) { + super(src); this.t = t; } - public void write (int b) throws IOException { + public void write(int b) throws IOException { if (closed) { - throw new StreamClosedException (); + throw new StreamClosedException(); } buf [pos++] = (byte)b; count ++; @@ -74,23 +74,23 @@ class ChunkedOutputStream extends FilterOutputStream assert count < CHUNK_SIZE; } - public void write (byte[]b, int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); if (len == 0) { return; } if (closed) { - throw new StreamClosedException (); + throw new StreamClosedException(); } int remain = CHUNK_SIZE - count; if (len > remain) { - System.arraycopy (b,off,buf,pos,remain); + System.arraycopy(b, off, buf, pos, remain); count = CHUNK_SIZE; writeChunk(); len -= remain; off += remain; while (len >= CHUNK_SIZE) { - System.arraycopy (b,off,buf,OFFSET,CHUNK_SIZE); + System.arraycopy(b, off, buf, OFFSET, CHUNK_SIZE); len -= CHUNK_SIZE; off += CHUNK_SIZE; count = CHUNK_SIZE; @@ -98,7 +98,7 @@ class ChunkedOutputStream extends FilterOutputStream } } if (len > 0) { - System.arraycopy (b,off,buf,pos,len); + System.arraycopy(b, off, buf, pos, len); count += len; pos += len; } @@ -112,8 +112,8 @@ class ChunkedOutputStream extends FilterOutputStream * chunk does not have to be CHUNK_SIZE bytes * count must == number of user bytes (<= CHUNK_SIZE) */ - private void writeChunk () throws IOException { - char[] c = Integer.toHexString (count).toCharArray(); + private void writeChunk() throws IOException { + char[] c = Integer.toHexString(count).toCharArray(); int clen = c.length; int startByte = 4 - clen; int i; @@ -124,12 +124,12 @@ class ChunkedOutputStream extends FilterOutputStream buf[startByte + (i++)] = '\n'; buf[startByte + (i++) + count] = '\r'; buf[startByte + (i++) + count] = '\n'; - out.write (buf, startByte, i+count); + out.write(buf, startByte, i+count); count = 0; pos = OFFSET; } - public void close () throws IOException { + public void close() throws IOException { if (closed) { return; } @@ -156,12 +156,12 @@ class ChunkedOutputStream extends FilterOutputStream } Event e = new Event.WriteFinished(t); - t.getHttpContext().getServerImpl().addEvent (e); + t.getHttpContext().getServerImpl().addEvent(e); } - public void flush () throws IOException { + public void flush() throws IOException { if (closed) { - throw new StreamClosedException (); + throw new StreamClosedException(); } if (count > 0) { writeChunk(); diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java index 6b86b8fa5bd..c5391343f96 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Code.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -64,7 +64,7 @@ class Code { public static final int HTTP_GATEWAY_TIMEOUT = 504; public static final int HTTP_VERSION = 505; - static String msg (int code) { + static String msg(int code) { switch (code) { case HTTP_OK: return " OK"; diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java index cbedb6ca860..96b55575928 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ContextList.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -31,30 +31,30 @@ class ContextList { private final LinkedList list = new LinkedList<>(); - public synchronized void add (HttpContextImpl ctx) { + public synchronized void add(HttpContextImpl ctx) { assert ctx.getPath() != null; if (contains(ctx)) { - throw new IllegalArgumentException ("cannot add context to list"); + throw new IllegalArgumentException("cannot add context to list"); } - list.add (ctx); + list.add(ctx); } boolean contains(HttpContextImpl ctx) { return findContext(ctx.getProtocol(), ctx.getPath(), true) != null; } - public synchronized int size () { + public synchronized int size() { return list.size(); } /* initially contexts are located only by protocol:path. * Context with longest prefix matches (currently case-sensitive) */ - synchronized HttpContextImpl findContext (String protocol, String path) { - return findContext (protocol, path, false); + synchronized HttpContextImpl findContext(String protocol, String path) { + return findContext(protocol, path, false); } - synchronized HttpContextImpl findContext (String protocol, String path, boolean exact) { + synchronized HttpContextImpl findContext(String protocol, String path, boolean exact) { protocol = protocol.toLowerCase(Locale.ROOT); String longest = ""; HttpContextImpl lc = null; @@ -63,7 +63,7 @@ class ContextList { continue; } String cpath = ctx.getPath(); - if (exact && !cpath.equals (path)) { + if (exact && !cpath.equals(path)) { continue; } else if (!exact && !path.startsWith(cpath)) { continue; @@ -76,25 +76,25 @@ class ContextList { return lc; } - public synchronized void remove (String protocol, String path) + public synchronized void remove(String protocol, String path) throws IllegalArgumentException { - HttpContextImpl ctx = findContext (protocol, path, true); + HttpContextImpl ctx = findContext(protocol, path, true); if (ctx == null) { - throw new IllegalArgumentException ("cannot remove element from list"); + throw new IllegalArgumentException("cannot remove element from list"); } - list.remove (ctx); + list.remove(ctx); } - public synchronized void remove (HttpContextImpl context) + public synchronized void remove(HttpContextImpl context) throws IllegalArgumentException { for (HttpContextImpl ctx: list) { - if (ctx.equals (context)) { - list.remove (ctx); + if (ctx.equals(context)) { + list.remove(ctx); return; } } - throw new IllegalArgumentException ("no such context in list"); + throw new IllegalArgumentException("no such context in list"); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/DefaultHttpServerProvider.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/DefaultHttpServerProvider.java index fe746befb9f..7b54ef45e72 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/DefaultHttpServerProvider.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/DefaultHttpServerProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -31,11 +31,11 @@ import com.sun.net.httpserver.*; import com.sun.net.httpserver.spi.*; public class DefaultHttpServerProvider extends HttpServerProvider { - public HttpServer createHttpServer (InetSocketAddress addr, int backlog) throws IOException { - return new HttpServerImpl (addr, backlog); + public HttpServer createHttpServer(InetSocketAddress addr, int backlog) throws IOException { + return new HttpServerImpl(addr, backlog); } - public HttpsServer createHttpsServer (InetSocketAddress addr, int backlog) throws IOException { - return new HttpsServerImpl (addr, backlog); + public HttpsServer createHttpsServer(InetSocketAddress addr, int backlog) throws IOException { + return new HttpsServerImpl(addr, backlog); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java index 17dff13d4e5..8da98cdcfa5 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ExchangeImpl.java @@ -82,12 +82,12 @@ class ExchangeImpl { PlaceholderOutputStream uos_orig; boolean sentHeaders; /* true after response headers sent */ - final Map attributes; + final Map attributes; int rcode = -1; HttpPrincipal principal; ServerImpl server; - ExchangeImpl ( + ExchangeImpl( String m, URI u, Request req, long len, HttpConnection connection ) throws IOException { this.req = req; @@ -107,23 +107,23 @@ class ExchangeImpl { server.startExchange(); } - public Headers getRequestHeaders () { + public Headers getRequestHeaders() { return reqHdrs; } - public Headers getResponseHeaders () { + public Headers getResponseHeaders() { return rspHdrs; } - public URI getRequestURI () { + public URI getRequestURI() { return uri; } - public String getRequestMethod (){ + public String getRequestMethod() { return method; } - public HttpContextImpl getHttpContext (){ + public HttpContextImpl getHttpContext() { return connection.getHttpContext(); } @@ -131,7 +131,7 @@ class ExchangeImpl { return HEAD.equals(getRequestMethod()); } - public void close () { + public void close() { if (closed) { return; } @@ -160,38 +160,38 @@ class ExchangeImpl { } } - public InputStream getRequestBody () { + public InputStream getRequestBody() { if (uis != null) { return uis; } if (reqContentLen == -1L) { - uis_orig = new ChunkedInputStream (this, ris); + uis_orig = new ChunkedInputStream(this, ris); uis = uis_orig; } else { - uis_orig = new FixedLengthInputStream (this, ris, reqContentLen); + uis_orig = new FixedLengthInputStream(this, ris, reqContentLen); uis = uis_orig; } return uis; } - LeftOverInputStream getOriginalInputStream () { + LeftOverInputStream getOriginalInputStream() { return uis_orig; } - public int getResponseCode () { + public int getResponseCode() { return rcode; } - public OutputStream getResponseBody () { + public OutputStream getResponseBody() { /* TODO. Change spec to remove restriction below. Filters * cannot work with this restriction * * if (!sentHeaders) { - * throw new IllegalStateException ("headers not sent"); + * throw new IllegalStateException("headers not sent"); * } */ if (uos == null) { - uos_orig = new PlaceholderOutputStream (null); + uos_orig = new PlaceholderOutputStream(null); uos = uos_orig; } return uos; @@ -202,37 +202,37 @@ class ExchangeImpl { * returned from the 1st call to getResponseBody() * The "real" ouputstream is then placed inside this */ - PlaceholderOutputStream getPlaceholderResponseBody () { + PlaceholderOutputStream getPlaceholderResponseBody() { getResponseBody(); return uos_orig; } - public void sendResponseHeaders (int rCode, long contentLen) + public void sendResponseHeaders(int rCode, long contentLen) throws IOException { final Logger logger = server.getLogger(); if (sentHeaders) { - throw new IOException ("headers already sent"); + throw new IOException("headers already sent"); } this.rcode = rCode; - String statusLine = "HTTP/1.1 "+rCode+Code.msg(rCode)+"\r\n"; + String statusLine = "HTTP/1.1 " + rCode + Code.msg(rCode) + "\r\n"; ByteArrayOutputStream tmpout = new ByteArrayOutputStream(); PlaceholderOutputStream o = getPlaceholderResponseBody(); - tmpout.write (bytes(statusLine, 0), 0, statusLine.length()); + tmpout.write(bytes(statusLine, 0), 0, statusLine.length()); boolean noContentToSend = false; // assume there is content boolean noContentLengthHeader = false; // must not send Content-length is set rspHdrs.set("Date", FORMATTER.format(Instant.now())); /* check for response type that is not allowed to send a body */ - if ((rCode>=100 && rCode <200) /* informational */ + if ((rCode >= 100 && rCode < 200) /* informational */ ||(rCode == 204) /* no content */ ||(rCode == 304)) /* not modified */ { if (contentLen != RSPBODY_EMPTY) { - String msg = "sendResponseHeaders: rCode = "+ rCode + String msg = "sendResponseHeaders: rCode = " + rCode + ": forcing contentLen = RSPBODY_EMPTY"; - logger.log (Level.WARNING, msg); + logger.log(Level.WARNING, msg); } contentLen = RSPBODY_EMPTY; noContentLengthHeader = (rCode != 304); @@ -245,19 +245,19 @@ class ExchangeImpl { if (contentLen >= 0) { String msg = "sendResponseHeaders: being invoked with a content length for a HEAD request"; - logger.log (Level.WARNING, msg); + logger.log(Level.WARNING, msg); } noContentToSend = true; contentLen = 0; - o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen)); + o.setWrappedStream(new FixedLengthOutputStream(this, ros, contentLen)); } else { /* not a HEAD request or 304 response */ if (contentLen == RSPBODY_CHUNKED) { if (http10) { - o.setWrappedStream (new UndefLengthOutputStream (this, ros)); + o.setWrappedStream(new UndefLengthOutputStream(this, ros)); close = true; } else { - rspHdrs.set ("Transfer-encoding", "chunked"); - o.setWrappedStream (new ChunkedOutputStream (this, ros)); + rspHdrs.set("Transfer-encoding", "chunked"); + o.setWrappedStream(new ChunkedOutputStream(this, ros)); } } else { if (contentLen == RSPBODY_EMPTY) { @@ -267,7 +267,7 @@ class ExchangeImpl { if (!noContentLengthHeader) { rspHdrs.set("Content-length", Long.toString(contentLen)); } - o.setWrappedStream (new FixedLengthOutputStream (this, ros, contentLen)); + o.setWrappedStream(new FixedLengthOutputStream(this, ros, contentLen)); } } @@ -280,12 +280,12 @@ class ExchangeImpl { Optional.ofNullable(rspHdrs.get("Connection")) .map(List::stream).orElse(Stream.empty()); if (conheader.anyMatch("close"::equalsIgnoreCase)) { - logger.log (Level.DEBUG, "Connection: close requested by handler"); + logger.log(Level.DEBUG, "Connection: close requested by handler"); close = true; } } - write (rspHdrs, tmpout); + write(rspHdrs, tmpout); this.rspContentLen = contentLen; tmpout.writeTo(ros); sentHeaders = true; @@ -294,33 +294,33 @@ class ExchangeImpl { ros.flush(); close(); } - server.logReply (rCode, req.requestLine(), null); + server.logReply(rCode, req.requestLine(), null); } - void write (Headers map, OutputStream os) throws IOException { - Set>> entries = map.entrySet(); - for (Map.Entry> entry : entries) { + void write(Headers map, OutputStream os) throws IOException { + Set>> entries = map.entrySet(); + for (Map.Entry> entry : entries) { String key = entry.getKey(); byte[] buf; List values = entry.getValue(); for (String val : values) { int i = key.length(); - buf = bytes (key, 2); + buf = bytes(key, 2); buf[i++] = ':'; buf[i++] = ' '; - os.write (buf, 0, i); - buf = bytes (val, 2); + os.write(buf, 0, i); + buf = bytes(val, 2); i = val.length(); buf[i++] = '\r'; buf[i++] = '\n'; - os.write (buf, 0, i); + os.write(buf, 0, i); } } - os.write ('\r'); - os.write ('\n'); + os.write('\r'); + os.write('\n'); } - private byte[] rspbuf = new byte [128]; // used by bytes() + private byte[] rspbuf = new byte[128]; // used by bytes() /** * convert string to byte[], using rspbuf @@ -328,7 +328,7 @@ class ExchangeImpl { * of rspbuf. Reallocate rspbuf if not big enough. * caller must check return value to see if rspbuf moved */ - private byte[] bytes (String s, int extra) { + private byte[] bytes(String s, int extra) { int slen = s.length(); if (slen+extra > rspbuf.length) { int diff = slen + extra - rspbuf.length; @@ -341,27 +341,27 @@ class ExchangeImpl { return rspbuf; } - public InetSocketAddress getRemoteAddress (){ + public InetSocketAddress getRemoteAddress() { Socket s = connection.getChannel().socket(); InetAddress ia = s.getInetAddress(); int port = s.getPort(); - return new InetSocketAddress (ia, port); + return new InetSocketAddress(ia, port); } - public InetSocketAddress getLocalAddress (){ + public InetSocketAddress getLocalAddress() { Socket s = connection.getChannel().socket(); InetAddress ia = s.getLocalAddress(); int port = s.getLocalPort(); - return new InetSocketAddress (ia, port); + return new InetSocketAddress(ia, port); } - public String getProtocol (){ + public String getProtocol() { String reqline = req.requestLine(); - int index = reqline.lastIndexOf (' '); - return reqline.substring (index+1); + int index = reqline.lastIndexOf(' '); + return reqline.substring(index+1); } - public SSLSession getSSLSession () { + public SSLSession getSSLSession() { SSLEngine e = connection.getSSLEngine(); if (e == null) { return null; @@ -369,11 +369,11 @@ class ExchangeImpl { return e.getSession(); } - public Object getAttribute (String name) { + public Object getAttribute(String name) { return attributes.get(Objects.requireNonNull(name, "null name parameter")); } - public void setAttribute (String name, Object value) { + public void setAttribute(String name, Object value) { var key = Objects.requireNonNull(name, "null name parameter"); if (value != null) { attributes.put(key, value); @@ -382,7 +382,7 @@ class ExchangeImpl { } } - public void setStreams (InputStream i, OutputStream o) { + public void setStreams(InputStream i, OutputStream o) { assert uis != null; if (i != null) { uis = i; @@ -395,23 +395,23 @@ class ExchangeImpl { /** * PP */ - HttpConnection getConnection () { + HttpConnection getConnection() { return connection; } - ServerImpl getServerImpl () { + ServerImpl getServerImpl() { return getHttpContext().getServerImpl(); } - public HttpPrincipal getPrincipal () { + public HttpPrincipal getPrincipal() { return principal; } - void setPrincipal (HttpPrincipal principal) { + void setPrincipal(HttpPrincipal principal) { this.principal = principal; } - static ExchangeImpl get (HttpExchange t) { + static ExchangeImpl get(HttpExchange t) { if (t instanceof HttpExchangeImpl) { return ((HttpExchangeImpl)t).getExchangeImpl(); } else { @@ -432,37 +432,37 @@ class PlaceholderOutputStream extends java.io.OutputStream { OutputStream wrapped; - PlaceholderOutputStream (OutputStream os) { + PlaceholderOutputStream(OutputStream os) { wrapped = os; } - void setWrappedStream (OutputStream os) { + void setWrappedStream(OutputStream os) { wrapped = os; } - boolean isWrapped () { + boolean isWrapped() { return wrapped != null; } - private void checkWrap () throws IOException { + private void checkWrap() throws IOException { if (wrapped == null) { - throw new IOException ("response headers not sent yet"); + throw new IOException("response headers not sent yet"); } } public void write(int b) throws IOException { checkWrap(); - wrapped.write (b); + wrapped.write(b); } public void write(byte b[]) throws IOException { checkWrap(); - wrapped.write (b); + wrapped.write(b); } public void write(byte b[], int off, int len) throws IOException { checkWrap(); - wrapped.write (b, off, len); + wrapped.write(b, off, len); } public void flush() throws IOException { diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java index ac6fb7be005..100ba9e1b3b 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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,15 +39,15 @@ import com.sun.net.httpserver.spi.*; class FixedLengthInputStream extends LeftOverInputStream { private long remaining; - FixedLengthInputStream (ExchangeImpl t, InputStream src, long len) { - super (t, src); + FixedLengthInputStream(ExchangeImpl t, InputStream src, long len) { + super(t, src); if (len < 0) { throw new IllegalArgumentException("Content-Length: " + len); } this.remaining = len; } - protected int readImpl (byte[]b, int off, int len) throws IOException { + protected int readImpl(byte[] b, int off, int len) throws IOException { eof = (remaining == 0L); if (eof) { @@ -60,7 +60,7 @@ class FixedLengthInputStream extends LeftOverInputStream { if (n > -1) { remaining -= n; if (remaining == 0) { - t.getServerImpl().requestCompleted (t.getConnection()); + t.getServerImpl().requestCompleted(t.getConnection()); } } if (n < 0 && !eof) @@ -68,7 +68,7 @@ class FixedLengthInputStream extends LeftOverInputStream { return n; } - public int available () throws IOException { + public int available() throws IOException { if (eof) { return 0; } @@ -76,12 +76,12 @@ class FixedLengthInputStream extends LeftOverInputStream { return n < remaining? n: (int)remaining; } - public boolean markSupported () {return false;} + public boolean markSupported() {return false;} - public void mark (int l) { + public void mark(int l) { } - public void reset () throws IOException { - throw new IOException ("mark/reset not supported"); + public void reset() throws IOException { + throw new IOException("mark/reset not supported"); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java index f800bdaba18..95de03d27fa 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/FixedLengthOutputStream.java @@ -42,7 +42,7 @@ class FixedLengthOutputStream extends FilterOutputStream private boolean closed = false; ExchangeImpl t; - FixedLengthOutputStream (ExchangeImpl t, OutputStream src, long len) { + FixedLengthOutputStream(ExchangeImpl t, OutputStream src, long len) { super (src); if (len < 0) { throw new IllegalArgumentException("Content-Length: " + len); @@ -51,9 +51,9 @@ class FixedLengthOutputStream extends FilterOutputStream this.remaining = len; } - public void write (int b) throws IOException { + public void write(int b) throws IOException { if (closed) { - throw new IOException ("stream closed"); + throw new IOException("stream closed"); } if (remaining == 0) { throw new StreamClosedException(); @@ -62,30 +62,30 @@ class FixedLengthOutputStream extends FilterOutputStream remaining --; } - public void write (byte[]b, int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); if (len == 0) { return; } if (closed) { - throw new IOException ("stream closed"); + throw new IOException("stream closed"); } if (len > remaining) { // stream is still open, caller can retry - throw new IOException ("too many bytes to write to stream"); + throw new IOException("too many bytes to write to stream"); } out.write(b, off, len); remaining -= len; } - public void close () throws IOException { + public void close() throws IOException { if (closed) { return; } closed = true; if (remaining > 0) { t.close(); - throw new IOException ("insufficient bytes written to stream"); + throw new IOException("insufficient bytes written to stream"); } flush(); LeftOverInputStream is = t.getOriginalInputStream(); @@ -95,7 +95,7 @@ class FixedLengthOutputStream extends FilterOutputStream } catch (IOException e) {} } Event e = new Event.WriteFinished(t); - t.getHttpContext().getServerImpl().addEvent (e); + t.getHttpContext().getServerImpl().addEvent(e); } // flush is a pass-through diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java index 38aabe1136e..2be4a37d432 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -73,14 +73,14 @@ class HttpConnection { return sb.toString(); } - HttpConnection () { + HttpConnection() { } - void setChannel (SocketChannel c) { + void setChannel(SocketChannel c) { chan = c; } - void setContext (HttpContextImpl ctx) { + void setContext(HttpContextImpl ctx) { context = ctx; } @@ -88,11 +88,11 @@ class HttpConnection { return state; } - void setState (State s) { + void setState(State s) { state = s; } - void setParameters ( + void setParameters( InputStream in, OutputStream rawout, SocketChannel chan, SSLEngine engine, SSLStreams sslStreams, SSLContext sslContext, String protocol, HttpContextImpl context, InputStream raw @@ -110,21 +110,21 @@ class HttpConnection { this.logger = context.getLogger(); } - SocketChannel getChannel () { + SocketChannel getChannel() { return chan; } - synchronized void close () { + synchronized void close() { if (closed) { return; } closed = true; if (logger != null && chan != null) { - logger.log (Level.TRACE, "Closing connection: " + chan.toString()); + logger.log(Level.TRACE, "Closing connection: " + chan.toString()); } if (!chan.isOpen()) { - ServerImpl.dprint ("Channel already closed"); + ServerImpl.dprint("Channel already closed"); return; } try { @@ -133,65 +133,65 @@ class HttpConnection { raw.close(); } } catch (IOException e) { - ServerImpl.dprint (e); + ServerImpl.dprint(e); } try { if (rawout != null) { rawout.close(); } } catch (IOException e) { - ServerImpl.dprint (e); + ServerImpl.dprint(e); } try { if (sslStreams != null) { sslStreams.close(); } } catch (IOException e) { - ServerImpl.dprint (e); + ServerImpl.dprint(e); } try { chan.close(); } catch (IOException e) { - ServerImpl.dprint (e); + ServerImpl.dprint(e); } } /* remaining is the number of bytes left on the lowest level inputstream * after the exchange is finished */ - void setRemaining (int r) { + void setRemaining(int r) { remaining = r; } - int getRemaining () { + int getRemaining() { return remaining; } - SelectionKey getSelectionKey () { + SelectionKey getSelectionKey() { return selectionKey; } - InputStream getInputStream () { + InputStream getInputStream() { return i; } - OutputStream getRawOutputStream () { + OutputStream getRawOutputStream() { return rawout; } - String getProtocol () { + String getProtocol() { return protocol; } - SSLEngine getSSLEngine () { + SSLEngine getSSLEngine() { return engine; } - SSLContext getSSLContext () { + SSLContext getSSLContext() { return sslContext; } - HttpContextImpl getHttpContext () { + HttpContextImpl getHttpContext() { return context; } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java index f1583954115..10cd116a3a0 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpContextImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -35,7 +35,7 @@ import com.sun.net.httpserver.*; * to a {@link HttpHandler} which is invoked to handle requests destined * for the protocol/path on the associated HttpServer. *

    - * HttpContext instances are created by {@link HttpServer#createContext(String,String,HttpHandler,Object)} + * HttpContext instances are created by {@link HttpServer#createContext(String, String, HttpHandler, Object)} *

    */ class HttpContextImpl extends HttpContext { @@ -44,7 +44,7 @@ class HttpContextImpl extends HttpContext { private final String protocol; private final ServerImpl server; private final AuthFilter authfilter; - private final Map attributes = new ConcurrentHashMap<>(); + private final Map attributes = new ConcurrentHashMap<>(); /* system filters, not visible to applications */ private final List sfilters = new CopyOnWriteArrayList<>(); /* user filters, set by applications */ @@ -55,35 +55,35 @@ class HttpContextImpl extends HttpContext { /** * constructor is package private. */ - HttpContextImpl (String protocol, String path, HttpHandler cb, ServerImpl server) { + HttpContextImpl(String protocol, String path, HttpHandler cb, ServerImpl server) { if (path == null || protocol == null || path.length() < 1 || path.charAt(0) != '/') { - throw new IllegalArgumentException ("Illegal value for path or protocol"); + throw new IllegalArgumentException("Illegal value for path or protocol"); } this.protocol = protocol.toLowerCase(Locale.ROOT); this.path = path; - if (!this.protocol.equals ("http") && !this.protocol.equals ("https")) { - throw new IllegalArgumentException ("Illegal value for protocol"); + if (!this.protocol.equals("http") && !this.protocol.equals("https")) { + throw new IllegalArgumentException("Illegal value for protocol"); } this.handler = cb; this.server = server; authfilter = new AuthFilter(null); - sfilters.add (authfilter); + sfilters.add(authfilter); } /** * returns the handler for this context * @return the HttpHandler for this context */ - public HttpHandler getHandler () { + public HttpHandler getHandler() { return handler; } - public void setHandler (HttpHandler h) { + public void setHandler(HttpHandler h) { if (h == null) { - throw new NullPointerException ("Null handler parameter"); + throw new NullPointerException("Null handler parameter"); } if (handler != null) { - throw new IllegalArgumentException ("handler already set"); + throw new IllegalArgumentException("handler already set"); } handler = h; } @@ -100,11 +100,11 @@ class HttpContextImpl extends HttpContext { * returns the server this context was created with * @return this context's server */ - public HttpServer getServer () { + public HttpServer getServer() { return server.getWrapper(); } - ServerImpl getServerImpl () { + ServerImpl getServerImpl() { return server; } @@ -124,29 +124,29 @@ class HttpContextImpl extends HttpContext { * Every attribute stored in this Map will be visible to * every HttpExchange processed by this context */ - public Map getAttributes() { + public Map getAttributes() { return attributes; } - public List getFilters () { + public List getFilters() { return ufilters; } - List getSystemFilters () { + List getSystemFilters() { return sfilters; } - public Authenticator setAuthenticator (Authenticator auth) { + public Authenticator setAuthenticator(Authenticator auth) { Authenticator old = authenticator; authenticator = auth; - authfilter.setAuthenticator (auth); + authfilter.setAuthenticator(auth); return old; } - public Authenticator getAuthenticator () { + public Authenticator getAuthenticator() { return authenticator; } - Logger getLogger () { + Logger getLogger() { return server.getLogger(); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpError.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpError.java index de9dfba8cfb..b201c822193 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpError.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpError.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -31,7 +31,7 @@ package sun.net.httpserver; class HttpError extends RuntimeException { private static final long serialVersionUID = 8769596371344178179L; - public HttpError (String msg) { - super (msg); + public HttpError(String msg) { + super(msg); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpExchangeImpl.java index 420ef3d9e64..d4606019c56 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpExchangeImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpExchangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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,82 +38,82 @@ class HttpExchangeImpl extends HttpExchange { ExchangeImpl impl; - HttpExchangeImpl (ExchangeImpl impl) { + HttpExchangeImpl(ExchangeImpl impl) { this.impl = impl; } - public Headers getRequestHeaders () { + public Headers getRequestHeaders() { return impl.getRequestHeaders(); } - public Headers getResponseHeaders () { + public Headers getResponseHeaders() { return impl.getResponseHeaders(); } - public URI getRequestURI () { + public URI getRequestURI() { return impl.getRequestURI(); } - public String getRequestMethod (){ + public String getRequestMethod() { return impl.getRequestMethod(); } - public HttpContextImpl getHttpContext (){ + public HttpContextImpl getHttpContext() { return impl.getHttpContext(); } - public void close () { + public void close() { impl.close(); } - public InputStream getRequestBody () { + public InputStream getRequestBody() { return impl.getRequestBody(); } - public int getResponseCode () { + public int getResponseCode() { return impl.getResponseCode(); } - public OutputStream getResponseBody () { + public OutputStream getResponseBody() { return impl.getResponseBody(); } - public void sendResponseHeaders (int rCode, long contentLen) + public void sendResponseHeaders(int rCode, long contentLen) throws IOException { - impl.sendResponseHeaders (rCode, contentLen); + impl.sendResponseHeaders(rCode, contentLen); } - public InetSocketAddress getRemoteAddress (){ + public InetSocketAddress getRemoteAddress() { return impl.getRemoteAddress(); } - public InetSocketAddress getLocalAddress (){ + public InetSocketAddress getLocalAddress() { return impl.getLocalAddress(); } - public String getProtocol (){ + public String getProtocol() { return impl.getProtocol(); } - public Object getAttribute (String name) { - return impl.getAttribute (name); + public Object getAttribute(String name) { + return impl.getAttribute(name); } - public void setAttribute (String name, Object value) { - impl.setAttribute (name, value); + public void setAttribute(String name, Object value) { + impl.setAttribute(name, value); } - public void setStreams (InputStream i, OutputStream o) { - impl.setStreams (i, o); + public void setStreams(InputStream i, OutputStream o) { + impl.setStreams(i, o); } - public HttpPrincipal getPrincipal () { + public HttpPrincipal getPrincipal() { return impl.getPrincipal(); } - ExchangeImpl getExchangeImpl () { + ExchangeImpl getExchangeImpl() { return impl; } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpServerImpl.java index dd09957c0c6..93ace4e7bd2 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -35,50 +35,50 @@ public class HttpServerImpl extends HttpServer { ServerImpl server; - HttpServerImpl () throws IOException { - this (new InetSocketAddress(80), 0); + HttpServerImpl() throws IOException { + this(new InetSocketAddress(80), 0); } - HttpServerImpl ( + HttpServerImpl( InetSocketAddress addr, int backlog ) throws IOException { - server = new ServerImpl (this, "http", addr, backlog); + server = new ServerImpl(this, "http", addr, backlog); } - public void bind (InetSocketAddress addr, int backlog) throws IOException { - server.bind (addr, backlog); + public void bind(InetSocketAddress addr, int backlog) throws IOException { + server.bind(addr, backlog); } - public void start () { + public void start() { server.start(); } - public void setExecutor (Executor executor) { + public void setExecutor(Executor executor) { server.setExecutor(executor); } - public Executor getExecutor () { + public Executor getExecutor() { return server.getExecutor(); } - public void stop (int delay) { - server.stop (delay); + public void stop(int delay) { + server.stop(delay); } - public HttpContextImpl createContext (String path, HttpHandler handler) { - return server.createContext (path, handler); + public HttpContextImpl createContext(String path, HttpHandler handler) { + return server.createContext(path, handler); } - public HttpContextImpl createContext (String path) { - return server.createContext (path); + public HttpContextImpl createContext(String path) { + return server.createContext(path); } - public void removeContext (String path) throws IllegalArgumentException { - server.removeContext (path); + public void removeContext(String path) throws IllegalArgumentException { + server.removeContext(path); } - public void removeContext (HttpContext context) throws IllegalArgumentException { - server.removeContext (context); + public void removeContext(HttpContext context) throws IllegalArgumentException { + server.removeContext(context); } public InetSocketAddress getAddress() { diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsExchangeImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsExchangeImpl.java index f7f43d7feca..939b88d3928 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsExchangeImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsExchangeImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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,86 +38,86 @@ class HttpsExchangeImpl extends HttpsExchange { ExchangeImpl impl; - HttpsExchangeImpl (ExchangeImpl impl) throws IOException { + HttpsExchangeImpl(ExchangeImpl impl) throws IOException { this.impl = impl; } - public Headers getRequestHeaders () { + public Headers getRequestHeaders() { return impl.getRequestHeaders(); } - public Headers getResponseHeaders () { + public Headers getResponseHeaders() { return impl.getResponseHeaders(); } - public URI getRequestURI () { + public URI getRequestURI() { return impl.getRequestURI(); } - public String getRequestMethod (){ + public String getRequestMethod() { return impl.getRequestMethod(); } - public HttpContextImpl getHttpContext (){ + public HttpContextImpl getHttpContext() { return impl.getHttpContext(); } - public void close () { + public void close() { impl.close(); } - public InputStream getRequestBody () { + public InputStream getRequestBody() { return impl.getRequestBody(); } - public int getResponseCode () { + public int getResponseCode() { return impl.getResponseCode(); } - public OutputStream getResponseBody () { + public OutputStream getResponseBody() { return impl.getResponseBody(); } - public void sendResponseHeaders (int rCode, long contentLen) + public void sendResponseHeaders(int rCode, long contentLen) throws IOException { - impl.sendResponseHeaders (rCode, contentLen); + impl.sendResponseHeaders(rCode, contentLen); } - public InetSocketAddress getRemoteAddress (){ + public InetSocketAddress getRemoteAddress() { return impl.getRemoteAddress(); } - public InetSocketAddress getLocalAddress (){ + public InetSocketAddress getLocalAddress() { return impl.getLocalAddress(); } - public String getProtocol (){ + public String getProtocol() { return impl.getProtocol(); } - public SSLSession getSSLSession () { - return impl.getSSLSession (); + public SSLSession getSSLSession() { + return impl.getSSLSession(); } - public Object getAttribute (String name) { - return impl.getAttribute (name); + public Object getAttribute(String name) { + return impl.getAttribute(name); } - public void setAttribute (String name, Object value) { - impl.setAttribute (name, value); + public void setAttribute(String name, Object value) { + impl.setAttribute(name, value); } - public void setStreams (InputStream i, OutputStream o) { - impl.setStreams (i, o); + public void setStreams(InputStream i, OutputStream o) { + impl.setStreams(i, o); } - public HttpPrincipal getPrincipal () { + public HttpPrincipal getPrincipal() { return impl.getPrincipal(); } - ExchangeImpl getExchangeImpl () { + ExchangeImpl getExchangeImpl() { return impl; } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsServerImpl.java index 97312ec29e6..8ef179c1194 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/HttpsServerImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -35,58 +35,58 @@ public class HttpsServerImpl extends HttpsServer { ServerImpl server; - HttpsServerImpl () throws IOException { - this (new InetSocketAddress(443), 0); + HttpsServerImpl() throws IOException { + this(new InetSocketAddress(443), 0); } - HttpsServerImpl ( + HttpsServerImpl( InetSocketAddress addr, int backlog ) throws IOException { - server = new ServerImpl (this, "https", addr, backlog); + server = new ServerImpl(this, "https", addr, backlog); } - public void setHttpsConfigurator (HttpsConfigurator config) { - server.setHttpsConfigurator (config); + public void setHttpsConfigurator(HttpsConfigurator config) { + server.setHttpsConfigurator(config); } - public HttpsConfigurator getHttpsConfigurator () { + public HttpsConfigurator getHttpsConfigurator() { return server.getHttpsConfigurator(); } - public void bind (InetSocketAddress addr, int backlog) throws IOException { - server.bind (addr, backlog); + public void bind(InetSocketAddress addr, int backlog) throws IOException { + server.bind(addr, backlog); } - public void start () { + public void start() { server.start(); } - public void setExecutor (Executor executor) { + public void setExecutor(Executor executor) { server.setExecutor(executor); } - public Executor getExecutor () { + public Executor getExecutor() { return server.getExecutor(); } - public void stop (int delay) { - server.stop (delay); + public void stop(int delay) { + server.stop(delay); } - public HttpContextImpl createContext (String path, HttpHandler handler) { - return server.createContext (path, handler); + public HttpContextImpl createContext(String path, HttpHandler handler) { + return server.createContext(path, handler); } - public HttpContextImpl createContext (String path) { - return server.createContext (path); + public HttpContextImpl createContext(String path) { + return server.createContext(path); } - public void removeContext (String path) throws IllegalArgumentException { - server.removeContext (path); + public void removeContext(String path) throws IllegalArgumentException { + server.removeContext(path); } - public void removeContext (HttpContext context) throws IllegalArgumentException { - server.removeContext (context); + public void removeContext(HttpContext context) throws IllegalArgumentException { + server.removeContext(context); } public InetSocketAddress getAddress() { diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/LeftOverInputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/LeftOverInputStream.java index 772fa621076..ea904835770 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/LeftOverInputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/LeftOverInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -45,47 +45,47 @@ abstract class LeftOverInputStream extends FilterInputStream { final ServerImpl server; protected boolean closed = false; protected boolean eof = false; - byte[] one = new byte [1]; + byte[] one = new byte[1]; private static final int MAX_SKIP_BUFFER_SIZE = 2048; - public LeftOverInputStream (ExchangeImpl t, InputStream src) { - super (src); + public LeftOverInputStream(ExchangeImpl t, InputStream src) { + super(src); this.t = t; this.server = t.getServerImpl(); } /** * if bytes are left over buffered on *the UNDERLYING* stream */ - public boolean isDataBuffered () throws IOException { + public boolean isDataBuffered() throws IOException { assert eof; return super.available() > 0; } - public void close () throws IOException { + public void close() throws IOException { if (closed) { return; } closed = true; if (!eof) { - eof = drain (ServerConfig.getDrainAmount()); + eof = drain(ServerConfig.getDrainAmount()); } } - public boolean isClosed () { + public boolean isClosed() { return closed; } - public boolean isEOF () { + public boolean isEOF() { return eof; } - protected abstract int readImpl (byte[]b, int off, int len) throws IOException; + protected abstract int readImpl(byte[] b, int off, int len) throws IOException; - public synchronized int read () throws IOException { + public synchronized int read() throws IOException { if (closed) { - throw new IOException ("Stream is closed"); + throw new IOException("Stream is closed"); } - int c = readImpl (one, 0, 1); + int c = readImpl(one, 0, 1); if (c == -1 || c == 0) { return c; } else { @@ -93,11 +93,11 @@ abstract class LeftOverInputStream extends FilterInputStream { } } - public synchronized int read (byte[]b, int off, int len) throws IOException { + public synchronized int read(byte[] b, int off, int len) throws IOException { if (closed) { - throw new IOException ("Stream is closed"); + throw new IOException("Stream is closed"); } - return readImpl (b, off, len); + return readImpl(b, off, len); } @Override @@ -132,7 +132,7 @@ abstract class LeftOverInputStream extends FilterInputStream { * is at eof (ie. all bytes were read) or false if not * (still bytes to be read) */ - public boolean drain (long l) throws IOException { + public boolean drain(long l) throws IOException { while (l > 0) { long skip = skip(l); if (skip <= 0) break; // might return 0 if isFinishing or EOF diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java index 6c0c2c271ed..4a4afc8d7ce 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -46,7 +46,7 @@ class Request { private OutputStream os; private final int maxReqHeaderSize; - Request (InputStream rawInputStream, OutputStream rawout) throws IOException { + Request(InputStream rawInputStream, OutputStream rawout) throws IOException { this.maxReqHeaderSize = ServerConfig.getMaxReqHeaderSize(); is = rawInputStream; os = rawout; @@ -57,15 +57,15 @@ class Request { } - char[] buf = new char [BUF_LEN]; + char[] buf = new char[BUF_LEN]; int pos; StringBuffer lineBuf; - public InputStream inputStream () { + public InputStream inputStream() { return is; } - public OutputStream outputStream () { + public OutputStream outputStream() { return os; } @@ -74,7 +74,7 @@ class Request { * Not used for reading headers. */ - public String readLine () throws IOException { + public String readLine() throws IOException { boolean gotCR = false, gotLF = false; pos = 0; lineBuf = new StringBuffer(); long lsize = 32; @@ -88,15 +88,15 @@ class Request { gotLF = true; } else { gotCR = false; - consume (CR); - consume (c); + consume(CR); + consume(c); lsize = lsize + 2; } } else { if (c == CR) { gotCR = true; } else { - consume (c); + consume(c); lsize = lsize + 1; } } @@ -106,13 +106,13 @@ class Request { ServerConfig.getMaxReqHeaderSize() + "."); } } - lineBuf.append (buf, 0, pos); - return new String (lineBuf); + lineBuf.append(buf, 0, pos); + return new String(lineBuf); } - private void consume (int c) throws IOException { + private void consume(int c) throws IOException { if (pos == BUF_LEN) { - lineBuf.append (buf); + lineBuf.append(buf); pos = 0; } buf[pos++] = (char)c; @@ -121,13 +121,13 @@ class Request { /** * returns the request line (first line of a request) */ - public String requestLine () { + public String requestLine() { return startLine; } Headers hdrs = null; @SuppressWarnings("fallthrough") - Headers headers () throws IOException { + Headers headers() throws IOException { if (hdrs != null) { return hdrs; } @@ -239,7 +239,7 @@ class Request { if (k == null) { // Headers disallows null keys, use empty string k = ""; // instead to represent invalid key } - hdrs.add (k,v); + hdrs.add(k, v); len = 0; } return hdrs; @@ -262,21 +262,21 @@ class Request { ServerImpl server; static final int BUFSIZE = 8 * 1024; - public ReadStream (ServerImpl server, SocketChannel chan) throws IOException { + public ReadStream(ServerImpl server, SocketChannel chan) throws IOException { this.channel = chan; this.server = server; - chanbuf = ByteBuffer.allocate (BUFSIZE); + chanbuf = ByteBuffer.allocate(BUFSIZE); chanbuf.clear(); one = new byte[1]; closed = marked = reset = false; } - public synchronized int read (byte[] b) throws IOException { - return read (b, 0, b.length); + public synchronized int read(byte[] b) throws IOException { + return read(b, 0, b.length); } - public synchronized int read () throws IOException { - int result = read (one, 0, 1); + public synchronized int read() throws IOException { + int result = read(one, 0, 1); if (result == 1) { return one[0] & 0xFF; } else { @@ -284,12 +284,12 @@ class Request { } } - public synchronized int read (byte[] b, int off, int srclen) throws IOException { + public synchronized int read(byte[] b, int off, int srclen) throws IOException { int canreturn, willreturn; if (closed) - throw new IOException ("Stream closed"); + throw new IOException("Stream closed"); if (eof) { return -1; @@ -300,30 +300,30 @@ class Request { Objects.checkFromIndexSize(off, srclen, b.length); if (reset) { /* satisfy from markBuf */ - canreturn = markBuf.remaining (); + canreturn = markBuf.remaining(); willreturn = canreturn>srclen ? srclen : canreturn; markBuf.get(b, off, willreturn); if (canreturn == willreturn) { reset = false; } } else { /* satisfy from channel */ - chanbuf.clear (); + chanbuf.clear(); if (srclen < BUFSIZE) { - chanbuf.limit (srclen); + chanbuf.limit(srclen); } do { - willreturn = channel.read (chanbuf); + willreturn = channel.read(chanbuf); } while (willreturn == 0); if (willreturn == -1) { eof = true; return -1; } - chanbuf.flip (); + chanbuf.flip(); chanbuf.get(b, off, willreturn); if (marked) { /* copy into markBuf */ try { - markBuf.put (b, off, willreturn); + markBuf.put(b, off, willreturn); } catch (BufferOverflowException e) { marked = false; } @@ -332,14 +332,14 @@ class Request { return willreturn; } - public boolean markSupported () { + public boolean markSupported() { return true; } /* Does not query the OS socket */ - public synchronized int available () throws IOException { + public synchronized int available() throws IOException { if (closed) - throw new IOException ("Stream is closed"); + throw new IOException("Stream is closed"); if (eof) return -1; @@ -350,31 +350,31 @@ class Request { return chanbuf.remaining(); } - public void close () throws IOException { + public void close() throws IOException { if (closed) { return; } - channel.close (); + channel.close(); closed = true; } - public synchronized void mark (int readlimit) { + public synchronized void mark(int readlimit) { if (closed) return; this.readlimit = readlimit; - markBuf = ByteBuffer.allocate (readlimit); + markBuf = ByteBuffer.allocate(readlimit); marked = true; reset = false; } - public synchronized void reset () throws IOException { + public synchronized void reset() throws IOException { if (closed ) return; if (!marked) - throw new IOException ("Stream not marked"); + throw new IOException("Stream not marked"); marked = false; reset = true; - markBuf.flip (); + markBuf.flip(); } } @@ -386,50 +386,50 @@ class Request { byte[] one; ServerImpl server; - public WriteStream (ServerImpl server, SocketChannel channel) throws IOException { + public WriteStream(ServerImpl server, SocketChannel channel) throws IOException { this.channel = channel; this.server = server; assert channel.isBlocking(); closed = false; one = new byte [1]; - buf = ByteBuffer.allocate (4096); + buf = ByteBuffer.allocate(4096); } - public synchronized void write (int b) throws IOException { + public synchronized void write(int b) throws IOException { one[0] = (byte)b; write (one, 0, 1); } - public synchronized void write (byte[] b) throws IOException { + public synchronized void write(byte[] b) throws IOException { write (b, 0, b.length); } - public synchronized void write (byte[] b, int off, int len) throws IOException { + public synchronized void write(byte[] b, int off, int len) throws IOException { int l = len; if (closed) - throw new IOException ("stream is closed"); + throw new IOException("stream is closed"); int cap = buf.capacity(); if (cap < len) { int diff = len - cap; - buf = ByteBuffer.allocate (2*(cap+diff)); + buf = ByteBuffer.allocate(2*(cap+diff)); } buf.clear(); - buf.put (b, off, len); - buf.flip (); + buf.put(b, off, len); + buf.flip(); int n; - while ((n = channel.write (buf)) < l) { + while ((n = channel.write(buf)) < l) { l -= n; if (l == 0) return; } } - public void close () throws IOException { + public void close() throws IOException { if (closed) return; - //server.logStackTrace ("Request.OS.close: isOpen="+channel.isOpen()); - channel.close (); + //server.logStackTrace("Request.OS.close: isOpen="+channel.isOpen()); + channel.close(); closed = true; } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/SSLStreams.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/SSLStreams.java index 5cc16befa96..5f5eef0c684 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/SSLStreams.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/SSLStreams.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -53,35 +53,35 @@ class SSLStreams { /* held by thread doing the hand-shake on this connection */ Lock handshaking = new ReentrantLock(); - SSLStreams (ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException { + SSLStreams(ServerImpl server, SSLContext sslctx, SocketChannel chan) throws IOException { this.server = server; this.sslctx= sslctx; this.chan= chan; InetSocketAddress addr = (InetSocketAddress)chan.socket().getRemoteSocketAddress(); - engine = sslctx.createSSLEngine (addr.getHostName(), addr.getPort()); - engine.setUseClientMode (false); + engine = sslctx.createSSLEngine(addr.getHostName(), addr.getPort()); + engine.setUseClientMode(false); HttpsConfigurator cfg = server.getHttpsConfigurator(); - configureEngine (cfg, addr); - wrapper = new EngineWrapper (chan, engine); + configureEngine(cfg, addr); + wrapper = new EngineWrapper(chan, engine); } @SuppressWarnings("deprecation") - private void configureEngine(HttpsConfigurator cfg, InetSocketAddress addr){ + private void configureEngine(HttpsConfigurator cfg, InetSocketAddress addr) { if (cfg != null) { - Parameters params = new Parameters (cfg, addr); + Parameters params = new Parameters(cfg, addr); //BEGIN_TIGER_EXCLUDE - cfg.configure (params); + cfg.configure(params); SSLParameters sslParams = params.getSSLParameters(); if (sslParams != null) { - engine.setSSLParameters (sslParams); + engine.setSSLParameters(sslParams); } else //END_TIGER_EXCLUDE { /* tiger compatibility */ if (params.getCipherSuites() != null) { try { - engine.setEnabledCipherSuites ( + engine.setEnabledCipherSuites( params.getCipherSuites() ); } catch (IllegalArgumentException e) { /* LOG */} @@ -93,7 +93,7 @@ class SSLStreams { } if (params.getProtocols() != null) { try { - engine.setEnabledProtocols ( + engine.setEnabledProtocols( params.getProtocols() ); } catch (IllegalArgumentException e) { /* LOG */} @@ -106,11 +106,11 @@ class SSLStreams { InetSocketAddress addr; HttpsConfigurator cfg; - Parameters (HttpsConfigurator cfg, InetSocketAddress addr) { + Parameters(HttpsConfigurator cfg, InetSocketAddress addr) { this.addr = addr; this.cfg = cfg; } - public InetSocketAddress getClientAddress () { + public InetSocketAddress getClientAddress() { return addr; } public HttpsConfigurator getHttpsConfigurator() { @@ -118,10 +118,10 @@ class SSLStreams { } //BEGIN_TIGER_EXCLUDE SSLParameters params; - public void setSSLParameters (SSLParameters p) { + public void setSSLParameters(SSLParameters p) { params = p; } - SSLParameters getSSLParameters () { + SSLParameters getSSLParameters() { return params; } //END_TIGER_EXCLUDE @@ -130,14 +130,14 @@ class SSLStreams { /** * cleanup resources allocated inside this object */ - void close () throws IOException { + void close() throws IOException { wrapper.close(); } /** * return the SSL InputStream */ - InputStream getInputStream () throws IOException { + InputStream getInputStream() throws IOException { if (is == null) { is = new InputStream(); } @@ -147,14 +147,14 @@ class SSLStreams { /** * return the SSL OutputStream */ - OutputStream getOutputStream () throws IOException { + OutputStream getOutputStream() throws IOException { if (os == null) { os = new OutputStream(); } return os; } - SSLEngine getSSLEngine () { + SSLEngine getSSLEngine() { return engine; } @@ -183,11 +183,11 @@ class SSLStreams { PACKET, APPLICATION }; - private ByteBuffer allocate (BufType type) { - return allocate (type, -1); + private ByteBuffer allocate(BufType type) { + return allocate(type, -1); } - private ByteBuffer allocate (BufType type, int len) { + private ByteBuffer allocate(BufType type, int len) { assert engine != null; synchronized (this) { int size; @@ -210,7 +210,7 @@ class SSLStreams { } size = app_buf_size; } - return ByteBuffer.allocate (size); + return ByteBuffer.allocate(size); } } @@ -222,10 +222,10 @@ class SSLStreams { * flip is set to true if the old buffer needs to be flipped * before it is copied. */ - private ByteBuffer realloc (ByteBuffer b, boolean flip, BufType type) { + private ByteBuffer realloc(ByteBuffer b, boolean flip, BufType type) { synchronized (this) { int nsize = 2 * b.capacity(); - ByteBuffer n = allocate (type, nsize); + ByteBuffer n = allocate(type, nsize); if (flip) { b.flip(); } @@ -252,7 +252,7 @@ class SSLStreams { boolean closed = false; int u_remaining; // the number of bytes left in unwrap_src after an unwrap() - EngineWrapper (SocketChannel chan, SSLEngine engine) throws IOException { + EngineWrapper(SocketChannel chan, SSLEngine engine) throws IOException { this.chan = chan; this.engine = engine; wrapLock = new Object(); @@ -261,7 +261,7 @@ class SSLStreams { wrap_dst = allocate(BufType.PACKET); } - void close () throws IOException { + void close() throws IOException { } /* try to wrap and send the data in src. Handles OVERFLOW. @@ -275,17 +275,17 @@ class SSLStreams { WrapperResult wrapAndSendX(ByteBuffer src, boolean ignoreClose) throws IOException { if (closed && !ignoreClose) { - throw new IOException ("Engine is closed"); + throw new IOException("Engine is closed"); } Status status; WrapperResult r = new WrapperResult(); synchronized (wrapLock) { wrap_dst.clear(); do { - r.result = engine.wrap (src, wrap_dst); + r.result = engine.wrap(src, wrap_dst); status = r.result.getStatus(); if (status == Status.BUFFER_OVERFLOW) { - wrap_dst = realloc (wrap_dst, true, BufType.PACKET); + wrap_dst = realloc(wrap_dst, true, BufType.PACKET); } } while (status == Status.BUFFER_OVERFLOW); if (status == Status.CLOSED && !ignoreClose) { @@ -296,7 +296,7 @@ class SSLStreams { int l = wrap_dst.remaining(); assert l == r.result.bytesProduced(); while (l>0) { - l -= chan.write (wrap_dst); + l -= chan.write(wrap_dst); } } } @@ -313,7 +313,7 @@ class SSLStreams { WrapperResult r = new WrapperResult(); r.buf = dst; if (closed) { - throw new IOException ("Engine is closed"); + throw new IOException("Engine is closed"); } boolean needData; if (u_remaining > 0) { @@ -329,19 +329,19 @@ class SSLStreams { do { if (needData) { do { - x = chan.read (unwrap_src); + x = chan.read(unwrap_src); } while (x == 0); if (x == -1) { - throw new IOException ("connection closed for reading"); + throw new IOException("connection closed for reading"); } unwrap_src.flip(); } - r.result = engine.unwrap (unwrap_src, r.buf); + r.result = engine.unwrap(unwrap_src, r.buf); status = r.result.getStatus(); if (status == Status.BUFFER_UNDERFLOW) { if (unwrap_src.limit() == unwrap_src.capacity()) { /* buffer not big enough */ - unwrap_src = realloc ( + unwrap_src = realloc( unwrap_src, false, BufType.PACKET ); } else { @@ -349,12 +349,12 @@ class SSLStreams { * data off the channel. Reset pointers * for reading off SocketChannel */ - unwrap_src.position (unwrap_src.limit()); - unwrap_src.limit (unwrap_src.capacity()); + unwrap_src.position(unwrap_src.limit()); + unwrap_src.limit(unwrap_src.capacity()); } needData = true; } else if (status == Status.BUFFER_OVERFLOW) { - r.buf = realloc (r.buf, true, BufType.APPLICATION); + r.buf = realloc(r.buf, true, BufType.APPLICATION); needData = false; } else if (status == Status.CLOSED) { closed = true; @@ -374,13 +374,13 @@ class SSLStreams { * all of the given user data has been sent and any handshake has been * completed. Caller should check if engine has been closed. */ - public WrapperResult sendData (ByteBuffer src) throws IOException { + public WrapperResult sendData(ByteBuffer src) throws IOException { WrapperResult r=null; while (src.remaining() > 0) { r = wrapper.wrapAndSend(src); Status status = r.result.getStatus(); if (status == Status.CLOSED) { - doClosure (); + doClosure(); return r; } HandshakeStatus hs_status = r.result.getHandshakeStatus(); @@ -399,16 +399,16 @@ class SSLStreams { * and returned. This call handles handshaking automatically. * Caller should check if engine has been closed. */ - public WrapperResult recvData (ByteBuffer dst) throws IOException { + public WrapperResult recvData(ByteBuffer dst) throws IOException { /* we wait until some user data arrives */ WrapperResult r = null; assert dst.position() == 0; while (dst.position() == 0) { - r = wrapper.recvAndUnwrap (dst); + r = wrapper.recvAndUnwrap(dst); dst = (r.buf != dst) ? r.buf: dst; Status status = r.result.getStatus(); if (status == Status.CLOSED) { - doClosure (); + doClosure(); return r; } @@ -416,7 +416,7 @@ class SSLStreams { if (hs_status != HandshakeStatus.FINISHED && hs_status != HandshakeStatus.NOT_HANDSHAKING) { - doHandshake (hs_status); + doHandshake(hs_status); } } dst.flip(); @@ -426,7 +426,7 @@ class SSLStreams { /* we've received a close notify. Need to call wrap to send * the response */ - void doClosure () throws IOException { + void doClosure() throws IOException { try { handshaking.lock(); ByteBuffer tmp = allocate(BufType.APPLICATION); @@ -435,8 +435,8 @@ class SSLStreams { HandshakeStatus hs; do { tmp.clear(); - tmp.flip (); - r = wrapper.wrapAndSendX (tmp, true); + tmp.flip(); + r = wrapper.wrapAndSendX(tmp, true); hs = r.result.getHandshakeStatus(); st = r.result.getStatus(); } while (st != Status.CLOSED && @@ -452,7 +452,7 @@ class SSLStreams { * is called with no data to send then there must be no problem */ @SuppressWarnings("fallthrough") - void doHandshake (HandshakeStatus hs_status) throws IOException { + void doHandshake(HandshakeStatus hs_status) throws IOException { try { handshaking.lock(); ByteBuffer tmp = allocate(BufType.APPLICATION); @@ -478,7 +478,7 @@ class SSLStreams { case NEED_UNWRAP: tmp.clear(); - r = wrapper.recvAndUnwrap (tmp); + r = wrapper.recvAndUnwrap(tmp); if (r.buf != tmp) { tmp = r.buf; } @@ -507,27 +507,27 @@ class SSLStreams { boolean needData = true; - InputStream () { - bbuf = allocate (BufType.APPLICATION); + InputStream() { + bbuf = allocate(BufType.APPLICATION); } - public int read (byte[] buf, int off, int len) throws IOException { + public int read(byte[] buf, int off, int len) throws IOException { if (closed) { - throw new IOException ("SSL stream is closed"); + throw new IOException("SSL stream is closed"); } if (eof) { return -1; } - int available=0; + int available = 0; if (!needData) { available = bbuf.remaining(); - needData = (available==0); + needData = (available == 0); } if (needData) { bbuf.clear(); - WrapperResult r = recvData (bbuf); - bbuf = r.buf== bbuf? bbuf: r.buf; - if ((available=bbuf.remaining()) == 0) { + WrapperResult r = recvData(bbuf); + bbuf = r.buf == bbuf ? bbuf: r.buf; + if ((available = bbuf.remaining()) == 0) { eof = true; return -1; } else { @@ -538,26 +538,26 @@ class SSLStreams { if (len > available) { len = available; } - bbuf.get (buf, off, len); + bbuf.get(buf, off, len); return len; } - public int available () throws IOException { + public int available() throws IOException { return bbuf.remaining(); } - public boolean markSupported () { + public boolean markSupported() { return false; /* not possible with SSLEngine */ } - public void reset () throws IOException { - throw new IOException ("mark/reset not supported"); + public void reset() throws IOException { + throw new IOException("mark/reset not supported"); } - public long skip (long s) throws IOException { + public long skip(long s) throws IOException { int n = (int)s; if (closed) { - throw new IOException ("SSL stream is closed"); + throw new IOException("SSL stream is closed"); } if (eof) { return 0; @@ -565,13 +565,13 @@ class SSLStreams { int ret = n; while (n > 0) { if (bbuf.remaining() >= n) { - bbuf.position (bbuf.position()+n); + bbuf.position(bbuf.position()+n); return ret; } else { n -= bbuf.remaining(); bbuf.clear(); - WrapperResult r = recvData (bbuf); - bbuf = r.buf==bbuf? bbuf: r.buf; + WrapperResult r = recvData(bbuf); + bbuf = r.buf == bbuf ? bbuf: r.buf; } } return ret; /* not reached */ @@ -582,22 +582,22 @@ class SSLStreams { * before this is called. Otherwise an exception will be thrown. * [Note. May need to revisit this. not quite the normal close() semantics */ - public void close () throws IOException { + public void close() throws IOException { eof = true; - engine.closeInbound (); + engine.closeInbound(); } - public int read (byte[] buf) throws IOException { - return read (buf, 0, buf.length); + public int read(byte[] buf) throws IOException { + return read(buf, 0, buf.length); } byte single[] = new byte [1]; - public int read () throws IOException { + public int read() throws IOException { if (eof) { return -1; } - int n = read (single, 0, 1); + int n = read(single, 0, 1); if (n <= 0) { return -1; } else { @@ -622,28 +622,28 @@ class SSLStreams { public void write(int b) throws IOException { single[0] = (byte)b; - write (single, 0, 1); + write(single, 0, 1); } public void write(byte b[]) throws IOException { - write (b, 0, b.length); + write(b, 0, b.length); } public void write(byte b[], int off, int len) throws IOException { if (closed) { - throw new IOException ("output stream is closed"); + throw new IOException("output stream is closed"); } while (len > 0) { int l = len > buf.capacity() ? buf.capacity() : len; buf.clear(); - buf.put (b, off, l); + buf.put(b, off, l); len -= l; off += l; buf.flip(); - WrapperResult r = sendData (buf); + WrapperResult r = sendData(buf); if (r.result.getStatus() == Status.CLOSED) { closed = true; if (len > 0) { - throw new IOException ("output stream is closed"); + throw new IOException("output stream is closed"); } } } @@ -654,13 +654,13 @@ class SSLStreams { } public void close() throws IOException { - WrapperResult r=null; + WrapperResult r = null; engine.closeOutbound(); closed = true; HandshakeStatus stat = HandshakeStatus.NEED_WRAP; buf.clear(); while (stat == HandshakeStatus.NEED_WRAP) { - r = wrapper.wrapAndSend (buf); + r = wrapper.wrapAndSend(buf); stat = r.result.getHandshakeStatus(); } assert r.result.getStatus() == Status.CLOSED diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index 217ae86f5d3..1eb918b4e66 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -128,61 +128,61 @@ class ServerImpl { private final Logger logger; private Thread dispatcherThread; - ServerImpl ( + ServerImpl( HttpServer wrapper, String protocol, InetSocketAddress addr, int backlog ) throws IOException { this.protocol = protocol; this.wrapper = wrapper; - this.logger = System.getLogger ("com.sun.net.httpserver"); - ServerConfig.checkLegacyProperties (logger); - https = protocol.equalsIgnoreCase ("https"); + this.logger = System.getLogger("com.sun.net.httpserver"); + ServerConfig.checkLegacyProperties(logger); + https = protocol.equalsIgnoreCase("https"); this.address = addr; contexts = new ContextList(); schan = ServerSocketChannel.open(); if (addr != null) { ServerSocket socket = schan.socket(); - socket.bind (addr, backlog); + socket.bind(addr, backlog); bound = true; } - selector = Selector.open (); - schan.configureBlocking (false); - listenerKey = schan.register (selector, SelectionKey.OP_ACCEPT); + selector = Selector.open(); + schan.configureBlocking(false); + listenerKey = schan.register(selector, SelectionKey.OP_ACCEPT); dispatcher = new Dispatcher(); - idleConnections = Collections.synchronizedSet (new HashSet()); - allConnections = Collections.synchronizedSet (new HashSet()); - reqConnections = Collections.synchronizedSet (new HashSet()); - rspConnections = Collections.synchronizedSet (new HashSet()); + idleConnections = Collections.synchronizedSet(new HashSet()); + allConnections = Collections.synchronizedSet(new HashSet()); + reqConnections = Collections.synchronizedSet(new HashSet()); + rspConnections = Collections.synchronizedSet(new HashSet()); newlyAcceptedConnections = Collections.synchronizedSet(new HashSet<>()); - timer = new Timer ("idle-timeout-task", true); - timer.schedule (new IdleTimeoutTask(), IDLE_TIMER_TASK_SCHEDULE, IDLE_TIMER_TASK_SCHEDULE); + timer = new Timer("idle-timeout-task", true); + timer.schedule(new IdleTimeoutTask(), IDLE_TIMER_TASK_SCHEDULE, IDLE_TIMER_TASK_SCHEDULE); if (reqRspTimeoutEnabled) { - timer1 = new Timer ("req-rsp-timeout-task", true); - timer1.schedule (new ReqRspTimeoutTask(), REQ_RSP_TIMER_SCHEDULE, REQ_RSP_TIMER_SCHEDULE); + timer1 = new Timer("req-rsp-timeout-task", true); + timer1.schedule(new ReqRspTimeoutTask(), REQ_RSP_TIMER_SCHEDULE, REQ_RSP_TIMER_SCHEDULE); logger.log(Level.DEBUG, "HttpServer request/response timeout task schedule ms: ", REQ_RSP_TIMER_SCHEDULE); - logger.log (Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME); - logger.log (Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME); + logger.log(Level.DEBUG, "MAX_REQ_TIME: "+MAX_REQ_TIME); + logger.log(Level.DEBUG, "MAX_RSP_TIME: "+MAX_RSP_TIME); } events = new ArrayList<>(); - logger.log (Level.DEBUG, "HttpServer created "+protocol+" "+ addr); + logger.log(Level.DEBUG, "HttpServer created "+protocol+" "+ addr); } - public void bind (InetSocketAddress addr, int backlog) throws IOException { + public void bind(InetSocketAddress addr, int backlog) throws IOException { if (bound) { - throw new BindException ("HttpServer already bound"); + throw new BindException("HttpServer already bound"); } if (addr == null) { - throw new NullPointerException ("null address"); + throw new NullPointerException("null address"); } ServerSocket socket = schan.socket(); - socket.bind (addr, backlog); + socket.bind(addr, backlog); bound = true; } - public void start () { + public void start() { if (!bound || started || finished()) { - throw new IllegalStateException ("server in wrong state"); + throw new IllegalStateException("server in wrong state"); } if (executor == null) { executor = new DefaultExecutor(); @@ -192,39 +192,39 @@ class ServerImpl { dispatcherThread.start(); } - public void setExecutor (Executor executor) { + public void setExecutor(Executor executor) { if (started) { - throw new IllegalStateException ("server already started"); + throw new IllegalStateException("server already started"); } this.executor = executor; } private static class DefaultExecutor implements Executor { - public void execute (Runnable task) { + public void execute(Runnable task) { task.run(); } } - public Executor getExecutor () { + public Executor getExecutor() { return executor; } - public void setHttpsConfigurator (HttpsConfigurator config) { + public void setHttpsConfigurator(HttpsConfigurator config) { if (config == null) { - throw new NullPointerException ("null HttpsConfigurator"); + throw new NullPointerException("null HttpsConfigurator"); } if (started) { - throw new IllegalStateException ("server already started"); + throw new IllegalStateException("server already started"); } this.httpsConfig = config; sslContext = config.getSSLContext(); } - public HttpsConfigurator getHttpsConfigurator () { + public HttpsConfigurator getHttpsConfigurator() { return httpsConfig; } - private final boolean finished(){ + private final boolean finished() { // if the latch is 0, the server is finished return finishedLatch.getCount() == 0; } @@ -242,9 +242,9 @@ class ServerImpl { * * @param delay maximum delay to wait for exchanges completion, in seconds */ - public void stop (int delay) { + public void stop(int delay) { if (delay < 0) { - throw new IllegalArgumentException ("negative delay parameter"); + throw new IllegalArgumentException("negative delay parameter"); } logger.log(Level.TRACE, "stopping"); @@ -298,49 +298,49 @@ class ServerImpl { Dispatcher dispatcher; - public synchronized HttpContextImpl createContext (String path, HttpHandler handler) { + public synchronized HttpContextImpl createContext(String path, HttpHandler handler) { if (handler == null || path == null) { - throw new NullPointerException ("null handler, or path parameter"); + throw new NullPointerException("null handler, or path parameter"); } - HttpContextImpl context = new HttpContextImpl (protocol, path, handler, this); - contexts.add (context); - logger.log (Level.DEBUG, "context created: " + path); + HttpContextImpl context = new HttpContextImpl(protocol, path, handler, this); + contexts.add(context); + logger.log(Level.DEBUG, "context created: " + path); return context; } - public synchronized HttpContextImpl createContext (String path) { + public synchronized HttpContextImpl createContext(String path) { if (path == null) { - throw new NullPointerException ("null path parameter"); + throw new NullPointerException("null path parameter"); } - HttpContextImpl context = new HttpContextImpl (protocol, path, null, this); - contexts.add (context); - logger.log (Level.DEBUG, "context created: " + path); + HttpContextImpl context = new HttpContextImpl(protocol, path, null, this); + contexts.add(context); + logger.log(Level.DEBUG, "context created: " + path); return context; } - public synchronized void removeContext (String path) throws IllegalArgumentException { + public synchronized void removeContext(String path) throws IllegalArgumentException { if (path == null) { - throw new NullPointerException ("null path parameter"); + throw new NullPointerException("null path parameter"); } - contexts.remove (protocol, path); - logger.log (Level.DEBUG, "context removed: " + path); + contexts.remove(protocol, path); + logger.log(Level.DEBUG, "context removed: " + path); } - public synchronized void removeContext (HttpContext context) throws IllegalArgumentException { + public synchronized void removeContext(HttpContext context) throws IllegalArgumentException { if (!(context instanceof HttpContextImpl)) { - throw new IllegalArgumentException ("wrong HttpContext type"); + throw new IllegalArgumentException("wrong HttpContext type"); } - contexts.remove ((HttpContextImpl)context); - logger.log (Level.DEBUG, "context removed: " + context.getPath()); + contexts.remove((HttpContextImpl)context); + logger.log(Level.DEBUG, "context removed: " + context.getPath()); } public InetSocketAddress getAddress() { return (InetSocketAddress) schan.socket().getLocalSocketAddress(); } - void addEvent (Event r) { + void addEvent(Event r) { synchronized (lolock) { - events.add (r); + events.add(r); selector.wakeup(); } } @@ -413,7 +413,7 @@ class ServerImpl { */ class Dispatcher implements Runnable { - private void handleEvent (Event r) { + private void handleEvent(Event r) { // Stopping marking the state as finished if stop is requested, // termination is in progress and exchange count is 0 @@ -450,22 +450,22 @@ class ServerImpl { requestCompleted(c); } } - responseCompleted (c); + responseCompleted(c); if (t.close) { c.close(); - allConnections.remove (c); + allConnections.remove(c); } else { if (is.isDataBuffered()) { /* don't re-enable the interestops, just handle it */ - requestStarted (c); - handle (c.getChannel(), c); + requestStarted(c); + handle(c.getChannel(), c); } else { - connsToRegister.add (c); + connsToRegister.add(c); } } } } catch (IOException e) { - logger.log ( + logger.log( Level.TRACE, "Dispatcher (1)", e ); c.close(); @@ -474,18 +474,18 @@ class ServerImpl { final ArrayList connsToRegister = new ArrayList<>(); - void reRegister (HttpConnection c) { + void reRegister(HttpConnection c) { /* re-register with selector */ try { SocketChannel chan = c.getChannel(); - chan.configureBlocking (false); - SelectionKey key = chan.register (selector, SelectionKey.OP_READ); - key.attach (c); + chan.configureBlocking(false); + SelectionKey key = chan.register(selector, SelectionKey.OP_READ); + key.attach(c); c.selectionKey = key; markIdle(c); } catch (IOException e) { dprint(e); - logger.log (Level.TRACE, "Dispatcher(8)", e); + logger.log(Level.TRACE, "Dispatcher (8)", e); c.close(); } } @@ -504,7 +504,7 @@ class ServerImpl { if (list != null) { for (Event r: list) { - handleEvent (r); + handleEvent(r); } } @@ -525,7 +525,7 @@ class ServerImpl { for (final SelectionKey key : selected.toArray(SelectionKey[]::new)) { // remove the key from the original selected keys (live) Set selected.remove(key); - if (key.equals (listenerKey)) { + if (key.equals(listenerKey)) { if (terminating) { continue; } @@ -546,15 +546,15 @@ class ServerImpl { if (ServerConfig.noDelay()) { chan.socket().setTcpNoDelay(true); } - chan.configureBlocking (false); + chan.configureBlocking(false); SelectionKey newkey = - chan.register (selector, SelectionKey.OP_READ); - HttpConnection c = new HttpConnection (); + chan.register(selector, SelectionKey.OP_READ); + HttpConnection c = new HttpConnection(); c.selectionKey = newkey; - c.setChannel (chan); - newkey.attach (c); + c.setChannel(chan); + newkey.attach(c); markNewlyAccepted(c); - allConnections.add (c); + allConnections.add(c); } } else { try { @@ -563,7 +563,7 @@ class ServerImpl { HttpConnection conn = (HttpConnection)key.attachment(); key.cancel(); - chan.configureBlocking (true); + chan.configureBlocking(true); // check if connection is being closed if (newlyAcceptedConnections.remove(conn) || idleConnections.remove(conn)) { @@ -571,7 +571,7 @@ class ServerImpl { // connection. In either case, we mark that the request // has now started on this connection. requestStarted(conn); - handle (chan, conn); + handle(chan, conn); } } else { assert false : "Unexpected non-readable key:" + key; @@ -586,56 +586,56 @@ class ServerImpl { // call the selector just to process the cancelled keys selector.selectNow(); } catch (IOException e) { - logger.log (Level.TRACE, "Dispatcher (4)", e); + logger.log(Level.TRACE, "Dispatcher (4)", e); } catch (Exception e) { - logger.log (Level.TRACE, "Dispatcher (7)", e); + logger.log(Level.TRACE, "Dispatcher (7)", e); } } - try {selector.close(); } catch (Exception e) {} + try { selector.close(); } catch (Exception e) {} } - private void handleException (SelectionKey key, Exception e) { + private void handleException(SelectionKey key, Exception e) { HttpConnection conn = (HttpConnection)key.attachment(); if (e != null) { - logger.log (Level.TRACE, "Dispatcher (2)", e); + logger.log(Level.TRACE, "Dispatcher (2)", e); } closeConnection(conn); } - public void handle (SocketChannel chan, HttpConnection conn) + public void handle(SocketChannel chan, HttpConnection conn) { try { - Exchange t = new Exchange (chan, protocol, conn); - executor.execute (t); + Exchange t = new Exchange(chan, protocol, conn); + executor.execute(t); } catch (HttpError e1) { - logger.log (Level.TRACE, "Dispatcher (4)", e1); + logger.log(Level.TRACE, "Dispatcher (4)", e1); closeConnection(conn); } catch (IOException e) { - logger.log (Level.TRACE, "Dispatcher (5)", e); + logger.log(Level.TRACE, "Dispatcher (5)", e); closeConnection(conn); } catch (Throwable e) { - logger.log (Level.TRACE, "Dispatcher (6)", e); + logger.log(Level.TRACE, "Dispatcher (6)", e); closeConnection(conn); } } } - static boolean debug = ServerConfig.debugEnabled (); + static boolean debug = ServerConfig.debugEnabled(); - static synchronized void dprint (String s) { + static synchronized void dprint(String s) { if (debug) { - System.out.println (s); + System.out.println(s); } } - static synchronized void dprint (Exception e) { + static synchronized void dprint(Exception e) { if (debug) { - System.out.println (e); + System.out.println(e); e.printStackTrace(); } } - Logger getLogger () { + Logger getLogger() { return logger; } @@ -675,13 +675,13 @@ class ServerImpl { HttpContextImpl ctx; boolean rejected = false; - Exchange (SocketChannel chan, String protocol, HttpConnection conn) throws IOException { + Exchange(SocketChannel chan, String protocol, HttpConnection conn) throws IOException { this.chan = chan; this.connection = conn; this.protocol = protocol; } - public void run () { + public void run() { /* context will be null for new connections */ logger.log(Level.TRACE, "exchange started"); @@ -702,7 +702,7 @@ class ServerImpl { String requestLine = null; SSLStreams sslStreams = null; try { - if (context != null ) { + if (context != null) { this.rawin = connection.getInputStream(); this.rawout = connection.getRawOutputStream(); newconnection = false; @@ -711,21 +711,21 @@ class ServerImpl { newconnection = true; if (https) { if (sslContext == null) { - logger.log (Level.WARNING, + logger.log(Level.WARNING, "SSL connection received. No https context created"); - throw new HttpError ("No SSL context established"); + throw new HttpError("No SSL context established"); } - sslStreams = new SSLStreams (ServerImpl.this, sslContext, chan); + sslStreams = new SSLStreams(ServerImpl.this, sslContext, chan); rawin = sslStreams.getInputStream(); rawout = sslStreams.getOutputStream(); engine = sslStreams.getSSLEngine(); connection.sslStreams = sslStreams; } else { rawin = new BufferedInputStream( - new Request.ReadStream ( + new Request.ReadStream( ServerImpl.this, chan )); - rawout = new Request.WriteStream ( + rawout = new Request.WriteStream( ServerImpl.this, chan ); } @@ -733,7 +733,7 @@ class ServerImpl { connection.raw = rawin; connection.rawout = rawout; } - Request req = new Request (rawin, rawout); + Request req = new Request(rawin, rawout); requestLine = req.requestLine(); if (requestLine == null) { /* connection closed */ @@ -742,31 +742,31 @@ class ServerImpl { return; } logger.log(Level.DEBUG, "Exchange request line: {0}", requestLine); - int space = requestLine.indexOf (' '); + int space = requestLine.indexOf(' '); if (space == -1) { - reject (Code.HTTP_BAD_REQUEST, + reject(Code.HTTP_BAD_REQUEST, requestLine, "Bad request line"); return; } - String method = requestLine.substring (0, space); + String method = requestLine.substring(0, space); int start = space+1; space = requestLine.indexOf(' ', start); if (space == -1) { - reject (Code.HTTP_BAD_REQUEST, + reject(Code.HTTP_BAD_REQUEST, requestLine, "Bad request line"); return; } - String uriStr = requestLine.substring (start, space); + String uriStr = requestLine.substring(start, space); URI uri; try { - uri = new URI (uriStr); + uri = new URI(uriStr); } catch (URISyntaxException e3) { reject(Code.HTTP_BAD_REQUEST, requestLine, "URISyntaxException thrown"); return; } start = space+1; - String version = requestLine.substring (start); + String version = requestLine.substring(start); Headers headers = req.headers(); /* check key for illegal characters */ for (var k : headers.keySet()) { @@ -817,32 +817,32 @@ class ServerImpl { requestCompleted(connection); } } - ctx = contexts.findContext (protocol, uri.getPath()); + ctx = contexts.findContext(protocol, uri.getPath()); if (ctx == null) { - reject (Code.HTTP_NOT_FOUND, + reject(Code.HTTP_NOT_FOUND, requestLine, "No context found for request"); return; } - connection.setContext (ctx); + connection.setContext(ctx); if (ctx.getHandler() == null) { - reject (Code.HTTP_INTERNAL_ERROR, + reject(Code.HTTP_INTERNAL_ERROR, requestLine, "No handler for context"); return; } - tx = new ExchangeImpl ( + tx = new ExchangeImpl( method, uri, req, clen, connection ); String chdr = headers.getFirst("Connection"); Headers rheaders = tx.getResponseHeaders(); - if (chdr != null && chdr.equalsIgnoreCase ("close")) { + if (chdr != null && chdr.equalsIgnoreCase("close")) { tx.close = true; } - if (version.equalsIgnoreCase ("http/1.0")) { + if (version.equalsIgnoreCase("http/1.0")) { tx.http10 = true; if (chdr == null) { tx.close = true; - rheaders.set ("Connection", "close"); + rheaders.set("Connection", "close"); } else if (chdr.equalsIgnoreCase("keep-alive")) { rheaders.set("Connection", "keep-alive"); int idleSeconds = (int) (ServerConfig.getIdleIntervalMillis() / 1000); @@ -852,7 +852,7 @@ class ServerImpl { } if (newconnection) { - connection.setParameters ( + connection.setParameters( rawin, rawout, chan, engine, sslStreams, sslContext, protocol, ctx, rawin ); @@ -863,9 +863,9 @@ class ServerImpl { * be involved in this process. */ String exp = headers.getFirst("Expect"); - if (exp != null && exp.equalsIgnoreCase ("100-continue")) { - logReply (100, requestLine, null); - sendReply ( + if (exp != null && exp.equalsIgnoreCase("100-continue")) { + logReply(100, requestLine, null); + sendReply( Code.HTTP_CONTINUE, false, null ); } @@ -880,19 +880,19 @@ class ServerImpl { final List uf = ctx.getFilters(); final Filter.Chain sc = new Filter.Chain(sf, ctx.getHandler()); - final Filter.Chain uc = new Filter.Chain(uf, new LinkHandler (sc)); + final Filter.Chain uc = new Filter.Chain(uf, new LinkHandler(sc)); /* set up the two stream references */ tx.getRequestBody(); tx.getResponseBody(); if (https) { - uc.doFilter (new HttpsExchangeImpl (tx)); + uc.doFilter(new HttpsExchangeImpl(tx)); } else { - uc.doFilter (new HttpExchangeImpl (tx)); + uc.doFilter(new HttpExchangeImpl(tx)); } } catch (Exception e) { - logger.log (Level.TRACE, "ServerImpl.Exchange", e); + logger.log(Level.TRACE, "ServerImpl.Exchange", e); if (tx == null || !tx.writefinished) { closeConnection(connection); } @@ -907,59 +907,59 @@ class ServerImpl { class LinkHandler implements HttpHandler { Filter.Chain nextChain; - LinkHandler (Filter.Chain nextChain) { + LinkHandler(Filter.Chain nextChain) { this.nextChain = nextChain; } - public void handle (HttpExchange exchange) throws IOException { - nextChain.doFilter (exchange); + public void handle(HttpExchange exchange) throws IOException { + nextChain.doFilter(exchange); } } - void reject (int code, String requestStr, String message) { + void reject(int code, String requestStr, String message) { rejected = true; - logReply (code, requestStr, message); - sendReply ( + logReply(code, requestStr, message); + sendReply( code, true, "

    "+code+Code.msg(code)+"

    "+message ); } - void sendReply ( + void sendReply( int code, boolean closeNow, String text) { try { - StringBuilder builder = new StringBuilder (512); - builder.append ("HTTP/1.1 ") - .append (code).append (Code.msg(code)).append ("\r\n"); + StringBuilder builder = new StringBuilder(512); + builder.append("HTTP/1.1 ") + .append(code).append(Code.msg(code)).append("\r\n"); if (text != null && text.length() != 0) { - builder.append ("Content-Length: ") - .append (text.length()).append ("\r\n") - .append ("Content-Type: text/html\r\n"); + builder.append("Content-Length: ") + .append(text.length()).append("\r\n") + .append("Content-Type: text/html\r\n"); } else { - builder.append ("Content-Length: 0\r\n"); + builder.append("Content-Length: 0\r\n"); text = ""; } if (closeNow) { - builder.append ("Connection: close\r\n"); + builder.append("Connection: close\r\n"); } - builder.append ("\r\n").append (text); + builder.append("\r\n").append(text); String s = builder.toString(); byte[] b = s.getBytes(ISO_8859_1); - rawout.write (b); + rawout.write(b); rawout.flush(); if (closeNow) { closeConnection(connection); } } catch (IOException e) { - logger.log (Level.TRACE, "ServerImpl.sendReply", e); + logger.log(Level.TRACE, "ServerImpl.sendReply", e); closeConnection(connection); } } } - void logReply (int code, String requestStr, String text) { + void logReply(int code, String requestStr, String text) { if (!logger.isLoggable(Level.DEBUG)) { return; } @@ -968,18 +968,18 @@ class ServerImpl { } String r; if (requestStr.length() > 80) { - r = requestStr.substring (0, 80) + ""; + r = requestStr.substring(0, 80) + ""; } else { r = requestStr; } String message = r + " [" + code + " " + Code.msg(code) + "] ("+text+")"; - logger.log (Level.DEBUG, message); + logger.log(Level.DEBUG, message); } private int exchangeCount = 0; - synchronized void startExchange () { + synchronized void startExchange() { exchangeCount ++; } @@ -987,20 +987,20 @@ class ServerImpl { return exchangeCount; } - synchronized int endExchange () { + synchronized int endExchange() { exchangeCount --; assert exchangeCount >= 0; return exchangeCount; } - HttpServer getWrapper () { + HttpServer getWrapper() { return wrapper; } - void requestStarted (HttpConnection c) { + void requestStarted(HttpConnection c) { c.reqStartedTime = System.currentTimeMillis(); - c.setState (State.REQUEST); - reqConnections.add (c); + c.setState(State.REQUEST); + reqConnections.add(c); } void markIdle(HttpConnection c) { @@ -1037,21 +1037,21 @@ class ServerImpl { // that ensures the client reads the response in a timely // fashion. - void requestCompleted (HttpConnection c) { + void requestCompleted(HttpConnection c) { State s = c.getState(); assert s == State.REQUEST : "State is not REQUEST ("+s+")"; - reqConnections.remove (c); + reqConnections.remove(c); c.rspStartedTime = System.currentTimeMillis(); - rspConnections.add (c); - c.setState (State.RESPONSE); + rspConnections.add(c); + c.setState(State.RESPONSE); } // called after response has been sent - void responseCompleted (HttpConnection c) { + void responseCompleted(HttpConnection c) { State s = c.getState(); assert s == State.RESPONSE : "State is not RESPONSE ("+s+")"; - rspConnections.remove (c); - c.setState (State.IDLE); + rspConnections.remove(c); + c.setState(State.IDLE); } /** @@ -1059,7 +1059,7 @@ class ServerImpl { * TimerTask run every CLOCK_TICK ms */ class IdleTimeoutTask extends TimerTask { - public void run () { + public void run() { closeConnections(idleConnections, IDLE_INTERVAL); // if any newly accepted connection has been idle (i.e. no byte has been sent on that // connection during the configured idle timeout period) then close it as well @@ -1095,20 +1095,20 @@ class ServerImpl { class ReqRspTimeoutTask extends TimerTask { // runs every TIMER_MILLIS - public void run () { + public void run() { ArrayList toClose = new ArrayList<>(); final long currentTime = System.currentTimeMillis(); synchronized (reqConnections) { if (MAX_REQ_TIME != -1) { for (HttpConnection c : reqConnections) { if (currentTime - c.reqStartedTime >= MAX_REQ_TIME) { - toClose.add (c); + toClose.add(c); } } for (HttpConnection c : toClose) { - logger.log (Level.DEBUG, "closing: no request: " + c); - reqConnections.remove (c); - allConnections.remove (c); + logger.log(Level.DEBUG, "closing: no request: " + c); + reqConnections.remove(c); + allConnections.remove(c); c.close(); } } @@ -1118,13 +1118,13 @@ class ServerImpl { if (MAX_RSP_TIME != -1) { for (HttpConnection c : rspConnections) { if (currentTime - c.rspStartedTime >= MAX_RSP_TIME) { - toClose.add (c); + toClose.add(c); } } for (HttpConnection c : toClose) { - logger.log (Level.DEBUG, "closing: no response: " + c); - rspConnections.remove (c); - allConnections.remove (c); + logger.log(Level.DEBUG, "closing: no response: " + c); + rspConnections.remove(c); + allConnections.remove(c); c.close(); } } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/UndefLengthOutputStream.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/UndefLengthOutputStream.java index 7bfc39c84a1..ecda32ecc31 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/UndefLengthOutputStream.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/UndefLengthOutputStream.java @@ -40,30 +40,30 @@ class UndefLengthOutputStream extends FilterOutputStream private boolean closed = false; ExchangeImpl t; - UndefLengthOutputStream (ExchangeImpl t, OutputStream src) { - super (src); + UndefLengthOutputStream(ExchangeImpl t, OutputStream src) { + super(src); this.t = t; } - public void write (int b) throws IOException { + public void write(int b) throws IOException { if (closed) { - throw new IOException ("stream closed"); + throw new IOException("stream closed"); } out.write(b); } - public void write (byte[]b, int off, int len) throws IOException { + public void write(byte[] b, int off, int len) throws IOException { Objects.checkFromIndexSize(off, len, b.length); if (len == 0) { return; } if (closed) { - throw new IOException ("stream closed"); + throw new IOException("stream closed"); } out.write(b, off, len); } - public void close () throws IOException { + public void close() throws IOException { if (closed) { return; } @@ -76,7 +76,7 @@ class UndefLengthOutputStream extends FilterOutputStream } catch (IOException e) {} } Event e = new Event.WriteFinished(t); - t.getHttpContext().getServerImpl().addEvent (e); + t.getHttpContext().getServerImpl().addEvent(e); } // flush is a pass-through diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/UnmodifiableHeaders.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/UnmodifiableHeaders.java index 91bfc186828..503004b35e0 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/UnmodifiableHeaders.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/UnmodifiableHeaders.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -62,32 +62,32 @@ public class UnmodifiableHeaders extends Headers { @Override public List put(String key, List value) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public void add(String key, String value) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public void set(String key, String value) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public List remove(Object key) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public void putAll(Map> t) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public void clear() { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override @@ -106,19 +106,19 @@ public class UnmodifiableHeaders extends Headers { @Override public boolean replace(String key, List oldValue, List newValue) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override public void replaceAll(BiFunction, ? extends List> function) { - throw new UnsupportedOperationException ("unsupported operation"); + throw new UnsupportedOperationException("unsupported operation"); } @Override - public boolean equals(Object o) {return headers.equals(o);} + public boolean equals(Object o) { return headers.equals(o); } @Override - public int hashCode() {return headers.hashCode();} + public int hashCode() { return headers.hashCode(); } @Override public String toString() { diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java index 3a3654d4a73..cbf032e8398 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/simpleserver/FileServerHandler.java @@ -367,7 +367,7 @@ public final class FileServerHandler implements HttpHandler { // A non-exhaustive map of reserved-HTML and special characters to their // equivalent entity. - private static final Map RESERVED_CHARS = Map.of( + private static final Map RESERVED_CHARS = Map.of( (int) '&' , "&" , (int) '<' , "<" , (int) '>' , ">" , From a05d5d2514c835f2bfeaf7a8c7df0ac241f0177f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Maillard?= Date: Fri, 12 Dec 2025 13:45:28 +0000 Subject: [PATCH 068/211] 8373579: Problem list compiler/runtime/Test7196199.java Reviewed-by: chagedorn, epeter --- test/hotspot/jtreg/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 177c14da785..4e16e328ab4 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -49,6 +49,7 @@ compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all compiler/runtime/Test8168712.java#with-dtrace 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x compiler/runtime/Test8168712.java#without-dtrace 8211769,8211771 generic-ppc64,generic-ppc64le,linux-s390x +compiler/runtime/Test7196199.java 8365196 windows-x64 compiler/c2/Test8004741.java 8235801 generic-all compiler/c2/irTests/TestDuplicateBackedge.java 8318904 generic-all From 410014377c210463d654b841bafbcf36947aa960 Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Fri, 12 Dec 2025 14:02:35 +0000 Subject: [PATCH 069/211] 8373225: GenShen: More adaptive old-generation growth heuristics Reviewed-by: wkemper, ysr --- .../shenandoahGenerationalHeuristics.cpp | 2 +- .../heuristics/shenandoahOldHeuristics.cpp | 49 +++++++++++++++++-- .../heuristics/shenandoahOldHeuristics.hpp | 30 ++++++++++++ .../gc/shenandoah/shenandoahGeneration.cpp | 11 +++-- .../gc/shenandoah/shenandoahGeneration.hpp | 2 +- .../shenandoahGenerationalEvacuationTask.cpp | 5 +- .../shenandoahGenerationalFullGC.cpp | 2 +- .../gc/shenandoah/shenandoahOldGeneration.cpp | 37 +++++++++----- .../gc/shenandoah/shenandoahOldGeneration.hpp | 33 ++++++------- .../gc/shenandoah/shenandoah_globals.hpp | 37 +++++++++----- .../generational/TestOldGrowthTriggers.java | 9 +++- 11 files changed, 158 insertions(+), 59 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp index cab6abc4e6f..b14d72f249b 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahGenerationalHeuristics.cpp @@ -104,7 +104,7 @@ void ShenandoahGenerationalHeuristics::choose_collection_set(ShenandoahCollectio // Note that for GLOBAL GC, region may be OLD, and OLD regions do not qualify for pre-selection // This region is old enough to be promoted but it was not preselected, either because its garbage is below - // ShenandoahOldGarbageThreshold so it will be promoted in place, or because there is not sufficient room + // old garbage threshold so it will be promoted in place, or because there is not sufficient room // in old gen to hold the evacuated copies of this region's live data. In both cases, we choose not to // place this region into the collection set. if (region->get_top_before_promote() != nullptr) { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 1e4d40cfa46..1f257560bcb 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -71,7 +71,8 @@ ShenandoahOldHeuristics::ShenandoahOldHeuristics(ShenandoahOldGeneration* genera _growth_trigger(false), _fragmentation_density(0.0), _fragmentation_first_old_region(0), - _fragmentation_last_old_region(0) + _fragmentation_last_old_region(0), + _old_garbage_threshold(ShenandoahOldGarbageThreshold) { } @@ -373,7 +374,8 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { } } - _old_generation->set_live_bytes_after_last_mark(live_data); + // TODO: subtract from live_data bytes promoted during concurrent GC. + _old_generation->set_live_bytes_at_last_mark(live_data); // Unlike young, we are more interested in efficiently packing OLD-gen than in reclaiming garbage first. We sort by live-data. // Some regular regions may have been promoted in place with no garbage but also with very little live data. When we "compact" @@ -385,7 +387,7 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { const size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); // The convention is to collect regions that have more than this amount of garbage. - const size_t garbage_threshold = region_size_bytes * ShenandoahOldGarbageThreshold / 100; + const size_t garbage_threshold = region_size_bytes * get_old_garbage_threshold() / 100; // Enlightened interpretation: collect regions that have less than this amount of live. const size_t live_threshold = region_size_bytes - garbage_threshold; @@ -655,6 +657,7 @@ bool ShenandoahOldHeuristics::should_start_gc() { const double percent = percent_of(old_gen_capacity, heap_capacity); log_trigger("Expansion failure, current size: %zu%s which is %.1f%% of total heap size", byte_size_in_proper_unit(old_gen_capacity), proper_unit_for_byte_size(old_gen_capacity), percent); + adjust_old_garbage_threshold(); return true; } @@ -677,6 +680,7 @@ bool ShenandoahOldHeuristics::should_start_gc() { "%zu to %zu (%zu), density: %.1f%%", byte_size_in_proper_unit(fragmented_free), proper_unit_for_byte_size(fragmented_free), first_old_region, last_old_region, span_of_old_regions, density * 100); + adjust_old_garbage_threshold(); return true; } @@ -699,12 +703,13 @@ bool ShenandoahOldHeuristics::should_start_gc() { consecutive_young_cycles); _growth_trigger = false; } else if (current_usage > trigger_threshold) { - const size_t live_at_previous_old = _old_generation->get_live_bytes_after_last_mark(); + const size_t live_at_previous_old = _old_generation->get_live_bytes_at_last_mark(); const double percent_growth = percent_of(current_usage - live_at_previous_old, live_at_previous_old); log_trigger("Old has overgrown, live at end of previous OLD marking: " "%zu%s, current usage: %zu%s, percent growth: %.1f%%", byte_size_in_proper_unit(live_at_previous_old), proper_unit_for_byte_size(live_at_previous_old), byte_size_in_proper_unit(current_usage), proper_unit_for_byte_size(current_usage), percent_growth); + adjust_old_garbage_threshold(); return true; } else { // Mixed evacuations have decreased current_usage such that old-growth trigger is no longer relevant. @@ -713,7 +718,41 @@ bool ShenandoahOldHeuristics::should_start_gc() { } // Otherwise, defer to inherited heuristic for gc trigger. - return this->ShenandoahHeuristics::should_start_gc(); + bool result = this->ShenandoahHeuristics::should_start_gc(); + if (result) { + adjust_old_garbage_threshold(); + } + return result; +} + +void ShenandoahOldHeuristics::adjust_old_garbage_threshold() { + const uintx MinimumOldGarbageThreshold = 10; + const uintx InterventionPercentage = 50; + + const ShenandoahHeap* heap = ShenandoahHeap::heap(); + size_t old_regions_size = _old_generation->used_regions_size(); + size_t soft_max_size = heap->soft_max_capacity(); + uintx percent_used = (uintx) ((old_regions_size * 100) / soft_max_size); + _old_garbage_threshold = ShenandoahOldGarbageThreshold; + if (percent_used > InterventionPercentage) { + uintx severity = percent_used - InterventionPercentage; // ranges from 0 to 50 + if (MinimumOldGarbageThreshold < ShenandoahOldGarbageThreshold) { + uintx adjustment_potential = ShenandoahOldGarbageThreshold - MinimumOldGarbageThreshold; + // With default values: + // if percent_used > 80, garbage_threshold is 10 + // else if percent_used > 65, garbage_threshold is 15 + // else if percent_used > 50, garbage_threshold is 20 + if (severity > 30) { + _old_garbage_threshold = ShenandoahOldGarbageThreshold - adjustment_potential; + } else if (severity > 15) { + _old_garbage_threshold = ShenandoahOldGarbageThreshold - 2 * adjustment_potential / 3; + } else { + _old_garbage_threshold = ShenandoahOldGarbageThreshold - adjustment_potential / 3; + } + log_info(gc)("Adjusting old garbage threshold to %lu because Old Generation used regions represents %lu%% of heap", + _old_garbage_threshold, percent_used); + } + } } void ShenandoahOldHeuristics::record_success_concurrent() { diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp index 8d3fec746ba..288d3d68e56 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.hpp @@ -102,6 +102,17 @@ private: size_t _fragmentation_first_old_region; size_t _fragmentation_last_old_region; + // The value of command-line argument ShenandoahOldGarbageThreshold represents the percent of garbage that must + // be present within an old-generation region before that region is considered a good candidate for inclusion in + // the collection set under normal circumstances. For our purposes, normal circustances are when the memory consumed + // by the old generation is less than 50% of the soft heap capacity. When the old generation grows beyond the 50% + // threshold, we dynamically adjust the old garbage threshold, allowing us to invest in packing the old generation + // more tightly so that more memory can be made available to the more frequent young GC cycles. This variable + // is used in place of ShenandoahOldGarbageThreshold. Under normal circumstances, its value is equal to + // ShenandoahOldGarbageThreshold. When the GC is under duress, this value may be adjusted to a smaller value, + // as scaled according to the severity of duress that we are experiencing. + uintx _old_garbage_threshold; + // Compare by live is used to prioritize compaction of old-gen regions. With old-gen compaction, the goal is // to tightly pack long-lived objects into available regions. In most cases, there has not been an accumulation // of garbage within old-gen regions. The more likely opportunity will be to combine multiple sparsely populated @@ -200,9 +211,28 @@ public: bool is_experimental() override; + // Returns the current value of a dynamically adjusted threshold percentage of garbage above which an old region is + // deemed eligible for evacuation. + inline uintx get_old_garbage_threshold() { return _old_garbage_threshold; } + private: void slide_pinned_regions_to_front(); bool all_candidates_are_pinned(); + + // The normal old_garbage_threshold is specified by ShenandoahOldGarbageThreshold command-line argument, with default + // value 25, denoting that a region that has at least 25% garbage is eligible for evacuation. With default values for + // all command-line arguments, we make the following adjustments: + // 1. If the old generation has grown to consume more than 80% of the soft max capacity, adjust threshold to 10% + // 2. Otherwise, if the old generation has grown to consume more than 65%, adjust threshold to 15% + // 3. Otherwise, if the old generation has grown to consume more than 50%, adjust threshold to 20% + // The effect is to compact the old generation more aggressively as the old generation consumes larger percentages + // of the available heap memory. In these circumstances, we pack the old generation more tightly in order to make + // more memory avaiable to the young generation so that the more frequent young collections can operate more + // efficiently. + // + // If the ShenandoahOldGarbageThreshold is specified on the command line, the effect of adjusting the old garbage + // threshold is scaled linearly. + void adjust_old_garbage_threshold(); }; #endif // SHARE_GC_SHENANDOAH_HEURISTICS_SHENANDOAHOLDHEURISTICS_HPP diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index 55d6033b3bc..b9295654b6f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -505,10 +505,10 @@ inline void assert_no_in_place_promotions() { #endif } -// Preselect for inclusion into the collection set regions whose age is at or above tenure age which contain more than -// ShenandoahOldGarbageThreshold amounts of garbage. We identify these regions by setting the appropriate entry of -// the collection set's preselected regions array to true. All entries are initialized to false before calling this -// function. +// Preselect for inclusion into the collection set all regions whose age is at or above tenure age and for which the +// garbage percentage exceeds a dynamically adjusted threshold (known as the old-garbage threshold percentage). We +// identify these regions by setting the appropriate entry of the collection set's preselected regions array to true. +// All entries are initialized to false before calling this function. // // During the subsequent selection of the collection set, we give priority to these promotion set candidates. // Without this prioritization, we found that the aged regions tend to be ignored because they typically have @@ -531,7 +531,8 @@ size_t ShenandoahGeneration::select_aged_regions(const size_t old_promotion_rese bool* const candidate_regions_for_promotion_by_copy = heap->collection_set()->preselected_regions(); ShenandoahMarkingContext* const ctx = heap->marking_context(); - const size_t old_garbage_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahOldGarbageThreshold) / 100; + const size_t old_garbage_threshold = + (ShenandoahHeapRegion::region_size_bytes() * heap->old_generation()->heuristics()->get_old_garbage_threshold()) / 100; const size_t pip_used_threshold = (ShenandoahHeapRegion::region_size_bytes() * ShenandoahGenerationalMinPIPUsage) / 100; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 424a00f789d..6f393110666 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -71,7 +71,7 @@ private: // garbage-dense regions, including those that satisfy criteria 1 & 2 below, // and whose live bytes will fit within old_available budget: // Criterion 1. region age >= tenuring threshold - // Criterion 2. region garbage percentage > ShenandoahOldGarbageThreshold + // Criterion 2. region garbage percentage > old garbage threshold // // Identifies regions eligible for promotion in place, // being those of at least tenuring_threshold age that have lower garbage diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index 4a3faa2c707..de45877994c 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -145,7 +145,7 @@ void ShenandoahGenerationalEvacuationTask::maybe_promote_region(ShenandoahHeapRe // triggers the load-reference barrier (LRB) to copy on reference fetch. // // Aged humongous continuation regions are handled with their start region. If an aged regular region has - // more garbage than ShenandoahOldGarbageThreshold, we'll promote by evacuation. If there is room for evacuation + // more garbage than the old garbage threshold, we'll promote by evacuation. If there is room for evacuation // in this cycle, the region will be in the collection set. If there is not room, the region will be promoted // by evacuation in some future GC cycle. @@ -177,7 +177,8 @@ void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion size_t region_size_bytes = ShenandoahHeapRegion::region_size_bytes(); { - const size_t old_garbage_threshold = (region_size_bytes * ShenandoahOldGarbageThreshold) / 100; + const size_t old_garbage_threshold = + (region_size_bytes * _heap->old_generation()->heuristics()->get_old_garbage_threshold()) / 100; assert(!_heap->is_concurrent_old_mark_in_progress(), "Cannot promote in place during old marking"); assert(region->garbage_before_padded_for_promote() < old_garbage_threshold, "Region %zu has too much garbage for promotion", region->index()); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp index ef913362df3..78672ee10a5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalFullGC.cpp @@ -83,7 +83,7 @@ void ShenandoahGenerationalFullGC::handle_completion(ShenandoahHeap* heap) { assert_usage_not_more_than_regions_used(young); // Establish baseline for next old-has-grown trigger. - old->set_live_bytes_after_last_mark(old->used()); + old->set_live_bytes_at_last_mark(old->used()); } void ShenandoahGenerationalFullGC::rebuild_remembered_set(ShenandoahHeap* heap) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp index 6a0f986cde5..c7cf013d034 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.cpp @@ -116,11 +116,10 @@ ShenandoahOldGeneration::ShenandoahOldGeneration(uint max_queues) _is_parsable(true), _card_scan(nullptr), _state(WAITING_FOR_BOOTSTRAP), - _growth_before_compaction(INITIAL_GROWTH_BEFORE_COMPACTION), - _min_growth_before_compaction ((ShenandoahMinOldGenGrowthPercent * FRACTIONAL_DENOMINATOR) / 100) + _growth_percent_before_collection(INITIAL_GROWTH_PERCENT_BEFORE_COLLECTION) { assert(type() == ShenandoahGenerationType::OLD, "OO sanity"); - _live_bytes_after_last_mark = ShenandoahHeap::heap()->capacity() * INITIAL_LIVE_FRACTION / FRACTIONAL_DENOMINATOR; + _live_bytes_at_last_mark = (ShenandoahHeap::heap()->soft_max_capacity() * INITIAL_LIVE_PERCENT) / 100; // Always clear references for old generation ref_processor()->set_soft_reference_policy(true); @@ -221,20 +220,20 @@ ShenandoahOldGeneration::configure_plab_for_current_thread(const ShenandoahAlloc } } -size_t ShenandoahOldGeneration::get_live_bytes_after_last_mark() const { - return _live_bytes_after_last_mark; +size_t ShenandoahOldGeneration::get_live_bytes_at_last_mark() const { + return _live_bytes_at_last_mark; } -void ShenandoahOldGeneration::set_live_bytes_after_last_mark(size_t bytes) { +void ShenandoahOldGeneration::set_live_bytes_at_last_mark(size_t bytes) { if (bytes == 0) { // Restart search for best old-gen size to the initial state - _live_bytes_after_last_mark = ShenandoahHeap::heap()->capacity() * INITIAL_LIVE_FRACTION / FRACTIONAL_DENOMINATOR; - _growth_before_compaction = INITIAL_GROWTH_BEFORE_COMPACTION; + _live_bytes_at_last_mark = (ShenandoahHeap::heap()->soft_max_capacity() * INITIAL_LIVE_PERCENT) / 100; + _growth_percent_before_collection = INITIAL_GROWTH_PERCENT_BEFORE_COLLECTION; } else { - _live_bytes_after_last_mark = bytes; - _growth_before_compaction /= 2; - if (_growth_before_compaction < _min_growth_before_compaction) { - _growth_before_compaction = _min_growth_before_compaction; + _live_bytes_at_last_mark = bytes; + _growth_percent_before_collection /= 2; + if (_growth_percent_before_collection < ShenandoahMinOldGenGrowthPercent) { + _growth_percent_before_collection = ShenandoahMinOldGenGrowthPercent; } } } @@ -244,7 +243,19 @@ void ShenandoahOldGeneration::handle_failed_transfer() { } size_t ShenandoahOldGeneration::usage_trigger_threshold() const { - size_t result = _live_bytes_after_last_mark + (_live_bytes_after_last_mark * _growth_before_compaction) / FRACTIONAL_DENOMINATOR; + size_t threshold_by_relative_growth = + _live_bytes_at_last_mark + (_live_bytes_at_last_mark * _growth_percent_before_collection) / 100; + size_t soft_max_capacity = ShenandoahHeap::heap()->soft_max_capacity(); + size_t threshold_by_growth_into_percent_remaining; + if (_live_bytes_at_last_mark < soft_max_capacity) { + threshold_by_growth_into_percent_remaining = (size_t) + (_live_bytes_at_last_mark + ((soft_max_capacity - _live_bytes_at_last_mark) + * ShenandoahMinOldGenGrowthRemainingHeapPercent / 100.0)); + } else { + // we're already consuming more than soft max capacity, so we should start old GC right away. + threshold_by_growth_into_percent_remaining = soft_max_capacity; + } + size_t result = MIN2(threshold_by_relative_growth, threshold_by_growth_into_percent_remaining); return result; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp index 614a1596287..90c1458ac97 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahOldGeneration.hpp @@ -287,28 +287,23 @@ public: private: State _state; - static const size_t FRACTIONAL_DENOMINATOR = 65536; - // During initialization of the JVM, we search for the correct old-gen size by initially performing old-gen - // collection when old-gen usage is 50% more (INITIAL_GROWTH_BEFORE_COMPACTION) than the initial old-gen size - // estimate (3.125% of heap). The next old-gen trigger occurs when old-gen grows 25% larger than its live - // memory at the end of the first old-gen collection. Then we trigger again when old-gen grows 12.5% - // more than its live memory at the end of the previous old-gen collection. Thereafter, we trigger each time - // old-gen grows more than 12.5% following the end of its previous old-gen collection. - static const size_t INITIAL_GROWTH_BEFORE_COMPACTION = FRACTIONAL_DENOMINATOR / 2; // 50.0% + // collection when old-gen usage is 50% more (INITIAL_GROWTH_PERCENT_BEFORE_COLLECTION) than the initial old-gen size + // estimate (16% of heap). With each successive old-gen collection, we divide the growth trigger by two, but + // never use a growth trigger smaller than ShenandoahMinOldGenGrowthPercent. + static const size_t INITIAL_GROWTH_PERCENT_BEFORE_COLLECTION = 50; - // INITIAL_LIVE_FRACTION represents the initial guess of how large old-gen should be. We estimate that old-gen - // needs to consume 6.25% of the total heap size. And we "pretend" that we start out with this amount of live + // INITIAL_LIVE_PERCENT represents the initial guess of how large old-gen should be. We estimate that old gen + // needs to consume 16% of the total heap size. And we "pretend" that we start out with this amount of live // old-gen memory. The first old-collection trigger will occur when old-gen occupies 50% more than this initial - // approximation of the old-gen memory requirement, in other words when old-gen usage is 150% of 6.25%, which - // is 9.375% of the total heap size. - static const uint16_t INITIAL_LIVE_FRACTION = FRACTIONAL_DENOMINATOR / 16; // 6.25% + // approximation of the old-gen memory requirement, in other words when old-gen usage is 150% of 16%, which + // is 24% of the heap size. + static const size_t INITIAL_LIVE_PERCENT = 16; - size_t _live_bytes_after_last_mark; + size_t _live_bytes_at_last_mark; - // How much growth in usage before we trigger old collection, per FRACTIONAL_DENOMINATOR (65_536) - size_t _growth_before_compaction; - const size_t _min_growth_before_compaction; // Default is 12.5% + // How much growth in usage before we trigger old collection as a percent of soft_max_capacity + size_t _growth_percent_before_collection; void validate_transition(State new_state) NOT_DEBUG_RETURN; @@ -323,8 +318,8 @@ public: void transition_to(State new_state); - size_t get_live_bytes_after_last_mark() const; - void set_live_bytes_after_last_mark(size_t new_live); + size_t get_live_bytes_at_last_mark() const; + void set_live_bytes_at_last_mark(size_t new_live); size_t usage_trigger_threshold() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp index 8bd59beb93b..96ebf23bbb5 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoah_globals.hpp @@ -59,15 +59,29 @@ "fail, resulting in stop-the-world full GCs.") \ range(0,100) \ \ - product(double, ShenandoahMinOldGenGrowthPercent, 12.5, EXPERIMENTAL, \ + product(double, ShenandoahMinOldGenGrowthPercent, 50, EXPERIMENTAL, \ "(Generational mode only) If the usage within old generation " \ "has grown by at least this percent of its live memory size " \ - "at completion of the most recent old-generation marking " \ - "effort, heuristics may trigger the start of a new old-gen " \ - "collection.") \ + "at the start of the previous old-generation marking effort, " \ + "heuristics may trigger the start of a new old-gen collection.") \ range(0.0,100.0) \ \ - product(uintx, ShenandoahIgnoreOldGrowthBelowPercentage,10, EXPERIMENTAL, \ + product(double, ShenandoahMinOldGenGrowthRemainingHeapPercent, \ + 35, EXPERIMENTAL, \ + "(Generational mode only) If the usage within old generation " \ + "has grown to exceed this percent of the remaining heap that " \ + "was not marked live within the old generation at the time " \ + "of the last old-generation marking effort, heuristics may " \ + "trigger the start of a new old-gen collection. Setting " \ + "this value to a smaller value may cause back-to-back old " \ + "generation marking triggers, since the typical memory used " \ + "by the old generation is about 30% larger than the live " \ + "memory contained within the old generation (because default " \ + "value of ShenandoahOldGarbageThreshold is 25.") \ + range(0.0,100.0) \ + \ + product(uintx, ShenandoahIgnoreOldGrowthBelowPercentage, \ + 40, EXPERIMENTAL, \ "(Generational mode only) If the total usage of the old " \ "generation is smaller than this percent, we do not trigger " \ "old gen collections even if old has grown, except when " \ @@ -77,12 +91,13 @@ range(0,100) \ \ product(uintx, ShenandoahDoNotIgnoreGrowthAfterYoungCycles, \ - 50, EXPERIMENTAL, \ - "(Generational mode only) Even if the usage of old generation " \ - "is below ShenandoahIgnoreOldGrowthBelowPercentage, " \ - "trigger an old-generation mark if old has grown and this " \ - "many consecutive young-gen collections have been " \ - "completed following the preceding old-gen collection.") \ + 100, EXPERIMENTAL, \ + "(Generational mode only) Trigger an old-generation mark " \ + "if old has grown and this many consecutive young-gen " \ + "collections have been completed following the preceding " \ + "old-gen collection. We perform this old-generation mark " \ + "evvort even if the usage of old generation is below " \ + "ShenandoahIgnoreOldGrowthBelowPercentage.") \ \ product(bool, ShenandoahGenerationalAdaptiveTenuring, true, EXPERIMENTAL, \ "(Generational mode only) Dynamically adapt tenuring age.") \ diff --git a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java index 5182d4a9ea3..a66b9161c7e 100644 --- a/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java +++ b/test/hotspot/jtreg/gc/shenandoah/generational/TestOldGrowthTriggers.java @@ -99,8 +99,12 @@ public class TestOldGrowthTriggers { "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCMode=generational", + "-XX:ShenandoahMinOldGenGrowthPercent=12.5", + "-XX:ShenandoahIgnoreOldGrowthBelowPercentage=10", + "-XX:ShenandoahMinOldGenGrowthRemainingHeapPercent=100", "-XX:ShenandoahGuaranteedYoungGCInterval=0", - "-XX:ShenandoahGuaranteedOldGCInterval=0" + "-XX:ShenandoahGuaranteedOldGCInterval=0", + "-XX:-UseCompactObjectHeaders" ); testOld("-Xlog:gc", @@ -110,6 +114,9 @@ public class TestOldGrowthTriggers { "-XX:+UnlockExperimentalVMOptions", "-XX:+UseShenandoahGC", "-XX:ShenandoahGCMode=generational", + "-XX:ShenandoahMinOldGenGrowthPercent=12.5", + "-XX:ShenandoahIgnoreOldGrowthBelowPercentage=10", + "-XX:ShenandoahMinOldGenGrowthRemainingHeapPercent=100", "-XX:ShenandoahGuaranteedYoungGCInterval=0", "-XX:ShenandoahGuaranteedOldGCInterval=0", "-XX:+UseCompactObjectHeaders" From d854a04231a437a6af36ae65780961f40f336343 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Fri, 12 Dec 2025 14:02:50 +0000 Subject: [PATCH 070/211] 8373411: Crash when PrintSharedArchiveAndExit is enabled but shared heap is disabled Reviewed-by: shade, iklam --- src/hotspot/share/cds/aotMetaspace.cpp | 2 +- .../cds/PrintSharedArchiveAndExitNoHeap.java | 44 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/runtime/cds/PrintSharedArchiveAndExitNoHeap.java diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 3c87e3ef797..098d3baed58 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -2205,7 +2205,7 @@ void AOTMetaspace::initialize_shared_spaces() { CountSharedSymbols cl; SymbolTable::shared_symbols_do(&cl); tty->print_cr("Number of shared symbols: %zu", cl.total()); - if (HeapShared::is_loading_mapping_mode()) { + if (HeapShared::is_loading() && HeapShared::is_loading_mapping_mode()) { tty->print_cr("Number of shared strings: %zu", StringTable::shared_entry_count()); } tty->print_cr("VM version: %s\r\n", static_mapinfo->vm_version()); diff --git a/test/hotspot/jtreg/runtime/cds/PrintSharedArchiveAndExitNoHeap.java b/test/hotspot/jtreg/runtime/cds/PrintSharedArchiveAndExitNoHeap.java new file mode 100644 index 00000000000..969218dbc16 --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/PrintSharedArchiveAndExitNoHeap.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8373411 + * @summary Testing -XX:+PrintSharedArchiveAndExit option with no shared heap + * @requires vm.cds + * @library /test/lib + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class PrintSharedArchiveAndExitNoHeap { + public static void main(String[] args) throws Exception { + // This used to crash when trying to figure out if interned string should be printed + OutputAnalyzer oa = ProcessTools.executeTestJava("-XX:AOTCacheOutput=./PrintSharedArchiveAndExitNoHeap.jsa", "-XX:+PrintSharedArchiveAndExit", "-version"); + oa.shouldHaveExitValue(0); + // AOTCacheOutput forks a process, if that crashes then the above check is not enough + // and we have to check the output to figure out if it crashed. + oa.shouldNotContain("Internal Error"); + } +} From a99f340e1b9686431d944ab114918d2b849718fe Mon Sep 17 00:00:00 2001 From: Artur Barashev Date: Fri, 12 Dec 2025 14:39:42 +0000 Subject: [PATCH 071/211] 8371721: Refactor checkTrusted methods in X509TrustManagerImpl Reviewed-by: coffeys, djelinski --- .../security/ssl/X509TrustManagerImpl.java | 153 +++++++----------- 1 file changed, 58 insertions(+), 95 deletions(-) diff --git a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java index 1bbe0bfb9c7..40ee01d284a 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java +++ b/src/java.base/share/classes/sun/security/ssl/X509TrustManagerImpl.java @@ -30,9 +30,7 @@ import java.security.*; import java.security.cert.*; import java.util.*; import java.util.concurrent.locks.ReentrantLock; - import javax.net.ssl.*; - import sun.security.ssl.SSLAlgorithmConstraints.SIGNATURE_CONSTRAINTS_MODE; import sun.security.util.AnchorCertificates; import sun.security.util.HostnameChecker; @@ -40,19 +38,14 @@ import sun.security.validator.*; /** * This class implements the SunJSSE X.509 trust manager using the internal - * validator API in J2SE core. The logic in this class is minimal.

    + * validator API in J2SE core. The logic in this class is minimal. *

    * This class supports both the Simple validation algorithm from previous - * JSSE versions and PKIX validation. Currently, it is not possible for the - * application to specify PKIX parameters other than trust anchors. This will - * be fixed in a future release using new APIs. When that happens, it may also - * make sense to separate the Simple and PKIX trust managers into separate - * classes. + * JSSE versions and PKIX validation. * * @author Andreas Sterbenz */ -final class X509TrustManagerImpl extends X509ExtendedTrustManager - implements X509TrustManager { +final class X509TrustManagerImpl extends X509ExtendedTrustManager { private final String validatorType; @@ -208,120 +201,90 @@ final class X509TrustManagerImpl extends X509ExtendedTrustManager private void checkTrusted(X509Certificate[] chain, String authType, Socket socket, boolean checkClientTrusted) throws CertificateException { - Validator v = checkTrustedInit(chain, authType, checkClientTrusted); - X509Certificate[] trustedChain; + SSLSession session = null; + AlgorithmConstraints constraints = null; + String identityAlg = null; + if (socket instanceof SSLSocket sslSocket && sslSocket.isConnected()) { - - SSLSession session = sslSocket.getHandshakeSession(); - if (session == null) { - throw new CertificateException("No handshake session"); - } - - AlgorithmConstraints constraints = SSLAlgorithmConstraints.forSocket( + session = sslSocket.getHandshakeSession(); + constraints = SSLAlgorithmConstraints.forSocket( sslSocket, SIGNATURE_CONSTRAINTS_MODE.LOCAL, false); - - // Grab any stapled OCSP responses for use in validation - List responseList = Collections.emptyList(); - if (!checkClientTrusted && session instanceof ExtendedSSLSession) { - responseList = - ((ExtendedSSLSession)session).getStatusResponses(); - } - trustedChain = v.validate(chain, null, responseList, - constraints, checkClientTrusted ? null : authType); - - // check endpoint identity - String identityAlg = sslSocket.getSSLParameters(). + identityAlg = sslSocket.getSSLParameters(). getEndpointIdentificationAlgorithm(); - if (identityAlg != null && !identityAlg.isEmpty()) { - checkIdentity(session, - trustedChain, identityAlg, checkClientTrusted); - } - } else { - trustedChain = v.validate(chain, null, Collections.emptyList(), - null, checkClientTrusted ? null : authType); } - if (SSLLogger.isOn() && SSLLogger.isOn("ssl,trustmanager")) { - SSLLogger.fine("Found trusted certificate", - trustedChain[trustedChain.length - 1]); + findTrustedCertificate(chain, authType, + session, constraints, identityAlg, checkClientTrusted); + } + + private void checkTrusted(X509Certificate[] chain, + String authType, SSLEngine engine, + boolean checkClientTrusted) throws CertificateException { + + SSLSession session = null; + AlgorithmConstraints constraints = null; + String identityAlg = null; + + if (engine != null) { + session = engine.getHandshakeSession(); + constraints = SSLAlgorithmConstraints.forEngine( + engine, SIGNATURE_CONSTRAINTS_MODE.LOCAL, false); + identityAlg = engine.getSSLParameters(). + getEndpointIdentificationAlgorithm(); } + + findTrustedCertificate(chain, authType, + session, constraints, identityAlg, checkClientTrusted); } private void checkTrusted(X509Certificate[] chain, String authType, QuicTLSEngineImpl quicTLSEngine, boolean checkClientTrusted) throws CertificateException { - Validator v = checkTrustedInit(chain, authType, checkClientTrusted); + + SSLSession session = null; + AlgorithmConstraints constraints = null; + String identityAlg = null; + + if (quicTLSEngine != null) { + session = quicTLSEngine.getHandshakeSession(); + constraints = SSLAlgorithmConstraints.forQUIC( + quicTLSEngine, SIGNATURE_CONSTRAINTS_MODE.LOCAL, false); + identityAlg = quicTLSEngine.getSSLParameters(). + getEndpointIdentificationAlgorithm(); + } + + findTrustedCertificate(chain, authType, + session, constraints, identityAlg, checkClientTrusted); + } + + private void findTrustedCertificate(X509Certificate[] chain, + String authType, SSLSession session, + AlgorithmConstraints constraints, String identityAlg, + boolean checkClientTrusted) throws CertificateException { final X509Certificate[] trustedChain; - if (quicTLSEngine != null) { + Validator v = checkTrustedInit(chain, authType, checkClientTrusted); - final SSLSession session = quicTLSEngine.getHandshakeSession(); + if (constraints != null) { if (session == null) { throw new CertificateException("No handshake session"); } - // create the algorithm constraints - final AlgorithmConstraints constraints = SSLAlgorithmConstraints.forQUIC( - quicTLSEngine, SIGNATURE_CONSTRAINTS_MODE.LOCAL, false); + // Grab any stapled OCSP responses for use in validation final List responseList; - // grab any stapled OCSP responses for use in validation if (!checkClientTrusted && session instanceof ExtendedSSLSession extSession) { responseList = extSession.getStatusResponses(); } else { responseList = Collections.emptyList(); } - // do the certificate chain validation + + // Certificate chain validation trustedChain = v.validate(chain, null, responseList, constraints, checkClientTrusted ? null : authType); - // check endpoint identity - String identityAlg = quicTLSEngine.getSSLParameters(). - getEndpointIdentificationAlgorithm(); - if (identityAlg != null && !identityAlg.isEmpty()) { - checkIdentity(session, trustedChain, - identityAlg, checkClientTrusted); - } - } else { - trustedChain = v.validate(chain, null, Collections.emptyList(), - null, checkClientTrusted ? null : authType); - } - - if (SSLLogger.isOn() && SSLLogger.isOn("ssl,trustmanager")) { - SSLLogger.fine("Found trusted certificate", - trustedChain[trustedChain.length - 1]); - } - } - - private void checkTrusted(X509Certificate[] chain, - String authType, SSLEngine engine, - boolean checkClientTrusted) throws CertificateException { - Validator v = checkTrustedInit(chain, authType, checkClientTrusted); - - X509Certificate[] trustedChain; - if (engine != null) { - - SSLSession session = engine.getHandshakeSession(); - if (session == null) { - throw new CertificateException("No handshake session"); - } - - AlgorithmConstraints constraints = SSLAlgorithmConstraints.forEngine( - engine, SIGNATURE_CONSTRAINTS_MODE.LOCAL, false); - - // Grab any stapled OCSP responses for use in validation - List responseList = Collections.emptyList(); - if (!checkClientTrusted && session instanceof ExtendedSSLSession) { - responseList = - ((ExtendedSSLSession)session).getStatusResponses(); - } - trustedChain = v.validate(chain, null, responseList, - constraints, checkClientTrusted ? null : authType); - - // check endpoint identity - String identityAlg = engine.getSSLParameters(). - getEndpointIdentificationAlgorithm(); + // Check endpoint identity if (identityAlg != null && !identityAlg.isEmpty()) { checkIdentity(session, trustedChain, identityAlg, checkClientTrusted); From 6ec36d348b1eaeedb993a905e42650242fac0918 Mon Sep 17 00:00:00 2001 From: Ferenc Rakoczi Date: Fri, 12 Dec 2025 16:04:56 +0000 Subject: [PATCH 072/211] 8373059: Test sun/security/provider/acvp/ML_DSA_Intrinsic_Test.java should pass on Aarch64 Reviewed-by: weijun, vpaprotski --- .../classes/sun/security/provider/ML_DSA.java | 2 +- .../{acvp => pqc}/ML_DSA_Intrinsic_Test.java | 90 +++++++++++++------ 2 files changed, 63 insertions(+), 29 deletions(-) rename test/jdk/sun/security/provider/{acvp => pqc}/ML_DSA_Intrinsic_Test.java (90%) diff --git a/src/java.base/share/classes/sun/security/provider/ML_DSA.java b/src/java.base/share/classes/sun/security/provider/ML_DSA.java index af64ef399a8..6a578427e51 100644 --- a/src/java.base/share/classes/sun/security/provider/ML_DSA.java +++ b/src/java.base/share/classes/sun/security/provider/ML_DSA.java @@ -1555,7 +1555,7 @@ public class ML_DSA { return res; } - // precondition: -2^31 * MONT_Q <= a, b < 2^31, -2^31 < a * b < 2^31 * MONT_Q + // precondition: -2^31 <= a, b < 2^31, -2^31 * MONT_Q <= a * b < 2^31 * MONT_Q // computes a * b * 2^-32 mod MONT_Q // the result is greater than -MONT_Q and less than MONT_Q // See e.g. Algorithm 3 in https://eprint.iacr.org/2018/039.pdf diff --git a/test/jdk/sun/security/provider/acvp/ML_DSA_Intrinsic_Test.java b/test/jdk/sun/security/provider/pqc/ML_DSA_Intrinsic_Test.java similarity index 90% rename from test/jdk/sun/security/provider/acvp/ML_DSA_Intrinsic_Test.java rename to test/jdk/sun/security/provider/pqc/ML_DSA_Intrinsic_Test.java index 1e9faf7fb74..d6d9fea789f 100644 --- a/test/jdk/sun/security/provider/acvp/ML_DSA_Intrinsic_Test.java +++ b/test/jdk/sun/security/provider/pqc/ML_DSA_Intrinsic_Test.java @@ -38,16 +38,17 @@ import java.util.HexFormat; */ /* * @test - * @comment This test should be reenabled on aarch64 - * @requires os.simpleArch == "x64" * @library /test/lib * @key randomness * @modules java.base/sun.security.provider:+open * @run main ML_DSA_Intrinsic_Test */ -// To run manually: java --add-opens java.base/sun.security.provider=ALL-UNNAMED --add-exports java.base/sun.security.provider=ALL-UNNAMED -// -XX:+UnlockDiagnosticVMOptions -XX:+UseDilithiumIntrinsics test/jdk/sun/security/provider/acvp/ML_DSA_Intrinsic_Test.java +// To run manually: +// java --add-opens java.base/sun.security.provider=ALL-UNNAMED +// --add-exports java.base/sun.security.provider=ALL-UNNAMED +// -XX:+UnlockDiagnosticVMOptions -XX:+UseDilithiumIntrinsics +// test/jdk/sun/security/provider/pqc/ML_DSA_Intrinsic_Test.java public class ML_DSA_Intrinsic_Test { public static void main(String[] args) throws Throwable { @@ -104,9 +105,10 @@ public class ML_DSA_Intrinsic_Test { m.setAccessible(true); MethodHandle inverseNttJava = lookup.unreflect(m); - // Hint: if test fails, you can hardcode the seed to make the test more reproducible Random rnd = new Random(); long seed = rnd.nextLong(); + // Hint: if a test fails, it prints the seed, so you can hardcode + // it here to reproduce the failure rnd.setSeed(seed); //Note: it might be useful to increase this number during development of new intrinsics final int repeat = 10000; @@ -117,32 +119,49 @@ public class ML_DSA_Intrinsic_Test { int[] prod3 = new int[ML_DSA_N]; int[] prod4 = new int[ML_DSA_N]; for (int i = 0; i < repeat; i++) { - // Hint: if test fails, you can hardcode the seed to make the test more reproducible: - // rnd.setSeed(seed); - testMult(prod1, prod2, coeffs1, coeffs2, mult, multJava, rnd, seed, i); + testMult(prod1, prod2, coeffs1, coeffs2, + mult, multJava, rnd, seed, i); testMultConst(prod1, prod2, multConst, multConstJava, rnd, seed, i); - testDecompose(prod1, prod2, prod3, prod4, coeffs1, coeffs2, decompose, decomposeJava, rnd, seed, i); + testDecompose(prod1, prod2, prod3, prod4, coeffs1, coeffs2, + decompose, decomposeJava, rnd, seed, i); testAlmostNtt(coeffs1, coeffs2, almostNtt, almostNttJava, rnd, seed, i); testInverseNtt(coeffs1, coeffs2, inverseNtt, inverseNttJava, rnd, seed, i); } System.out.println("Fuzz Success"); } - private static final int ML_DSA_N = 256; - public static void testMult(int[] prod1, int[] prod2, int[] coeffs1, int[] coeffs2, + public static void testMult(int[] prod1, int[] prod2, + int[] coeffs1, int[] coeffs2, MethodHandle mult, MethodHandle multJava, Random rnd, long seed, int i) throws Throwable { - for (int j = 0; jcapacity(); - } -} - -PtrQueueSet::PtrQueueSet(BufferNode::Allocator* allocator) : - _allocator(allocator) -{} - -PtrQueueSet::~PtrQueueSet() {} - -void PtrQueueSet::reset_queue(PtrQueue& queue) { - queue.set_index(queue.current_capacity()); -} - -void PtrQueueSet::flush_queue(PtrQueue& queue) { - void** buffer = queue.buffer(); - if (buffer != nullptr) { - size_t index = queue.index(); - queue.set_buffer(nullptr); - queue.set_index(0); - BufferNode* node = BufferNode::make_node_from_buffer(buffer, index); - if (index == node->capacity()) { - deallocate_buffer(node); - } else { - enqueue_completed_buffer(node); - } - } -} - -bool PtrQueueSet::try_enqueue(PtrQueue& queue, void* value) { - size_t index = queue.index(); - if (index == 0) return false; - void** buffer = queue.buffer(); - assert(buffer != nullptr, "no buffer but non-zero index"); - buffer[--index] = value; - queue.set_index(index); - return true; -} - -void PtrQueueSet::retry_enqueue(PtrQueue& queue, void* value) { - assert(queue.index() != 0, "precondition"); - assert(queue.buffer() != nullptr, "precondition"); - size_t index = queue.index(); - queue.buffer()[--index] = value; - queue.set_index(index); -} - -BufferNode* PtrQueueSet::exchange_buffer_with_new(PtrQueue& queue) { - BufferNode* node = nullptr; - void** buffer = queue.buffer(); - if (buffer != nullptr) { - node = BufferNode::make_node_from_buffer(buffer, queue.index()); - } - install_new_buffer(queue); - return node; -} - -void PtrQueueSet::install_new_buffer(PtrQueue& queue) { - BufferNode* node = _allocator->allocate(); - queue.set_buffer(BufferNode::make_buffer_from_node(node)); - queue.set_index(node->capacity()); -} - -void** PtrQueueSet::allocate_buffer() { - BufferNode* node = _allocator->allocate(); - return BufferNode::make_buffer_from_node(node); -} - -void PtrQueueSet::deallocate_buffer(BufferNode* node) { - _allocator->release(node); -} diff --git a/src/hotspot/share/gc/shared/ptrQueue.hpp b/src/hotspot/share/gc/shared/ptrQueue.hpp deleted file mode 100644 index 8aa5e16d40b..00000000000 --- a/src/hotspot/share/gc/shared/ptrQueue.hpp +++ /dev/null @@ -1,168 +0,0 @@ -/* - * Copyright (c) 2001, 2023, 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. - * - */ - -#ifndef SHARE_GC_SHARED_PTRQUEUE_HPP -#define SHARE_GC_SHARED_PTRQUEUE_HPP - -#include "gc/shared/bufferNode.hpp" -#include "utilities/align.hpp" -#include "utilities/debug.hpp" -#include "utilities/globalDefinitions.hpp" -#include "utilities/sizes.hpp" - -// There are various techniques that require threads to be able to log -// addresses. For example, a generational write barrier might log -// the addresses of modified old-generation objects. This type supports -// this operation. - -class PtrQueueSet; -class PtrQueue { - friend class VMStructs; - - NONCOPYABLE(PtrQueue); - - // The (byte) index at which an object was last enqueued. Starts at - // capacity (in bytes) (indicating an empty buffer) and goes towards zero. - // Value is always pointer-size aligned. - size_t _index; - - static const size_t _element_size = sizeof(void*); - - static size_t byte_index_to_index(size_t ind) { - assert(is_aligned(ind, _element_size), "precondition"); - return ind / _element_size; - } - - static size_t index_to_byte_index(size_t ind) { - return ind * _element_size; - } - -protected: - // The buffer. - void** _buf; - - // Initialize this queue to contain a null buffer, and be part of the - // given PtrQueueSet. - PtrQueue(PtrQueueSet* qset); - - // Requires queue flushed. - ~PtrQueue(); - -public: - - void** buffer() const { return _buf; } - void set_buffer(void** buffer) { _buf = buffer; } - - size_t index() const { - return byte_index_to_index(_index); - } - - void set_index(size_t new_index) { - assert(new_index <= current_capacity(), "precondition"); - _index = index_to_byte_index(new_index); - } - - // Returns the capacity of the buffer, or 0 if the queue doesn't currently - // have a buffer. - size_t current_capacity() const; - - bool is_empty() const { return index() == current_capacity(); } - size_t size() const { return current_capacity() - index(); } - -protected: - // To support compiler. - template - static ByteSize byte_offset_of_index() { - return byte_offset_of(Derived, _index); - } - - static constexpr ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); } - - template - static ByteSize byte_offset_of_buf() { - return byte_offset_of(Derived, _buf); - } - - static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); } -}; - -// A PtrQueueSet represents resources common to a set of pointer queues. -// In particular, the individual queues allocate buffers from this shared -// set, and return completed buffers to the set. -class PtrQueueSet { - BufferNode::Allocator* _allocator; - - NONCOPYABLE(PtrQueueSet); - -protected: - // Create an empty ptr queue set. - PtrQueueSet(BufferNode::Allocator* allocator); - ~PtrQueueSet(); - - // Discard any buffered enqueued data. - void reset_queue(PtrQueue& queue); - - // If queue has any buffered enqueued data, transfer it to this qset. - // Otherwise, deallocate queue's buffer. - void flush_queue(PtrQueue& queue); - - // Add value to queue's buffer, returning true. If buffer is full - // or if queue doesn't have a buffer, does nothing and returns false. - bool try_enqueue(PtrQueue& queue, void* value); - - // Add value to queue's buffer. The queue must have a non-full buffer. - // Used after an initial try_enqueue has failed and the situation resolved. - void retry_enqueue(PtrQueue& queue, void* value); - - // Installs a new buffer into queue. - // Returns the old buffer, or null if queue didn't have a buffer. - BufferNode* exchange_buffer_with_new(PtrQueue& queue); - - // Installs a new buffer into queue. - void install_new_buffer(PtrQueue& queue); - -public: - - // Return the associated BufferNode allocator. - BufferNode::Allocator* allocator() const { return _allocator; } - - // Return the buffer for a BufferNode of size buffer_capacity(). - void** allocate_buffer(); - - // Return an empty buffer to the free list. The node is required - // to have been allocated with a size of buffer_capacity(). - void deallocate_buffer(BufferNode* node); - - // A completed buffer is a buffer the mutator is finished with, and - // is ready to be processed by the collector. It need not be full. - - // Adds node to the completed buffer list. - virtual void enqueue_completed_buffer(BufferNode* node) = 0; - - size_t buffer_capacity() const { - return _allocator->buffer_capacity(); - } -}; - -#endif // SHARE_GC_SHARED_PTRQUEUE_HPP diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.cpp b/src/hotspot/share/gc/shared/satbMarkQueue.cpp index 93c52b499a0..63496f2eb25 100644 --- a/src/hotspot/share/gc/shared/satbMarkQueue.cpp +++ b/src/hotspot/share/gc/shared/satbMarkQueue.cpp @@ -36,14 +36,19 @@ #include "utilities/globalCounter.inline.hpp" SATBMarkQueue::SATBMarkQueue(SATBMarkQueueSet* qset) : - PtrQueue(qset), + _buf(nullptr), + _index(0), // SATB queues are only active during marking cycles. We create them // with their active field set to false. If a thread is created // during a cycle, it's SATB queue needs to be activated before the // thread starts running. This is handled by the collector-specific // BarrierSet thread attachment protocol. _active(false) -{ } +{} + +SATBMarkQueue::~SATBMarkQueue() { + assert(_buf == nullptr, "queue must be flushed before delete"); +} #ifndef PRODUCT // Helpful for debugging @@ -64,7 +69,7 @@ void SATBMarkQueue::print(const char* name) { #endif // PRODUCT SATBMarkQueueSet::SATBMarkQueueSet(BufferNode::Allocator* allocator) : - PtrQueueSet(allocator), + _allocator(allocator), _list(), _count_and_process_flag(0), _process_completed_buffers_threshold(SIZE_MAX), @@ -214,13 +219,6 @@ bool SATBMarkQueueSet::apply_closure_to_completed_buffer(SATBBufferClosure* cl) } } -void SATBMarkQueueSet::flush_queue(SATBMarkQueue& queue) { - // Filter now to possibly save work later. If filtering empties the - // buffer then flush_queue can deallocate the buffer. - filter(queue); - PtrQueueSet::flush_queue(queue); -} - void SATBMarkQueueSet::enqueue_known_active(SATBMarkQueue& queue, oop obj) { assert(queue.is_active(), "precondition"); void* value = cast_from_oop(obj); @@ -355,3 +353,76 @@ void SATBMarkQueueSet::abandon_partial_marking() { } closure(*this); Threads::threads_do(&closure); } + +size_t SATBMarkQueue::current_capacity() const { + if (_buf == nullptr) { + return 0; + } else { + return BufferNode::make_node_from_buffer(_buf)->capacity(); + } +} + +void SATBMarkQueueSet::reset_queue(SATBMarkQueue& queue) { + queue.set_index(queue.current_capacity()); +} + +void SATBMarkQueueSet::flush_queue(SATBMarkQueue& queue) { + // Filter now to possibly save work later. If filtering empties the + // buffer then flush_queue can deallocate the buffer. + filter(queue); + void** buffer = queue.buffer(); + if (buffer != nullptr) { + size_t index = queue.index(); + queue.set_buffer(nullptr); + queue.set_index(0); + BufferNode* node = BufferNode::make_node_from_buffer(buffer, index); + if (index == node->capacity()) { + deallocate_buffer(node); + } else { + enqueue_completed_buffer(node); + } + } +} + +bool SATBMarkQueueSet::try_enqueue(SATBMarkQueue& queue, void* value) { + size_t index = queue.index(); + if (index == 0) return false; + void** buffer = queue.buffer(); + assert(buffer != nullptr, "no buffer but non-zero index"); + buffer[--index] = value; + queue.set_index(index); + return true; +} + +void SATBMarkQueueSet::retry_enqueue(SATBMarkQueue& queue, void* value) { + assert(queue.index() != 0, "precondition"); + assert(queue.buffer() != nullptr, "precondition"); + size_t index = queue.index(); + queue.buffer()[--index] = value; + queue.set_index(index); +} + +BufferNode* SATBMarkQueueSet::exchange_buffer_with_new(SATBMarkQueue& queue) { + BufferNode* node = nullptr; + void** buffer = queue.buffer(); + if (buffer != nullptr) { + node = BufferNode::make_node_from_buffer(buffer, queue.index()); + } + install_new_buffer(queue); + return node; +} + +void SATBMarkQueueSet::install_new_buffer(SATBMarkQueue& queue) { + BufferNode* node = _allocator->allocate(); + queue.set_buffer(BufferNode::make_buffer_from_node(node)); + queue.set_index(node->capacity()); +} + +void** SATBMarkQueueSet::allocate_buffer() { + BufferNode* node = _allocator->allocate(); + return BufferNode::make_buffer_from_node(node); +} + +void SATBMarkQueueSet::deallocate_buffer(BufferNode* node) { + _allocator->release(node); +} diff --git a/src/hotspot/share/gc/shared/satbMarkQueue.hpp b/src/hotspot/share/gc/shared/satbMarkQueue.hpp index d2b14a3cc92..f1577c004de 100644 --- a/src/hotspot/share/gc/shared/satbMarkQueue.hpp +++ b/src/hotspot/share/gc/shared/satbMarkQueue.hpp @@ -25,11 +25,15 @@ #ifndef SHARE_GC_SHARED_SATBMARKQUEUE_HPP #define SHARE_GC_SHARED_SATBMARKQUEUE_HPP -#include "gc/shared/ptrQueue.hpp" +#include "gc/shared/bufferNode.hpp" #include "memory/allocation.hpp" #include "memory/padded.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/atomic.hpp" +#include "utilities/align.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/sizes.hpp" class Thread; class Monitor; @@ -45,12 +49,33 @@ public: virtual void do_buffer(void** buffer, size_t size) = 0; }; -// A PtrQueue whose elements are (possibly stale) pointers to object heads. -class SATBMarkQueue: public PtrQueue { +// A queue whose elements are (possibly stale) pointers to object heads. +class SATBMarkQueue { friend class VMStructs; friend class SATBMarkQueueSet; private: + NONCOPYABLE(SATBMarkQueue); + + // The buffer. + void** _buf; + + // The (byte) index at which an object was last enqueued. Starts at + // capacity (in bytes) (indicating an empty buffer) and goes towards zero. + // Value is always pointer-size aligned. + size_t _index; + + static const size_t _element_size = sizeof(void*); + + static size_t byte_index_to_index(size_t ind) { + assert(is_aligned(ind, _element_size), "precondition"); + return ind / _element_size; + } + + static size_t index_to_byte_index(size_t ind) { + return ind * _element_size; + } + // Per-queue (so thread-local) cache of the SATBMarkQueueSet's // active state, to support inline barriers in compiled code. bool _active; @@ -58,6 +83,29 @@ private: public: SATBMarkQueue(SATBMarkQueueSet* qset); + // Queue must be flushed + ~SATBMarkQueue(); + + void** buffer() const { return _buf; } + + void set_buffer(void** buffer) { _buf = buffer; } + + size_t index() const { + return byte_index_to_index(_index); + } + + void set_index(size_t new_index) { + assert(new_index <= current_capacity(), "precondition"); + _index = index_to_byte_index(new_index); + } + + // Returns the capacity of the buffer, or 0 if the queue doesn't currently + // have a buffer. + size_t current_capacity() const; + + bool is_empty() const { return index() == current_capacity(); } + size_t size() const { return current_capacity() - index(); } + bool is_active() const { return _active; } void set_active(bool value) { _active = value; } @@ -68,14 +116,16 @@ public: // Compiler support. static ByteSize byte_offset_of_index() { - return PtrQueue::byte_offset_of_index(); + return byte_offset_of(SATBMarkQueue, _index); } - using PtrQueue::byte_width_of_index; + + static constexpr ByteSize byte_width_of_index() { return in_ByteSize(sizeof(size_t)); } static ByteSize byte_offset_of_buf() { - return PtrQueue::byte_offset_of_buf(); + return byte_offset_of(SATBMarkQueue, _buf); } - using PtrQueue::byte_width_of_buf; + + static ByteSize byte_width_of_buf() { return in_ByteSize(_element_size); } static ByteSize byte_offset_of_active() { return byte_offset_of(SATBMarkQueue, _active); @@ -84,7 +134,18 @@ public: static ByteSize byte_width_of_active() { return in_ByteSize(sizeof(bool)); } }; -class SATBMarkQueueSet: public PtrQueueSet { + +// A SATBMarkQueueSet represents resources common to a set of SATBMarkQueues. +// In particular, the individual queues allocate buffers from this shared +// set, and return completed buffers to the set. +// A completed buffer is a buffer the mutator is finished with, and +// is ready to be processed by the collector. It need not be full. + +class SATBMarkQueueSet { + + BufferNode::Allocator* _allocator; + + NONCOPYABLE(SATBMarkQueueSet); DEFINE_PAD_MINUS_SIZE(1, DEFAULT_PADDING_SIZE, 0); PaddedEnd _list; @@ -99,6 +160,24 @@ class SATBMarkQueueSet: public PtrQueueSet { BufferNode* get_completed_buffer(); void abandon_completed_buffers(); + // Discard any buffered enqueued data. + void reset_queue(SATBMarkQueue& queue); + + // Add value to queue's buffer, returning true. If buffer is full + // or if queue doesn't have a buffer, does nothing and returns false. + bool try_enqueue(SATBMarkQueue& queue, void* value); + + // Add value to queue's buffer. The queue must have a non-full buffer. + // Used after an initial try_enqueue has failed and the situation resolved. + void retry_enqueue(SATBMarkQueue& queue, void* value); + + // Installs a new buffer into queue. + // Returns the old buffer, or null if queue didn't have a buffer. + BufferNode* exchange_buffer_with_new(SATBMarkQueue& queue); + + // Installs a new buffer into queue. + void install_new_buffer(SATBMarkQueue& queue); + #ifdef ASSERT void dump_active_states(bool expected_active); void verify_active_states(bool expected_active); @@ -106,6 +185,7 @@ class SATBMarkQueueSet: public PtrQueueSet { protected: SATBMarkQueueSet(BufferNode::Allocator* allocator); + ~SATBMarkQueueSet(); void handle_zero_index(SATBMarkQueue& queue); @@ -131,6 +211,7 @@ public: void set_process_completed_buffers_threshold(size_t value); size_t buffer_enqueue_threshold() const { return _buffer_enqueue_threshold; } + void set_buffer_enqueue_threshold_percentage(uint value); // If there exists some completed buffer, pop and process it, and @@ -144,7 +225,7 @@ public: // Add obj to queue. This qset and the queue must be active. void enqueue_known_active(SATBMarkQueue& queue, oop obj); virtual void filter(SATBMarkQueue& queue) = 0; - virtual void enqueue_completed_buffer(BufferNode* node); + void enqueue_completed_buffer(BufferNode* node); // The number of buffers in the list. Racy and not updated atomically // with the set of completed buffers. @@ -157,6 +238,20 @@ public: return (_count_and_process_flag.load_relaxed() & 1) != 0; } + // Return the associated BufferNode allocator. + BufferNode::Allocator* allocator() const { return _allocator; } + + // Return the buffer for a BufferNode of size buffer_capacity(). + void** allocate_buffer(); + + // Return an empty buffer to the free list. The node is required + // to have been allocated with a size of buffer_capacity(). + void deallocate_buffer(BufferNode* node); + + size_t buffer_capacity() const { + return _allocator->buffer_capacity(); + } + #ifndef PRODUCT // Helpful for debugging void print_all(const char* msg); From e65e06867e7a841c7edce0625f856b8bc2888893 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 12 Dec 2025 18:04:14 +0000 Subject: [PATCH 074/211] 8372592: Adjust logger usage in java2d tests Reviewed-by: kizune, serb, rriggs --- test/jdk/sun/java2d/marlin/Bug8341381.java | 4 ++-- test/jdk/sun/java2d/marlin/CrashNaNTest.java | 5 +++-- test/jdk/sun/java2d/marlin/CrashPaintTest.java | 5 +++-- test/jdk/sun/java2d/marlin/TextClipErrorTest.java | 5 +++-- 4 files changed, 11 insertions(+), 8 deletions(-) diff --git a/test/jdk/sun/java2d/marlin/Bug8341381.java b/test/jdk/sun/java2d/marlin/Bug8341381.java index b469ac49313..19223e3bdbb 100644 --- a/test/jdk/sun/java2d/marlin/Bug8341381.java +++ b/test/jdk/sun/java2d/marlin/Bug8341381.java @@ -89,13 +89,13 @@ public final class Bug8341381 { static final AtomicBoolean isMarlin = new AtomicBoolean(); static final CountDownLatch latch = new CountDownLatch(1); + // initialize j.u.l Logger: + static final Logger log = Logger.getLogger("sun.java2d.marlin"); public static void main(final String[] args) { Locale.setDefault(Locale.US); // FIRST: Get Marlin runtime state from its log: - // initialize j.u.l Logger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { diff --git a/test/jdk/sun/java2d/marlin/CrashNaNTest.java b/test/jdk/sun/java2d/marlin/CrashNaNTest.java index f25be866f85..88ca3ea245f 100644 --- a/test/jdk/sun/java2d/marlin/CrashNaNTest.java +++ b/test/jdk/sun/java2d/marlin/CrashNaNTest.java @@ -54,11 +54,12 @@ public class CrashNaNTest { static final boolean SAVE_IMAGE = false; + // initialize j.u.l Looger: + static final Logger log = Logger.getLogger("sun.java2d.marlin"); + public static void main(String argv[]) { Locale.setDefault(Locale.US); - // initialize j.u.l Looger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { diff --git a/test/jdk/sun/java2d/marlin/CrashPaintTest.java b/test/jdk/sun/java2d/marlin/CrashPaintTest.java index cf710bc83a5..81652761acb 100644 --- a/test/jdk/sun/java2d/marlin/CrashPaintTest.java +++ b/test/jdk/sun/java2d/marlin/CrashPaintTest.java @@ -53,11 +53,12 @@ public class CrashPaintTest { static final boolean SAVE_IMAGE = false; + // initialize j.u.l Looger: + static final Logger log = Logger.getLogger("sun.java2d.marlin"); + public static void main(String argv[]) { Locale.setDefault(Locale.US); - // initialize j.u.l Looger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { diff --git a/test/jdk/sun/java2d/marlin/TextClipErrorTest.java b/test/jdk/sun/java2d/marlin/TextClipErrorTest.java index 2e63e4689fa..4d1c841a688 100644 --- a/test/jdk/sun/java2d/marlin/TextClipErrorTest.java +++ b/test/jdk/sun/java2d/marlin/TextClipErrorTest.java @@ -61,11 +61,12 @@ public class TextClipErrorTest { static final boolean SAVE_IMAGE = false; static final boolean SERIALIZE = false; + // initialize j.u.l Looger: + static final Logger log = Logger.getLogger("sun.java2d.marlin"); + public static void main(String[] args) { Locale.setDefault(Locale.US); - // initialize j.u.l Looger: - final Logger log = Logger.getLogger("sun.java2d.marlin"); log.addHandler(new Handler() { @Override public void publish(LogRecord record) { From 9b12c0bb190de3f7d06db71411f37f9465992a04 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Fri, 12 Dec 2025 18:06:46 +0000 Subject: [PATCH 075/211] 7067310: 3 tests from closed/javax/sound/sampled caused BSOD on win 7 x86 8307574: ClipIsRunningAfterStop.java failed with "../nptl/pthread_mutex_lock.c:81: __pthread_mutex_lock: Assertion `mutex->__data.__owner == 0' failed." 8308395: javax/sound/sampled/Clip/ClipFlushCrash.java timed out Reviewed-by: serb --- test/jdk/ProblemList.txt | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 757d9c0ba63..789fc93fe7d 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -641,19 +641,9 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8316183 linux-pp ############################################################################ # jdk_sound -javax/sound/sampled/DirectAudio/bug6372428.java 8055097 generic-all -javax/sound/sampled/Clip/bug5070081.java 8055097 generic-all -javax/sound/sampled/DataLine/LongFramePosition.java 8055097 generic-all javax/sound/sampled/Clip/Drain/ClipDrain.java 7062792 generic-all -javax/sound/sampled/Mixers/DisabledAssertionCrash.java 7067310 generic-all - -javax/sound/midi/Sequencer/Recording.java 8167580,8265485 linux-all,macosx-aarch64 -javax/sound/midi/Sequencer/Looping.java 8136897 generic-all -javax/sound/sampled/Clip/ClipIsRunningAfterStop.java 8307574 linux-x64 -javax/sound/sampled/Clip/ClipFlushCrash.java 8308395 linux-x64 - ############################################################################ # jdk_imageio From 6e2ab84154e7cc11a31026c588a7dc3ceb446cc2 Mon Sep 17 00:00:00 2001 From: Srinivas Mandalika Date: Fri, 12 Dec 2025 18:09:51 +0000 Subject: [PATCH 076/211] 8068378: [TEST_BUG]The java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java instruction need to update Reviewed-by: psadhukhan, prr --- test/jdk/ProblemList.txt | 1 - .../PrintDialogsTest/PrintDialogsTest.java | 63 +++++++++---------- .../java/awt/Modal/PrintDialogsTest/Test.java | 1 + 3 files changed, 30 insertions(+), 35 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 789fc93fe7d..974e719c1c9 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -772,7 +772,6 @@ java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_1.java 7131438,802 java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter_2.java 7131438,8022539 generic-all java/awt/Modal/WsDisabledStyle/CloseBlocker/CloseBlocker.java 7187741 linux-all,macosx-all java/awt/xembed/server/TestXEmbedServerJava.java 8001150,8004031 generic-all -java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java 8068378 generic-all java/awt/image/VolatileImage/VolatileImageConfigurationTest.java 8171069 macosx-all,linux-all java/awt/Modal/InvisibleParentTest/InvisibleParentTest.java 8172245 linux-all java/awt/Frame/FrameStateTest/FrameStateTest.java 8203920 macosx-all,linux-all diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java index e2b2d8cac78..3e191fa0c4c 100644 --- a/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java +++ b/test/jdk/java/awt/Modal/PrintDialogsTest/PrintDialogsTest.java @@ -49,40 +49,35 @@ import java.awt.event.ActionListener; public class PrintDialogsTest extends Panel implements ActionListener { - static final String INSTRUCTIONS = """ - This test is free format, which means there is no enforced or guided sequence. - - Please select each of - (a) The dialog parent type. - (b) The dialog modality type - (c) The print dialog type (Print dialog or Page Setup dialog) - - Once the choices have been made click the "Start test" button. - - Three windows will appear - (1) A Frame or a Dialog - in the case you selected "Dialog" as the parent type - (2) a Window (ie an undecorated top-level) - (3) A dialog with two buttons "Open" and "Finish" - - Now check as follows whether modal blocking works as expected. - Windows (1) and (2) contain a button which you should be able to press - ONLY if you selected "Non-modal", or "Modeless" for modality type. - In other cases window (3) will block input to (1) and (2) - - Then push the "Open" button on the Dialog to show the printing dialog and check - if it blocks the rest of the application - ie all of windows (1), (2) and (3) - should ALWAYS be blocked when the print dialog is showing. - Now cancel the printing dialog and check the correctness of modal blocking - behavior for the Dialog again. - To close all the 3 test windows please push the "Finish" button. - - Repeat all the above for different combinations, which should include - using all of the Dialog parent choices and all of the Dialog Modality types. - - If any behave incorrectly, note the combination of choices and press Fail. - - If all behave correctly, press Pass. - """; + static final String INSTRUCTIONS = + "1. On the Test UI Select:\n" + + "\tThe dialog parent type. (e.g. Frame, Dialog, Hidden, Null)\n" + + "\tThe dialog modality type. (e.g. Modal, Non-Modal, Toolkit modal).\n" + + "\tThe print dialog type. (Print dialog or Page Setup dialog).\n\n" + + "2. Next, click on 'Start test' - Three windows will appear:\n" + + "\tWindow (1) -a Frame or Dialog (depending on selected parent type).\n" + + "\tWindow (2) -an undecorated top-level Window.\n" + + "\tWindow (3) -a Dialog containing two buttons: 'Open' and 'Finish'.\n" + + "\tWindows (1) & (2) have a Dummy button.\n\n" + + "3. Press the button on Window (1) & Window (2) \n" + + "Verification step:\n" + + "\tIf Modality is 'Non-modal' or 'Modeless', Button is pressed \n" + + "\tIf Modality is 'Document' & parent is not Frame/Dialog, Button is pressed \n" + + "\tIn all other cases, button is not pressed & Window (3) should \n" + + "\tblock input to Windows (1) & (2).\n\n" + + "4. Next, press the 'Open' button in Window (3) to open print dialog.\n\n" + + "5. Press the button on Window (1) & Window (2)\n" + + "Verification step:\n" + + "\tThe print dialog should block all three windows (1, 2, and 3).\n\n" + + "6. Cancel the print dialog, Check again if Window (3) " + + "blocks Windows (1) and (2) correctly.\n" + + "Verification step:\n" + + "\tConditions as seen in Verification step 3 " + + "should be seen, as before.\n" + + "To close all test windows, press 'Finish'.\n\n" + + "7. Repeat the steps for different combinations of Dialog Parent, Dialog Modality Type, Print Dialg Type.\n" + + "Try every dialog parent type and every dialog modality type.\n\n" + + "If any of the Verification step fails, note the combination and press 'Fail'.\n"; public static void main(String[] args) throws Exception { diff --git a/test/jdk/java/awt/Modal/PrintDialogsTest/Test.java b/test/jdk/java/awt/Modal/PrintDialogsTest/Test.java index 3c8faceb3a9..0f190971186 100644 --- a/test/jdk/java/awt/Modal/PrintDialogsTest/Test.java +++ b/test/jdk/java/awt/Modal/PrintDialogsTest/Test.java @@ -191,6 +191,7 @@ public class Test { break; case DIALOG: dialog = new CustomDialog(parent); + break; case FRAME: dialog = new CustomDialog(frame); break; From b6319f5b42738cc760711a3b8b5d442d14a0ed74 Mon Sep 17 00:00:00 2001 From: Volkan Yazici Date: Fri, 12 Dec 2025 18:19:35 +0000 Subject: [PATCH 077/211] 8369595: HttpClient: HttpHeaders.firstValueAsLong failures should be converted to ProtocolException Reviewed-by: dfuchs, djelinski --- .../jdk/internal/net/http/Http1Response.java | 57 +- .../internal/net/http/Http3ExchangeImpl.java | 12 +- .../jdk/internal/net/http/Http3Stream.java | 47 +- .../jdk/internal/net/http/MultiExchange.java | 42 +- .../classes/jdk/internal/net/http/Stream.java | 36 +- .../jdk/internal/net/http/common/Utils.java | 42 ++ .../http3/H3MalformedResponseTest.java | 699 ++++++++++-------- 7 files changed, 529 insertions(+), 406 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java index f9442df9ac4..35ce4972ed9 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http1Response.java @@ -30,6 +30,7 @@ import java.lang.System.Logger.Level; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.net.http.HttpResponse.BodySubscriber; +import java.net.ProtocolException; import java.nio.ByteBuffer; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Executor; @@ -46,6 +47,7 @@ import jdk.internal.net.http.common.MinimalFuture; import jdk.internal.net.http.common.Utils; import static java.net.http.HttpClient.Version.HTTP_1_1; import static java.net.http.HttpResponse.BodySubscribers.discarding; +import static jdk.internal.net.http.common.Utils.readContentLength; import static jdk.internal.net.http.common.Utils.wrapWithExtraDetail; import static jdk.internal.net.http.RedirectFilter.HTTP_NOT_MODIFIED; @@ -272,16 +274,31 @@ class Http1Response { } /** - * Read up to MAX_IGNORE bytes discarding + * Reads the body, if it is present and less than {@value MAX_IGNORE} bytes. + * Otherwise, just the connection is closed. */ public CompletableFuture ignoreBody(Executor executor) { - int clen = (int)headers.firstValueAsLong("Content-Length").orElse(-1); - if (clen == -1 || clen > MAX_IGNORE) { + + // Read the `Content-Length` header + long clen; + try { + clen = readContentLength(headers, "", -1); + } catch (ProtocolException pe) { + return MinimalFuture.failedFuture(pe); + } + + // Read the body, if it is present and less than `MAX_IGNORE` bytes. + // + // We proceed with reading the body even when `Content-Length: 0` to + // ensure that the happy path is taken, and upon success, the connection + // is returned back to the pool. + if (clen != -1 && clen <= MAX_IGNORE) { + return readBody(discarding(), !request.isWebSocket(), executor); + } else { connection.close(); return MinimalFuture.completedFuture(null); // not treating as error - } else { - return readBody(discarding(), !request.isWebSocket(), executor); } + } // Used for those response codes that have no body associated @@ -308,11 +325,28 @@ class Http1Response { this.return2Cache = return2Cache; final BodySubscriber subscriber = p; - final CompletableFuture cf = new MinimalFuture<>(); - long clen0 = headers.firstValueAsLong("Content-Length").orElse(-1L); - final long clen = fixupContentLen(clen0); + Consumer errorNotifier = error -> { + try { + subscriber.onError(error); + cf.completeExceptionally(error); + } finally { + asyncReceiver.setRetryOnError(false); + asyncReceiver.onReadError(error); + } + }; + + // Read the content length + long clen; + try { + long clen0 = readContentLength(headers, "", -1); + clen = fixupContentLen(clen0); + } catch (ProtocolException pe) { + errorNotifier.accept(pe); + connection.close(pe); + return cf; + } // expect-continue reads headers and body twice. // if we reach here, we must reset the headersReader state. @@ -398,12 +432,7 @@ class Http1Response { } }); - ResponseSubscribers.getBodyAsync(executor, p, cf, (t) -> { - subscriber.onError(t); - cf.completeExceptionally(t); - asyncReceiver.setRetryOnError(false); - asyncReceiver.onReadError(t); - }); + ResponseSubscribers.getBodyAsync(executor, p, cf, errorNotifier); return cf.whenComplete((s,t) -> { if (t != null) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http3ExchangeImpl.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http3ExchangeImpl.java index 81475a47c4a..4625968682f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http3ExchangeImpl.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http3ExchangeImpl.java @@ -81,6 +81,8 @@ import jdk.internal.net.http.qpack.writers.HeaderFrameWriter; import jdk.internal.net.http.quic.streams.QuicBidiStream; import jdk.internal.net.http.quic.streams.QuicStreamReader; import jdk.internal.net.http.quic.streams.QuicStreamWriter; + +import static jdk.internal.net.http.common.Utils.readContentLength; import static jdk.internal.net.http.http3.ConnectionSettings.UNLIMITED_MAX_FIELD_SECTION_SIZE; /** @@ -1293,12 +1295,16 @@ final class Http3ExchangeImpl extends Http3Stream { if (Set.of("PUT", "DELETE", "OPTIONS", "TRACE").contains(method)) { throw new ProtocolException("push method not allowed pushId=" + pushId); } - long clen = promiseHeaders.firstValueAsLong("Content-Length").orElse(-1); + + // Read & validate `Content-Length` + long clen = readContentLength( + promiseHeaders, "illegal push headers for pushId=%s: ".formatted(pushId), -1); if (clen > 0) { - throw new ProtocolException("push headers contain non-zero Content-Length for pushId=" + pushId); + throw new ProtocolException("push headers contain non-zero \"Content-Length\" for pushId=" + pushId); } + if (promiseHeaders.firstValue("Transfer-Encoding").isPresent()) { - throw new ProtocolException("push headers contain Transfer-Encoding for pushId=" + pushId); + throw new ProtocolException("push headers contain \"Transfer-Encoding\" for pushId=" + pushId); } diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http3Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http3Stream.java index cdac68b47f1..14e440a0e33 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http3Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http3Stream.java @@ -31,7 +31,6 @@ import java.net.ProtocolException; import java.net.http.HttpHeaders; import java.nio.ByteBuffer; import java.util.List; -import java.util.OptionalLong; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.atomic.AtomicInteger; @@ -58,6 +57,8 @@ import jdk.internal.net.http.quic.streams.QuicStreamReader; import static jdk.internal.net.http.Exchange.MAX_NON_FINAL_RESPONSES; import static jdk.internal.net.http.RedirectFilter.HTTP_NOT_MODIFIED; +import static jdk.internal.net.http.common.Utils.readContentLength; +import static jdk.internal.net.http.common.Utils.readStatusCode; /** * A common super class for the HTTP/3 request/response stream ({@link Http3ExchangeImpl} @@ -606,23 +607,17 @@ sealed abstract class Http3Stream extends ExchangeImpl permits Http3Exchan } int responseCode; - boolean finalResponse = false; try { - responseCode = (int) responseHeaders - .firstValueAsLong(":status") - .orElseThrow(() -> new IOException("no statuscode in response")); - } catch (IOException | NumberFormatException exception) { + responseCode = readStatusCode(responseHeaders, ""); + } catch (ProtocolException pe) { // RFC-9114: 4.1.2. Malformed Requests and Responses: // "Malformed requests or responses that are // detected MUST be treated as a stream error of type H3_MESSAGE_ERROR" - cancelImpl(exception, Http3Error.H3_MESSAGE_ERROR); - return; - } - if (responseCode < 100 || responseCode > 999) { - cancelImpl(new IOException("Unexpected :status header value"), Http3Error.H3_MESSAGE_ERROR); + cancelImpl(pe, Http3Error.H3_MESSAGE_ERROR); return; } + boolean finalResponse = false; if (responseCode >= 200) { responseState = ResponseState.PERMIT_TRAILER; finalResponse = true; @@ -653,23 +648,21 @@ sealed abstract class Http3Stream extends ExchangeImpl permits Http3Exchan responseHeaders); } - try { - OptionalLong cl = responseHeaders.firstValueAsLong("content-length"); - if (finalResponse && cl.isPresent()) { - long cll = cl.getAsLong(); - if (cll < 0) { - cancelImpl(new IOException("Invalid content-length value "+cll), Http3Error.H3_MESSAGE_ERROR); - return; - } - if (!(exchange.request().method().equalsIgnoreCase("HEAD") || responseCode == HTTP_NOT_MODIFIED)) { - // HEAD response and 304 response might have a content-length header, - // but it carries no meaning - contentLength = cll; - } + if (finalResponse) { + long cl; + try { + cl = readContentLength(responseHeaders, "", -1); + } catch (ProtocolException pe) { + cancelImpl(pe, Http3Error.H3_MESSAGE_ERROR); + return; + } + if (cl != -1 && + !(exchange.request().method().equalsIgnoreCase("HEAD") || + responseCode == HTTP_NOT_MODIFIED)) { + // HEAD response and 304 response might have a content-length header, + // but it carries no meaning + contentLength = cl; } - } catch (NumberFormatException nfe) { - cancelImpl(nfe, Http3Error.H3_MESSAGE_ERROR); - return; } if (Log.headers() || debug.on()) { diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java index 60eb55ec0ad..671874b8fb5 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/MultiExchange.java @@ -28,8 +28,11 @@ package jdk.internal.net.http; import java.io.IOException; import java.lang.ref.WeakReference; import java.net.ConnectException; +import java.net.ProtocolException; +import java.net.ProtocolException; import java.net.http.HttpClient.Version; import java.net.http.HttpConnectTimeoutException; +import java.net.http.HttpHeaders; import java.net.http.StreamLimitException; import java.time.Duration; import java.util.List; @@ -47,7 +50,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Function; import java.net.http.HttpClient; -import java.net.http.HttpHeaders; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodySubscriber; @@ -62,6 +64,7 @@ import jdk.internal.net.http.common.Utils; import static jdk.internal.net.http.common.MinimalFuture.completedFuture; import static jdk.internal.net.http.common.MinimalFuture.failedFuture; import static jdk.internal.net.http.AltSvcProcessor.processAltSvcHeader; +import static jdk.internal.net.http.common.Utils.readContentLength; /** @@ -358,13 +361,22 @@ class MultiExchange implements Cancelable { return r.statusCode == 204; } - private boolean bodyIsPresent(Response r) { - HttpHeaders headers = r.headers(); - if (headers.firstValueAsLong("Content-length").orElse(0L) != 0L) - return true; - if (headers.firstValue("Transfer-encoding").isPresent()) - return true; - return false; + private void ensureNoBody(HttpHeaders headers) throws ProtocolException { + + // Check `Content-Length` + var contentLength = readContentLength(headers, "", 0); + if (contentLength > 0) { + throw new ProtocolException( + "Unexpected \"Content-Length\" header in a 204 response: " + contentLength); + } + + // Check `Transfer-Encoding` + var transferEncoding = headers.firstValue("Transfer-Encoding"); + if (transferEncoding.isPresent()) { + throw new ProtocolException( + "Unexpected \"Transfer-Encoding\" header in a 204 response: " + transferEncoding.get()); + } + } // Call the user's body handler to get an empty body object @@ -405,13 +417,13 @@ class MultiExchange implements Cancelable { if (bodyNotPermitted(r)) { // No response body consumption is expected, we can cancel the timer right away cancelTimer(); - if (bodyIsPresent(r)) { - IOException ioe = new IOException( - "unexpected content length header with 204 response"); - exch.cancel(ioe); - return MinimalFuture.failedFuture(ioe); - } else - return handleNoBody(r, exch); + try { + ensureNoBody(r.headers); + } catch (ProtocolException pe) { + exch.cancel(pe); + return MinimalFuture.failedFuture(pe); + } + return handleNoBody(r, exch); } return exch.readBodyAsync(responseHandler) .thenApply((T body) -> setNewResponse(r.request, r, body, exch)); diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java index bf9170f8f51..9826b280438 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Stream.java @@ -61,6 +61,7 @@ import jdk.internal.net.http.hpack.DecodingCallback; import static jdk.internal.net.http.AltSvcProcessor.processAltSvcFrame; import static jdk.internal.net.http.Exchange.MAX_NON_FINAL_RESPONSES; +import static jdk.internal.net.http.common.Utils.readStatusCode; /** * Http/2 Stream handling. @@ -615,18 +616,14 @@ class Stream extends ExchangeImpl { return null; } - protected void handleResponse(HeaderFrame hf) throws IOException { + protected void handleResponse(HeaderFrame hf) { HttpHeaders responseHeaders = responseHeadersBuilder.build(); if (!finalResponseCodeReceived) { try { - responseCode = (int) responseHeaders - .firstValueAsLong(":status") - .orElseThrow(() -> new ProtocolException(String.format( - "Stream %s PROTOCOL_ERROR: no status code in response", - streamid))); - } catch (ProtocolException cause) { - cancelImpl(cause, ResetFrame.PROTOCOL_ERROR); + responseCode = readStatusCode(responseHeaders, "Stream %s PROTOCOL_ERROR: ".formatted(streamid)); + } catch (ProtocolException pe) { + cancelImpl(pe, ResetFrame.PROTOCOL_ERROR); rspHeadersConsumer.reset(); return; } @@ -1730,21 +1727,18 @@ class Stream extends ExchangeImpl { HttpHeaders responseHeaders = responseHeadersBuilder.build(); if (!finalPushResponseCodeReceived) { - responseCode = (int)responseHeaders - .firstValueAsLong(":status") - .orElse(-1); - - if (responseCode == -1) { - cancelImpl(new ProtocolException("No status code"), ResetFrame.PROTOCOL_ERROR); + try { + responseCode = readStatusCode(responseHeaders, ""); + if (responseCode >= 100 && responseCode < 200) { + String protocolErrorMsg = checkInterimResponseCountExceeded(); + if (protocolErrorMsg != null) { + throw new ProtocolException(protocolErrorMsg); + } + } + } catch (ProtocolException pe) { + cancelImpl(pe, ResetFrame.PROTOCOL_ERROR); rspHeadersConsumer.reset(); return; - } else if (responseCode >= 100 && responseCode < 200) { - String protocolErrorMsg = checkInterimResponseCountExceeded(); - if (protocolErrorMsg != null) { - cancelImpl(new ProtocolException(protocolErrorMsg), ResetFrame.PROTOCOL_ERROR); - rspHeadersConsumer.reset(); - return; - } } this.finalPushResponseCodeReceived = true; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java index 20b0338215c..e5ea07c3b97 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/Utils.java @@ -39,6 +39,7 @@ import java.lang.System.Logger.Level; import java.net.ConnectException; import java.net.Inet6Address; import java.net.InetSocketAddress; +import java.net.ProtocolException; import java.net.SocketAddress; import java.net.StandardSocketOptions; import java.net.Proxy; @@ -1354,6 +1355,47 @@ public final class Utils { } // -- toAsciiString-like support to encode path and query URI segments + public static int readStatusCode(HttpHeaders headers, String errorPrefix) throws ProtocolException { + var s = headers.firstValue(":status").orElse(null); + if (s == null) { + throw new ProtocolException(errorPrefix + "missing status code"); + } + Throwable t = null; + int i = 0; + try { + i = Integer.parseInt(s); + } catch (NumberFormatException nfe) { + t = nfe; + } + if (t != null || i < 100 || i > 999) { + var pe = new ProtocolException(errorPrefix + "invalid status code: " + s); + pe.initCause(t); + throw pe; + } + return i; + } + + public static long readContentLength(HttpHeaders headers, String errorPrefix, long defaultIfMissing) throws ProtocolException { + var k = "Content-Length"; + var s = headers.firstValue(k).orElse(null); + if (s == null) { + return defaultIfMissing; + } + Throwable t = null; + long i = 0; + try { + i = Long.parseLong(s); + } catch (NumberFormatException nfe) { + t = nfe; + } + if (t != null || i < 0) { + var pe = new ProtocolException("%sinvalid \"%s\": %s".formatted(errorPrefix, k, s)); + pe.initCause(t); + throw pe; + } + return i; + } + // Encodes all characters >= \u0080 into escaped, normalized UTF-8 octets, // assuming that s is otherwise legal // diff --git a/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java b/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java index 881277da1f8..ea1efaf4933 100644 --- a/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java +++ b/test/jdk/java/net/httpclient/http3/H3MalformedResponseTest.java @@ -22,410 +22,457 @@ */ import jdk.httpclient.test.lib.common.HttpServerAdapters; -import jdk.httpclient.test.lib.quic.QuicServerConnection; import jdk.httpclient.test.lib.quic.QuicStandaloneServer; -import jdk.internal.net.http.http3.Http3Error; -import jdk.internal.net.http.quic.TerminationCause; +import jdk.internal.net.http.common.Logger; +import jdk.internal.net.http.common.Utils; import jdk.internal.net.quic.QuicVersion; import jdk.test.lib.net.SimpleSSLContext; import jdk.test.lib.net.URIBuilder; -import jdk.test.lib.Utils; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; import javax.net.ssl.SSLContext; +import java.io.IOException; import java.io.OutputStream; -import java.net.URI; -import java.net.URISyntaxException; +import java.net.ProtocolException; import java.net.http.HttpClient; import java.net.http.HttpClient.Version; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.net.http.HttpResponse.BodyHandlers; import java.util.HexFormat; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.function.BooleanSupplier; -import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; +import static java.net.http.HttpClient.Builder.NO_PROXY; import static java.net.http.HttpOption.H3_DISCOVERY; -import static org.testng.Assert.*; +import static java.net.http.HttpOption.Http3DiscoveryMode.HTTP_3_URI_ONLY; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /* * @test - * @summary Verifies that the HTTP client correctly handles malformed responses - * @library /test/lib /test/jdk/java/net/httpclient/lib - * @library ../access - * @build jdk.test.lib.net.SimpleSSLContext - * jdk.httpclient.test.lib.common.HttpServerAdapters - * @build java.net.http/jdk.internal.net.http.Http3ConnectionAccess - * @run testng/othervm - * -Djdk.internal.httpclient.debug=true - * -Djdk.httpclient.HttpClient.log=requests,responses,errors H3MalformedResponseTest + * @bug 8369595 + * @summary Verifies that the HTTP/3 malformed responses are correctly handled + * @library /test/jdk/java/net/httpclient/lib + * /test/lib + * @run junit ${test.main.class} */ -public class H3MalformedResponseTest implements HttpServerAdapters { - private SSLContext sslContext; - private QuicStandaloneServer server; - private String requestURIBase; +/// Verifies that the HTTP/3 malformed responses are correctly handled. +/// +/// ### HTTP/3 `HEADERS` frame & QPACK Field Section encoding crash course +/// +/// Consider an HTTP/3 `HEADERS` frame that carries: +/// +/// ``` +/// :status: 200 +/// content-length: 2 +/// ``` +/// +/// This will be encoded as the following byte sequence: +/// +/// ``` +/// 01 06 00 00 D9 54 01 32 +/// ``` +/// +/// Let's start with decoding the HTTP/3 frame: +/// +/// - `01`: Frame Type (`01` denotes `HEADERS``) +/// +/// - `06`: Payload length (6 bytes) +/// +/// Figured this is a `HEADERS` frame containing 6 bytes: `00 00 D9 54 01 32`. +/// Let's decode the QPACK Field Section +/// +/// - `00`: Required Insert Count (0) +/// +/// - `00`: Base (0) +/// +/// - `D9`: +/// QPACK has a static table (indexed from 0) and `:status: 200` is at the +/// static-table index 25. +/// +/// ``` +/// D9 = <1101 1001> +/// = <1> (Indexed Field Line) +/// + <1> (Static Table) +/// + <01 1001> (entry index = 25) +/// ``` +/// +/// - `54 01 32`: +/// `content-length: 2` can be encoded as a *literal field line with name +/// reference* using the static name `content-length` (static index 4) and +/// the literal value `2`. +/// +/// ``` +/// 54 01 32 = <0101 0100 0000 0001 0011 0010> +/// = <0> (Literal Field Line) +/// + <1> (Name Reference) +/// + <0100> (entry index = 4) +/// + <0000 0001> (value length = 1 byte) +/// + <0011 0010> (value = ASCII "2" = 0x32 = 50) +/// ``` +/// +/// Note that the `value length` field (i.e., `0000 0001`) follows a variable +/// coding scheme: +/// +/// | Prefix | Total size | Payload size | Max value | +/// | --------------------- | ---------- | ------------ | ------------- | +/// | `00xx xxxx` | 1 byte | 6 bits | 63 | +/// | `01xx xxxx xxxx xxxx` | 2 bytes | 14 bits | 16,383 | +/// | `10xx xxx…` | 4 bytes | 30 bits | 1,073,741,823 | +/// | `11xx xxx…` | 8 bytes | 62 bits | 4.61e18 | +class H3MalformedResponseTest { - // These responses are malformed and should not be accepted by the client, - // but they should not cause connection closure - @DataProvider - public static Object[][] malformedResponse() { + private static final String CLASS_NAME = H3MalformedResponseTest.class.getSimpleName(); + + private static final Logger LOGGER = Utils.getDebugLogger(CLASS_NAME::toString, Utils.DEBUG); + + private static SSLContext SSL_CONTEXT; + + private static QuicStandaloneServer SERVER; + + private static HttpRequest REQUEST; + + @BeforeAll + static void setUp() throws Exception { + + // Obtain an `SSLContext` + SSL_CONTEXT = new SimpleSSLContext().get(); + assertNotNull(SSL_CONTEXT); + + // Create and start the server + SERVER = QuicStandaloneServer.newBuilder() + .availableVersions(new QuicVersion[]{QuicVersion.QUIC_V1}) + .sslContext(SSL_CONTEXT) + .alpn("h3") + .build(); + SERVER.start(); + LOGGER.log("Server is started at {}", SERVER.getAddress()); + + // Create the request + var requestURI = URIBuilder.newBuilder() + .scheme("https") + .loopback() + .port(SERVER.getAddress().getPort()) + .path("/" + CLASS_NAME) + .build(); + REQUEST = HttpRequest.newBuilder(requestURI) + .version(Version.HTTP_3) + .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY) + .build(); + + } + + @AfterAll + static void tearDown() { + close("server", SERVER); + } + + private static void close(String name, AutoCloseable closeable) { + if (closeable != null) { + LOGGER.log("Closing {}", name); + try { + closeable.close(); + } catch (Exception e) { + LOGGER.log("Could not close " + name, e); + } + } + } + + /// Malformed responses that should not be accepted by the client, but + /// should neither cause the connection to get closed. + static Object[][] malformedResponsesPreservingConnection() { return new Object[][]{ - new Object[] {"empty", HexFormat.of().parseHex( - "" + {"empty", IOException.class, parseHex("")}, + {"non-final response", IOException.class, parseHex( + "01040000", // headers, length 4, section prefix + "ff00" // :status:100 )}, - new Object[] {"non-final response", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "ff00" // :status:100 + {"uppercase header name", ProtocolException.class, parseHex( + "01090000", // headers, length 9, section prefix + "d9", // :status:200 + "234147450130", // AGE:0 + "000100" // data, 1 byte )}, - new Object[] {"uppercase header name", HexFormat.of().parseHex( - "01090000"+ // headers, length 9, section prefix - "d9"+ // :status:200 - "234147450130"+ // AGE:0 + {"content too long", IOException.class, parseHex( + "01040000", // headers, length 4, section prefix + "d9", // :status:200 + "c4", // content-length:0 + "000100" // data, 1 byte + )}, + {"content too short", IOException.class, parseHex( + "01060000", // headers, length 6, section prefix + "d9", // :status:200 + "540132", // content-length:2 + "000100" // data, 1 byte + )}, + {"text in content-length", ProtocolException.class, parseHex( + "01060000" + // headers, length 6, section prefix + "d9" + // :status:200 + "540161" + // content-length:a "000100" // data, 1 byte )}, - new Object[] {"content too long", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "d9"+ // :status:200 - "c4"+ // content-length:0 - "000100" // data, 1 byte - )}, - new Object[] {"content too short", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "540132"+ // content-length:2 - "000100" // data, 1 byte - )}, - new Object[] {"text in content-length", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "540161"+ // content-length:a - "000100" // data, 1 byte - )}, - new Object[] {"connection: close", HexFormat.of().parseHex( - "01150000"+ // headers, length 21, section prefix - "d9"+ // :status:200 - "2703636F6E6E656374696F6E05636C6F7365"+ // connection:close + {"connection: close", ProtocolException.class, parseHex( + "01150000", // headers, length 21, section prefix + "d9", // :status:200 + "2703636F6E6E656374696F6E05636C6F7365" + // connection:close "000100" // data, 1 byte )}, // request pseudo-headers in response - new Object[] {":method in response", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "d9"+ // :status:200 - "d1"+ // :method:get - "000100" // data, 1 byte + {":method in response", ProtocolException.class, parseHex( + "01040000", // headers, length 4, section prefix + "d9", // :status:200 + "d1", // :method:get + "000100" // data, 1 byte )}, - new Object[] {":authority in response", HexFormat.of().parseHex( - "01100000"+ // headers, length 16, section prefix - "d9"+ // :status:200 - "508b089d5c0b8170dc702fbce7"+ // :authority - "000100" // data, 1 byte + {":authority in response", ProtocolException.class, parseHex( + "01100000", // headers, length 16, section prefix + "d9", // :status:200 + "508b089d5c0b8170dc702fbce7", // :authority + "000100" // data, 1 byte )}, - new Object[] {":path in response", HexFormat.of().parseHex( - "010a0000"+ // headers, length 10, section prefix - "d9"+ // :status:200 - "51856272d141ff"+ // :path - "000100" // data, 1 byte + {":path in response", ProtocolException.class, parseHex( + "010a0000", // headers, length 10, section prefix + "d9", // :status:200 + "51856272d141ff", // :path + "000100" // data, 1 byte )}, - new Object[] {":scheme in response", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "d9"+ // :status:200 - "d7"+ // :scheme:https - "000100" // data, 1 byte + {":scheme in response", ProtocolException.class, parseHex( + "01040000", // headers, length 4, section prefix + "d9", // :status:200 + "d7", // :scheme:https + "000100" // data, 1 byte )}, - new Object[] {"undefined pseudo-header", HexFormat.of().parseHex( - "01080000"+ // headers, length 8, section prefix - "d9"+ // :status:200 - "223A6D0130"+ // :m:0 - "000100" // data, 1 byte + {"undefined pseudo-header", ProtocolException.class, parseHex( + "01080000", // headers, length 8, section prefix + "d9", // :status:200 + "223A6D0130", // :m:0 + "000100" // data, 1 byte )}, - new Object[] {"pseudo-header after regular", HexFormat.of().parseHex( - "011a0000"+ // headers, length 26, section prefix - "5f5094ca3ee35a74a6b589418b5258132b1aa496ca8747"+ //user-agent - "d9"+ // :status:200 - "000100" // data, 1 byte + {"pseudo-header after regular", ProtocolException.class, parseHex( + "011a0000", // headers, length 26, section prefix + "5f5094ca3ee35a74a6b589418b5258132b1aa496ca8747", //user-agent + "d9", // :status:200 + "000100" // data, 1 byte )}, - new Object[] {"trailer", HexFormat.of().parseHex( + {"trailer", IOException.class, parseHex( "01020000" // headers, length 2, section prefix )}, - new Object[] {"trailer+data", HexFormat.of().parseHex( - "01020000"+ // headers, length 2, section prefix - "000100" // data, 1 byte + {"trailer+data", IOException.class, parseHex( + "01020000", // headers, length 2, section prefix + "000100" // data, 1 byte )}, // valid characters include \t, 0x20-0x7e, 0x80-0xff (RFC 9110, section 5.5) - new Object[] {"invalid character in field value 00", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "570100"+ // etag:\0 - "000100" // data, 1 byte + {"invalid character in field value 00", ProtocolException.class, parseHex( + "01060000", // headers, length 6, section prefix + "d9", // :status:200 + "570100", // etag:\0 + "000100" // data, 1 byte )}, - new Object[] {"invalid character in field value 0a", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "57010a"+ // etag:\n - "000100" // data, 1 byte + {"invalid character in field value 0a", ProtocolException.class, parseHex( + "01060000", // headers, length 6, section prefix + "d9", // :status:200 + "57010a", // etag:\n + "000100" // data, 1 byte )}, - new Object[] {"invalid character in field value 0d", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "57010d"+ // etag:\r - "000100" // data, 1 byte + {"invalid character in field value 0d", ProtocolException.class, parseHex( + "01060000", // headers, length 6, section prefix + "d9", // :status:200 + "57010d", // etag:\r + "000100" // data, 1 byte )}, - new Object[] {"invalid character in field value 7f", HexFormat.of().parseHex( - "01060000"+ // headers, length 6, section prefix - "d9"+ // :status:200 - "57017f"+ // etag: 0x7f - "000100" // data, 1 byte + {"invalid character in field value 7f", ProtocolException.class, parseHex( + "01060000", // headers, length 6, section prefix + "d9", // :status:200 + "57017f", // etag: 0x7f + "000100" // data, 1 byte )}, }; } - // These responses are malformed and should not be accepted by the client. - // They might or might not cause connection closure (H3_FRAME_UNEXPECTED) - @DataProvider - public static Object[][] malformedResponse2() { + /// Malformed responses that should not be accepted by the client. + /// They might or might not cause the connection to get closed (`H3_FRAME_UNEXPECTED`). + static Object[][] malformedResponses() { // data before headers is covered by H3ErrorHandlingTest return new Object[][]{ - new Object[] {"100+data", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "ff00"+ // :status:100 - "000100" // data, 1 byte + {"100+data", IOException.class, parseHex( + "01040000", // headers, length 4, section prefix + "ff00", // :status:100 + "000100" // data, 1 byte )}, - new Object[] {"100+data+200", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "ff00"+ // :status:100 - "000100"+ // data, 1 byte - "01030000"+ // headers, length 3, section prefix - "d9" // :status:200 + {"100+data+200", IOException.class, parseHex( + "01040000", // headers, length 4, section prefix + "ff00", // :status:100 + "000100", // data, 1 byte + "01030000", // headers, length 3, section prefix + "d9" // :status:200 )}, - new Object[] {"200+data+200", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "01030000"+ // headers, length 3, section prefix - "d9" // :status:200 + {"200+data+200", IOException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "01030000", // headers, length 3, section prefix + "d9" // :status:200 )}, - new Object[] {"200+data+100", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "01040000"+ // headers, length 4, section prefix - "ff00" // :status:100 + {"200+data+100", IOException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "01040000", // headers, length 4, section prefix + "ff00" // :status:100 )}, - new Object[] {"200+data+trailers+data", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "01020000"+ // trailers, length 2, section prefix - "000100" // data, 1 byte + {"200+data+trailers+data", ProtocolException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "01020000", // trailers, length 2, section prefix + "000100" // data, 1 byte )}, - new Object[] {"200+trailers+data", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "01020000"+ // trailers, length 2, section prefix - "000100" // data, 1 byte + {"200+trailers+data", IOException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "01020000", // trailers, length 2, section prefix + "000100" // data, 1 byte )}, - new Object[] {"200+200", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "01030000"+ // headers, length 3, section prefix - "d9" // :status:200 + {"200+200", IOException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "01030000", // headers, length 3, section prefix + "d9" // :status:200 )}, - new Object[] {"200+100", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "01040000"+ // headers, length 4, section prefix - "ff00" // :status:100 + {"200+100", IOException.class, parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "01040000", // headers, length 4, section prefix + "ff00" // :status:100 )}, }; } - @DataProvider - public static Object[][] wellformedResponse() { + /// Well-formed responses that should be accepted by the client. + static Object[][] wellFormedResponses() { return new Object[][]{ - new Object[] {"100+200+data+reserved", HexFormat.of().parseHex( - "01040000"+ // headers, length 4, section prefix - "ff00"+ // :status:100 - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "210100" // reserved, 1 byte + {"100+200+data+reserved", parseHex( + "01040000", // headers, length 4, section prefix + "ff00", // :status:100 + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "210100" // reserved, 1 byte )}, - new Object[] {"200+data+reserved", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "210100" // reserved, 1 byte + {"200+data+reserved", parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "210100" // reserved, 1 byte )}, - new Object[] {"200+data", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100" // data, 1 byte + {"200+data", parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100" // data, 1 byte )}, - new Object[] {"200+user-agent+data", HexFormat.of().parseHex( - "011a0000"+ // headers, length 26, section prefix - "d9"+ // :status:200 - "5f5094ca3ee35a74a6b589418b5258132b1aa496ca8747"+ //user-agent - "000100" // data, 1 byte + {"200+user-agent+data", parseHex( + "011a0000", // headers, length 26, section prefix + "d9", // :status:200 + "5f5094ca3ee35a74a6b589418b5258132b1aa496ca8747", //user-agent + "000100" // data, 1 byte )}, - new Object[] {"200", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9" // :status:200 + {"200", parseHex( + "01030000", // headers, length 3, section prefix + "d9" // :status:200 )}, - new Object[] {"200+data+data", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "000100" // data, 1 byte + {"200+data+data", parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "000100" // data, 1 byte )}, - new Object[] {"200+data+trailers", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "000100"+ // data, 1 byte - "01020000" // trailers, length 2, section prefix + {"200+data+trailers", parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "000100", // data, 1 byte + "01020000" // trailers, length 2, section prefix )}, - new Object[] {"200+trailers", HexFormat.of().parseHex( - "01030000"+ // headers, length 3, section prefix - "d9"+ // :status:200 - "01020000" // trailers, length 2, section prefix + {"200+trailers", parseHex( + "01030000", // headers, length 3, section prefix + "d9", // :status:200 + "01020000" // trailers, length 2, section prefix )}, }; } - @BeforeClass - public void beforeClass() throws Exception { - sslContext = new SimpleSSLContext().get(); - if (sslContext == null) { - throw new AssertionError("Unexpected null sslContext"); + private static byte[] parseHex(String... strings) { + var buffer = new StringBuilder(); + for (String string : strings) { + buffer.append(string); } - server = QuicStandaloneServer.newBuilder() - .availableVersions(new QuicVersion[]{QuicVersion.QUIC_V1}) - .sslContext(sslContext) - .alpn("h3") + return HexFormat.of().parseHex(buffer.toString()); + } + + @ParameterizedTest + @MethodSource("wellFormedResponses") + void testWellFormedResponse(String desc, byte[] serverResponseBytes) throws Exception { + var connectionTerminated = configureServerResponse(serverResponseBytes); + try (var client = createClient()) { + final HttpResponse response = client.send(REQUEST, BodyHandlers.discarding()); + assertEquals(200, response.statusCode()); + assertFalse(connectionTerminated.getAsBoolean(), "Expected the connection to be open"); + } + } + + @ParameterizedTest + @MethodSource("malformedResponsesPreservingConnection") + void testMalformedResponsePreservingConnection( + String desc, + Class exceptionClass, + byte[] serverResponseBytes) { + var connectionTerminated = configureServerResponse(serverResponseBytes); + try (var client = createClient()) { + var exception = assertThrows(exceptionClass, () -> client.send(REQUEST, BodyHandlers.discarding())); + LOGGER.log("Got expected exception for: " + desc, exception); + assertFalse(connectionTerminated.getAsBoolean(), "Expected the connection to be open"); + } + } + + @ParameterizedTest + @MethodSource("malformedResponses") + void testMalformedResponse( + String desc, + Class exceptionClass, + byte[] serverResponseBytes) { + configureServerResponse(serverResponseBytes); + try (var client = createClient()) { + var exception = assertThrows(exceptionClass, () -> client.send(REQUEST, BodyHandlers.discarding())); + LOGGER.log("Got expected exception for: " + desc, exception); + } + } + + private static HttpClient createClient() { + return HttpServerAdapters.createClientBuilderForH3() + .proxy(NO_PROXY) + .version(Version.HTTP_3) + .sslContext(SSL_CONTEXT) .build(); - server.start(); - System.out.println("Server started at " + server.getAddress()); - requestURIBase = URIBuilder.newBuilder().scheme("https").loopback() - .port(server.getAddress().getPort()).build().toString(); } - @AfterClass - public void afterClass() throws Exception { - if (server != null) { - System.out.println("Stopping server " + server.getAddress()); - server.close(); - } - } - - /** - * Server sends a well-formed response - */ - @Test(dataProvider = "wellformedResponse") - public void testWellFormedResponse(String desc, byte[] response) throws Exception { - CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { + private static BooleanSupplier configureServerResponse(byte[] serverResponseBytes) { + var connectionTerminated = new AtomicBoolean(); + SERVER.addHandler((c, s)-> { try (OutputStream outputStream = s.outputStream()) { - outputStream.write(response); + outputStream.write(serverResponseBytes); } - // verify that the connection stays open - completeUponTermination(c, errorCF); + c.futureTerminationCause().handle((_, _) -> { + connectionTerminated.set(true); + return true; + }); }); - HttpClient client = getHttpClient(); - try { - HttpRequest request = getRequest(); - final HttpResponse response1 = client.send( - request, - BodyHandlers.discarding()); - assertEquals(response1.statusCode(), 200); - assertFalse(errorCF.isDone(), "Expected the connection to be open"); - } finally { - client.shutdownNow(); - } + return connectionTerminated::get; } - - /** - * Server sends a malformed response that should not close connection - */ - @Test(dataProvider = "malformedResponse") - public void testMalformedResponse(String desc, byte[] response) throws Exception { - CompletableFuture errorCF = new CompletableFuture<>(); - server.addHandler((c,s)-> { - try (OutputStream outputStream = s.outputStream()) { - outputStream.write(response); - } - // verify that the connection stays open - completeUponTermination(c, errorCF); - }); - HttpClient client = getHttpClient(); - try { - HttpRequest request = getRequest(); - final HttpResponse response1 = client.send( - request, - BodyHandlers.discarding()); - fail("Expected the request to fail, got " + response1); - } catch (Exception e) { - System.out.println("Got expected exception: " +e); - e.printStackTrace(); - assertFalse(errorCF.isDone(), "Expected the connection to be open"); - } finally { - client.shutdownNow(); - } - } - - /** - * Server sends a malformed response that might close connection - */ - @Test(dataProvider = "malformedResponse2") - public void testMalformedResponse2(String desc, byte[] response) throws Exception { - server.addHandler((c,s)-> { - try (OutputStream outputStream = s.outputStream()) { - outputStream.write(response); - } - }); - HttpClient client = getHttpClient(); - try { - HttpRequest request = getRequest(); - final HttpResponse response1 = client.send( - request, - BodyHandlers.discarding()); - fail("Expected the request to fail, got " + response1); - } catch (Exception e) { - System.out.println("Got expected exception: " +e); - e.printStackTrace(); - } finally { - client.shutdownNow(); - } - } - - private HttpRequest getRequest() throws URISyntaxException { - final URI reqURI = new URI(requestURIBase + "/hello"); - final HttpRequest.Builder reqBuilder = HttpRequest.newBuilder(reqURI) - .version(Version.HTTP_3) - .setOption(H3_DISCOVERY, HTTP_3_URI_ONLY); - return reqBuilder.build(); - } - - private HttpClient getHttpClient() { - final HttpClient client = newClientBuilderForH3() - .proxy(HttpClient.Builder.NO_PROXY) - .version(Version.HTTP_3) - .sslContext(sslContext).build(); - return client; - } - - private static String toHexString(final Http3Error error) { - return error.name() + "(0x" + Long.toHexString(error.code()) + ")"; - } - - private static void completeUponTermination(final QuicServerConnection serverConnection, - final CompletableFuture cf) { - serverConnection.futureTerminationCause().handle( - (r,t) -> t != null ? cf.completeExceptionally(t) : cf.complete(r)); - } } From 4e9525ef3619b02e905f16b89261b82c70830f3a Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Fri, 12 Dec 2025 18:57:25 +0000 Subject: [PATCH 078/211] 8373388: Reenable LTO for libsplashscreen Reviewed-by: erikj, dholmes, serb, prr --- make/modules/java.desktop/lib/ClientLibraries.gmk | 1 + 1 file changed, 1 insertion(+) diff --git a/make/modules/java.desktop/lib/ClientLibraries.gmk b/make/modules/java.desktop/lib/ClientLibraries.gmk index 499d5bef841..f273065a6df 100644 --- a/make/modules/java.desktop/lib/ClientLibraries.gmk +++ b/make/modules/java.desktop/lib/ClientLibraries.gmk @@ -226,6 +226,7 @@ ifeq ($(ENABLE_HEADLESS_ONLY), false) EXCLUDE_FILES := imageioJPEG.c jpegdecoder.c pngtest.c, \ EXCLUDES := $(LIBSPLASHSCREEN_EXCLUDES), \ OPTIMIZATION := SIZE, \ + LINK_TIME_OPTIMIZATION := true, \ CFLAGS := $(LIBSPLASHSCREEN_CFLAGS) \ $(GIFLIB_CFLAGS) $(LIBJPEG_CFLAGS) $(PNG_CFLAGS) $(LIBZ_CFLAGS) \ $(ICONV_CFLAGS), \ From f2e56e4c18080616e8ef275a3d9c1da824efda26 Mon Sep 17 00:00:00 2001 From: Vladimir Ivanov Date: Fri, 12 Dec 2025 21:12:09 +0000 Subject: [PATCH 079/211] 8372634: C2: Materialize type information from instanceof checks Reviewed-by: dlong, qamai, roland --- .../share/compiler/compilerDirectives.cpp | 14 + .../share/compiler/compilerDirectives.hpp | 1 + src/hotspot/share/compiler/compilerOracle.cpp | 4 + src/hotspot/share/compiler/compilerOracle.hpp | 4 + src/hotspot/share/compiler/methodMatcher.hpp | 1 + src/hotspot/share/opto/compile.hpp | 3 +- src/hotspot/share/opto/doCall.cpp | 2 +- src/hotspot/share/opto/parse2.cpp | 129 +++-- .../inlining/TestSubtypeCheckTypeInfo.java | 479 ++++++++++++++++++ .../klass/CastNullCheckDroppingsTest.java | 6 +- 10 files changed, 609 insertions(+), 34 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/inlining/TestSubtypeCheckTypeInfo.java diff --git a/src/hotspot/share/compiler/compilerDirectives.cpp b/src/hotspot/share/compiler/compilerDirectives.cpp index 5431b03f6a1..1cd8bd1b510 100644 --- a/src/hotspot/share/compiler/compilerDirectives.cpp +++ b/src/hotspot/share/compiler/compilerDirectives.cpp @@ -561,6 +561,20 @@ bool DirectiveSet::should_not_inline(ciMethod* inlinee) { return false; } +bool DirectiveSet::should_delay_inline(ciMethod* inlinee) { + inlinee->check_is_loaded(); + VM_ENTRY_MARK; + methodHandle mh(THREAD, inlinee->get_Method()); + + if (_inlinematchers != nullptr) { + return matches_inline(mh, InlineMatcher::delay_inline); + } + if (!CompilerDirectivesIgnoreCompileCommandsOption) { + return CompilerOracle::should_delay_inline(mh); + } + return false; +} + bool DirectiveSet::parse_and_add_inline(char* str, const char*& error_msg) { InlineMatcher* m = InlineMatcher::parse_inline_pattern(str, error_msg); if (m != nullptr) { diff --git a/src/hotspot/share/compiler/compilerDirectives.hpp b/src/hotspot/share/compiler/compilerDirectives.hpp index 27aafe06919..e4826b3056c 100644 --- a/src/hotspot/share/compiler/compilerDirectives.hpp +++ b/src/hotspot/share/compiler/compilerDirectives.hpp @@ -142,6 +142,7 @@ public: void append_inline(InlineMatcher* m); bool should_inline(ciMethod* inlinee); bool should_not_inline(ciMethod* inlinee); + bool should_delay_inline(ciMethod* inlinee); void print_inline(outputStream* st); DirectiveSet* compilecommand_compatibility_init(const methodHandle& method); bool is_exclusive_copy() { return _directive == nullptr; } diff --git a/src/hotspot/share/compiler/compilerOracle.cpp b/src/hotspot/share/compiler/compilerOracle.cpp index 23bb754f432..5bcd01a4d09 100644 --- a/src/hotspot/share/compiler/compilerOracle.cpp +++ b/src/hotspot/share/compiler/compilerOracle.cpp @@ -480,6 +480,10 @@ bool CompilerOracle::should_not_inline(const methodHandle& method) { return check_predicate(CompileCommandEnum::DontInline, method) || check_predicate(CompileCommandEnum::Exclude, method); } +bool CompilerOracle::should_delay_inline(const methodHandle& method) { + return (check_predicate(CompileCommandEnum::DelayInline, method)); +} + bool CompilerOracle::should_print(const methodHandle& method) { return check_predicate(CompileCommandEnum::Print, method); } diff --git a/src/hotspot/share/compiler/compilerOracle.hpp b/src/hotspot/share/compiler/compilerOracle.hpp index 09984705792..665f3b2fbfd 100644 --- a/src/hotspot/share/compiler/compilerOracle.hpp +++ b/src/hotspot/share/compiler/compilerOracle.hpp @@ -51,6 +51,7 @@ class methodHandle; option(Log, "log", Bool) \ option(Print, "print", Bool) \ option(Inline, "inline", Bool) \ + option(DelayInline, "delayinline", Bool) \ option(DontInline, "dontinline", Bool) \ option(Blackhole, "blackhole", Bool) \ option(CompileOnly, "compileonly", Bool)\ @@ -150,6 +151,9 @@ class CompilerOracle : AllStatic { // Tells whether we want to disallow inlining of this method static bool should_not_inline(const methodHandle& method); + // Tells whether we want to delay inlining of this method + static bool should_delay_inline(const methodHandle& method); + // Tells whether this method changes Thread.currentThread() static bool changes_current_thread(const methodHandle& method); diff --git a/src/hotspot/share/compiler/methodMatcher.hpp b/src/hotspot/share/compiler/methodMatcher.hpp index ba70747ad26..62945129e90 100644 --- a/src/hotspot/share/compiler/methodMatcher.hpp +++ b/src/hotspot/share/compiler/methodMatcher.hpp @@ -100,6 +100,7 @@ public: enum InlineType { unknown_inline, dont_inline, + delay_inline, force_inline }; diff --git a/src/hotspot/share/opto/compile.hpp b/src/hotspot/share/opto/compile.hpp index f5611062f2c..45a3a4f548f 100644 --- a/src/hotspot/share/opto/compile.hpp +++ b/src/hotspot/share/opto/compile.hpp @@ -984,7 +984,8 @@ public: JVMState* jvms, bool allow_inline, float profile_factor, ciKlass* speculative_receiver_type = nullptr, bool allow_intrinsics = true); bool should_delay_inlining(ciMethod* call_method, JVMState* jvms) { - return should_delay_string_inlining(call_method, jvms) || + return C->directive()->should_delay_inline(call_method) || + should_delay_string_inlining(call_method, jvms) || should_delay_boxing_inlining(call_method, jvms) || should_delay_vector_inlining(call_method, jvms); } diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index 5533b19897b..e4418631d17 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -192,7 +192,7 @@ CallGenerator* Compile::call_generator(ciMethod* callee, int vtable_index, bool // Try inlining a bytecoded method: if (!call_does_dispatch) { InlineTree* ilt = InlineTree::find_subtree_from_root(this->ilt(), jvms->caller(), jvms->method()); - bool should_delay = C->should_delay_inlining(); + bool should_delay = C->should_delay_inlining() || C->directive()->should_delay_inline(callee); if (ilt->ok_to_inline(callee, jvms, profile, should_delay)) { CallGenerator* cg = CallGenerator::for_inline(callee, expected_uses); // For optimized virtual calls assert at runtime that receiver object diff --git a/src/hotspot/share/opto/parse2.cpp b/src/hotspot/share/opto/parse2.cpp index cb8073144a5..eac2b3e863a 100644 --- a/src/hotspot/share/opto/parse2.cpp +++ b/src/hotspot/share/opto/parse2.cpp @@ -41,6 +41,7 @@ #include "opto/opaquenode.hpp" #include "opto/parse.hpp" #include "opto/runtime.hpp" +#include "opto/subtypenode.hpp" #include "runtime/deoptimization.hpp" #include "runtime/sharedRuntime.hpp" @@ -1719,38 +1720,108 @@ static Node* extract_obj_from_klass_load(PhaseGVN* gvn, Node* n) { return obj; } +// Matches exact and inexact type check IR shapes during parsing. +// On successful match, returns type checked object node and its type after successful check +// as out parameters. +static bool match_type_check(PhaseGVN& gvn, + BoolTest::mask btest, + Node* con, const Type* tcon, + Node* val, const Type* tval, + Node** obj, const TypeOopPtr** cast_type) { // out-parameters + // Look for opportunities to sharpen the type of a node whose klass is compared with a constant klass. + // The constant klass being tested against can come from many bytecode instructions (implicitly or explicitly), + // and also from profile data used by speculative casts. + if (btest == BoolTest::eq && tcon->isa_klassptr()) { + // Found: + // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) + // or the narrowOop equivalent. + (*obj) = extract_obj_from_klass_load(&gvn, val); + (*cast_type) = tcon->isa_klassptr()->as_instance_type(); + return true; // found + } + + // Match an instanceof check. + // During parsing its IR shape is not canonicalized yet. + // + // obj superklass + // | | + // SubTypeCheck + // | + // Bool [eq] / [ne] + // | + // If + // / \ + // T F + // \ / + // Region + // \ ConI ConI + // \ | / + // val -> Phi ConI <- con + // \ / + // CmpI + // | + // Bool [btest] + // | + // + if (tval->isa_int() && val->is_Phi() && val->in(0)->as_Region()->is_diamond()) { + RegionNode* diamond = val->in(0)->as_Region(); + IfNode* if1 = diamond->in(1)->in(0)->as_If(); + BoolNode* b1 = if1->in(1)->isa_Bool(); + if (b1 != nullptr && b1->in(1)->isa_SubTypeCheck()) { + assert(b1->_test._test == BoolTest::eq || + b1->_test._test == BoolTest::ne, "%d", b1->_test._test); + + ProjNode* success_proj = if1->proj_out(b1->_test._test == BoolTest::eq ? 1 : 0); + int idx = diamond->find_edge(success_proj); + assert(idx == 1 || idx == 2, ""); + Node* vcon = val->in(idx); + + assert(val->find_edge(con) > 0, ""); + if ((btest == BoolTest::eq && vcon == con) || (btest == BoolTest::ne && vcon != con)) { + SubTypeCheckNode* sub = b1->in(1)->as_SubTypeCheck(); + Node* obj_or_subklass = sub->in(SubTypeCheckNode::ObjOrSubKlass); + Node* superklass = sub->in(SubTypeCheckNode::SuperKlass); + + if (gvn.type(obj_or_subklass)->isa_oopptr()) { + const TypeKlassPtr* klass_ptr_type = gvn.type(superklass)->is_klassptr(); + const TypeKlassPtr* improved_klass_ptr_type = klass_ptr_type->try_improve(); + + (*obj) = obj_or_subklass; + (*cast_type) = improved_klass_ptr_type->cast_to_exactness(false)->as_instance_type(); + return true; // found + } + } + } + } + return false; // not found +} + void Parse::sharpen_type_after_if(BoolTest::mask btest, Node* con, const Type* tcon, Node* val, const Type* tval) { - // Look for opportunities to sharpen the type of a node - // whose klass is compared with a constant klass. - if (btest == BoolTest::eq && tcon->isa_klassptr()) { - Node* obj = extract_obj_from_klass_load(&_gvn, val); - const TypeOopPtr* con_type = tcon->isa_klassptr()->as_instance_type(); - if (obj != nullptr && (con_type->isa_instptr() || con_type->isa_aryptr())) { - // Found: - // Bool(CmpP(LoadKlass(obj._klass), ConP(Foo.klass)), [eq]) - // or the narrowOop equivalent. - const Type* obj_type = _gvn.type(obj); - const TypeOopPtr* tboth = obj_type->join_speculative(con_type)->isa_oopptr(); - if (tboth != nullptr && tboth->klass_is_exact() && tboth != obj_type && - tboth->higher_equal(obj_type)) { - // obj has to be of the exact type Foo if the CmpP succeeds. - int obj_in_map = map()->find_edge(obj); - JVMState* jvms = this->jvms(); - if (obj_in_map >= 0 && - (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { - TypeNode* ccast = new CheckCastPPNode(control(), obj, tboth); - const Type* tcc = ccast->as_Type()->type(); - assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); - // Delay transform() call to allow recovery of pre-cast value - // at the control merge. - _gvn.set_type_bottom(ccast); - record_for_igvn(ccast); - // Here's the payoff. - replace_in_map(obj, ccast); - } - } + Node* obj = nullptr; + const TypeOopPtr* cast_type = nullptr; + // Insert a cast node with a narrowed type after a successful type check. + if (match_type_check(_gvn, btest, con, tcon, val, tval, + &obj, &cast_type)) { + assert(obj != nullptr && cast_type != nullptr, "missing type check info"); + const Type* obj_type = _gvn.type(obj); + const TypeOopPtr* tboth = obj_type->join_speculative(cast_type)->isa_oopptr(); + if (tboth != nullptr && tboth != obj_type && tboth->higher_equal(obj_type)) { + int obj_in_map = map()->find_edge(obj); + JVMState* jvms = this->jvms(); + if (obj_in_map >= 0 && + (jvms->is_loc(obj_in_map) || jvms->is_stk(obj_in_map))) { + TypeNode* ccast = new CheckCastPPNode(control(), obj, tboth); + const Type* tcc = ccast->as_Type()->type(); + assert(tcc != obj_type && tcc->higher_equal(obj_type), "must improve"); + // Delay transform() call to allow recovery of pre-cast value + // at the control merge. + _gvn.set_type_bottom(ccast); + record_for_igvn(ccast); + // Here's the payoff. + replace_in_map(obj, ccast); + } } } diff --git a/test/hotspot/jtreg/compiler/inlining/TestSubtypeCheckTypeInfo.java b/test/hotspot/jtreg/compiler/inlining/TestSubtypeCheckTypeInfo.java new file mode 100644 index 00000000000..93767ca8416 --- /dev/null +++ b/test/hotspot/jtreg/compiler/inlining/TestSubtypeCheckTypeInfo.java @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2025, 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 + * @summary 8372634 + * + * @requires vm.flagless + * @library /test/lib / + * + * @run driver compiler.inlining.TestSubtypeCheckTypeInfo + */ +package compiler.inlining; + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TestSubtypeCheckTypeInfo { + static final Class THIS_CLASS = TestSubtypeCheckTypeInfo.class; + static final String TEST_CLASS_NAME = THIS_CLASS.getName(); + + public static void main(String[] args) throws Exception { + ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( + "-XX:+IgnoreUnrecognizedVMOptions", "-showversion", + "-XX:-TieredCompilation", "-Xbatch", "-XX:CICompilerCount=1", + "-XX:+PrintCompilation", "-XX:+UnlockDiagnosticVMOptions", "-XX:+PrintInlining", + "-XX:CompileCommand=quiet", + "-XX:CompileCommand=compileonly," + TEST_CLASS_NAME + "::test*", + "-XX:CompileCommand=delayinline," + TEST_CLASS_NAME + "::lateInline*", + TestSubtypeCheckTypeInfo.Launcher.class.getName()); + + OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); + + analyzer.shouldHaveExitValue(0); + + // The test is applicable only to C2 (present in Server VM). + if (analyzer.getStderr().contains("Server VM")) { + List output = analyzer.asLinesWithoutVMWarnings(); + + parseOutput(output); + System.out.println("TEST PASSED"); + } + } + + static class Launcher { + public static void main(String[] args) { + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOf); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfCondPre); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfCondPost); + + runTestCase(TestSubtypeCheckTypeInfo::testIsInstance); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceCondPre); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceCondPost); + + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfLate); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfLateCondPre); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfLateCondPost); + + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceLate); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceLateCondPre); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceLateCondPost); + + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfCondLate); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfCondLatePre); + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfCondLatePost); + + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceCondLate); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceCondLatePre); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceCondLatePost); + + runTestCase(TestSubtypeCheckTypeInfo::testInstanceOfNulls); + runTestCase(TestSubtypeCheckTypeInfo::testIsInstanceNulls); + } + } + + /* =========================================================== */ + + @InlineSuccess + // @ 8 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testInstanceOf(A o, boolean cond) { + if (o instanceof B) { + o.m(); + } + } + + @InlineSuccess + // @ 12 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testInstanceOfCondPre(A o, boolean cond) { + if (cond && (o instanceof B)) { + o.m(); + } + } + + @InlineSuccess + // @ 12 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testInstanceOfCondPost(A o, boolean cond) { + if ((o instanceof B) && cond) { + o.m(); + } + } + + /* =========================================================== */ + + @InlineSuccess + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 3 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 10 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testIsInstance(A o, boolean cond) { + if (B.class.isInstance(o)) { + o.m(); + } + } + + @InlineSuccess + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 7 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 14 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testIsInstanceCondPre(A o, boolean cond) { + if (cond && B.class.isInstance(o)) { + o.m(); + } + } + + @InlineSuccess + // @ 3 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 14 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testIsInstanceCondPost(A o, boolean cond) { + if (B.class.isInstance(o) && cond) { + o.m(); + } + } + + /* =========================================================== */ + + @InlineSuccess + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testInstanceOfLate(A o, boolean cond) { + // if (o instanceof B) { o.m(); } + lateInline(o, o instanceof B); + } + + @InlineFailure + // @ 17 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfLateCondPre(A o, boolean cond) { + // if (cond && o instanceof B) { o.m(); } + lateInline(o, cond && (o instanceof B)); + } + + @InlineFailure + // @ 17 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfLateCondPost(A o, boolean cond) { + // if ((o instanceof B) && cond) { o.m(); } + lateInline(o, (o instanceof B) && cond); + } + + /* =========================================================== */ + + @InlineSuccess + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 4 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 7 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$B::m (1 bytes) inline (hot) + static void testIsInstanceLate(A o, boolean cond) { + // if (B.class.isInstance(o)) { o.m(); } + lateInline(o, B.class.isInstance(o)); + } + + @InlineFailure + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 8 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 19 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceLateCondPre(A o, boolean cond) { + // if (cond && B.class.isInstance(o)) { o.m(); } + lateInline(o, cond && (B.class.isInstance(o))); + } + + @InlineFailure + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 4 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 19 compiler.inlining.TestSubtypeCheckTypeInfo::lateInline (9 bytes) inline (hot) late inline succeeded + // @ 5 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceLateCondPost(A o, boolean cond) { + // if (B.class.isInstance(o) && cond) { o.m(); } + lateInline(o, (B.class.isInstance(o) && cond)); + } + + /* =========================================================== */ + + @InlineFailure + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineInstanceOfCondPre (17 bytes) inline (hot) late inline succeeded + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfCondLate(A a, boolean cond) { + if (lateInlineInstanceOfCondPre(a, true)) { + a.m(); + } + } + + @InlineFailure + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineInstanceOfCondPre (17 bytes) inline (hot) late inline succeeded + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfCondLatePre(A a, boolean cond) { + if (lateInlineInstanceOfCondPre(a, cond)) { + a.m(); + } + } + + @InlineFailure + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineInstanceOfCondPost (17 bytes) inline (hot) late inline succeeded + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfCondLatePost(A a, boolean cond) { + if (lateInlineInstanceOfCondPost(a, cond)) { + a.m(); + } + } + + /* =========================================================== */ + + @InlineFailure + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineIsInstanceCondPre (19 bytes) inline (hot) late inline succeeded + // @ 7 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceCondLate(A a, boolean cond) { + if (lateInlineIsInstanceCondPre(a, true)) { + a.m(); + } + } + + @InlineFailure + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineIsInstanceCondPre (19 bytes) inline (hot) late inline succeeded + // @ 7 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceCondLatePre(A a, boolean cond) { + if (lateInlineIsInstanceCondPre(a, cond)) { + a.m(); + } + } + + @InlineFailure + // Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 2 compiler.inlining.TestSubtypeCheckTypeInfo::lateInlineIsInstanceCondPost (19 bytes) inline (hot) late inline succeeded + // @ 3 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 9 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceCondLatePost(A a, boolean cond) { + if (lateInlineIsInstanceCondPost(a, cond)) { + a.m(); + } + } + + /* =========================================================== */ + + @InlineFailure + // @ 20 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testInstanceOfNulls(A o, boolean cond) { + A recv = (cond ? o : null); + if (recv instanceof B) { + o.m(); + } + } + + @InlineFailure + //Inlining _isInstance on constant Class compiler/inlining/TestSubtypeCheckTypeInfo$B + // @ 13 java.lang.Class::isInstance (0 bytes) (intrinsic) + // @ 20 compiler.inlining.TestSubtypeCheckTypeInfo$A::m (0 bytes) failed to inline: virtual call + static void testIsInstanceNulls(A o, boolean cond) { + A recv = (cond ? o : null); + if (B.class.isInstance(recv)) { + o.m(); + } + } + + /* =========================================================== */ + + static abstract class A { + public abstract void m(); + } + static abstract class B extends A { + public void m() {} + } + + static class C extends A { + public void m() {} + } + + static void lateInline(A o, boolean cond) { + if (cond) { + o.m(); + } + } + + static boolean lateInlineInstanceOfCondPre(A o, boolean cond) { + return cond && (o instanceof B); + } + + static boolean lateInlineInstanceOfCondPost(A o, boolean cond) { + return (o instanceof B) && cond; + } + + static boolean lateInlineIsInstanceCondPre(A o, boolean cond) { + return cond && B.class.isInstance(o); + } + static boolean lateInlineIsInstanceCondPost(A o, boolean cond) { + return B.class.isInstance(o) && cond; + } + + /* =========================================================== */ + + static final String INLINE_SUCCESS_MESSAGE = "B::m (1 bytes) inline (hot)"; + static final String INLINE_FAILURE_MESSAGE = "A::m (0 bytes) failed to inline: virtual call"; + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface InlineSuccess { + String[] shouldContain() default INLINE_SUCCESS_MESSAGE; + String[] shouldNotContain() default INLINE_FAILURE_MESSAGE; + } + + @Retention(RetentionPolicy.RUNTIME) + @Target(ElementType.METHOD) + public @interface InlineFailure { + String[] shouldContain() default INLINE_FAILURE_MESSAGE; + String[] shouldNotContain() default INLINE_SUCCESS_MESSAGE; + } + + /* =========================================================== */ + + // Parse compilation log (-XX:+PrintCompilation -XX:+PrintInlining output). + static void parseOutput(List output) { + Pattern compilation = Pattern.compile("^\\d+\\s+\\d+.*"); + StringBuilder inlineTree = new StringBuilder(); + Set passedTests = new HashSet(); + Set failedTests = new HashSet(); + for (String line : output) { + // Detect start of next compilation. + if (compilation.matcher(line).matches()) { + // Parse output for previous compilation. + validateInliningOutput(inlineTree.toString(), passedTests, failedTests); + inlineTree = new StringBuilder(); // reset + } + inlineTree.append(line); + } + // Process last compilation + validateInliningOutput(inlineTree.toString(), passedTests, failedTests); + + if (!failedTests.isEmpty()) { + String msg = String.format("TEST FAILED: %d test cases failed", failedTests.size()); + throw new AssertionError(msg); + } else if (passedTests.size() != totalTestCount()) { + String msg = String.format("TEST FAILED: %d out of %d test cases passed", passedTests.size(), totalTestCount()); + throw new AssertionError(msg); + } + } + + // Sample: + // 213 42 b compiler.inlining.TestSubtypeCheckTypeInfo::testIsInstanceCondLatePost (13 bytes) + static final Pattern TEST_CASE = Pattern.compile("^\\d+\\s+\\d+\\s+b\\s+" + TEST_CLASS_NAME + "::(\\w+) .*"); + + static boolean validateInliningOutput(String inlineTree, Set passedTests, Set failedTests) { + Matcher m = TEST_CASE.matcher(inlineTree); + if (m.matches()) { + String testName = m.group(1); + System.out.print(testName); + try { + Method testMethod = TestSubtypeCheckTypeInfo.class.getDeclaredMethod(testName, A.class, boolean.class); + if (validate(inlineTree, testMethod.getAnnotation(InlineSuccess.class)) && + validate(inlineTree, testMethod.getAnnotation(InlineFailure.class))) { + System.out.println(": SUCCESS"); + passedTests.add(testName); + return true; + } else { + failedTests.add(testName); + return false; + } + } catch (NoSuchMethodException e) { + System.out.println(": FAILURE: Missing test info for " + testName + ": " + inlineTree); + throw new InternalError(e); + } + } else { + return false; // not a test method; ignored + } + } + + static boolean validate(String message, InlineSuccess ann) { + if (ann != null) { + return validatePatterns(message, ann.shouldContain(), ann.shouldNotContain()); + } + return true; // no patterns to validate + } + + static boolean validate(String message, InlineFailure ann) { + if (ann != null) { + return validatePatterns(message, ann.shouldContain(), ann.shouldNotContain()); + } + return true; // no patterns to validate + } + + static boolean validatePatterns(String message, String[] shouldContain, String[] shouldNotContain) { + for (String pattern : shouldContain) { + if (!message.contains(pattern)) { + System.out.printf(": FAILURE: '%s' not found in '%s'\n", pattern, message); + return false; + } + } + for (String pattern : shouldNotContain) { + if (message.contains(pattern)) { + System.out.printf(": FAILURE: '%s' found in '%s'\n", pattern, message); + return false; + } + } + return true; + } + + static int totalTestCount() { + int count = 0; + for (Method m : THIS_CLASS.getDeclaredMethods()) { + if (m.isAnnotationPresent(InlineSuccess.class) || m.isAnnotationPresent(InlineFailure.class)) { + String testName = m.getName(); + if (testName.startsWith("test")) { + count++; + } else { + throw new InternalError("wrong test name: " + testName); + } + } + } + return count; + } + + /* =========================================================== */ + + interface TestCase { + void run(A o, boolean cond); + } + + static void runTestCase(TestCase t) { + A[] receivers = new A[] { new B() {}, new B() {}, new B() {}, new C() {}, new C() {}}; + for (int i = 0; i < 20_000; i++) { + // Pollute type profile and branch frequencies. + A recv = receivers[i % receivers.length]; + boolean cond = (i % 2 == 0); + t.run(recv, cond); + } + } +} diff --git a/test/hotspot/jtreg/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java b/test/hotspot/jtreg/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java index 2d2bf14d76f..17a4034350f 100644 --- a/test/hotspot/jtreg/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java +++ b/test/hotspot/jtreg/compiler/intrinsics/klass/CastNullCheckDroppingsTest.java @@ -132,13 +132,13 @@ public class CastNullCheckDroppingsTest { t.runTest(methodClassCastNull, false, svalue); t.runTest(methodNullClassCast, false, svalue); t.runTest(methodClassCastObj, false, svalue); - t.runTest(methodObjClassCast, false, svalue); + t.runTest(methodObjClassCast, false, svalue); t.runTest(methodClassCastInt, false, svalue); - t.runTest(methodIntClassCast, true, svalue); + t.runTest(methodIntClassCast, false, svalue); t.runTest(methodClassCastint, false, svalue); t.runTest(methodintClassCast, false, svalue); t.runTest(methodClassCastPrim, false, svalue); - t.runTest(methodPrimClassCast, true, svalue); + t.runTest(methodPrimClassCast, false, svalue); t.runTest(methodVarClassCast, true, objClass); } From 23c39757ecdc834c631f98f4487cfea21c9b948b Mon Sep 17 00:00:00 2001 From: Man Cao Date: Fri, 12 Dec 2025 21:19:09 +0000 Subject: [PATCH 080/211] 8373403: [TESTBUG] TestG1ClassUnloadingHWM.java could fail with large G1HeapRegionSize and small InitialHeapSize Reviewed-by: tschatzl, iwalulya --- .../class_unloading/TestG1ClassUnloadingHWM.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java index 59289f10c37..7faae885f70 100644 --- a/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java +++ b/test/hotspot/jtreg/gc/class_unloading/TestG1ClassUnloadingHWM.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -68,19 +68,21 @@ public class TestG1ClassUnloadingHWM { } public static void testWithoutG1ClassUnloading() throws Exception { - // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC instead of a concurrent cycle. + // -XX:-ClassUnloadingWithConcurrentMark is used, so we expect a full GC due to Metadata GC Threshold + // instead of a concurrent cycle. OutputAnalyzer out = runWithoutG1ClassUnloading(); - out.shouldMatch(".*Pause Full.*"); - out.shouldNotMatch(".*Pause Young \\(Concurrent Start\\).*"); + out.shouldMatch(".*Pause Full \\(Metadata GC Threshold\\).*"); + out.shouldNotMatch(".*Pause Young \\(Concurrent Start\\) \\(Metadata GC Threshold\\).*"); } public static void testWithG1ClassUnloading() throws Exception { - // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle instead of a full GC. + // -XX:+ClassUnloadingWithConcurrentMark is used, so we expect a concurrent cycle due to Metadata GC Threshold + // instead of a full GC. OutputAnalyzer out = runWithG1ClassUnloading(); - out.shouldMatch(".*Pause Young \\(Concurrent Start\\).*"); - out.shouldNotMatch(".*Pause Full.*"); + out.shouldMatch(".*Pause Young \\(Concurrent Start\\) \\(Metadata GC Threshold\\).*"); + out.shouldNotMatch(".*Pause Full \\(Metadata GC Threshold\\).*"); } public static void main(String args[]) throws Exception { From d05486520036a4a6b3e3eee46a18f5b0e1ef493e Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Sat, 13 Dec 2025 01:35:24 +0000 Subject: [PATCH 081/211] 8371975: Apply java.io.Serial annotations in java.security.sasl Reviewed-by: mullan --- .../share/classes/com/sun/security/sasl/Provider.java | 4 +++- .../classes/javax/security/sasl/AuthenticationException.java | 5 ++++- .../share/classes/javax/security/sasl/AuthorizeCallback.java | 5 ++++- .../share/classes/javax/security/sasl/RealmCallback.java | 5 ++++- .../classes/javax/security/sasl/RealmChoiceCallback.java | 5 ++++- .../share/classes/javax/security/sasl/SaslException.java | 4 +++- 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java b/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java index c3d4cdcc54b..6a6c1bb3ce3 100644 --- a/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java +++ b/src/java.security.sasl/share/classes/com/sun/security/sasl/Provider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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,6 +24,7 @@ */ package com.sun.security.sasl; +import java.io.Serial; import java.security.NoSuchAlgorithmException; import java.security.InvalidParameterException; import java.security.ProviderException; @@ -45,6 +46,7 @@ import static sun.security.util.SecurityConstants.PROVIDER_VER; public final class Provider extends java.security.Provider { + @Serial private static final long serialVersionUID = 8622598936488630849L; private static final String info = "Sun SASL provider" + diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/AuthenticationException.java b/src/java.security.sasl/share/classes/javax/security/sasl/AuthenticationException.java index b61981bc16f..c9c3a274c44 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/AuthenticationException.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/AuthenticationException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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,8 @@ package javax.security.sasl; +import java.io.Serial; + /** * This exception is thrown by a SASL mechanism implementation * to indicate that the SASL @@ -79,5 +81,6 @@ public class AuthenticationException extends SaslException { } /** Use serialVersionUID from JSR 28 RI for interoperability */ + @Serial private static final long serialVersionUID = -3579708765071815007L; } diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/AuthorizeCallback.java b/src/java.security.sasl/share/classes/javax/security/sasl/AuthorizeCallback.java index e0f323d36c9..a254159229b 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/AuthorizeCallback.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/AuthorizeCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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,8 @@ package javax.security.sasl; +import java.io.Serial; + import javax.security.auth.callback.Callback; /** @@ -141,5 +143,6 @@ public class AuthorizeCallback implements Callback, java.io.Serializable { authorizedID = id; } + @Serial private static final long serialVersionUID = -2353344186490470805L; } diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/RealmCallback.java b/src/java.security.sasl/share/classes/javax/security/sasl/RealmCallback.java index af14158aa77..4d87b4da9d9 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/RealmCallback.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/RealmCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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,8 @@ package javax.security.sasl; +import java.io.Serial; + import javax.security.auth.callback.TextInputCallback; /** @@ -63,5 +65,6 @@ public class RealmCallback extends TextInputCallback { super(prompt, defaultRealmInfo); } + @Serial private static final long serialVersionUID = -4342673378785456908L; } diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/RealmChoiceCallback.java b/src/java.security.sasl/share/classes/javax/security/sasl/RealmChoiceCallback.java index 61d9c0edd35..6a782268fb6 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/RealmChoiceCallback.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/RealmChoiceCallback.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2025, 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,8 @@ package javax.security.sasl; +import java.io.Serial; + import javax.security.auth.callback.ChoiceCallback; /** @@ -58,5 +60,6 @@ public class RealmChoiceCallback extends ChoiceCallback { super(prompt, choices, defaultChoice, multiple); } + @Serial private static final long serialVersionUID = -8588141348846281332L; } diff --git a/src/java.security.sasl/share/classes/javax/security/sasl/SaslException.java b/src/java.security.sasl/share/classes/javax/security/sasl/SaslException.java index 0398d8d7277..4d07eb18d36 100644 --- a/src/java.security.sasl/share/classes/javax/security/sasl/SaslException.java +++ b/src/java.security.sasl/share/classes/javax/security/sasl/SaslException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -26,6 +26,7 @@ package javax.security.sasl; import java.io.IOException; +import java.io.Serial; /** * This class represents an error that has occurred when using SASL. @@ -125,5 +126,6 @@ public class SaslException extends IOException { } /** Use serialVersionUID from JSR 28 RI for interoperability */ + @Serial private static final long serialVersionUID = 4579784287983423626L; } From 17744fbfc004dfed5a3e959cd9ac7e7081b5be7a Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Sat, 13 Dec 2025 02:53:57 +0000 Subject: [PATCH 082/211] 8373628: jpackage doesn't print to console until completetion Reviewed-by: almatvee --- .../jdk/jpackage/internal/cli/Main.java | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java index f377b22374d..af51bc9fd98 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java @@ -31,6 +31,7 @@ import static jdk.jpackage.internal.cli.StandardOption.VERSION; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.PrintStream; import java.io.PrintWriter; import java.io.UncheckedIOException; import java.nio.file.NoSuchFileException; @@ -65,6 +66,21 @@ public final class Main { public int run(PrintWriter out, PrintWriter err, String... args) { return Main.run(out, err, args); } + + @Override + public int run(PrintStream out, PrintStream err, String... args) { + PrintWriter outWriter = new PrintWriter(out, true); + PrintWriter errWriter = new PrintWriter(err, true); + try { + try { + return run(outWriter, errWriter, args); + } finally { + outWriter.flush(); + } + } finally { + errWriter.flush(); + } + } } @@ -78,6 +94,10 @@ public final class Main { } public static int run(PrintWriter out, PrintWriter err, String... args) { + Objects.requireNonNull(args); + for (String arg : args) { + Objects.requireNonNull(arg); + } Objects.requireNonNull(out); Objects.requireNonNull(err); From 4f1dcf89b841e9a37d342bdf8c66bbbab9edb0d4 Mon Sep 17 00:00:00 2001 From: Mohamed Issa Date: Sat, 13 Dec 2025 03:16:46 +0000 Subject: [PATCH 083/211] 8368977: Provide clear naming for AVX10 identifiers Reviewed-by: jbhateja, mhaessig, vlivanov --- src/hotspot/cpu/x86/assembler_x86.hpp | 4 +- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 12 +-- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 8 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 16 ++-- src/hotspot/cpu/x86/x86.ad | 86 +++++++++---------- .../floatingpoint/ScalarFPtoIntCastTest.java | 16 ++-- .../compiler/lib/ir_framework/IRNode.java | 24 +++--- .../vectorapi/VectorFPtoIntCastTest.java | 16 ++-- .../runner/ArrayTypeConvertTest.java | 16 ++-- 9 files changed, 99 insertions(+), 99 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 43471a88391..26c57fc2d80 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -449,8 +449,8 @@ const int FPUStateSizeInWords = 2688 / wordSize; // imm8[1:0] = 00 (min) / 01 (max) // // [1] https://www.intel.com/content/www/us/en/content-details/856721/intel-advanced-vector-extensions-10-2-intel-avx10-2-architecture-specification.html?wapkw=AVX10 -const int AVX10_MINMAX_MAX_COMPARE_SIGN = 0x5; -const int AVX10_MINMAX_MIN_COMPARE_SIGN = 0x4; +const int AVX10_2_MINMAX_MAX_COMPARE_SIGN = 0x5; +const int AVX10_2_MINMAX_MIN_COMPARE_SIGN = 0x4; // The Intel x86/Amd64 Assembler: Pure assembler doing NO optimizations on the instruction // level (e.g. mov rax, 0 is not translated into xor rax, rax!); i.e., what you write diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 3de7f473fea..e1a64cb5c2e 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -1033,8 +1033,8 @@ void C2_MacroAssembler::vminmax_fp(int opc, BasicType elem_bt, XMMRegister dst, assert(opc == Op_MinV || opc == Op_MinReductionV || opc == Op_MaxV || opc == Op_MaxReductionV, "sanity"); - int imm8 = (opc == Op_MinV || opc == Op_MinReductionV) ? AVX10_MINMAX_MIN_COMPARE_SIGN - : AVX10_MINMAX_MAX_COMPARE_SIGN; + int imm8 = (opc == Op_MinV || opc == Op_MinReductionV) ? AVX10_2_MINMAX_MIN_COMPARE_SIGN + : AVX10_2_MINMAX_MAX_COMPARE_SIGN; if (elem_bt == T_FLOAT) { evminmaxps(dst, mask, src1, src2, true, imm8, vlen_enc); } else { @@ -5163,7 +5163,7 @@ void C2_MacroAssembler::vector_castD2X_evex(BasicType to_elem_bt, XMMRegister ds } } -void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { +void C2_MacroAssembler::vector_castF2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { switch(to_elem_bt) { case T_LONG: evcvttps2qqs(dst, src, vec_enc); @@ -5183,7 +5183,7 @@ void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister d } } -void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { +void C2_MacroAssembler::vector_castF2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { switch(to_elem_bt) { case T_LONG: evcvttps2qqs(dst, src, vec_enc); @@ -5203,7 +5203,7 @@ void C2_MacroAssembler::vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister d } } -void C2_MacroAssembler::vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { +void C2_MacroAssembler::vector_castD2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc) { switch(to_elem_bt) { case T_LONG: evcvttpd2qqs(dst, src, vec_enc); @@ -5223,7 +5223,7 @@ void C2_MacroAssembler::vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister d } } -void C2_MacroAssembler::vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { +void C2_MacroAssembler::vector_castD2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc) { switch(to_elem_bt) { case T_LONG: evcvttpd2qqs(dst, src, vec_enc); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index cd5f0ceb900..6d8b0ceaebe 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -347,13 +347,13 @@ public: XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, XMMRegister xtmp5, AddressLiteral float_sign_flip, Register rscratch, int vec_enc); - void vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); + void vector_castF2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); - void vector_castF2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); + void vector_castF2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); - void vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); + void vector_castD2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vec_enc); - void vector_castD2X_avx10(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); + void vector_castD2X_avx10_2(BasicType to_elem_bt, XMMRegister dst, Address src, int vec_enc); void vector_cast_double_to_int_special_cases_avx(XMMRegister dst, XMMRegister src, XMMRegister xtmp1, XMMRegister xtmp2, XMMRegister xtmp3, XMMRegister xtmp4, XMMRegister xtmp5, Register rscratch, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 44f1a35d443..48928b0db3f 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -8899,9 +8899,9 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM case T_LONG: evpminsq(dst, mask, nds, src, merge, vector_len); break; case T_FLOAT: - evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vector_len); break; case T_DOUBLE: - evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + evminmaxpd(dst, mask, nds, src, merge, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -8918,9 +8918,9 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM case T_LONG: evpmaxsq(dst, mask, nds, src, merge, vector_len); break; case T_FLOAT: - evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; case T_DOUBLE: - evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + evminmaxpd(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -8937,9 +8937,9 @@ void MacroAssembler::evpmins(BasicType type, XMMRegister dst, KRegister mask, XM case T_LONG: evpminsq(dst, mask, nds, src, merge, vector_len); break; case T_FLOAT: - evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vector_len); break; case T_DOUBLE: - evminmaxpd(dst, mask, nds, src, merge, AVX10_MINMAX_MIN_COMPARE_SIGN, vector_len); break; + evminmaxpd(dst, mask, nds, src, merge, AVX10_2_MINMAX_MIN_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } @@ -8956,9 +8956,9 @@ void MacroAssembler::evpmaxs(BasicType type, XMMRegister dst, KRegister mask, XM case T_LONG: evpmaxsq(dst, mask, nds, src, merge, vector_len); break; case T_FLOAT: - evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; case T_DOUBLE: - evminmaxps(dst, mask, nds, src, merge, AVX10_MINMAX_MAX_COMPARE_SIGN, vector_len); break; + evminmaxps(dst, mask, nds, src, merge, AVX10_2_MINMAX_MAX_COMPARE_SIGN, vector_len); break; default: fatal("Unexpected type argument %s", type2name(type)); break; } diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 42d2e815e45..5958db5d1eb 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -7289,12 +7289,12 @@ instruct loadD(regD dst, memory mem) %} // max = java.lang.Math.max(float a, float b) -instruct maxF_avx10_reg(regF dst, regF a, regF b) %{ +instruct maxF_reg_avx10_2(regF dst, regF a, regF b) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MaxF a b)); format %{ "maxF $dst, $a, $b" %} ins_encode %{ - __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN); + __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MAX_COMPARE_SIGN); %} ins_pipe( pipe_slow ); %} @@ -7325,12 +7325,12 @@ instruct maxF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRe %} // max = java.lang.Math.max(double a, double b) -instruct maxD_avx10_reg(regD dst, regD a, regD b) %{ +instruct maxD_reg_avx10_2(regD dst, regD a, regD b) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MaxD a b)); format %{ "maxD $dst, $a, $b" %} ins_encode %{ - __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MAX_COMPARE_SIGN); + __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MAX_COMPARE_SIGN); %} ins_pipe( pipe_slow ); %} @@ -7361,12 +7361,12 @@ instruct maxD_reduction_reg(legRegD dst, legRegD a, legRegD b, legRegD xtmp, rRe %} // max = java.lang.Math.min(float a, float b) -instruct minF_avx10_reg(regF dst, regF a, regF b) %{ +instruct minF_reg_avx10_2(regF dst, regF a, regF b) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MinF a b)); format %{ "minF $dst, $a, $b" %} ins_encode %{ - __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN); + __ eminmaxss($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MIN_COMPARE_SIGN); %} ins_pipe( pipe_slow ); %} @@ -7397,12 +7397,12 @@ instruct minF_reduction_reg(legRegF dst, legRegF a, legRegF b, legRegF xtmp, rRe %} // max = java.lang.Math.min(double a, double b) -instruct minD_avx10_reg(regD dst, regD a, regD b) %{ +instruct minD_reg_avx10_2(regD dst, regD a, regD b) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MinD a b)); format %{ "minD $dst, $a, $b" %} ins_encode %{ - __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_MINMAX_MIN_COMPARE_SIGN); + __ eminmaxsd($dst$$XMMRegister, $a$$XMMRegister, $b$$XMMRegister, AVX10_2_MINMAX_MIN_COMPARE_SIGN); %} ins_pipe( pipe_slow ); %} @@ -14586,7 +14586,7 @@ instruct convF2I_reg_reg(rRegI dst, regF src, rFlagsReg cr) ins_pipe(pipe_slow); %} -instruct convF2I_reg_reg_avx10(rRegI dst, regF src) +instruct convF2I_reg_reg_avx10_2(rRegI dst, regF src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvF2I src)); @@ -14597,7 +14597,7 @@ instruct convF2I_reg_reg_avx10(rRegI dst, regF src) ins_pipe(pipe_slow); %} -instruct convF2I_reg_mem_avx10(rRegI dst, memory src) +instruct convF2I_reg_mem_avx10_2(rRegI dst, memory src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvF2I (LoadF src))); @@ -14620,7 +14620,7 @@ instruct convF2L_reg_reg(rRegL dst, regF src, rFlagsReg cr) ins_pipe(pipe_slow); %} -instruct convF2L_reg_reg_avx10(rRegL dst, regF src) +instruct convF2L_reg_reg_avx10_2(rRegL dst, regF src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvF2L src)); @@ -14631,7 +14631,7 @@ instruct convF2L_reg_reg_avx10(rRegL dst, regF src) ins_pipe(pipe_slow); %} -instruct convF2L_reg_mem_avx10(rRegL dst, memory src) +instruct convF2L_reg_mem_avx10_2(rRegL dst, memory src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvF2L (LoadF src))); @@ -14654,7 +14654,7 @@ instruct convD2I_reg_reg(rRegI dst, regD src, rFlagsReg cr) ins_pipe(pipe_slow); %} -instruct convD2I_reg_reg_avx10(rRegI dst, regD src) +instruct convD2I_reg_reg_avx10_2(rRegI dst, regD src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvD2I src)); @@ -14665,7 +14665,7 @@ instruct convD2I_reg_reg_avx10(rRegI dst, regD src) ins_pipe(pipe_slow); %} -instruct convD2I_reg_mem_avx10(rRegI dst, memory src) +instruct convD2I_reg_mem_avx10_2(rRegI dst, memory src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvD2I (LoadD src))); @@ -14688,7 +14688,7 @@ instruct convD2L_reg_reg(rRegL dst, regD src, rFlagsReg cr) ins_pipe(pipe_slow); %} -instruct convD2L_reg_reg_avx10(rRegL dst, regD src) +instruct convD2L_reg_reg_avx10_2(rRegL dst, regD src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvD2L src)); @@ -14699,7 +14699,7 @@ instruct convD2L_reg_reg_avx10(rRegL dst, regD src) ins_pipe(pipe_slow); %} -instruct convD2L_reg_mem_avx10(rRegL dst, memory src) +instruct convD2L_reg_mem_avx10_2(rRegL dst, memory src) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (ConvD2L (LoadD src))); @@ -19660,7 +19660,7 @@ instruct minmax_reductionF_av(legRegF dst, legVec src, legVec tmp, legVec atmp, ins_pipe( pipe_slow ); %} -instruct minmax_reduction2F_avx10(regF dst, immF src1, vec src2, vec xtmp1) %{ +instruct minmax_reduction2F_avx10_2(regF dst, immF src1, vec src2, vec xtmp1) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && @@ -19678,7 +19678,7 @@ instruct minmax_reduction2F_avx10(regF dst, immF src1, vec src2, vec xtmp1) %{ ins_pipe( pipe_slow ); %} -instruct minmax_reductionF_avx10(regF dst, immF src1, vec src2, vec xtmp1, vec xtmp2) %{ +instruct minmax_reductionF_avx10_2(regF dst, immF src1, vec src2, vec xtmp1, vec xtmp2) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeF::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeF::NEG_INF)) && @@ -19696,7 +19696,7 @@ instruct minmax_reductionF_avx10(regF dst, immF src1, vec src2, vec xtmp1, vec x ins_pipe( pipe_slow ); %} -instruct minmax_reduction2F_avx10_av(regF dst, vec src, vec xtmp1) %{ +instruct minmax_reduction2F_av_avx10_2(regF dst, vec src, vec xtmp1) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && Matcher::vector_length(n->in(2)) == 2); match(Set dst (MinReductionV dst src)); @@ -19712,7 +19712,7 @@ instruct minmax_reduction2F_avx10_av(regF dst, vec src, vec xtmp1) %{ ins_pipe( pipe_slow ); %} -instruct minmax_reductionF_avx10_av(regF dst, vec src, vec xtmp1, vec xtmp2) %{ +instruct minmax_reductionF_av_avx10_2(regF dst, vec src, vec xtmp1, vec xtmp2) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_FLOAT && Matcher::vector_length(n->in(2)) >= 4); match(Set dst (MinReductionV dst src)); @@ -19810,7 +19810,7 @@ instruct minmax_reductionD_av(legRegD dst, legVec src, legVec tmp1, legVec tmp2, ins_pipe( pipe_slow ); %} -instruct minmax_reduction2D_avx10(regD dst, immD src1, vec src2, vec xtmp1) %{ +instruct minmax_reduction2D_avx10_2(regD dst, immD src1, vec src2, vec xtmp1) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && @@ -19828,7 +19828,7 @@ instruct minmax_reduction2D_avx10(regD dst, immD src1, vec src2, vec xtmp1) %{ ins_pipe( pipe_slow ); %} -instruct minmax_reductionD_avx10(regD dst, immD src1, vec src2, vec xtmp1, vec xtmp2) %{ +instruct minmax_reductionD_avx10_2(regD dst, immD src1, vec src2, vec xtmp1, vec xtmp2) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && ((n->Opcode() == Op_MinReductionV && n->in(1)->bottom_type() == TypeD::POS_INF) || (n->Opcode() == Op_MaxReductionV && n->in(1)->bottom_type() == TypeD::NEG_INF)) && @@ -19847,7 +19847,7 @@ instruct minmax_reductionD_avx10(regD dst, immD src1, vec src2, vec xtmp1, vec x %} -instruct minmax_reduction2D_av_avx10(regD dst, vec src, vec xtmp1) %{ +instruct minmax_reduction2D_av_avx10_2(regD dst, vec src, vec xtmp1) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && Matcher::vector_length(n->in(2)) == 2); match(Set dst (MinReductionV dst src)); @@ -19863,7 +19863,7 @@ instruct minmax_reduction2D_av_avx10(regD dst, vec src, vec xtmp1) %{ ins_pipe( pipe_slow ); %} -instruct minmax_reductionD_av_avx10(regD dst, vec src, vec xtmp1, vec xtmp2) %{ +instruct minmax_reductionD_av_avx10_2(regD dst, vec src, vec xtmp1, vec xtmp2) %{ predicate(VM_Version::supports_avx10_2() && Matcher::vector_element_basic_type(n->in(2)) == T_DOUBLE && Matcher::vector_length(n->in(2)) >= 4); match(Set dst (MinReductionV dst src)); @@ -20766,7 +20766,7 @@ instruct vminmaxL_reg_evex(vec dst, vec src1, vec src2) %{ %} // Float/Double vector Min/Max -instruct minmaxFP_avx10_reg(vec dst, vec a, vec b) %{ +instruct minmaxFP_reg_avx10_2(vec dst, vec a, vec b) %{ predicate(VM_Version::supports_avx10_2() && is_floating_point_type(Matcher::vector_element_basic_type(n))); // T_FLOAT, T_DOUBLE match(Set dst (MinV a b)); @@ -22113,29 +22113,29 @@ instruct castFtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, k ins_pipe( pipe_slow ); %} -instruct castFtoX_reg_avx10(vec dst, vec src) %{ +instruct castFtoX_reg_avx10_2(vec dst, vec src) %{ predicate(VM_Version::supports_avx10_2() && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastF2X src)); - format %{ "vector_cast_f2x_avx10 $dst, $src\t!" %} + format %{ "vector_cast_f2x_avx10_2 $dst, $src\t!" %} ins_encode %{ BasicType to_elem_bt = Matcher::vector_element_basic_type(this); int vlen_enc = (to_elem_bt == T_LONG) ? vector_length_encoding(this) : vector_length_encoding(this, $src); - __ vector_castF2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + __ vector_castF2X_avx10_2(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct castFtoX_mem_avx10(vec dst, memory src) %{ +instruct castFtoX_mem_avx10_2(vec dst, memory src) %{ predicate(VM_Version::supports_avx10_2() && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastF2X (LoadVector src))); - format %{ "vector_cast_f2x_avx10 $dst, $src\t!" %} + format %{ "vector_cast_f2x_avx10_2 $dst, $src\t!" %} ins_encode %{ int vlen = Matcher::vector_length(this); BasicType to_elem_bt = Matcher::vector_element_basic_type(this); int vlen_enc = (to_elem_bt == T_LONG) ? vector_length_encoding(this) : vector_length_encoding(vlen * sizeof(jfloat)); - __ vector_castF2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); + __ vector_castF2X_avx10_2(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -22187,29 +22187,29 @@ instruct castDtoX_reg_evex(vec dst, vec src, vec xtmp1, vec xtmp2, kReg ktmp1, k ins_pipe( pipe_slow ); %} -instruct castDtoX_reg_avx10(vec dst, vec src) %{ +instruct castDtoX_reg_avx10_2(vec dst, vec src) %{ predicate(VM_Version::supports_avx10_2() && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastD2X src)); - format %{ "vector_cast_d2x_avx10 $dst, $src\t!" %} + format %{ "vector_cast_d2x_avx10_2 $dst, $src\t!" %} ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType to_elem_bt = Matcher::vector_element_basic_type(this); - __ vector_castD2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + __ vector_castD2X_avx10_2(to_elem_bt, $dst$$XMMRegister, $src$$XMMRegister, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct castDtoX_mem_avx10(vec dst, memory src) %{ +instruct castDtoX_mem_avx10_2(vec dst, memory src) %{ predicate(VM_Version::supports_avx10_2() && is_integral_type(Matcher::vector_element_basic_type(n))); match(Set dst (VectorCastD2X (LoadVector src))); - format %{ "vector_cast_d2x_avx10 $dst, $src\t!" %} + format %{ "vector_cast_d2x_avx10_2 $dst, $src\t!" %} ins_encode %{ int vlen = Matcher::vector_length(this); int vlen_enc = vector_length_encoding(vlen * sizeof(jdouble)); BasicType to_elem_bt = Matcher::vector_element_basic_type(this); - __ vector_castD2X_avx10(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); + __ vector_castD2X_avx10_2(to_elem_bt, $dst$$XMMRegister, $src$$Address, vlen_enc); %} ins_pipe( pipe_slow ); %} @@ -25181,14 +25181,14 @@ instruct scalar_binOps_HF_reg(regF dst, regF src1, regF src2) ins_pipe(pipe_slow); %} -instruct scalar_minmax_HF_avx10_reg(regF dst, regF src1, regF src2) +instruct scalar_minmax_HF_reg_avx10_2(regF dst, regF src1, regF src2) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MaxHF src1 src2)); match(Set dst (MinHF src1 src2)); format %{ "scalar_min_max_fp16 $dst, $src1, $src2" %} ins_encode %{ - int function = this->ideal_Opcode() == Op_MinHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + int function = this->ideal_Opcode() == Op_MinHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; __ eminmaxsh($dst$$XMMRegister, $src1$$XMMRegister, $src2$$XMMRegister, function); %} ins_pipe( pipe_slow ); @@ -25296,7 +25296,7 @@ instruct vector_fma_HF_mem(vec dst, memory src1, vec src2) ins_pipe( pipe_slow ); %} -instruct vector_minmax_HF_avx10_mem(vec dst, vec src1, memory src2) +instruct vector_minmax_HF_mem_avx10_2(vec dst, vec src1, memory src2) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MinVHF src1 (VectorReinterpret (LoadVector src2)))); @@ -25304,13 +25304,13 @@ instruct vector_minmax_HF_avx10_mem(vec dst, vec src1, memory src2) format %{ "vector_min_max_fp16_mem $dst, $src1, $src2" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); - int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$Address, true, function, vlen_enc); %} ins_pipe( pipe_slow ); %} -instruct vector_minmax_HF_avx10_reg(vec dst, vec src1, vec src2) +instruct vector_minmax_HF_reg_avx10_2(vec dst, vec src1, vec src2) %{ predicate(VM_Version::supports_avx10_2()); match(Set dst (MinVHF src1 src2)); @@ -25318,7 +25318,7 @@ instruct vector_minmax_HF_avx10_reg(vec dst, vec src1, vec src2) format %{ "vector_min_max_fp16 $dst, $src1, $src2" %} ins_encode %{ int vlen_enc = vector_length_encoding(this); - int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_MINMAX_MIN_COMPARE_SIGN : AVX10_MINMAX_MAX_COMPARE_SIGN; + int function = this->ideal_Opcode() == Op_MinVHF ? AVX10_2_MINMAX_MIN_COMPARE_SIGN : AVX10_2_MINMAX_MAX_COMPARE_SIGN; __ evminmaxph($dst$$XMMRegister, k0, $src1$$XMMRegister, $src2$$XMMRegister, true, function, vlen_enc); %} ins_pipe( pipe_slow ); diff --git a/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java index e8575cfe6b6..80a9aca9ae2 100644 --- a/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java +++ b/test/hotspot/jtreg/compiler/floatingpoint/ScalarFPtoIntCastTest.java @@ -90,7 +90,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2int() { for (int i = 0; i < COUNT; i++) { @@ -106,7 +106,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_F2L, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_F2L_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_F2L_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2long() { for (int i = 0; i < COUNT; i++) { @@ -122,7 +122,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2short() { for (int i = 0; i < COUNT; i++) { @@ -138,7 +138,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_F2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_F2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_F2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2byte() { for (int i = 0; i < COUNT; i++) { @@ -154,7 +154,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2int() { for (int i = 0; i < COUNT; i++) { @@ -170,7 +170,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_D2L, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_D2L_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_D2L_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2long() { for (int i = 0; i < COUNT; i++) { @@ -186,7 +186,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2short() { for (int i = 0; i < COUNT; i++) { @@ -202,7 +202,7 @@ public class ScalarFPtoIntCastTest { @IR(counts = {IRNode.X86_SCONV_D2I, "> 0"}, applyIfPlatform = {"x64", "true"}, applyIfCPUFeature = {"avx10_2", "false"}) - @IR(counts = {IRNode.X86_SCONV_D2I_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_SCONV_D2I_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2byte() { for (int i = 0; i < COUNT; i++) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 608027e7ee1..d5799e5aa05 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -2801,24 +2801,24 @@ public class IRNode { machOnlyNameRegex(X86_SCONV_F2L, "convF2L_reg_reg"); } - public static final String X86_SCONV_D2I_AVX10 = PREFIX + "X86_SCONV2_D2I_AVX10" + POSTFIX; + public static final String X86_SCONV_D2I_AVX10_2 = PREFIX + "X86_SCONV_D2I_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_SCONV_D2I_AVX10, "convD2I_(reg_reg|reg_mem)_avx10"); + machOnlyNameRegex(X86_SCONV_D2I_AVX10_2, "convD2I_(reg_reg|reg_mem)_avx10_2"); } - public static final String X86_SCONV_D2L_AVX10 = PREFIX + "X86_SCONV_D2L_AVX10" + POSTFIX; + public static final String X86_SCONV_D2L_AVX10_2 = PREFIX + "X86_SCONV_D2L_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_SCONV_D2L_AVX10, "convD2L_(reg_reg|reg_mem)_avx10"); + machOnlyNameRegex(X86_SCONV_D2L_AVX10_2, "convD2L_(reg_reg|reg_mem)_avx10_2"); } - public static final String X86_SCONV_F2I_AVX10 = PREFIX + "X86_SCONV_F2I_AVX10" + POSTFIX; + public static final String X86_SCONV_F2I_AVX10_2 = PREFIX + "X86_SCONV_F2I_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_SCONV_F2I_AVX10, "convF2I_(reg_reg|reg_mem)_avx10"); + machOnlyNameRegex(X86_SCONV_F2I_AVX10_2, "convF2I_(reg_reg|reg_mem)_avx10_2"); } - public static final String X86_SCONV_F2L_AVX10 = PREFIX + "X86_SCONV_F2L_AVX10" + POSTFIX; + public static final String X86_SCONV_F2L_AVX10_2 = PREFIX + "X86_SCONV_F2L_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_SCONV_F2L_AVX10, "convF2L_(reg_reg|reg_mem)_avx10"); + machOnlyNameRegex(X86_SCONV_F2L_AVX10_2, "convF2L_(reg_reg|reg_mem)_avx10_2"); } public static final String X86_VCAST_F2X = PREFIX + "X86_VCAST_F2X" + POSTFIX; @@ -2831,14 +2831,14 @@ public class IRNode { machOnlyNameRegex(X86_VCAST_D2X, "castDtoX_reg_(av|eve)x"); } - public static final String X86_VCAST_F2X_AVX10 = PREFIX + "X86_VCAST_F2X_AVX10" + POSTFIX; + public static final String X86_VCAST_F2X_AVX10_2 = PREFIX + "X86_VCAST_F2X_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_VCAST_F2X_AVX10, "castFtoX_(reg|mem)_avx10"); + machOnlyNameRegex(X86_VCAST_F2X_AVX10_2, "castFtoX_(reg|mem)_avx10_2"); } - public static final String X86_VCAST_D2X_AVX10 = PREFIX + "X86_VCAST_D2X_AVX10" + POSTFIX; + public static final String X86_VCAST_D2X_AVX10_2 = PREFIX + "X86_VCAST_D2X_AVX10_2" + POSTFIX; static { - machOnlyNameRegex(X86_VCAST_D2X_AVX10, "castDtoX_(reg|mem)_avx10"); + machOnlyNameRegex(X86_VCAST_D2X_AVX10_2, "castDtoX_(reg|mem)_avx10_2"); } public static final String XOR = PREFIX + "XOR" + POSTFIX; diff --git a/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java b/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java index 1037a2989f9..888750ec226 100644 --- a/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java +++ b/test/hotspot/jtreg/compiler/vectorapi/VectorFPtoIntCastTest.java @@ -90,7 +90,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2int() { var cvec = (IntVector)fvec512.convertShape(VectorOperators.F2I, ispec512, 0); @@ -112,7 +112,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512dq", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2long() { var cvec = (LongVector)fvec512.convertShape(VectorOperators.F2L, lspec512, 0); @@ -134,7 +134,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2short() { var cvec = (ShortVector)fvec512.convertShape(VectorOperators.F2S, sspec256, 0); @@ -156,7 +156,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void float2byte() { var cvec = (ByteVector)fvec512.convertShape(VectorOperators.F2B, bspec128, 0); @@ -178,7 +178,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2int() { var cvec = (IntVector)dvec512.convertShape(VectorOperators.D2I, ispec256, 0); @@ -200,7 +200,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512dq", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2long() { var cvec = (LongVector)dvec512.convertShape(VectorOperators.D2L, lspec512, 0); @@ -222,7 +222,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2short() { var cvec = (ShortVector)dvec512.convertShape(VectorOperators.D2S, sspec128, 0); @@ -244,7 +244,7 @@ public class VectorFPtoIntCastTest { applyIfCPUFeatureOr = {"avx512f", "true", "avx10_2", "true"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512f", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public void double2byte() { var cvec = (ByteVector)dvec512.convertShape(VectorOperators.D2B, bspec64, 0); diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java index 4db973ff728..d3119a00c37 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/ArrayTypeConvertTest.java @@ -298,7 +298,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { counts = {IRNode.VECTOR_CAST_F2I, IRNode.VECTOR_SIZE + "min(max_float, max_int)", "> 0"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public int[] convertFloatToInt() { int[] res = new int[SIZE]; @@ -313,7 +313,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { counts = {IRNode.VECTOR_CAST_F2L, IRNode.VECTOR_SIZE + "min(max_float, max_long)", "> 0"}) @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public long[] convertFloatToLong() { long[] res = new long[SIZE]; @@ -328,7 +328,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { counts = {IRNode.VECTOR_CAST_D2I, IRNode.VECTOR_SIZE + "min(max_double, max_int)", "> 0"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public int[] convertDoubleToInt() { int[] res = new int[SIZE]; @@ -343,7 +343,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { counts = {IRNode.VECTOR_CAST_D2L, IRNode.VECTOR_SIZE + "min(max_double, max_long)", "> 0"}) @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIfCPUFeatureAnd = {"avx512dq", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIfCPUFeature = {"avx10_2", "true"}) public long[] convertDoubleToLong() { long[] res = new long[SIZE]; @@ -361,7 +361,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, applyIfCPUFeature = {"avx10_2", "true"}) public short[] convertFloatToShort() { @@ -386,7 +386,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { @IR(counts = {IRNode.X86_VCAST_F2X, "> 0"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, applyIfCPUFeatureAnd = {"avx2", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_F2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_F2X_AVX10_2, "> 0"}, applyIfOr = {"AlignVector", "false", "UseCompactObjectHeaders", "false"}, applyIfCPUFeature = {"avx10_2", "true"}) public char[] convertFloatToChar() { @@ -414,7 +414,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, applyIfCPUFeature = {"avx10_2", "true"}) public short[] convertDoubleToShort() { @@ -435,7 +435,7 @@ public class ArrayTypeConvertTest extends VectorizationTestRunner { @IR(counts = {IRNode.X86_VCAST_D2X, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, applyIfCPUFeatureAnd = {"avx", "true", "avx10_2", "false"}) - @IR(counts = {IRNode.X86_VCAST_D2X_AVX10, "> 0"}, + @IR(counts = {IRNode.X86_VCAST_D2X_AVX10_2, "> 0"}, applyIf = {"MaxVectorSize", ">=16"}, applyIfCPUFeature = {"avx10_2", "true"}) public char[] convertDoubleToChar() { From 104d0cb542d12f133ac8a0a34f2b21ca3aa4a5cc Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Sat, 13 Dec 2025 14:07:24 +0000 Subject: [PATCH 084/211] 8373577: C2: Cleanup adr_type of CallLeafPureNode Reviewed-by: roland, vlivanov --- src/hotspot/share/opto/callnode.hpp | 5 ++--- src/hotspot/share/opto/divnode.cpp | 2 +- src/hotspot/share/opto/graphKit.cpp | 3 ++- src/hotspot/share/opto/macro.cpp | 3 +-- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/opto/callnode.hpp b/src/hotspot/share/opto/callnode.hpp index 90a86d76679..de4b8941359 100644 --- a/src/hotspot/share/opto/callnode.hpp +++ b/src/hotspot/share/opto/callnode.hpp @@ -943,9 +943,8 @@ protected: TupleNode* make_tuple_of_input_state_and_top_return_values(const Compile* C) const; public: - CallLeafPureNode(const TypeFunc* tf, address addr, const char* name, - const TypePtr* adr_type) - : CallLeafNode(tf, addr, name, adr_type) { + CallLeafPureNode(const TypeFunc* tf, address addr, const char* name) + : CallLeafNode(tf, addr, name, nullptr) { init_class_id(Class_CallLeafPure); } int Opcode() const override; diff --git a/src/hotspot/share/opto/divnode.cpp b/src/hotspot/share/opto/divnode.cpp index cf5bc8ce643..f3039b12508 100644 --- a/src/hotspot/share/opto/divnode.cpp +++ b/src/hotspot/share/opto/divnode.cpp @@ -42,7 +42,7 @@ #include -ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name) : CallLeafPureNode(tf, addr, name, TypeRawPtr::BOTTOM) { +ModFloatingNode::ModFloatingNode(Compile* C, const TypeFunc* tf, address addr, const char* name) : CallLeafPureNode(tf, addr, name) { add_flag(Flag_is_macro); C->add_macro_node(this); } diff --git a/src/hotspot/share/opto/graphKit.cpp b/src/hotspot/share/opto/graphKit.cpp index 49c411843d5..f5c15a81cb6 100644 --- a/src/hotspot/share/opto/graphKit.cpp +++ b/src/hotspot/share/opto/graphKit.cpp @@ -2505,7 +2505,8 @@ Node* GraphKit::make_runtime_call(int flags, uint num_bits = call_type->range()->field_at(TypeFunc::Parms)->is_vect()->length_in_bytes() * BitsPerByte; call = new CallLeafVectorNode(call_type, call_addr, call_name, adr_type, num_bits); } else if (flags & RC_PURE) { - call = new CallLeafPureNode(call_type, call_addr, call_name, adr_type); + assert(adr_type == nullptr, "pure call does not touch memory"); + call = new CallLeafPureNode(call_type, call_addr, call_name); } else { call = new CallLeafNode(call_type, call_addr, call_name, adr_type); } diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 90602bc2b35..bc07f937f1e 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2658,8 +2658,7 @@ bool PhaseMacroExpand::expand_macro_nodes() { case Op_ModD: case Op_ModF: { CallNode* mod_macro = n->as_Call(); - CallNode* call = new CallLeafPureNode(mod_macro->tf(), mod_macro->entry_point(), - mod_macro->_name, TypeRawPtr::BOTTOM); + CallNode* call = new CallLeafPureNode(mod_macro->tf(), mod_macro->entry_point(), mod_macro->_name); call->init_req(TypeFunc::Control, mod_macro->in(TypeFunc::Control)); call->init_req(TypeFunc::I_O, C->top()); call->init_req(TypeFunc::Memory, C->top()); From fb531cdaf3b30034e0efa86b9b20558478ce94d0 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Sat, 13 Dec 2025 22:43:30 +0000 Subject: [PATCH 085/211] 8373632: Some sound tests failing in CI due to lack of sound key Reviewed-by: iris --- test/jdk/javax/sound/midi/Sequencer/Looping.java | 2 +- test/jdk/javax/sound/sampled/Clip/IsRunningHang.java | 1 + test/jdk/javax/sound/sampled/DataLine/LongFramePosition.java | 1 + test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java | 1 + 4 files changed, 4 insertions(+), 1 deletion(-) diff --git a/test/jdk/javax/sound/midi/Sequencer/Looping.java b/test/jdk/javax/sound/midi/Sequencer/Looping.java index 9bcc9254653..9a5a89c6472 100644 --- a/test/jdk/javax/sound/midi/Sequencer/Looping.java +++ b/test/jdk/javax/sound/midi/Sequencer/Looping.java @@ -36,7 +36,7 @@ import javax.sound.midi.Track; * @test * @bug 4204105 * @summary RFE: add loop() method(s) to Sequencer - * @key intermittent + * @key sound */ public class Looping { diff --git a/test/jdk/javax/sound/sampled/Clip/IsRunningHang.java b/test/jdk/javax/sound/sampled/Clip/IsRunningHang.java index c417c5ad8d0..8ffd760b08a 100644 --- a/test/jdk/javax/sound/sampled/Clip/IsRunningHang.java +++ b/test/jdk/javax/sound/sampled/Clip/IsRunningHang.java @@ -36,6 +36,7 @@ import javax.sound.sampled.LineUnavailableException; /** * @test * @bug 8156169 + * @key sound * @run main/othervm/timeout=300 IsRunningHang */ public final class IsRunningHang { diff --git a/test/jdk/javax/sound/sampled/DataLine/LongFramePosition.java b/test/jdk/javax/sound/sampled/DataLine/LongFramePosition.java index 079a785de8b..42e70521b2b 100644 --- a/test/jdk/javax/sound/sampled/DataLine/LongFramePosition.java +++ b/test/jdk/javax/sound/sampled/DataLine/LongFramePosition.java @@ -29,6 +29,7 @@ import javax.sound.sampled.SourceDataLine; /** * @test * @bug 5049129 + * @key sound * @summary DataLine.getLongFramePosition */ public class LongFramePosition { diff --git a/test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java b/test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java index 177ebce85a0..a99caeea055 100644 --- a/test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java +++ b/test/jdk/javax/sound/sampled/DirectAudio/bug6372428.java @@ -31,6 +31,7 @@ import javax.sound.sampled.TargetDataLine; /* * @test * @bug 6372428 + * @key sound * @summary playback and capture doesn't interrupt after terminating thread that * calls start() * @run main bug6372428 From 99f90befafe9476de17e416d45a9875569171935 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Sun, 14 Dec 2025 11:57:00 +0000 Subject: [PATCH 086/211] 8373490: JFR Leak Profiler: path-to-gc-root very slow for large object arrays Reviewed-by: egahlin --- .../jfr/leakprofiler/chains/bfsClosure.cpp | 13 +- .../jcmd/TestJcmdDumpPathToGCRootsBFSDFS.java | 195 ++++++++++++++++++ 2 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 test/jdk/jdk/jfr/jcmd/TestJcmdDumpPathToGCRootsBFSDFS.java diff --git a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp index 4f96680fa6c..701f75ff87c 100644 --- a/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp +++ b/src/hotspot/share/jfr/leakprofiler/chains/bfsClosure.cpp @@ -121,13 +121,14 @@ void BFSClosure::closure_impl(UnifiedOopRef reference, const oop pointee) { return; } - if (_use_dfs) { - assert(_current_parent != nullptr, "invariant"); - DFSClosure::find_leaks_from_edge(_edge_store, _mark_bits, _current_parent); - return; - } - if (!_mark_bits->is_marked(pointee)) { + + if (_use_dfs) { + assert(_current_parent != nullptr, "invariant"); + DFSClosure::find_leaks_from_edge(_edge_store, _mark_bits, _current_parent); + return; + } + _mark_bits->mark_obj(pointee); // is the pointee a sample object? if (pointee->mark().is_marked()) { diff --git a/test/jdk/jdk/jfr/jcmd/TestJcmdDumpPathToGCRootsBFSDFS.java b/test/jdk/jdk/jfr/jcmd/TestJcmdDumpPathToGCRootsBFSDFS.java new file mode 100644 index 00000000000..6815d354309 --- /dev/null +++ b/test/jdk/jdk/jfr/jcmd/TestJcmdDumpPathToGCRootsBFSDFS.java @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2025, 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 jdk.jfr.jcmd; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import jdk.jfr.Enabled; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.jfr.consumer.RecordedObject; +import jdk.jfr.consumer.RecordingFile; +import jdk.jfr.internal.test.WhiteBox; +import jdk.test.lib.jfr.EventNames; + +/** + * @test id=dfs-only + * @summary Test dumping with path-to-gc-roots and DFS only + * @bug 8373490 + * @requires vm.hasJFR & vm.flagless + * @modules jdk.jfr/jdk.jfr.internal.test + * @library /test/lib /test/jdk + * + * @run main/othervm -XX:TLABSize=2k -Xmx256m jdk.jfr.jcmd.TestJcmdDumpPathToGCRootsBFSDFS dfs-only + */ + +/** + * @test id=bfs-only + * @summary Test dumping with path-to-gc-roots and BFS only + * @bug 8373490 + * @requires vm.hasJFR & vm.flagless + * @modules jdk.jfr/jdk.jfr.internal.test + * @library /test/lib /test/jdk + * + * @run main/othervm -XX:TLABSize=2k -Xmx256m jdk.jfr.jcmd.TestJcmdDumpPathToGCRootsBFSDFS bfs-only + */ + +/** + * @test id=bfsdfs + * @summary Test dumping with path-to-gc-roots and mixed BFS+DFS + * @bug 8373490 + * @requires vm.hasJFR & vm.flagless + * @modules jdk.jfr/jdk.jfr.internal.test + * @library /test/lib /test/jdk + * + * @run main/othervm -XX:TLABSize=2k -Xmx256m jdk.jfr.jcmd.TestJcmdDumpPathToGCRootsBFSDFS bfsdfs + */ +public class TestJcmdDumpPathToGCRootsBFSDFS { + + // Note: + // - We start with a small heap of 256M in order to get the minimum Edge Queue size in BFS (lower cap is 32MB, enough to hold ~2mio edges) + // - We build a leak with an array containing more than 2mio entries + // That will hit BFS first, then fall back to DFS, showing the performance problem JDK-8373490 describes. + // DFS-only mode should work well, and so should BFS-only mode. + + // The minimum size of the edge queue in BFS (keep in sync with hotspot) + private final static int minimumEdgeQueueSizeCap = 32 * 1024 * 1024; + // The size of the Edge structure (keep in sync with hotspot) + private final static int edgeSizeBytes = 16; + + public static List leak; + + public static void main(String[] args) throws Exception { + WhiteBox.setWriteAllObjectSamples(true); + String settingName = EventNames.OldObjectSample + "#" + "cutoff"; + + int edgesPerMinSizedQueue = minimumEdgeQueueSizeCap / 16; + int lower = 1_000_000; + int upper = 3_000_000; + int fudge = 250_000; + if (edgesPerMinSizedQueue < (lower + fudge)) { + throw new RuntimeException("edgesPerMinSizedQueue lower bound wrong?"); + } + if (edgesPerMinSizedQueue > (upper - fudge)) { + throw new RuntimeException("edgesPerMinSizedQueue upper bound wrong?"); + } + + int leakedObjectCount; + boolean skipBFS; + switch (args[0]) { + case "bfsdfs" -> { + // Mixed mode: enough objects to saturate BFS queue + leakedObjectCount = upper; + skipBFS = false; + } + case "dfs-only" -> { + // DFS-only mode: object count does not matter, we enter DFS right away + leakedObjectCount = upper; + skipBFS = true; + } + case "bfs-only" -> { + // BFS-only mode: not enough objects to saturate BFS queue + leakedObjectCount = lower; + skipBFS = false; + } + default -> { + throw new RuntimeException("Invalid argument"); + } + }; + + WhiteBox.setSkipBFS(skipBFS); + + testDump("path-to-gc-roots=true", Collections.singletonMap(settingName, "infinity"), leakedObjectCount, true); + } + + private static void testDump(String pathToGcRoots, Map settings, int leakedObjectCount, boolean expectedChains) throws Exception { + while (true) { + try (Recording r = new Recording()) { + Map p = new HashMap<>(settings); + p.put(EventNames.OldObjectSample + "#" + Enabled.NAME, "true"); + r.setName("dodo"); + r.setSettings(p); + r.setToDisk(true); + r.start(); + clearLeak(); + System.out.println("Recording id: " + r.getId()); + System.out.println("Settings: " + settings.toString()); + System.out.println("Command: JFR.dump " + pathToGcRoots); + System.out.println("Chains expected: " + expectedChains); + buildLeak(leakedObjectCount); + System.gc(); + System.gc(); + File recording = new File("TestJcmdDumpPathToGCRoots" + r.getId() + ".jfr"); + recording.delete(); + JcmdHelper.jcmd("JFR.dump", "name=dodo", pathToGcRoots, "filename=" + recording.getAbsolutePath()); + r.setSettings(Collections.emptyMap()); + List events = RecordingFile.readAllEvents(recording.toPath()); + if (events.isEmpty()) { + System.out.println("No events found in recording. Retrying."); + continue; + } + boolean chains = hasChains(events); + if (expectedChains && !chains) { + System.out.println(events); + System.out.println("Expected chains but found none. Retrying."); + continue; + } + if (!expectedChains && chains) { + System.out.println(events); + System.out.println("Didn't expect chains but found some. Retrying."); + continue; + } + return; // Success + } + } + } + + private static void clearLeak() { + leak = null; + System.gc(); + } + + private static boolean hasChains(List events) throws IOException { + for (RecordedEvent e : events) { + RecordedObject ro = e.getValue("object"); + if (ro.getValue("referrer") != null) { + return true; + } + } + return false; + } + + private static void buildLeak(int objectCount) { + leak = new ArrayList(objectCount); + for (int i = 0; i < objectCount;i ++) { + leak.add(new Object[0]); + } + } +} From d03e7cb87ae04c1d32559b4a49d71d32f9d616a8 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Sun, 14 Dec 2025 20:45:18 +0000 Subject: [PATCH 087/211] 8373522: Remove expired flags in JDK 27 Reviewed-by: kvn, ayang --- src/hotspot/share/runtime/arguments.cpp | 26 ------------------------- src/java.base/share/man/java.md | 2 ++ 2 files changed, 2 insertions(+), 26 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index dab3a60c650..dbf10c8a7b3 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -534,7 +534,6 @@ static SpecialFlag const special_jvm_flags[] = { { "DynamicDumpSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "RequireSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, { "UseSharedSpaces", JDK_Version::jdk(18), JDK_Version::jdk(19), JDK_Version::undefined() }, - { "LockingMode", JDK_Version::jdk(24), JDK_Version::jdk(26), JDK_Version::jdk(27) }, #ifdef _LP64 { "UseCompressedClassPointers", JDK_Version::jdk(25), JDK_Version::jdk(27), JDK_Version::undefined() }, #endif @@ -550,36 +549,11 @@ static SpecialFlag const special_jvm_flags[] = { // -------------- Obsolete Flags - sorted by expired_in -------------- -#ifdef LINUX - { "UseOprofile", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) }, -#endif { "MetaspaceReclaimPolicy", JDK_Version::undefined(), JDK_Version::jdk(21), JDK_Version::undefined() }, - { "G1UpdateBufferSize", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "ShenandoahPacing", JDK_Version::jdk(25), JDK_Version::jdk(26), JDK_Version::jdk(27) }, #if defined(AARCH64) { "NearCpool", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, #endif - { "AdaptiveSizeMajorGCDecayTimeScale", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "AdaptiveSizePolicyInitializingSteps", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "AdaptiveSizePolicyOutputInterval", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "AdaptiveSizeThroughPutPolicy", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "AdaptiveTimeWeight", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "PausePadding", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "SurvivorPadding", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "TenuredGenerationSizeIncrement", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "TenuredGenerationSizeSupplement", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "TenuredGenerationSizeSupplementDecay", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UseAdaptiveGenerationSizePolicyAtMajorCollection", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UseAdaptiveGenerationSizePolicyAtMinorCollection", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UseAdaptiveSizeDecayMajorGCCost", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UseAdaptiveSizePolicyFootprintGoal", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UseAdaptiveSizePolicyWithSystemGC", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "UsePSAdaptiveSurvivorSizePolicy", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - - { "PretenureSizeThreshold", JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - { "HeapMaximumCompactionInterval",JDK_Version::undefined(), JDK_Version::jdk(26), JDK_Version::jdk(27) }, - #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif diff --git a/src/java.base/share/man/java.md b/src/java.base/share/man/java.md index 8517e161e3f..30661a3f387 100644 --- a/src/java.base/share/man/java.md +++ b/src/java.base/share/man/java.md @@ -3002,6 +3002,8 @@ No documented java options have been removed in JDK @@VERSION_SPECIFICATION@@. For the lists and descriptions of options removed in previous releases see the *Removed Java Options* section in: +- [The `java` Command, Release 26](https://docs.oracle.com/en/java/javase/26/docs/specs/man/java.html) + - [The `java` Command, Release 25](https://docs.oracle.com/en/java/javase/25/docs/specs/man/java.html) - [The `java` Command, Release 24](https://docs.oracle.com/en/java/javase/24/docs/specs/man/java.html) From eda1ab2143f8bb25fce2e5c086aeb4ecb4141f55 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 15 Dec 2025 01:50:25 +0000 Subject: [PATCH 088/211] 8373449: Parallel: Obsolete deprecated PSChunkLargeArrays Reviewed-by: kbarrett, dholmes, tschatzl --- src/hotspot/share/gc/parallel/parallel_globals.hpp | 5 +---- src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp | 4 +--- src/hotspot/share/runtime/arguments.cpp | 3 ++- 3 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/hotspot/share/gc/parallel/parallel_globals.hpp b/src/hotspot/share/gc/parallel/parallel_globals.hpp index 84d884f128c..22e495e7db4 100644 --- a/src/hotspot/share/gc/parallel/parallel_globals.hpp +++ b/src/hotspot/share/gc/parallel/parallel_globals.hpp @@ -33,10 +33,7 @@ constraint) \ product(bool, UseMaximumCompactionOnSystemGC, true, \ "Use maximum compaction in the Parallel Old garbage collector " \ - "for a system GC") \ - \ - product(bool, PSChunkLargeArrays, true, \ - "(Deprecated) Process large arrays in chunks") + "for a system GC") // end of GC_PARALLEL_FLAGS diff --git a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp index fb58c22cf29..f1fd49c7dfe 100644 --- a/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp +++ b/src/hotspot/share/gc/parallel/psPromotionManager.inline.hpp @@ -299,8 +299,7 @@ inline oop PSPromotionManager::copy_unmarked_to_survivor_space(oop o, // _min_array_size_for_chunking, and most of them will be arrays. // So, the objArray test would be very infrequent. if (new_obj_size > _min_array_size_for_chunking && - klass->is_objArray_klass() && - PSChunkLargeArrays) { + klass->is_objArray_klass()) { push_objArray(o, new_obj); } else { // we'll just push its contents @@ -344,7 +343,6 @@ inline void PSPromotionManager::copy_and_push_safe_barrier(T* p) { inline void PSPromotionManager::process_popped_location_depth(ScannerTask task, bool stolen) { if (task.is_partial_array_state()) { - assert(PSChunkLargeArrays, "invariant"); process_array_chunk(task.to_partial_array_state(), stolen); } else { if (task.is_narrow_oop_ptr()) { diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index dbf10c8a7b3..d4ba599fa9b 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -539,7 +539,6 @@ static SpecialFlag const special_jvm_flags[] = { #endif { "ParallelRefProcEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "ParallelRefProcBalancingEnabled", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, - { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "MaxRAM", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "AggressiveHeap", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, { "NeverActAsServerClassMachine", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, @@ -554,6 +553,8 @@ static SpecialFlag const special_jvm_flags[] = { { "NearCpool", JDK_Version::undefined(), JDK_Version::jdk(25), JDK_Version::undefined() }, #endif + { "PSChunkLargeArrays", JDK_Version::jdk(26), JDK_Version::jdk(27), JDK_Version::jdk(28) }, + #ifdef ASSERT { "DummyObsoleteTestFlag", JDK_Version::undefined(), JDK_Version::jdk(18), JDK_Version::undefined() }, #endif From 5edeb71e3b148d52962c46180c92ebfeda018f67 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 15 Dec 2025 04:45:25 +0000 Subject: [PATCH 089/211] 6292135: DefaultTableModel.setColumnIdentifiers() Clears JTable Row Heights Reviewed-by: tr, kizune --- .../share/classes/javax/swing/JTable.java | 2 - .../TestRowHeightWithColIdentifier.java | 64 +++++++++++++++++++ 2 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 test/jdk/javax/swing/JTable/TestRowHeightWithColIdentifier.java diff --git a/src/java.desktop/share/classes/javax/swing/JTable.java b/src/java.desktop/share/classes/javax/swing/JTable.java index e9ae9d82166..6e64b216d58 100644 --- a/src/java.desktop/share/classes/javax/swing/JTable.java +++ b/src/java.desktop/share/classes/javax/swing/JTable.java @@ -4454,8 +4454,6 @@ public class JTable extends JComponent implements TableModelListener, Scrollable // The whole thing changed clearSelectionAndLeadAnchor(); - rowModel = null; - if (sortManager != null) { try { ignoreSortChange = true; diff --git a/test/jdk/javax/swing/JTable/TestRowHeightWithColIdentifier.java b/test/jdk/javax/swing/JTable/TestRowHeightWithColIdentifier.java new file mode 100644 index 00000000000..ad2015e3b45 --- /dev/null +++ b/test/jdk/javax/swing/JTable/TestRowHeightWithColIdentifier.java @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2025, 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 + * @bug 6292135 + * @summary Verifies DefaultTableModel.setColumnIdentifiers() doesn't + * clear JTable Row Heights + * @run main TestRowHeightWithColIdentifier + */ + +import javax.swing.JTable; +import javax.swing.SwingUtilities; +import javax.swing.table.DefaultTableModel; + +public class TestRowHeightWithColIdentifier{ + + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(() -> { + DefaultTableModel model = new DefaultTableModel(null, new Object[] {"FOO", "BAR"}); + JTable table = new JTable(model); + + model.addRow(new Object[] {"00", "01"}); + model.addRow(new Object[] {"10", "11"}); + model.addRow(new Object[] {"20", "21"}); + for (int row = 0; row < table.getRowCount(); row++) { + table.setRowHeight(row, 100); + } + for (int row = 0; row < table.getRowCount(); row++) { + System.out.println("Before table rowHeight " + table.getRowHeight(row)); + } + int oldRowHeight = table.getRowHeight(0); + model.setColumnIdentifiers(new Object[] {"Check", "it out!"}); + for (int row = 0; row < table.getRowCount(); row++) { + System.out.println("After table rowHeight " + table.getRowHeight(row)); + } + int curRowHeight = table.getRowHeight(0); + if (curRowHeight != oldRowHeight) { + throw new RuntimeException("DefaultTableModel.setColumnIdentifiers() Clears JTable Row Height"); + } + }); + } +} From 0e7bc6b0928bd860c665ead26d2237055c0c9d27 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Mon, 15 Dec 2025 04:52:14 +0000 Subject: [PATCH 090/211] 6681958: Maximization state of JInternalFrames is corrupted by WindowsDesktopManager Reviewed-by: tr, kizune --- .../plaf/windows/WindowsDesktopManager.java | 11 +- .../JIFMaximizedTrfAttribute.java | 100 ++++++++++++++++++ 2 files changed, 107 insertions(+), 4 deletions(-) create mode 100644 test/jdk/javax/swing/JInternalFrame/JIFMaximizedTrfAttribute.java diff --git a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java index 355f70b4607..79d81bad089 100644 --- a/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java +++ b/src/java.desktop/windows/classes/com/sun/java/swing/plaf/windows/WindowsDesktopManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2025, 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 @@ -80,10 +80,13 @@ public final class WindowsDesktopManager extends DefaultDesktopManager if (f.isMaximizable()) { if (!f.isMaximum()) { f.setMaximum(true); - } else if (f.isMaximum() && f.isIcon()) { - f.setIcon(false); } else { - f.setMaximum(false); + // If frame being activated is set to maximised + // and iconified, let it be maximised + // else remain non-maximised + if (f.isIcon()) { + f.setIcon(false); + } } } } diff --git a/test/jdk/javax/swing/JInternalFrame/JIFMaximizedTrfAttribute.java b/test/jdk/javax/swing/JInternalFrame/JIFMaximizedTrfAttribute.java new file mode 100644 index 00000000000..f5030b934b6 --- /dev/null +++ b/test/jdk/javax/swing/JInternalFrame/JIFMaximizedTrfAttribute.java @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2025, 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 + * @bug 6681958 + * @summary Verifies Maximization state of JInternalFrames is + * not corrupted by WindowsDesktopManager + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @run main/manual JIFMaximizedTrfAttribute + */ + +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.BorderLayout; + +import javax.swing.JButton; +import javax.swing.JDesktopPane; +import javax.swing.JFrame; +import javax.swing.JInternalFrame; +import javax.swing.UIManager; + +import java.beans.PropertyVetoException; + +public class JIFMaximizedTrfAttribute { + + static final String INSTRUCTIONS = """ + A maximised JInternalFrame would be shown with a + button "open another internal frame". + Press the button on the internal frame. + A second internal frame is created and opened. + If second internal frame is maximized, + press Pass else press Fail."""; + + public static void main(String[] args) throws Exception { + // Set Windows L&F + UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel"); + PassFailJFrame.builder() + .title("Test Instructions") + .instructions(INSTRUCTIONS) + .columns(50) + .testUI(JIFMaximizedTrfAttribute::createUI) + .position(PassFailJFrame.Position.TOP_LEFT_CORNER) + .build() + .awaitAndCheck(); + } + + static JFrame createUI() { + + final JDesktopPane pane = new JDesktopPane(); + final JInternalFrame internal = new JInternalFrame("the first internal frame", true, true, true, true); + pane.add(internal); + internal.setBounds(0, 0, 200, 100); + try { + internal.setMaximum(true); + } catch (PropertyVetoException e) { } + internal.setVisible(true); + JButton button = new JButton("open another internal frame"); + button.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent evt) { + final JInternalFrame internal2 = new JInternalFrame("another one", true, true, true, true); + pane.add(internal2); + internal2.setBounds(250, 150, 200, 100); + try { + internal2.setMaximum(true); + } catch (PropertyVetoException e) {} + internal2.setVisible(true); + } + }); + internal.add(button, BorderLayout.SOUTH); + + JFrame f = new JFrame("JIFMaximizedTrfAttribute"); + f.add(pane, BorderLayout.CENTER); + f.setSize(800, 600); + f.setLocationRelativeTo(null); + return f; + } +} From dc1b0b5f81b6c3de85a0234d0315370b6413c077 Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Mon, 15 Dec 2025 06:13:07 +0000 Subject: [PATCH 091/211] 8373557: Remove stale comments after JDK-8372584 Reviewed-by: dholmes, jsjolen --- src/hotspot/os/linux/os_linux.cpp | 7 ------- src/hotspot/share/runtime/os.hpp | 5 +---- 2 files changed, 1 insertion(+), 11 deletions(-) diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index ba05fde7f12..8af89bb3a71 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -4298,13 +4298,6 @@ OSReturn os::get_native_priority(const Thread* const thread, return (*priority_ptr != -1 || errno == 0 ? OS_OK : OS_ERR); } -// This is the fastest way to get thread cpu time on Linux. -// Returns cpu time (user+sys) for any thread, not only for current. -// POSIX compliant clocks are implemented in the kernels 2.6.16+. -// It might work on 2.6.10+ with a special kernel/glibc patch. -// For reference, please, see IEEE Std 1003.1-2004: -// http://www.unix.org/single_unix_specification - jlong os::Linux::thread_cpu_time(clockid_t clockid) { struct timespec tp; int status = clock_gettime(clockid, &tp); diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index b65bf643cbf..6798140ed4d 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -980,10 +980,7 @@ class os: AllStatic { // The thread_cpu_time() and current_thread_cpu_time() are only // supported if is_thread_cpu_time_supported() returns true. - // Thread CPU Time - return the fast estimate on a platform - // On Linux - fast clock_gettime where available - user+sys - // - otherwise: very slow /proc fs - user+sys - // On Windows - GetThreadTimes - user+sys + // Thread CPU Time - return the fast estimate on a platform - user+sys static jlong current_thread_cpu_time(); static jlong thread_cpu_time(Thread* t); From 01adf28c946580751f7c041b13c987f477a6289a Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Mon, 15 Dec 2025 07:36:42 +0000 Subject: [PATCH 092/211] 8372974: Add missing @Override annotations in "com.sun.java.swing.plaf.gtk" package Reviewed-by: prr --- .../swing/plaf/gtk/GTKColorChooserPanel.java | 15 ++++- .../java/swing/plaf/gtk/GTKFileChooserUI.java | 65 +++++++++++++++++++ .../java/swing/plaf/gtk/GTKGraphicsUtils.java | 4 +- .../java/swing/plaf/gtk/GTKIconFactory.java | 13 +++- .../java/swing/plaf/gtk/GTKLookAndFeel.java | 19 +++++- .../sun/java/swing/plaf/gtk/GTKPainter.java | 53 ++++++++++++++- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 8 ++- .../java/swing/plaf/gtk/GTKStyleFactory.java | 3 +- .../com/sun/java/swing/plaf/gtk/Metacity.java | 26 +++++++- 9 files changed, 198 insertions(+), 8 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java index 1c8c1e88be4..7c243396dda 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKColorChooserPanel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -122,6 +122,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * Returns a user presentable description of this GTKColorChooserPane. */ + @Override public String getDisplayName() { return (String)UIManager.get("GTKColorChooserPanel.nameText"); } @@ -129,6 +130,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * Returns the mnemonic to use with getDisplayName. */ + @Override public int getMnemonic() { String m = (String)UIManager.get("GTKColorChooserPanel.mnemonic"); @@ -145,6 +147,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * Character to underline that represents the mnemonic. */ + @Override public int getDisplayedMnemonicIndex() { String m = (String)UIManager.get( "GTKColorChooserPanel.displayedMnemonicIndex"); @@ -159,14 +162,17 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements return -1; } + @Override public Icon getSmallDisplayIcon() { return null; } + @Override public Icon getLargeDisplayIcon() { return null; } + @Override public void uninstallChooserPanel(JColorChooser enclosingChooser) { super.uninstallChooserPanel(enclosingChooser); removeAll(); @@ -175,6 +181,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * Builds and configures the widgets for the GTKColorChooserPanel. */ + @Override protected void buildChooser() { triangle = new ColorTriangle(); triangle.setName("GTKColorChooserPanel.triangle"); @@ -307,6 +314,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * Refreshes the display from the model. */ + @Override public void updateChooser() { if (!settingColor) { lastLabel.setBackground(getColorFromModel()); @@ -490,6 +498,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements /** * ChangeListener method, updates the necessary display widgets. */ + @Override public void stateChanged(ChangeEvent e) { if (settingColor) { return; @@ -687,6 +696,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements return circleY + getIndicatorSize() / 2 - getWheelYOrigin(); } + @Override protected void processEvent(AWTEvent e) { if (!(getGTKColorChooserPanel().isEnabled())) { @@ -741,6 +751,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements super.processEvent(e); } + @Override public void paintComponent(Graphics g) { super.paintComponent(g); @@ -1259,6 +1270,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements this.type = type; } + @Override public void actionPerformed(ActionEvent e) { ColorTriangle triangle = (ColorTriangle)e.getSource(); @@ -1318,6 +1330,7 @@ class GTKColorChooserPanel extends AbstractColorChooserPanel implements @SuppressWarnings("serial") // Superclass is not serializable across versions private static class OpaqueLabel extends JLabel { + @Override public boolean isOpaque() { return true; } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java index 4f18dc84f4a..29d77650cb4 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKFileChooserUI.java @@ -188,6 +188,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super(filechooser); } + @Override protected ActionMap createActionMap() { ActionMap map = new ActionMapUIResource(); map.put("approveSelection", getApproveSelectionAction()); @@ -197,6 +198,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return map; } + @Override @SuppressWarnings("deprecation") public String getFileName() { JFileChooser fc = getFileChooser(); @@ -243,6 +245,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return sb.toString(); } + @Override public void setFileName(String fileName) { if (fileNameTextField != null) { fileNameTextField.setText(fileName); @@ -253,18 +256,22 @@ class GTKFileChooserUI extends SynthFileChooserUI { // return pathField.getText(); // } + @Override public void setDirectoryName(String dirname) { pathField.setText(dirname); } + @Override public void ensureFileIsVisible(JFileChooser fc, File f) { // PENDING } + @Override public void rescanCurrentDirectory(JFileChooser fc) { getModel().validateFileCache(); } + @Override public JPanel getAccessoryPanel() { return accessoryPanel; } @@ -273,6 +280,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { // * FileView operations * // *********************** + @Override public FileView getFileView(JFileChooser fc) { return fileView; } @@ -282,16 +290,20 @@ class GTKFileChooserUI extends SynthFileChooserUI { iconCache = null; } + @Override public void clearIconCache() { } + @Override public Icon getCachedIcon(File f) { return null; } + @Override public void cacheIcon(File f, Icon i) { } + @Override public Icon getIcon(File f) { return (f != null && f.isDirectory()) ? directoryIcon : fileIcon; } @@ -317,6 +329,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected void doSelectedFileChanged(PropertyChangeEvent e) { super.doSelectedFileChanged(e); File f = (File) e.getNewValue(); @@ -325,6 +338,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected void doDirectoryChanged(PropertyChangeEvent e) { directoryList.clearSelection(); ListSelectionModel sm = directoryList.getSelectionModel(); @@ -357,6 +371,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super.doDirectoryChanged(e); } + @Override protected void doAccessoryChanged(PropertyChangeEvent e) { if (getAccessoryPanel() != null) { if (e.getOldValue() != null) { @@ -374,6 +389,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected void doFileSelectionModeChanged(PropertyChangeEvent e) { directoryList.clearSelection(); rightPanel.setVisible(((Integer)e.getNewValue()).intValue() != JFileChooser.DIRECTORIES_ONLY); @@ -381,6 +397,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super.doFileSelectionModeChanged(e); } + @Override protected void doMultiSelectionChanged(PropertyChangeEvent e) { if (getFileChooser().isMultiSelectionEnabled()) { fileList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION); @@ -395,6 +412,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super.doMultiSelectionChanged(e); } + @Override protected void doControlButtonsChanged(PropertyChangeEvent e) { super.doControlButtonsChanged(e); @@ -407,6 +425,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { updateDefaultButton(); } + @Override protected void doAncestorChanged(PropertyChangeEvent e) { if (e.getOldValue() == null && e.getNewValue() != null) { // Ancestor was added, set initial focus @@ -424,6 +443,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { // ************ Create Listeners ************** // ******************************************** + @Override public ListSelectionListener createListSelectionListener(JFileChooser fc) { return new SelectionListener(); } @@ -434,6 +454,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { this.list = list; } + @Override public void mouseClicked(MouseEvent e) { if (!getFileChooser().isEnabled()) { @@ -464,6 +485,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override public void mouseEntered(MouseEvent evt) { if (list != null) { TransferHandler th1 = getFileChooser().getTransferHandler(); @@ -478,6 +500,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected MouseListener createDoubleClickListener(JFileChooser fc, JList list) { return new DoubleClickListener(list); } @@ -486,6 +509,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { @SuppressWarnings("deprecation") protected class SelectionListener implements ListSelectionListener { + @Override public void valueChanged(ListSelectionEvent e) { if (!e.getValueIsAdjusting()) { JFileChooser chooser = getFileChooser(); @@ -547,6 +571,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return new GTKFileChooserUI((JFileChooser)c); } + @Override public void installUI(JComponent c) { accessoryPanel = new JPanel(new BorderLayout(10, 10)); accessoryPanel.setName("GTKFileChooser.accessoryPanel"); @@ -554,6 +579,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super.installUI(c); } + @Override public void uninstallUI(JComponent c) { c.removePropertyChangeListener(filterComboBoxModel); super.uninstallUI(c); @@ -565,6 +591,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { getFileChooser().removeAll(); } + @Override public void installComponents(JFileChooser fc) { super.installComponents(fc); @@ -623,6 +650,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { JPanel comboBoxPanel = new JPanel(new FlowLayout(FlowLayout.CENTER, 0, 0) { + @Override public void layoutContainer(Container target) { super.layoutContainer(target); JComboBox comboBox = directoryComboBox; @@ -733,6 +761,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { curDirName = currentDirectory.getPath(); } JLabel tmp = new JLabel(curDirName) { + @Override public Dimension getMaximumSize() { Dimension d = super.getMaximumSize(); d.height = getPreferredSize().height; @@ -747,6 +776,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { // add the fileName field JTextField tmp2 = new JTextField() { + @Override public Dimension getMaximumSize() { Dimension d = super.getMaximumSize(); d.height = getPreferredSize().height; @@ -811,6 +841,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected void installListeners(JFileChooser fc) { super.installListeners(fc); @@ -822,6 +853,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return SwingUtilities2.getUIDefaultsInt(key, l); } + @Override protected void uninstallListeners(JFileChooser fc) { super.uninstallListeners(fc); @@ -831,6 +863,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } private class GTKFCPropertyChangeListener implements PropertyChangeListener { + @Override public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if (prop.equals("GTKFileChooser.showDirectoryIcons")) { @@ -841,6 +874,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override protected void installDefaults(JFileChooser fc) { super.installDefaults(fc); readOnly = UIManager.getBoolean("FileChooser.readOnly"); @@ -850,11 +884,13 @@ class GTKFileChooserUI extends SynthFileChooserUI { Boolean.TRUE.equals(fc.getClientProperty("GTKFileChooser.showFileIcons")); } + @Override protected void installIcons(JFileChooser fc) { directoryIcon = UIManager.getIcon("FileView.directoryIcon"); fileIcon = UIManager.getIcon("FileView.fileIcon"); } + @Override protected void installStrings(JFileChooser fc) { super.installStrings(fc); @@ -894,6 +930,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { filterLabelMnemonic = UIManager.getInt("FileChooser.filterLabelMnemonic"); } + @Override protected void uninstallStrings(JFileChooser fc) { super.uninstallStrings(fc); @@ -972,14 +1009,17 @@ class GTKFileChooserUI extends SynthFileChooserUI { return scrollpane; } + @Override protected void createModel() { model = new GTKDirectoryModel(); } + @Override public BasicDirectoryModel getModel() { return model; } + @Override public Action getApproveSelectionAction() { return approveSelectionAction; } @@ -990,6 +1030,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super(getFileChooser()); } + @Override protected void sort(Vector v) { FileSystemView fsv = getFileChooser().getFileSystemView(); if (fsv == null) { @@ -1028,6 +1069,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { directoryChanged(); } + @Override public int getSize() { return getModel().getDirectories().size() + 1; } @@ -1038,10 +1080,12 @@ class GTKFileChooserUI extends SynthFileChooserUI { curDir; } + @Override public void intervalAdded(ListDataEvent e) { fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); } + @Override public void intervalRemoved(ListDataEvent e) { fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); } @@ -1055,6 +1099,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { // PENDING - fire the correct interval changed - currently sending // out that everything has changed + @Override public void contentsChanged(ListDataEvent e) { fireContentsChanged(); } @@ -1071,6 +1116,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { getModel().addListDataListener(this); } + @Override public int getSize() { return getModel().getFiles().size(); } @@ -1088,10 +1134,12 @@ class GTKFileChooserUI extends SynthFileChooserUI { return getModel().getFiles().elementAt(index); } + @Override public void intervalAdded(ListDataEvent e) { fireIntervalAdded(this, e.getIndex0(), e.getIndex1()); } + @Override public void intervalRemoved(ListDataEvent e) { fireIntervalRemoved(this, e.getIndex0(), e.getIndex1()); } @@ -1104,6 +1152,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } // PENDING - fire the interval changed + @Override public void contentsChanged(ListDataEvent e) { fireContentsChanged(); } @@ -1112,6 +1161,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { @SuppressWarnings("serial") // Superclass is not serializable across versions protected class FileCellRenderer extends DefaultListCellRenderer { + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -1129,6 +1179,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { @SuppressWarnings("serial") // Superclass is not serializable across versions protected class DirectoryCellRenderer extends DefaultListCellRenderer { + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -1178,6 +1229,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { c.setAlignmentY(JComponent.TOP_ALIGNMENT); } + @Override public Action getNewFolderAction() { if (newFolderAction == null) { newFolderAction = new NewFolderAction(); @@ -1252,15 +1304,18 @@ class GTKFileChooserUI extends SynthFileChooserUI { setSelectedItem(canonical); } + @Override public void setSelectedItem(Object selectedDirectory) { this.selectedDirectory = (File)selectedDirectory; fireContentsChanged(this, -1, -1); } + @Override public Object getSelectedItem() { return selectedDirectory; } + @Override public int getSize() { return directories.size(); } @@ -1280,6 +1335,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { super("DirectoryComboBoxAction"); } + @Override public void actionPerformed(ActionEvent e) { File f = (File)directoryComboBox.getSelectedItem(); getFileChooser().setCurrentDirectory(f); @@ -1294,6 +1350,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { protected NewFolderAction() { super(FilePane.ACTION_NEW_FOLDER); } + @Override public void actionPerformed(ActionEvent e) { if (readOnly) { return; @@ -1327,6 +1384,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { @SuppressWarnings("serial") // Superclass is not serializable across versions private class GTKApproveSelectionAction extends ApproveSelectionAction { + @Override public void actionPerformed(ActionEvent e) { if (isDirectorySelected()) { File dir = getDirectory(); @@ -1362,6 +1420,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { protected RenameFileAction() { super(FilePane.ACTION_EDIT_FILE_NAME); } + @Override public void actionPerformed(ActionEvent e) { if (getFileName().isEmpty()) { return; @@ -1405,6 +1464,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { */ @SuppressWarnings("serial") // Superclass is not serializable across versions public class FilterComboBoxRenderer extends DefaultListCellRenderer { + @Override public String getName() { // As SynthComboBoxRenderer's are asked for a size BEFORE they // are parented getName is overridden to force the name to be @@ -1417,6 +1477,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return name; } + @Override public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) { @@ -1457,6 +1518,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { filters = getFileChooser().getChoosableFileFilters(); } + @Override public void propertyChange(PropertyChangeEvent e) { String prop = e.getPropertyName(); if (prop == JFileChooser.CHOOSABLE_FILE_FILTER_CHANGED_PROPERTY) { @@ -1467,6 +1529,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override public void setSelectedItem(Object filter) { if (filter != null) { getFileChooser().setFileFilter((FileFilter) filter); @@ -1474,6 +1537,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { } } + @Override public Object getSelectedItem() { // Ensure that the current filter is in the list. // NOTE: we shouldn't have to do this, since JFileChooser adds @@ -1495,6 +1559,7 @@ class GTKFileChooserUI extends SynthFileChooserUI { return getFileChooser().getFileFilter(); } + @Override public int getSize() { if (filters != null) { return filters.length; diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java index 2a0aa7be41c..49062277086 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKGraphicsUtils.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -41,6 +41,7 @@ import sun.swing.MnemonicHandler; * @author Joshua Outwater */ class GTKGraphicsUtils extends SynthGraphicsUtils { + @Override public void paintText(SynthContext context, Graphics g, String text, int x, int y, int mnemonicIndex) { if (text == null || text.length() <= 0) { @@ -83,6 +84,7 @@ class GTKGraphicsUtils extends SynthGraphicsUtils { * @param bounds Bounds of the text to be drawn. * @param mnemonicIndex Index to draw string at. */ + @Override public void paintText(SynthContext context, Graphics g, String text, Rectangle bounds, int mnemonicIndex) { if (text == null || text.length() <= 0) { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java index 4f04d729099..ffd7df909b5 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKIconFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -163,6 +163,7 @@ class GTKIconFactory { this.method = methodName; } + @Override public void paintIcon(SynthContext context, Graphics g, int x, int y, int w, int h) { if (context != null) { @@ -171,10 +172,12 @@ class GTKIconFactory { } } + @Override public int getIconWidth(SynthContext context) { return getIconDimension(context); } + @Override public int getIconHeight(SynthContext context) { return getIconDimension(context); } @@ -248,6 +251,7 @@ class GTKIconFactory { super(method); } + @Override public void paintIcon(SynthContext context, Graphics g, int x, int y, int w, int h) { if (context != null) { @@ -256,6 +260,7 @@ class GTKIconFactory { } } + @Override int getIconDimension(SynthContext context) { updateSizeIfNecessary(context); return (iconDimension == -1) ? DEFAULT_ICON_SIZE : @@ -285,10 +290,12 @@ class GTKIconFactory { super(TOOL_BAR_HANDLE_ICON); } + @Override protected Class[] getMethodParamTypes() { return PARAM_TYPES; } + @Override public void paintIcon(SynthContext context, Graphics g, int x, int y, int w, int h) { if (context != null) { @@ -309,6 +316,7 @@ class GTKIconFactory { } } + @Override public int getIconWidth(SynthContext context) { if (context == null) { return 10; @@ -321,6 +329,7 @@ class GTKIconFactory { } } + @Override public int getIconHeight(SynthContext context) { if (context == null) { return 10; @@ -344,10 +353,12 @@ class GTKIconFactory { super(MENU_ARROW_ICON); } + @Override protected Class[] getMethodParamTypes() { return PARAM_TYPES; } + @Override public void paintIcon(SynthContext context, Graphics g, int x, int y, int w, int h) { if (context != null) { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java index 480b8bacb30..24a1997bdc1 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKLookAndFeel.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -261,6 +261,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { region == Region.TREE); } + @Override public UIDefaults getDefaults() { // We need to call super for basic's properties file. UIDefaults table = super.getDefaults(); @@ -301,6 +302,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "com.sun.java.swing.plaf.gtk.resources.gtk"); } + @Override protected void initComponentDefaults(UIDefaults table) { // For compatibility with apps expecting certain defaults we'll // populate the table with the values from basic. @@ -511,6 +513,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { FontLazyValue(Region region) { this.region = region; } + @Override public Object createValue(UIDefaults table) { SynthStyleFactory factory = getStyleFactory(); GTKStyle style = (GTKStyle)factory.getStyle(null, region); @@ -556,6 +559,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "ColorChooser.showPreviewPanelText", Boolean.FALSE, "ColorChooser.panels", new UIDefaults.ActiveValue() { + @Override public Object createValue(UIDefaults table) { return new AbstractColorChooserPanel[] { new GTKColorChooserPanel() }; @@ -1168,6 +1172,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "TitledBorder.titleColor", controlText, "TitledBorder.border", new UIDefaults.LazyValue() { + @Override public Object createValue(UIDefaults table) { return new GTKPainter.TitledBorder(); } @@ -1184,6 +1189,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { "ToolBar.separatorSize", new DimensionUIResource(10, 10), "ToolBar.handleIcon", new UIDefaults.ActiveValue() { + @Override public Object createValue(UIDefaults table) { return GTKIconFactory.getToolBarHandleIcon(); } @@ -1312,6 +1318,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { } } + @Override protected void initSystemColorDefaults(UIDefaults table) { SynthStyleFactory factory = getStyleFactory(); GTKStyle windowStyle = @@ -1492,6 +1499,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { public String getKey() { return key; } + @Override public void propertyChange(final PropertyChangeEvent pce) { final GTKLookAndFeel lnf = get(); @@ -1504,6 +1512,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { // We are using invokeLater here because we are getting called // on the AWT-Motif thread which can cause a deadlock. SwingUtilities.invokeLater(new Runnable() { + @Override public void run() { String name = pce.getPropertyName(); /* We are listening for GTK desktop text AA settings: @@ -1531,30 +1540,36 @@ public class GTKLookAndFeel extends SynthLookAndFeel { } } + @Override public boolean isSupportedLookAndFeel() { Toolkit toolkit = Toolkit.getDefaultToolkit(); return (toolkit instanceof SunToolkit && ((SunToolkit)toolkit).isNativeGTKAvailable()); } + @Override public boolean isNativeLookAndFeel() { return true; } + @Override public String getDescription() { return "GTK look and feel"; } + @Override public String getName() { return "GTK look and feel"; } + @Override public String getID() { return "GTK"; } // Subclassed to pass in false to the superclass, we don't want to try // and load the system colors. + @Override protected void loadSystemColors(UIDefaults table, String[] systemColors, boolean useNative) { super.loadSystemColors(table, systemColors, false); } @@ -1663,6 +1678,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { * SynthStyles from the SynthStyleFactory * when the ancestor changed. */ + @Override public boolean shouldUpdateStyleOnAncestorChanged() { return true; } @@ -1670,6 +1686,7 @@ public class GTKLookAndFeel extends SynthLookAndFeel { /** * {@inheritDoc} */ + @Override public LayoutStyle getLayoutStyle() { return GnomeLayoutStyle.INSTANCE; } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java index fa28eb3ca71..cf9cd0f2551 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKPainter.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -77,17 +77,20 @@ class GTKPainter extends SynthPainter { context.getComponent().getName(); } + @Override public void paintCheckBoxBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { paintRadioButtonBackground(context, g, x, y, w, h); } + @Override public void paintCheckBoxMenuItemBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { paintRadioButtonMenuItemBackground(context, g, x, y, w, h); } // FORMATTED_TEXT_FIELD + @Override public void paintFormattedTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -97,6 +100,7 @@ class GTKPainter extends SynthPainter { // // TOOL_BAR_DRAG_WINDOW // + @Override public void paintToolBarDragWindowBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -107,6 +111,7 @@ class GTKPainter extends SynthPainter { // // TOOL_BAR // + @Override public void paintToolBarBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -126,6 +131,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintToolBarContentBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -144,6 +150,7 @@ class GTKPainter extends SynthPainter { // // PASSWORD_FIELD // + @Override public void paintPasswordFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -153,6 +160,7 @@ class GTKPainter extends SynthPainter { // // TEXT_FIELD // + @Override public void paintTextFieldBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { if (getName(context) == "Tree.cellEditor") { @@ -166,6 +174,7 @@ class GTKPainter extends SynthPainter { // RADIO_BUTTON // // NOTE: this is called for JCheckBox too + @Override public void paintRadioButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -204,6 +213,7 @@ class GTKPainter extends SynthPainter { // RADIO_BUTTON_MENU_ITEM // // NOTE: this is called for JCheckBoxMenuItem too + @Override public void paintRadioButtonMenuItemBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -218,6 +228,7 @@ class GTKPainter extends SynthPainter { // // LABEL // + @Override public void paintLabelBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -247,6 +258,7 @@ class GTKPainter extends SynthPainter { // // INTERNAL_FRAME // + @Override public void paintInternalFrameBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -256,6 +268,7 @@ class GTKPainter extends SynthPainter { // // DESKTOP_PANE // + @Override public void paintDesktopPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -266,12 +279,14 @@ class GTKPainter extends SynthPainter { // // DESKTOP_ICON // + @Override public void paintDesktopIconBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { Metacity.INSTANCE.paintFrameBorder(context, g, x, y, w, h); } + @Override public void paintButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { String name = getName(context); @@ -388,6 +403,7 @@ class GTKPainter extends SynthPainter { // // ARROW_BUTTON // + @Override public void paintArrowButtonForeground(SynthContext context, Graphics g, int x, int y, int w, int h, int direction) { @@ -437,6 +453,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintArrowButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = context.getRegion(); @@ -515,12 +532,14 @@ class GTKPainter extends SynthPainter { // // LIST // + @Override public void paintListBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // Does not call into ENGINE for better performance fillArea(context, g, x, y, w, h, GTKColorType.TEXT_BACKGROUND); } + @Override public void paintMenuBarBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = context.getRegion(); @@ -544,6 +563,7 @@ class GTKPainter extends SynthPainter { // // MENU // + @Override public void paintMenuBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -551,6 +571,7 @@ class GTKPainter extends SynthPainter { } // This is called for both MENU and MENU_ITEM + @Override public void paintMenuItemBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -561,6 +582,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintPopupMenuBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = context.getRegion(); @@ -604,6 +626,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintProgressBarBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -618,6 +641,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintProgressBarForeground(SynthContext context, Graphics g, int x, int y, int w, int h, int orientation) { @@ -637,6 +661,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintViewportBorder(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = context.getRegion(); @@ -650,6 +675,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintSeparatorBackground(SynthContext context, Graphics g, int x, int y, int w, int h, @@ -768,6 +794,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintSliderTrackBackground(SynthContext context, Graphics g, int x, int y, int w,int h) { @@ -830,6 +857,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintSliderThumbBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int dir) { Region id = context.getRegion(); @@ -856,6 +884,7 @@ class GTKPainter extends SynthPainter { // // SPINNER // + @Override public void paintSpinnerBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -865,6 +894,7 @@ class GTKPainter extends SynthPainter { // // SPLIT_PANE_DIVIDER // + @Override public void paintSplitPaneDividerBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -886,12 +916,14 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintSplitPaneDragDivider(SynthContext context, Graphics g,int x, int y, int w, int h, int orientation) { paintSplitPaneDividerForeground(context, g, x, y, w, h, orientation); } + @Override public void paintTabbedPaneContentBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { JTabbedPane pane = (JTabbedPane)context.getComponent(); @@ -931,6 +963,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintTabbedPaneTabBackground(SynthContext context, Graphics g, int x, int y, int w, int h, @@ -958,6 +991,7 @@ class GTKPainter extends SynthPainter { // // TEXT_PANE // + @Override public void paintTextPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { paintTextAreaBackground(context, g, x, y, w, h); @@ -966,6 +1000,7 @@ class GTKPainter extends SynthPainter { // // EDITOR_PANE // + @Override public void paintEditorPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { paintTextAreaBackground(context, g, x, y, w, h); @@ -974,6 +1009,7 @@ class GTKPainter extends SynthPainter { // // TEXT_AREA // + @Override public void paintTextAreaBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // Does not call into ENGINE for better performance @@ -1076,6 +1112,7 @@ class GTKPainter extends SynthPainter { // // ROOT_PANE // + @Override public void paintRootPaneBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // Does not call into ENGINE for better performance @@ -1085,6 +1122,7 @@ class GTKPainter extends SynthPainter { // // TOGGLE_BUTTON // + @Override public void paintToggleButtonBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { @@ -1103,6 +1141,7 @@ class GTKPainter extends SynthPainter { // // SCROLL_BAR // + @Override public void paintScrollBarBackground(SynthContext context, Graphics g, int x, int y, int w,int h) { @@ -1148,6 +1187,7 @@ class GTKPainter extends SynthPainter { // // SCROLL_BAR_THUMB // + @Override public void paintScrollBarThumbBackground(SynthContext context, Graphics g, int x, int y, int w, int h, int dir) { Region id = context.getRegion(); @@ -1206,6 +1246,7 @@ class GTKPainter extends SynthPainter { // // TOOL_TIP // + @Override public void paintToolTipBackground(SynthContext context, Graphics g, int x, int y, int w,int h) { Region id = context.getRegion(); @@ -1224,6 +1265,7 @@ class GTKPainter extends SynthPainter { // // TREE_CELL // + @Override public void paintTreeCellBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = context.getRegion(); @@ -1243,6 +1285,7 @@ class GTKPainter extends SynthPainter { } } + @Override public void paintTreeCellFocus(SynthContext context, Graphics g, int x, int y, int w, int h) { Region id = Region.TREE_CELL; @@ -1254,6 +1297,7 @@ class GTKPainter extends SynthPainter { // // TREE // + @Override public void paintTreeBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // As far as I can tell, these don't call into the ENGINE. @@ -1264,6 +1308,7 @@ class GTKPainter extends SynthPainter { // // VIEWPORT // + @Override public void paintViewportBackground(SynthContext context, Graphics g, int x, int y, int w, int h) { // As far as I can tell, these don't call into the ENGINE. @@ -1509,6 +1554,7 @@ class GTKPainter extends SynthPainter { return context; } + @Override public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { if (focusedCell) { @@ -1523,6 +1569,7 @@ class GTKPainter extends SynthPainter { } } + @Override public Insets getBorderInsets(Component c, Insets i) { SynthContext context = getContext(c); @@ -1533,6 +1580,7 @@ class GTKPainter extends SynthPainter { return i; } + @Override public boolean isBorderOpaque() { return true; } @@ -1542,6 +1590,7 @@ class GTKPainter extends SynthPainter { @SuppressWarnings("serial") // Superclass is not serializable across versions static class TitledBorder extends AbstractBorder implements UIResource { + @Override public void paintBorder(Component c, Graphics g, int x, int y, int w, int h) { SynthContext context = getContext((JComponent)c); @@ -1559,11 +1608,13 @@ class GTKPainter extends SynthPainter { } } + @Override public Insets getBorderInsets(Component c, Insets i) { SynthContext context = getContext((JComponent)c); return context.getStyle().getInsets(context, i); } + @Override public boolean isBorderOpaque() { return true; } diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java index cc7a1333b64..baeb249eaa8 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -142,6 +142,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { return GTKPainter.INSTANCE; } + @Override protected Color getColorForState(SynthContext context, ColorType type) { if (type == ColorType.FOCUS || type == GTKColorType.BLACK) { return BLACK_COLOR; @@ -292,6 +293,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { return font; } + @Override protected Font getFontForState(SynthContext context) { Font propFont = UIManager .getFont(context.getRegion().getName() + ".font"); @@ -1053,6 +1055,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { this.size = size; } + @Override public void paintIcon(SynthContext context, Graphics g, int x, int y, int w, int h) { Icon icon = getIcon(context); @@ -1067,6 +1070,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { } } + @Override public int getIconWidth(SynthContext context) { Icon icon = getIcon(context); @@ -1076,6 +1080,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { return 0; } + @Override public int getIconHeight(SynthContext context) { Icon icon = getIcon(context); @@ -1135,6 +1140,7 @@ class GTKStyle extends SynthStyle implements GTKConstants { this.methodName = methodName; } + @Override @SuppressWarnings("deprecation") public Object createValue(UIDefaults table) { try { diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyleFactory.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyleFactory.java index 9683ba06788..4127e39c172 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyleFactory.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/GTKStyleFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -58,6 +58,7 @@ class GTKStyleFactory extends SynthStyleFactory { * @param c this parameter isn't used, may be null. * @param id of the region to get the style. */ + @Override public synchronized SynthStyle getStyle(JComponent c, Region id) { WidgetType wt = GTKEngine.getWidgetType(c, id); diff --git a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java index 4f7d19355c8..6e8f64b457d 100644 --- a/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java +++ b/src/java.desktop/share/classes/com/sun/java/swing/plaf/gtk/Metacity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -693,6 +693,7 @@ class Metacity implements SynthConstants { return new ImageIcon(context.getComponent().createImage(producer)).getImage(); } + @Override public int filterRGB(int x, int y, int rgb) { // Assume all rgb values are shades of gray double grayLevel = 2 * (rgb & 0xff) / 255.0; @@ -729,12 +730,16 @@ class Metacity implements SynthConstants { protected class TitlePaneLayout implements LayoutManager { + @Override public void addLayoutComponent(String name, Component c) {} + @Override public void removeLayoutComponent(Component c) {} + @Override public Dimension preferredLayoutSize(Container c) { return minimumLayoutSize(c); } + @Override public Dimension minimumLayoutSize(Container c) { JComponent titlePane = (JComponent)c; Container titlePaneParent = titlePane.getParent(); @@ -794,6 +799,7 @@ class Metacity implements SynthConstants { return new Dimension(width, height); } + @Override public void layoutContainer(Container c) { JComponent titlePane = (JComponent)c; Container titlePaneParent = titlePane.getParent(); @@ -1943,10 +1949,12 @@ class Metacity implements SynthConstants { return token; } + @Override public boolean hasMoreTokens() { return (token != null || super.hasMoreTokens()); } + @Override public String nextToken() { if (token != null) { String t = token; @@ -2000,18 +2008,22 @@ class Metacity implements SynthConstants { this.archeight = arch; } + @Override public double getX() { return (double)x; } + @Override public double getY() { return (double)y; } + @Override public double getWidth() { return (double)width; } + @Override public double getHeight() { return (double)height; } @@ -2024,10 +2036,12 @@ class Metacity implements SynthConstants { return (double)archeight; } + @Override public boolean isEmpty() { return false; // Not called } + @Override public Rectangle2D getBounds2D() { return null; // Not called } @@ -2036,10 +2050,12 @@ class Metacity implements SynthConstants { return corners; } + @Override public void setFrame(double x, double y, double w, double h) { // Not called } + @Override public boolean contains(double x, double y) { return false; // Not called } @@ -2048,14 +2064,17 @@ class Metacity implements SynthConstants { return 0; // Not called } + @Override public boolean intersects(double x, double y, double w, double h) { return false; // Not called } + @Override public boolean contains(double x, double y, double w, double h) { return false; // Not called } + @Override public PathIterator getPathIterator(AffineTransform at) { return new RoundishRectIterator(this, at); } @@ -2148,18 +2167,22 @@ class Metacity implements SynthConstants { } } + @Override public int getWindingRule() { return WIND_NON_ZERO; } + @Override public boolean isDone() { return index >= ctrlpts.length; } + @Override public void next() { index++; } + @Override public int currentSegment(float[] coords) { if (isDone()) { throw new NoSuchElementException("roundrect iterator out of bounds"); @@ -2176,6 +2199,7 @@ class Metacity implements SynthConstants { return types[index]; } + @Override public int currentSegment(double[] coords) { if (isDone()) { throw new NoSuchElementException("roundrect iterator out of bounds"); From 5141e1a4f4ef7499ddd8684469d8038fd75403d2 Mon Sep 17 00:00:00 2001 From: Anton Artemov Date: Mon, 15 Dec 2025 08:39:47 +0000 Subject: [PATCH 093/211] 8373497: SpinCriticalSection should use SpinYield Reviewed-by: dholmes, coleenp --- .../share/utilities/spinCriticalSection.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/utilities/spinCriticalSection.cpp b/src/hotspot/share/utilities/spinCriticalSection.cpp index 0bbbc82c12b..4064c234e97 100644 --- a/src/hotspot/share/utilities/spinCriticalSection.cpp +++ b/src/hotspot/share/utilities/spinCriticalSection.cpp @@ -24,30 +24,19 @@ #include "runtime/atomicAccess.hpp" #include "utilities/spinCriticalSection.hpp" +#include "utilities/spinYield.hpp" void SpinCriticalSection::spin_acquire(volatile int* adr) { if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) { return; // normal fast-path return } + SpinYield sy(4096, 5, millis_to_nanos(1)); + // Slow-path : We've encountered contention -- Spin/Yield/Block strategy. - int ctr = 0; - int Yields = 0; for (;;) { while (*adr != 0) { - ++ctr; - if ((ctr & 0xFFF) == 0 || !os::is_MP()) { - if (Yields > 5) { - os::naked_short_sleep(1); - } - else { - os::naked_yield(); - ++Yields; - } - } - else { - SpinPause(); - } + sy.wait(); } if (AtomicAccess::cmpxchg(adr, 0, 1) == 0) return; } From 895232fc65cab9ba3863b48cab27b688096a7435 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Mon, 15 Dec 2025 08:40:05 +0000 Subject: [PATCH 094/211] 8372731: Detailed authentication failure messages Reviewed-by: dfuchs, michaelm --- .../www/protocol/http/AuthenticationInfo.java | 8 +- .../protocol/http/BasicAuthentication.java | 6 +- .../protocol/http/DigestAuthentication.java | 58 +++--- .../www/protocol/http/HttpURLConnection.java | 60 +++++-- .../http/NegotiateAuthentication.java | 29 ++- .../http/ntlm/NTLMAuthentication.java | 15 +- .../protocol/http/ntlm/NTLMAuthSequence.java | 3 +- .../http/ntlm/NTLMAuthentication.java | 11 +- .../windows/native/libnet/NTLMAuthSequence.c | 4 + .../net/www/protocol/http/NTLMFailTest.java | 167 ++++++++++++++++++ 10 files changed, 276 insertions(+), 85 deletions(-) create mode 100644 test/jdk/sun/net/www/protocol/http/NTLMFailTest.java diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java index f567d7bd643..9c9766e2ce2 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2025, 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 @@ package sun.net.www.protocol.http; +import java.io.IOException; import java.net.PasswordAuthentication; import java.net.URL; import java.util.HashMap; @@ -428,9 +429,10 @@ public abstract class AuthenticationInfo extends AuthCacheValue implements Clone * @param conn The connection to apply the header(s) to * @param p A source of header values for this connection, if needed. * @param raw The raw header field (if needed) - * @return true if all goes well, false if no headers were set. + * @throws IOException if no headers were set */ - public abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw); + public abstract void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) + throws IOException; /** * Check if the header indicates that the current auth. parameters are stale. diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java index f008c185b5d..aa2a9625a01 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/BasicAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -125,15 +125,13 @@ final class BasicAuthentication extends AuthenticationInfo { * @param conn The connection to apply the header(s) to * @param p A source of header values for this connection, if needed. * @param raw The raw header values for this connection, if needed. - * @return true if all goes well, false if no headers were set. */ @Override - public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { // no need to synchronize here: // already locked by s.n.w.p.h.HttpURLConnection assert conn.isLockHeldByCurrentThread(); conn.setAuthenticationProperty(getHeaderName(), getHeaderValue(null,null)); - return true; } /** diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java index 28d7bc5cf4e..87ea7c17085 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/DigestAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -321,7 +321,11 @@ final class DigestAuthentication extends AuthenticationInfo { */ @Override public String getHeaderValue(URL url, String method) { - return getHeaderValueImpl(url.getFile(), method); + try { + return getHeaderValueImpl(url.getFile(), method); + } catch (IOException _) { + return null; + } } /** @@ -339,7 +343,11 @@ final class DigestAuthentication extends AuthenticationInfo { * @return the value of the HTTP header this authentication wants set */ String getHeaderValue(String requestURI, String method) { - return getHeaderValueImpl(requestURI, method); + try { + return getHeaderValueImpl(requestURI, method); + } catch (IOException _) { + return null; + } } /** @@ -369,10 +377,11 @@ final class DigestAuthentication extends AuthenticationInfo { * @param conn The connection to apply the header(s) to * @param p A source of header values for this connection, if needed. * @param raw Raw header values for this connection, if needed. - * @return true if all goes well, false if no headers were set. + * @throws IOException if no headers were set */ @Override - public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) + throws IOException { // no need to synchronize here: // already locked by s.n.w.p.h.HttpURLConnection assert conn.isLockHeldByCurrentThread(); @@ -380,14 +389,14 @@ final class DigestAuthentication extends AuthenticationInfo { params.setNonce (p.findValue("nonce")); params.setOpaque (p.findValue("opaque")); params.setQop (p.findValue("qop")); - params.setUserhash (Boolean.valueOf(p.findValue("userhash"))); + params.setUserhash (Boolean.parseBoolean(p.findValue("userhash"))); String charset = p.findValue("charset"); if (charset == null) { charset = "ISO_8859_1"; } else if (!charset.equalsIgnoreCase("UTF-8")) { // UTF-8 is only valid value. ISO_8859_1 represents default behavior // when the parameter is not set. - return false; + throw new IOException("Illegal charset in header"); } params.setCharset(charset.toUpperCase(Locale.ROOT)); @@ -405,7 +414,7 @@ final class DigestAuthentication extends AuthenticationInfo { } if (params.nonce == null || authMethod == null || pw == null || realm == null) { - return false; + throw new IOException("Server challenge incomplete"); } if (authMethod.length() >= 1) { // Method seems to get converted to all lower case elsewhere. @@ -415,8 +424,7 @@ final class DigestAuthentication extends AuthenticationInfo { + authMethod.substring(1).toLowerCase(Locale.ROOT); } - if (!setAlgorithmNames(p, params)) - return false; + setAlgorithmNames(p, params); // If authQop is true, then the server is doing RFC2617 and // has offered qop=auth. We do not support any other modes @@ -426,20 +434,17 @@ final class DigestAuthentication extends AuthenticationInfo { params.setNewCnonce(); } - String value = getHeaderValueImpl (uri, method); - if (value != null) { - conn.setAuthenticationProperty(getHeaderName(), value); - return true; - } else { - return false; - } + String value = getHeaderValueImpl(uri, method); + assert value != null; + conn.setAuthenticationProperty(getHeaderName(), value); } // Algorithm name is stored in two separate fields (of Paramaeters) // This allows for variations in digest algorithm name (aliases) // and also allow for the -sess variant defined in HTTP Digest protocol - // returns false if algorithm not supported - private static boolean setAlgorithmNames(HeaderParser p, Parameters params) { + // throws IOException if algorithm not supported + private static void setAlgorithmNames(HeaderParser p, Parameters params) + throws IOException { String algorithm = p.findValue("algorithm"); String digestName = algorithm; if (algorithm == null || algorithm.isEmpty()) { @@ -459,18 +464,17 @@ final class DigestAuthentication extends AuthenticationInfo { var oid = KnownOIDs.findMatch(digestName); if (oid == null) { log("unknown algorithm: " + algorithm); - return false; + throw new IOException("Unknown algorithm: " + algorithm); } digestName = oid.stdName(); params.setAlgorithm (algorithm); params.setDigestName (digestName); - return true; } /* Calculate the Authorization header field given the request URI * and based on the authorization information in params */ - private String getHeaderValueImpl (String uri, String method) { + private String getHeaderValueImpl (String uri, String method) throws IOException { String response; char[] passwd = pw.getPassword(); boolean qop = params.authQop(); @@ -479,11 +483,7 @@ final class DigestAuthentication extends AuthenticationInfo { String nonce = params.getNonce (); String algorithm = params.getAlgorithm (); String digest = params.getDigestName (); - try { - validateDigest(digest); - } catch (IOException e) { - return null; - } + validateDigest(digest); Charset charset = params.getCharset(); boolean userhash = params.getUserhash (); params.incrementNC (); @@ -505,7 +505,7 @@ final class DigestAuthentication extends AuthenticationInfo { digest, session, charset); } catch (CharacterCodingException | NoSuchAlgorithmException ex) { log(ex.getMessage()); - return null; + throw new IOException("Failed to compute digest", ex); } String ncfield = "\""; @@ -534,7 +534,7 @@ final class DigestAuthentication extends AuthenticationInfo { } } catch (CharacterCodingException | NoSuchAlgorithmException ex) { log(ex.getMessage()); - return null; + throw new IOException("Failed to compute user hash", ex); } String value = authMethod diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java index aee9670ce26..89ad0cc48ed 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/HttpURLConnection.java @@ -61,6 +61,7 @@ import java.util.Set; import java.util.StringJoiner; import jdk.internal.access.JavaNetHttpCookieAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.util.Exceptions; import sun.net.NetProperties; import sun.net.NetworkClient; import sun.net.util.IPAddressUtil; @@ -1469,16 +1470,29 @@ public class HttpURLConnection extends java.net.HttpURLConnection { /* in this case, only one header field will be present */ String raw = responses.findValue ("Proxy-Authenticate"); reset (); - if (!proxyAuthentication.setHeaders(this, - authhdr.headerParser(), raw)) { + try { + proxyAuthentication.setHeaders(this, + authhdr.headerParser(), raw); + } catch (IOException ex) { disconnectInternal(); - throw new IOException ("Authentication failure"); + if (Exceptions.enhancedNonSocketExceptions()) { + throw new IOException ("Authentication failure", ex); + } else { + throw new IOException ("Authentication failure"); + } } - if (serverAuthentication != null && srvHdr != null && - !serverAuthentication.setHeaders(this, - srvHdr.headerParser(), raw)) { - disconnectInternal (); - throw new IOException ("Authentication failure"); + if (serverAuthentication != null && srvHdr != null) { + try { + serverAuthentication.setHeaders(this, + srvHdr.headerParser(), raw); + } catch (IOException ex) { + disconnectInternal(); + if (Exceptions.enhancedNonSocketExceptions()) { + throw new IOException ("Authentication failure", ex); + } else { + throw new IOException ("Authentication failure"); + } + } } authObj = null; doingNTLMp2ndStage = false; @@ -1557,9 +1571,15 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } else { reset (); /* header not used for ntlm */ - if (!serverAuthentication.setHeaders(this, null, raw)) { + try { + serverAuthentication.setHeaders(this, null, raw); + } catch (IOException ex) { disconnectWeb(); - throw new IOException ("Authentication failure"); + if (Exceptions.enhancedNonSocketExceptions()) { + throw new IOException ("Authentication failure", ex); + } else { + throw new IOException ("Authentication failure"); + } } doingNTLM2ndStage = false; authObj = null; @@ -1935,10 +1955,16 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } else { String raw = responses.findValue ("Proxy-Authenticate"); reset (); - if (!proxyAuthentication.setHeaders(this, - authhdr.headerParser(), raw)) { + try { + proxyAuthentication.setHeaders(this, + authhdr.headerParser(), raw); + } catch (IOException ex) { disconnectInternal(); - throw new IOException ("Authentication failure"); + if (Exceptions.enhancedNonSocketExceptions()) { + throw new IOException ("Authentication failure", ex); + } else { + throw new IOException ("Authentication failure"); + } } authObj = null; doingNTLMp2ndStage = false; @@ -2201,7 +2227,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { }; } if (ret != null) { - if (!ret.setHeaders(this, p, raw)) { + try { + ret.setHeaders(this, p, raw); + } catch (IOException e) { ret.disposeContext(); ret = null; } @@ -2358,7 +2386,9 @@ public class HttpURLConnection extends java.net.HttpURLConnection { } } if (ret != null ) { - if (!ret.setHeaders(this, p, raw)) { + try { + ret.setHeaders(this, p, raw); + } catch (IOException e) { ret.disposeContext(); ret = null; } diff --git a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java index c27d866f5ef..c016b0dae29 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java +++ b/src/java.base/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -168,29 +168,24 @@ final class NegotiateAuthentication extends AuthenticationInfo { * @param p A source of header values for this connection, not used because * HeaderParser converts the fields to lower case, use raw instead * @param raw The raw header field. - * @return true if all goes well, false if no headers were set. + * @throws IOException if no headers were set */ @Override - public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) throws IOException { // no need to synchronize here: // already locked by s.n.w.p.h.HttpURLConnection assert conn.isLockHeldByCurrentThread(); - try { - String response; - byte[] incoming = null; - String[] parts = raw.split("\\s+"); - if (parts.length > 1) { - incoming = Base64.getDecoder().decode(parts[1]); - } - response = hci.scheme + " " + Base64.getEncoder().encodeToString( - incoming==null?firstToken():nextToken(incoming)); - - conn.setAuthenticationProperty(getHeaderName(), response); - return true; - } catch (IOException e) { - return false; + String response; + byte[] incoming = null; + String[] parts = raw.split("\\s+"); + if (parts.length > 1) { + incoming = Base64.getDecoder().decode(parts[1]); } + response = hci.scheme + " " + Base64.getEncoder().encodeToString( + incoming==null?firstToken():nextToken(incoming)); + + conn.setAuthenticationProperty(getHeaderName(), response); } /** diff --git a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index dc56abb86df..efe72fc760f 100644 --- a/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/java.base/unix/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -35,7 +35,6 @@ import java.net.URL; import java.security.GeneralSecurityException; import java.util.Base64; import java.util.Locale; -import java.util.Properties; import sun.net.www.HeaderParser; import sun.net.www.protocol.http.AuthenticationInfo; @@ -203,10 +202,10 @@ public final class NTLMAuthentication extends AuthenticationInfo { * @param p A source of header values for this connection, not used because * HeaderParser converts the fields to lower case, use raw instead * @param raw The raw header field. - * @return true if all goes well, false if no headers were set. + * @throws IOException if no headers were set */ @Override - public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) throws IOException { // no need to synchronize here: // already locked by s.n.w.p.h.HttpURLConnection assert conn.isLockHeldByCurrentThread(); @@ -220,9 +219,8 @@ public final class NTLMAuthentication extends AuthenticationInfo { response = buildType3Msg (msg); } conn.setAuthenticationProperty(getHeaderName(), response); - return true; - } catch (IOException | GeneralSecurityException e) { - return false; + } catch (GeneralSecurityException e) { + throw new IOException(e); } } @@ -232,8 +230,7 @@ public final class NTLMAuthentication extends AuthenticationInfo { return result; } - private String buildType3Msg (String challenge) throws GeneralSecurityException, - IOException { + private String buildType3Msg (String challenge) throws GeneralSecurityException { /* First decode the type2 message to get the server nonce */ /* nonce is located at type2[24] for 8 bytes */ diff --git a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java index 517b4801e2c..76890045724 100644 --- a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java +++ b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java @@ -91,6 +91,7 @@ public class NTLMAuthSequence { private native long getCredentialsHandle (String user, String domain, String password); - private native byte[] getNextToken (long crdHandle, byte[] lastToken, Status returned); + private native byte[] getNextToken (long crdHandle, byte[] lastToken, Status returned) + throws IOException; } diff --git a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java index a7056082e12..75a9dc027b1 100644 --- a/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java +++ b/src/java.base/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -26,9 +26,7 @@ package sun.net.www.protocol.http.ntlm; import java.io.IOException; -import java.net.InetAddress; import java.net.PasswordAuthentication; -import java.net.UnknownHostException; import java.net.URL; import java.util.Locale; import sun.net.NetProperties; @@ -204,10 +202,10 @@ public final class NTLMAuthentication extends AuthenticationInfo { * @param p A source of header values for this connection, not used because * HeaderParser converts the fields to lower case, use raw instead * @param raw The raw header field. - * @return true if all goes well, false if no headers were set. + * @throws IOException if no headers were set */ @Override - public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) { + public void setHeaders(HttpURLConnection conn, HeaderParser p, String raw) throws IOException { // no need to synchronize here: // already locked by s.n.w.p.h.HttpURLConnection @@ -224,10 +222,9 @@ public final class NTLMAuthentication extends AuthenticationInfo { if (seq.isComplete()) { conn.authObj(null); } - return true; } catch (IOException e) { conn.authObj(null); - return false; + throw e; } } } diff --git a/src/java.base/windows/native/libnet/NTLMAuthSequence.c b/src/java.base/windows/native/libnet/NTLMAuthSequence.c index 507409e0ae6..c058c8ad234 100644 --- a/src/java.base/windows/native/libnet/NTLMAuthSequence.c +++ b/src/java.base/windows/native/libnet/NTLMAuthSequence.c @@ -230,6 +230,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequenc } if (ss < 0) { + SetLastError(ss); + JNU_ThrowIOExceptionWithLastError(env, "InitializeSecurityContext"); endSequence (pCred, pCtx, env, status); return 0; } @@ -238,6 +240,8 @@ JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequenc ss = CompleteAuthToken( pCtx, &OutBuffDesc ); if (ss < 0) { + SetLastError(ss); + JNU_ThrowIOExceptionWithLastError(env, "CompleteAuthToken"); endSequence (pCred, pCtx, env, status); return 0; } diff --git a/test/jdk/sun/net/www/protocol/http/NTLMFailTest.java b/test/jdk/sun/net/www/protocol/http/NTLMFailTest.java new file mode 100644 index 00000000000..86db3d400da --- /dev/null +++ b/test/jdk/sun/net/www/protocol/http/NTLMFailTest.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8372731 + * @library /test/lib + * @run main/othervm NTLMFailTest + * @run main/othervm -Djdk.includeInExceptions= NTLMFailTest + * @summary check that the Authentication failure exception + * honors the jdk.includeInExceptions setting + */ + +import jdk.test.lib.net.HttpHeaderParser; +import jdk.test.lib.net.URIBuilder; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.Authenticator; +import java.net.HttpURLConnection; +import java.net.InetAddress; +import java.net.PasswordAuthentication; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; + +public class NTLMFailTest { + + static final int BODY_LEN = 8192; + + static final String RESP_SERVER_AUTH = + "HTTP/1.1 401 Unauthorized\r\n" + + "WWW-Authenticate: NTLM\r\n" + + "Connection: close\r\n" + + "Content-Length: " + BODY_LEN + "\r\n" + + "\r\n"; + + static final String RESP_SERVER_NTLM = + "HTTP/1.1 401 Unauthorized\r\n" + + "WWW-Authenticate: NTLM InvalidChallenge\r\n" + + "Connection: Keep-Alive\r\n" + + "Content-Length: " + BODY_LEN + "\r\n" + + "\r\n"; + + public static void main(String[] args) throws Exception { + Authenticator.setDefault(new TestAuthenticator()); + try (NTLMServer server = startServer(new ServerSocket(0, 0, InetAddress.getLoopbackAddress()))) { + URL url = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(server.getLocalPort()) + .path("/") + .toURLUnchecked(); + HttpURLConnection uc = (HttpURLConnection) url.openConnection(); + uc.setRequestMethod("HEAD"); + uc.getInputStream().readAllBytes(); + throw new RuntimeException("Expected exception was not thrown"); + } catch (IOException e) { + if (e.getMessage().contains("Authentication failure")) { + System.err.println("Got expected exception:"); + e.printStackTrace(); + if (System.getProperty("jdk.includeInExceptions") == null) { + // detailed message enabled by default + if (e.getCause() == null) { + throw new RuntimeException("Expected a detailed exception", e); + } + // no checks on the detailed message; it's platform-specific and may be translated + } else { + // detailed message disabled + if (e.getCause() != null) { + throw new RuntimeException("Unexpected detailed exception", e); + } + } + } else { + throw e; + } + } + } + + static class NTLMServer extends Thread implements AutoCloseable { + final ServerSocket ss; + volatile boolean closed; + + NTLMServer(ServerSocket serverSS) { + super(); + setDaemon(true); + this.ss = serverSS; + } + + int getLocalPort() { return ss.getLocalPort(); } + + @Override + public void run() { + boolean doing2ndStageNTLM = false; + while (!closed) { + try { + Socket s = ss.accept(); + InputStream is = s.getInputStream(); + OutputStream os = s.getOutputStream(); + doServer(is, os, doing2ndStageNTLM); + if (!doing2ndStageNTLM) { + doing2ndStageNTLM = true; + } else { + os.close(); + } + } catch (IOException ioe) { + if (!closed) { + ioe.printStackTrace(); + } + } + } + } + + @Override + public void close() { + if (closed) return; + synchronized(this) { + if (closed) return; + closed = true; + } + try { ss.close(); } catch (IOException x) { }; + } + } + + static NTLMServer startServer(ServerSocket serverSS) { + NTLMServer server = new NTLMServer(serverSS); + server.start(); + return server; + } + + static void doServer(InputStream is, OutputStream os, boolean doing2ndStageNTLM) throws IOException { + if (!doing2ndStageNTLM) { + new HttpHeaderParser(is); + os.write(RESP_SERVER_AUTH.getBytes("ASCII")); + } else { + new HttpHeaderParser(is); + os.write(RESP_SERVER_NTLM.getBytes("ASCII")); + } + } + + static class TestAuthenticator extends Authenticator { + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("test", "secret".toCharArray()); + } + } +} From ad6611a9a3fd5f9cf8b73ce3ccf976187e344654 Mon Sep 17 00:00:00 2001 From: Fredrik Bredberg Date: Mon, 15 Dec 2025 08:55:08 +0000 Subject: [PATCH 095/211] 8371347: Move the ObjectMonitorTable to a separate new file Reviewed-by: dholmes, coleenp --- .../share/runtime/objectMonitorTable.cpp | 308 ++++++++++++++++++ .../share/runtime/objectMonitorTable.hpp | 77 +++++ src/hotspot/share/runtime/synchronizer.cpp | 286 +--------------- 3 files changed, 386 insertions(+), 285 deletions(-) create mode 100644 src/hotspot/share/runtime/objectMonitorTable.cpp create mode 100644 src/hotspot/share/runtime/objectMonitorTable.hpp diff --git a/src/hotspot/share/runtime/objectMonitorTable.cpp b/src/hotspot/share/runtime/objectMonitorTable.cpp new file mode 100644 index 00000000000..9b522720a28 --- /dev/null +++ b/src/hotspot/share/runtime/objectMonitorTable.cpp @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2024, 2025, 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. + * + */ + +#include "logging/log.hpp" +#include "runtime/interfaceSupport.inline.hpp" +#include "runtime/javaThread.hpp" +#include "runtime/mutexLocker.hpp" +#include "runtime/objectMonitorTable.hpp" +#include "runtime/safepoint.hpp" +#include "runtime/thread.hpp" +#include "runtime/timerTrace.hpp" +#include "runtime/trimNativeHeap.hpp" +#include "utilities/concurrentHashTableTasks.inline.hpp" +#include "utilities/globalDefinitions.hpp" + +// ----------------------------------------------------------------------------- +// ConcurrentHashTable storing links from objects to ObjectMonitors + +using ConcurrentTable = ConcurrentHashTable; + +static ConcurrentTable* _table = nullptr; +static volatile size_t _items_count = 0; +static size_t _table_size = 0; +static volatile bool _resize = false; + +class ObjectMonitorTableConfig : public AllStatic { + public: + using Value = ObjectMonitor*; + static uintx get_hash(Value const& value, bool* is_dead) { + return (uintx)value->hash(); + } + static void* allocate_node(void* context, size_t size, Value const& value) { + ObjectMonitorTable::inc_items_count(); + return AllocateHeap(size, mtObjectMonitor); + }; + static void free_node(void* context, void* memory, Value const& value) { + ObjectMonitorTable::dec_items_count(); + FreeHeap(memory); + } +}; + +class Lookup : public StackObj { + oop _obj; + + public: + explicit Lookup(oop obj) : _obj(obj) {} + + uintx get_hash() const { + uintx hash = _obj->mark().hash(); + assert(hash != 0, "should have a hash"); + return hash; + } + + bool equals(ObjectMonitor** value) { + assert(*value != nullptr, "must be"); + return (*value)->object_refers_to(_obj); + } + + bool is_dead(ObjectMonitor** value) { + assert(*value != nullptr, "must be"); + return false; + } +}; + +class LookupMonitor : public StackObj { + ObjectMonitor* _monitor; + + public: + explicit LookupMonitor(ObjectMonitor* monitor) : _monitor(monitor) {} + + uintx get_hash() const { + return _monitor->hash(); + } + + bool equals(ObjectMonitor** value) { + return (*value) == _monitor; + } + + bool is_dead(ObjectMonitor** value) { + assert(*value != nullptr, "must be"); + return (*value)->object_is_dead(); + } +}; + +void ObjectMonitorTable::inc_items_count() { + AtomicAccess::inc(&_items_count, memory_order_relaxed); +} + +void ObjectMonitorTable::dec_items_count() { + AtomicAccess::dec(&_items_count, memory_order_relaxed); +} + +double ObjectMonitorTable::get_load_factor() { + size_t count = AtomicAccess::load(&_items_count); + return (double)count / (double)_table_size; +} + +size_t ObjectMonitorTable::table_size(Thread* current) { + return ((size_t)1) << _table->get_size_log2(current); +} + +size_t ObjectMonitorTable::max_log_size() { + // TODO[OMTable]: Evaluate the max size. + // TODO[OMTable]: Need to fix init order to use Universe::heap()->max_capacity(); + // Using MaxHeapSize directly this early may be wrong, and there + // are definitely rounding errors (alignment). + const size_t max_capacity = MaxHeapSize; + const size_t min_object_size = CollectedHeap::min_dummy_object_size() * HeapWordSize; + const size_t max_objects = max_capacity / MAX2(MinObjAlignmentInBytes, checked_cast(min_object_size)); + const size_t log_max_objects = log2i_graceful(max_objects); + + return MAX2(MIN2(SIZE_BIG_LOG2, log_max_objects), min_log_size()); +} + +// ~= log(AvgMonitorsPerThreadEstimate default) +size_t ObjectMonitorTable::min_log_size() { + return 10; +} + +template +size_t ObjectMonitorTable::clamp_log_size(V log_size) { + return MAX2(MIN2(log_size, checked_cast(max_log_size())), checked_cast(min_log_size())); +} + +size_t ObjectMonitorTable::initial_log_size() { + const size_t estimate = log2i(MAX2(os::processor_count(), 1)) + log2i(MAX2(AvgMonitorsPerThreadEstimate, size_t(1))); + return clamp_log_size(estimate); +} + +size_t ObjectMonitorTable::grow_hint() { + return ConcurrentTable::DEFAULT_GROW_HINT; +} + +void ObjectMonitorTable::create() { + _table = new ConcurrentTable(initial_log_size(), max_log_size(), grow_hint()); + _items_count = 0; + _table_size = table_size(Thread::current()); + _resize = false; +} + +void ObjectMonitorTable::verify_monitor_get_result(oop obj, ObjectMonitor* monitor) { +#ifdef ASSERT + if (SafepointSynchronize::is_at_safepoint()) { + bool has_monitor = obj->mark().has_monitor(); + assert(has_monitor == (monitor != nullptr), + "Inconsistency between markWord and ObjectMonitorTable has_monitor: %s monitor: " PTR_FORMAT, + BOOL_TO_STR(has_monitor), p2i(monitor)); + } +#endif +} + +ObjectMonitor* ObjectMonitorTable::monitor_get(Thread* current, oop obj) { + ObjectMonitor* result = nullptr; + Lookup lookup_f(obj); + auto found_f = [&](ObjectMonitor** found) { + assert((*found)->object_peek() == obj, "must be"); + result = *found; + }; + _table->get(current, lookup_f, found_f); + verify_monitor_get_result(obj, result); + return result; +} + +void ObjectMonitorTable::try_notify_grow() { + if (!_table->is_max_size_reached() && !AtomicAccess::load(&_resize)) { + AtomicAccess::store(&_resize, true); + if (Service_lock->try_lock()) { + Service_lock->notify(); + Service_lock->unlock(); + } + } +} + +bool ObjectMonitorTable::should_grow() { + return get_load_factor() > GROW_LOAD_FACTOR && !_table->is_max_size_reached(); +} + +bool ObjectMonitorTable::should_resize() { + return should_grow() || should_shrink() || AtomicAccess::load(&_resize); +} + +template +bool ObjectMonitorTable::run_task(JavaThread* current, Task& task, const char* task_name, Args&... args) { + if (task.prepare(current)) { + log_trace(monitortable)("Started to %s", task_name); + TraceTime timer(task_name, TRACETIME_LOG(Debug, monitortable, perf)); + while (task.do_task(current, args...)) { + task.pause(current); + { + ThreadBlockInVM tbivm(current); + } + task.cont(current); + } + task.done(current); + return true; + } + return false; +} + +bool ObjectMonitorTable::grow(JavaThread* current) { + ConcurrentTable::GrowTask grow_task(_table); + if (run_task(current, grow_task, "Grow")) { + _table_size = table_size(current); + log_info(monitortable)("Grown to size: %zu", _table_size); + return true; + } + return false; +} + +bool ObjectMonitorTable::clean(JavaThread* current) { + ConcurrentTable::BulkDeleteTask clean_task(_table); + auto is_dead = [&](ObjectMonitor** monitor) { + return (*monitor)->object_is_dead(); + }; + auto do_nothing = [&](ObjectMonitor** monitor) {}; + NativeHeapTrimmer::SuspendMark sm("ObjectMonitorTable"); + return run_task(current, clean_task, "Clean", is_dead, do_nothing); +} + +bool ObjectMonitorTable::resize(JavaThread* current) { + LogTarget(Info, monitortable) lt; + bool success = false; + + if (should_grow()) { + lt.print("Start growing with load factor %f", get_load_factor()); + success = grow(current); + } else { + if (!_table->is_max_size_reached() && AtomicAccess::load(&_resize)) { + lt.print("WARNING: Getting resize hints with load factor %f", get_load_factor()); + } + lt.print("Start cleaning with load factor %f", get_load_factor()); + success = clean(current); + } + + AtomicAccess::store(&_resize, false); + + return success; +} + +ObjectMonitor* ObjectMonitorTable::monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj) { + // Enter the monitor into the concurrent hashtable. + ObjectMonitor* result = monitor; + Lookup lookup_f(obj); + auto found_f = [&](ObjectMonitor** found) { + assert((*found)->object_peek() == obj, "must be"); + result = *found; + }; + bool grow; + _table->insert_get(current, lookup_f, monitor, found_f, &grow); + verify_monitor_get_result(obj, result); + if (grow) { + try_notify_grow(); + } + return result; +} + +bool ObjectMonitorTable::remove_monitor_entry(Thread* current, ObjectMonitor* monitor) { + LookupMonitor lookup_f(monitor); + return _table->remove(current, lookup_f); +} + +bool ObjectMonitorTable::contains_monitor(Thread* current, ObjectMonitor* monitor) { + LookupMonitor lookup_f(monitor); + bool result = false; + auto found_f = [&](ObjectMonitor** found) { + result = true; + }; + _table->get(current, lookup_f, found_f); + return result; +} + +void ObjectMonitorTable::print_on(outputStream* st) { + auto printer = [&] (ObjectMonitor** entry) { + ObjectMonitor* om = *entry; + oop obj = om->object_peek(); + st->print("monitor=" PTR_FORMAT ", ", p2i(om)); + st->print("object=" PTR_FORMAT, p2i(obj)); + assert(obj->mark().hash() == om->hash(), "hash must match"); + st->cr(); + return true; + }; + if (SafepointSynchronize::is_at_safepoint()) { + _table->do_safepoint_scan(printer); + } else { + _table->do_scan(Thread::current(), printer); + } +} diff --git a/src/hotspot/share/runtime/objectMonitorTable.hpp b/src/hotspot/share/runtime/objectMonitorTable.hpp new file mode 100644 index 00000000000..146468d46b2 --- /dev/null +++ b/src/hotspot/share/runtime/objectMonitorTable.hpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2024, 2025, 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. + * + */ + +#ifndef SHARE_RUNTIME_OBJECTMONITORTABLE_HPP +#define SHARE_RUNTIME_OBJECTMONITORTABLE_HPP + +#include "memory/allStatic.hpp" +#include "oops/oopsHierarchy.hpp" +#include "utilities/globalDefinitions.hpp" + +class JavaThread; +class ObjectMonitor; +class ObjectMonitorTableConfig; +class outputStream; +class Thread; + +class ObjectMonitorTable : AllStatic { + friend class ObjectMonitorTableConfig; + + private: + static void inc_items_count(); + static void dec_items_count(); + static double get_load_factor(); + static size_t table_size(Thread* current); + static size_t max_log_size(); + static size_t min_log_size(); + + template + static size_t clamp_log_size(V log_size); + static size_t initial_log_size(); + static size_t grow_hint(); + + public: + static void create(); + static void verify_monitor_get_result(oop obj, ObjectMonitor* monitor); + static ObjectMonitor* monitor_get(Thread* current, oop obj); + static void try_notify_grow(); + static bool should_shrink() { return false; } // Not implemented + + static constexpr double GROW_LOAD_FACTOR = 0.75; + + static bool should_grow(); + static bool should_resize(); + + template + static bool run_task(JavaThread* current, Task& task, const char* task_name, Args&... args); + static bool grow(JavaThread* current); + static bool clean(JavaThread* current); + static bool resize(JavaThread* current); + static ObjectMonitor* monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj); + static bool remove_monitor_entry(Thread* current, ObjectMonitor* monitor); + static bool contains_monitor(Thread* current, ObjectMonitor* monitor); + static void print_on(outputStream* st); +}; + +#endif // SHARE_RUNTIME_OBJECTMONITORTABLE_HPP diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index fe95320c574..fde1aa50400 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -44,6 +44,7 @@ #include "runtime/lockStack.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/objectMonitor.inline.hpp" +#include "runtime/objectMonitorTable.hpp" #include "runtime/os.inline.hpp" #include "runtime/osThread.hpp" #include "runtime/safepointMechanism.inline.hpp" @@ -1470,291 +1471,6 @@ void ObjectSynchronizer::log_in_use_monitor_details(outputStream* out, bool log_ out->flush(); } -// ----------------------------------------------------------------------------- -// ConcurrentHashTable storing links from objects to ObjectMonitors -class ObjectMonitorTable : AllStatic { - struct Config { - using Value = ObjectMonitor*; - static uintx get_hash(Value const& value, bool* is_dead) { - return (uintx)value->hash(); - } - static void* allocate_node(void* context, size_t size, Value const& value) { - ObjectMonitorTable::inc_items_count(); - return AllocateHeap(size, mtObjectMonitor); - }; - static void free_node(void* context, void* memory, Value const& value) { - ObjectMonitorTable::dec_items_count(); - FreeHeap(memory); - } - }; - using ConcurrentTable = ConcurrentHashTable; - - static ConcurrentTable* _table; - static volatile size_t _items_count; - static size_t _table_size; - static volatile bool _resize; - - class Lookup : public StackObj { - oop _obj; - - public: - explicit Lookup(oop obj) : _obj(obj) {} - - uintx get_hash() const { - uintx hash = _obj->mark().hash(); - assert(hash != 0, "should have a hash"); - return hash; - } - - bool equals(ObjectMonitor** value) { - assert(*value != nullptr, "must be"); - return (*value)->object_refers_to(_obj); - } - - bool is_dead(ObjectMonitor** value) { - assert(*value != nullptr, "must be"); - return false; - } - }; - - class LookupMonitor : public StackObj { - ObjectMonitor* _monitor; - - public: - explicit LookupMonitor(ObjectMonitor* monitor) : _monitor(monitor) {} - - uintx get_hash() const { - return _monitor->hash(); - } - - bool equals(ObjectMonitor** value) { - return (*value) == _monitor; - } - - bool is_dead(ObjectMonitor** value) { - assert(*value != nullptr, "must be"); - return (*value)->object_is_dead(); - } - }; - - static void inc_items_count() { - AtomicAccess::inc(&_items_count, memory_order_relaxed); - } - - static void dec_items_count() { - AtomicAccess::dec(&_items_count, memory_order_relaxed); - } - - static double get_load_factor() { - size_t count = AtomicAccess::load(&_items_count); - return (double)count / (double)_table_size; - } - - static size_t table_size(Thread* current = Thread::current()) { - return ((size_t)1) << _table->get_size_log2(current); - } - - static size_t max_log_size() { - // TODO[OMTable]: Evaluate the max size. - // TODO[OMTable]: Need to fix init order to use Universe::heap()->max_capacity(); - // Using MaxHeapSize directly this early may be wrong, and there - // are definitely rounding errors (alignment). - const size_t max_capacity = MaxHeapSize; - const size_t min_object_size = CollectedHeap::min_dummy_object_size() * HeapWordSize; - const size_t max_objects = max_capacity / MAX2(MinObjAlignmentInBytes, checked_cast(min_object_size)); - const size_t log_max_objects = log2i_graceful(max_objects); - - return MAX2(MIN2(SIZE_BIG_LOG2, log_max_objects), min_log_size()); - } - - static size_t min_log_size() { - // ~= log(AvgMonitorsPerThreadEstimate default) - return 10; - } - - template - static size_t clamp_log_size(V log_size) { - return MAX2(MIN2(log_size, checked_cast(max_log_size())), checked_cast(min_log_size())); - } - - static size_t initial_log_size() { - const size_t estimate = log2i(MAX2(os::processor_count(), 1)) + log2i(MAX2(AvgMonitorsPerThreadEstimate, size_t(1))); - return clamp_log_size(estimate); - } - - static size_t grow_hint () { - return ConcurrentTable::DEFAULT_GROW_HINT; - } - - public: - static void create() { - _table = new ConcurrentTable(initial_log_size(), max_log_size(), grow_hint()); - _items_count = 0; - _table_size = table_size(); - _resize = false; - } - - static void verify_monitor_get_result(oop obj, ObjectMonitor* monitor) { -#ifdef ASSERT - if (SafepointSynchronize::is_at_safepoint()) { - bool has_monitor = obj->mark().has_monitor(); - assert(has_monitor == (monitor != nullptr), - "Inconsistency between markWord and ObjectMonitorTable has_monitor: %s monitor: " PTR_FORMAT, - BOOL_TO_STR(has_monitor), p2i(monitor)); - } -#endif - } - - static ObjectMonitor* monitor_get(Thread* current, oop obj) { - ObjectMonitor* result = nullptr; - Lookup lookup_f(obj); - auto found_f = [&](ObjectMonitor** found) { - assert((*found)->object_peek() == obj, "must be"); - result = *found; - }; - _table->get(current, lookup_f, found_f); - verify_monitor_get_result(obj, result); - return result; - } - - static void try_notify_grow() { - if (!_table->is_max_size_reached() && !AtomicAccess::load(&_resize)) { - AtomicAccess::store(&_resize, true); - if (Service_lock->try_lock()) { - Service_lock->notify(); - Service_lock->unlock(); - } - } - } - - static bool should_shrink() { - // Not implemented; - return false; - } - - static constexpr double GROW_LOAD_FACTOR = 0.75; - - static bool should_grow() { - return get_load_factor() > GROW_LOAD_FACTOR && !_table->is_max_size_reached(); - } - - static bool should_resize() { - return should_grow() || should_shrink() || AtomicAccess::load(&_resize); - } - - template - static bool run_task(JavaThread* current, Task& task, const char* task_name, Args&... args) { - if (task.prepare(current)) { - log_trace(monitortable)("Started to %s", task_name); - TraceTime timer(task_name, TRACETIME_LOG(Debug, monitortable, perf)); - while (task.do_task(current, args...)) { - task.pause(current); - { - ThreadBlockInVM tbivm(current); - } - task.cont(current); - } - task.done(current); - return true; - } - return false; - } - - static bool grow(JavaThread* current) { - ConcurrentTable::GrowTask grow_task(_table); - if (run_task(current, grow_task, "Grow")) { - _table_size = table_size(current); - log_info(monitortable)("Grown to size: %zu", _table_size); - return true; - } - return false; - } - - static bool clean(JavaThread* current) { - ConcurrentTable::BulkDeleteTask clean_task(_table); - auto is_dead = [&](ObjectMonitor** monitor) { - return (*monitor)->object_is_dead(); - }; - auto do_nothing = [&](ObjectMonitor** monitor) {}; - NativeHeapTrimmer::SuspendMark sm("ObjectMonitorTable"); - return run_task(current, clean_task, "Clean", is_dead, do_nothing); - } - - static bool resize(JavaThread* current) { - LogTarget(Info, monitortable) lt; - bool success = false; - - if (should_grow()) { - lt.print("Start growing with load factor %f", get_load_factor()); - success = grow(current); - } else { - if (!_table->is_max_size_reached() && AtomicAccess::load(&_resize)) { - lt.print("WARNING: Getting resize hints with load factor %f", get_load_factor()); - } - lt.print("Start cleaning with load factor %f", get_load_factor()); - success = clean(current); - } - - AtomicAccess::store(&_resize, false); - - return success; - } - - static ObjectMonitor* monitor_put_get(Thread* current, ObjectMonitor* monitor, oop obj) { - // Enter the monitor into the concurrent hashtable. - ObjectMonitor* result = monitor; - Lookup lookup_f(obj); - auto found_f = [&](ObjectMonitor** found) { - assert((*found)->object_peek() == obj, "must be"); - result = *found; - }; - bool grow; - _table->insert_get(current, lookup_f, monitor, found_f, &grow); - verify_monitor_get_result(obj, result); - if (grow) { - try_notify_grow(); - } - return result; - } - - static bool remove_monitor_entry(Thread* current, ObjectMonitor* monitor) { - LookupMonitor lookup_f(monitor); - return _table->remove(current, lookup_f); - } - - static bool contains_monitor(Thread* current, ObjectMonitor* monitor) { - LookupMonitor lookup_f(monitor); - bool result = false; - auto found_f = [&](ObjectMonitor** found) { - result = true; - }; - _table->get(current, lookup_f, found_f); - return result; - } - - static void print_on(outputStream* st) { - auto printer = [&] (ObjectMonitor** entry) { - ObjectMonitor* om = *entry; - oop obj = om->object_peek(); - st->print("monitor=" PTR_FORMAT ", ", p2i(om)); - st->print("object=" PTR_FORMAT, p2i(obj)); - assert(obj->mark().hash() == om->hash(), "hash must match"); - st->cr(); - return true; - }; - if (SafepointSynchronize::is_at_safepoint()) { - _table->do_safepoint_scan(printer); - } else { - _table->do_scan(Thread::current(), printer); - } - } -}; - -ObjectMonitorTable::ConcurrentTable* ObjectMonitorTable::_table = nullptr; -volatile size_t ObjectMonitorTable::_items_count = 0; -size_t ObjectMonitorTable::_table_size = 0; -volatile bool ObjectMonitorTable::_resize = false; - ObjectMonitor* ObjectSynchronizer::get_or_insert_monitor_from_table(oop object, JavaThread* current, bool* inserted) { ObjectMonitor* monitor = get_monitor_from_table(current, object); if (monitor != nullptr) { From 3559eeca0edd537c6160c6753cf6fc304afee4ca Mon Sep 17 00:00:00 2001 From: Hamlin Li Date: Mon, 15 Dec 2025 09:10:51 +0000 Subject: [PATCH 096/211] 8373428: Refine variables with the same name in nested scopes in PhaseChaitin::gather_lrg_masks Reviewed-by: phh --- src/hotspot/share/opto/chaitin.cpp | 40 +++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/opto/chaitin.cpp b/src/hotspot/share/opto/chaitin.cpp index 667270d96b4..3ba3ffc1045 100644 --- a/src/hotspot/share/opto/chaitin.cpp +++ b/src/hotspot/share/opto/chaitin.cpp @@ -1076,8 +1076,8 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // Prepare register mask for each input for( uint k = input_edge_start; k < cnt; k++ ) { - uint vreg = _lrg_map.live_range_id(n->in(k)); - if (!vreg) { + uint vreg_in = _lrg_map.live_range_id(n->in(k)); + if (!vreg_in) { continue; } @@ -1099,7 +1099,7 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { if (k >= cur_node->num_opnds()) continue; } - LRG &lrg = lrgs(vreg); + LRG &lrg_in = lrgs(vreg_in); // // Testing for floating point code shape // Node *test = n->in(k); // if( test->is_Mach() ) { @@ -1114,25 +1114,25 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // Do not limit registers from uncommon uses before // AggressiveCoalesce. This effectively pre-virtual-splits // around uncommon uses of common defs. - const RegMask &rm = n->in_RegMask(k); + const RegMask &rm_in = n->in_RegMask(k); if (!after_aggressive && _cfg.get_block_for_node(n->in(k))->_freq > 1000 * block->_freq) { // Since we are BEFORE aggressive coalesce, leave the register // mask untrimmed by the call. This encourages more coalescing. // Later, AFTER aggressive, this live range will have to spill // but the spiller handles slow-path calls very nicely. } else { - lrg.and_with(rm); + lrg_in.and_with(rm_in); } // Check for bound register masks - const RegMask &lrgmask = lrg.mask(); + const RegMask &lrgmask_in = lrg_in.mask(); uint kreg = n->in(k)->ideal_reg(); bool is_vect = RegMask::is_vector(kreg); assert(n->in(k)->bottom_type()->isa_vect() == nullptr || is_vect || kreg == Op_RegD || kreg == Op_RegL || kreg == Op_RegVectMask, "vector must be in vector registers"); - if (lrgmask.is_bound(kreg)) - lrg._is_bound = 1; + if (lrgmask_in.is_bound(kreg)) + lrg_in._is_bound = 1; // If this use of a double forces a mis-aligned double, // flag as '_fat_proj' - really flag as allowing misalignment @@ -1141,30 +1141,30 @@ void PhaseChaitin::gather_lrg_masks( bool after_aggressive ) { // FOUR registers! #ifdef ASSERT if (is_vect && !_scheduling_info_generated) { - if (lrg.num_regs() != 0) { - assert(lrgmask.is_aligned_sets(lrg.num_regs()), "vector should be aligned"); - assert(!lrg._fat_proj, "sanity"); - assert(RegMask::num_registers(kreg) == lrg.num_regs(), "sanity"); + if (lrg_in.num_regs() != 0) { + assert(lrgmask_in.is_aligned_sets(lrg_in.num_regs()), "vector should be aligned"); + assert(!lrg_in._fat_proj, "sanity"); + assert(RegMask::num_registers(kreg) == lrg_in.num_regs(), "sanity"); } else { assert(n->is_Phi(), "not all inputs processed only if Phi"); } } #endif - if (!is_vect && lrg.num_regs() == 2 && !lrg._fat_proj && rm.is_misaligned_pair()) { - lrg._fat_proj = 1; - lrg._is_bound = 1; + if (!is_vect && lrg_in.num_regs() == 2 && !lrg_in._fat_proj && rm_in.is_misaligned_pair()) { + lrg_in._fat_proj = 1; + lrg_in._is_bound = 1; } // if the LRG is an unaligned pair, we will have to spill // so clear the LRG's register mask if it is not already spilled if (!is_vect && !n->is_SpillCopy() && - (lrg._def == nullptr || lrg.is_multidef() || !lrg._def->is_SpillCopy()) && - lrgmask.is_misaligned_pair()) { - lrg.clear(); + (lrg_in._def == nullptr || lrg_in.is_multidef() || !lrg_in._def->is_SpillCopy()) && + lrgmask_in.is_misaligned_pair()) { + lrg_in.clear(); } // Check for maximum frequency value - if (lrg._maxfreq < block->_freq) { - lrg._maxfreq = block->_freq; + if (lrg_in._maxfreq < block->_freq) { + lrg_in._maxfreq = block->_freq; } } // End for all allocated inputs From 629bf20f59f98a735ca22018ad00c93580aff5f3 Mon Sep 17 00:00:00 2001 From: Casper Norrbin Date: Mon, 15 Dec 2025 10:23:31 +0000 Subject: [PATCH 097/211] 8371408: [Linux] VM.info output for container information is confusing Reviewed-by: sgehwolf, dholmes --- .../os/linux/cgroupV1Subsystem_linux.cpp | 6 +- .../os/linux/cgroupV2Subsystem_linux.cpp | 4 +- src/hotspot/os/linux/osContainer_linux.cpp | 34 +++++++++-- src/hotspot/os/linux/osContainer_linux.hpp | 2 + src/hotspot/os/linux/os_linux.cpp | 59 ++++++++----------- .../containers/docker/TestContainerInfo.java | 16 +---- .../containers/docker/TestLimitsUpdating.java | 12 ++-- .../docker/TestMemoryAwareness.java | 6 +- .../jtreg/containers/docker/TestMisc.java | 22 +++---- .../containers/docker/DockerTestUtils.java | 11 ++++ 10 files changed, 95 insertions(+), 77 deletions(-) diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index ddcb0db2161..2df604083d2 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -467,9 +467,9 @@ void CgroupV1MemoryController::print_version_specific_info(outputStream* st, phy kmem_max_usage.set_value(temp); } - OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit_in_bytes"); - OSContainer::print_container_helper(st, kmem_usage, "kernel_memory_usage_in_bytes"); - OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_max_usage_in_bytes"); + OSContainer::print_container_helper(st, kmem_limit, "kernel_memory_limit"); + OSContainer::print_container_helper(st, kmem_usage, "kernel_memory_usage"); + OSContainer::print_container_helper(st, kmem_max_usage, "kernel_memory_max_usage"); } char* CgroupV1Subsystem::cpu_cpuset_cpus() { diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index f435e53c02c..c61d30e9236 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -378,8 +378,8 @@ void CgroupV2MemoryController::print_version_specific_info(outputStream* st, phy if (memory_swap_limit_value(reader(), swap_limit_val)) { swap_limit.set_value(swap_limit_val); } - OSContainer::print_container_helper(st, swap_current, "memory_swap_current_in_bytes"); - OSContainer::print_container_helper(st, swap_limit, "memory_swap_max_limit_in_bytes"); + OSContainer::print_container_helper(st, swap_current, "memory_swap_current"); + OSContainer::print_container_helper(st, swap_limit, "memory_swap_max_limit"); } char* CgroupV2Controller::construct_path(char* mount_path, const char* cgroup_path) { diff --git a/src/hotspot/os/linux/osContainer_linux.cpp b/src/hotspot/os/linux/osContainer_linux.cpp index d86bbf7428a..15a6403d07f 100644 --- a/src/hotspot/os/linux/osContainer_linux.cpp +++ b/src/hotspot/os/linux/osContainer_linux.cpp @@ -287,20 +287,44 @@ bool OSContainer::pids_current(uint64_t& value) { return cgroup_subsystem->pids_current(value); } +template struct metric_fmt; +template<> struct metric_fmt { static constexpr const char* fmt = "%llu"; }; +template<> struct metric_fmt { static constexpr const char* fmt = "%lu"; }; +template<> struct metric_fmt { static constexpr const char* fmt = "%d"; }; +template<> struct metric_fmt { static constexpr const char* fmt = "%s"; }; + +template void OSContainer::print_container_metric(outputStream*, const char*, unsigned long long int, const char*); +template void OSContainer::print_container_metric(outputStream*, const char*, unsigned long int, const char*); +template void OSContainer::print_container_metric(outputStream*, const char*, int, const char*); +template void OSContainer::print_container_metric(outputStream*, const char*, const char*, const char*); + +template +void OSContainer::print_container_metric(outputStream* st, const char* metrics, T value, const char* unit) { + constexpr int max_length = 38; // Longest "metric: value" string ("maximum number of tasks: not supported") + constexpr int longest_value = max_length - 11; // Max length - shortest "metric: " string ("cpu_quota: ") + char value_str[longest_value + 1] = {}; + os::snprintf_checked(value_str, longest_value, metric_fmt::fmt, value); + st->print("%s: %*s", metrics, max_length - static_cast(strlen(metrics)) - 2, value_str); // -2 for the ": " + if (unit[0] != '\0') { + st->print_cr(" %s", unit); + } else { + st->print_cr(""); + } +} + void OSContainer::print_container_helper(outputStream* st, MetricResult& res, const char* metrics) { - st->print("%s: ", metrics); if (res.success()) { if (res.value() != value_unlimited) { if (res.value() >= 1024) { - st->print_cr(PHYS_MEM_TYPE_FORMAT " k", (physical_memory_size_type)(res.value() / K)); + print_container_metric(st, metrics, res.value() / K, "kB"); } else { - st->print_cr(PHYS_MEM_TYPE_FORMAT, res.value()); + print_container_metric(st, metrics, res.value(), "B"); } } else { - st->print_cr("%s", "unlimited"); + print_container_metric(st, metrics, "unlimited"); } } else { // Not supported - st->print_cr("%s", "unavailable"); + print_container_metric(st, metrics, "unavailable"); } } diff --git a/src/hotspot/os/linux/osContainer_linux.hpp b/src/hotspot/os/linux/osContainer_linux.hpp index 895c99ba167..11c3e086feb 100644 --- a/src/hotspot/os/linux/osContainer_linux.hpp +++ b/src/hotspot/os/linux/osContainer_linux.hpp @@ -65,6 +65,8 @@ class OSContainer: AllStatic { static void init(); static void print_version_specific_info(outputStream* st); static void print_container_helper(outputStream* st, MetricResult& res, const char* metrics); + template + static void print_container_metric(outputStream* st, const char* metrics, T value, const char* unit = ""); static inline bool is_containerized(); static const char * container_type(); diff --git a/src/hotspot/os/linux/os_linux.cpp b/src/hotspot/os/linux/os_linux.cpp index 8af89bb3a71..7f6b4851013 100644 --- a/src/hotspot/os/linux/os_linux.cpp +++ b/src/hotspot/os/linux/os_linux.cpp @@ -2432,62 +2432,57 @@ bool os::Linux::print_container_info(outputStream* st) { st->print_cr("container (cgroup) information:"); const char *p_ct = OSContainer::container_type(); - st->print_cr("container_type: %s", p_ct != nullptr ? p_ct : "not supported"); + OSContainer::print_container_metric(st, "container_type", p_ct != nullptr ? p_ct : "not supported"); char *p = OSContainer::cpu_cpuset_cpus(); - st->print_cr("cpu_cpuset_cpus: %s", p != nullptr ? p : "not supported"); + OSContainer::print_container_metric(st, "cpu_cpuset_cpus", p != nullptr ? p : "not supported"); free(p); p = OSContainer::cpu_cpuset_memory_nodes(); - st->print_cr("cpu_memory_nodes: %s", p != nullptr ? p : "not supported"); + OSContainer::print_container_metric(st, "cpu_memory_nodes", p != nullptr ? p : "not supported"); free(p); int i = -1; bool supported = OSContainer::active_processor_count(i); - st->print("active_processor_count: "); if (supported) { assert(i > 0, "must be"); if (ActiveProcessorCount > 0) { - st->print_cr("%d, but overridden by -XX:ActiveProcessorCount %d", i, ActiveProcessorCount); + OSContainer::print_container_metric(st, "active_processor_count", ActiveProcessorCount, "(from -XX:ActiveProcessorCount)"); } else { - st->print_cr("%d", i); + OSContainer::print_container_metric(st, "active_processor_count", i); } } else { - st->print_cr("not supported"); + OSContainer::print_container_metric(st, "active_processor_count", "not supported"); } supported = OSContainer::cpu_quota(i); - st->print("cpu_quota: "); if (supported && i > 0) { - st->print_cr("%d", i); + OSContainer::print_container_metric(st, "cpu_quota", i); } else { - st->print_cr("%s", !supported ? "not supported" : "no quota"); + OSContainer::print_container_metric(st, "cpu_quota", !supported ? "not supported" : "no quota"); } supported = OSContainer::cpu_period(i); - st->print("cpu_period: "); if (supported && i > 0) { - st->print_cr("%d", i); + OSContainer::print_container_metric(st, "cpu_period", i); } else { - st->print_cr("%s", !supported ? "not supported" : "no period"); + OSContainer::print_container_metric(st, "cpu_period", !supported ? "not supported" : "no period"); } supported = OSContainer::cpu_shares(i); - st->print("cpu_shares: "); if (supported && i > 0) { - st->print_cr("%d", i); + OSContainer::print_container_metric(st, "cpu_shares", i); } else { - st->print_cr("%s", !supported ? "not supported" : "no shares"); + OSContainer::print_container_metric(st, "cpu_shares", !supported ? "not supported" : "no shares"); } uint64_t j = 0; supported = OSContainer::cpu_usage_in_micros(j); - st->print("cpu_usage_in_micros: "); if (supported && j > 0) { - st->print_cr(UINT64_FORMAT, j); + OSContainer::print_container_metric(st, "cpu_usage", j, "us"); } else { - st->print_cr("%s", !supported ? "not supported" : "no usage"); + OSContainer::print_container_metric(st, "cpu_usage", !supported ? "not supported" : "no usage"); } MetricResult memory_limit; @@ -2530,31 +2525,29 @@ bool os::Linux::print_container_info(outputStream* st) { if (OSContainer::cache_usage_in_bytes(val)) { cache_usage.set_value(val); } - OSContainer::print_container_helper(st, memory_limit, "memory_limit_in_bytes"); - OSContainer::print_container_helper(st, mem_swap_limit, "memory_and_swap_limit_in_bytes"); - OSContainer::print_container_helper(st, mem_soft_limit, "memory_soft_limit_in_bytes"); - OSContainer::print_container_helper(st, mem_throttle_limit, "memory_throttle_limit_in_bytes"); - OSContainer::print_container_helper(st, mem_usage, "memory_usage_in_bytes"); - OSContainer::print_container_helper(st, mem_max_usage, "memory_max_usage_in_bytes"); - OSContainer::print_container_helper(st, rss_usage, "rss_usage_in_bytes"); - OSContainer::print_container_helper(st, cache_usage, "cache_usage_in_bytes"); + OSContainer::print_container_helper(st, memory_limit, "memory_limit"); + OSContainer::print_container_helper(st, mem_swap_limit, "memory_and_swap_limit"); + OSContainer::print_container_helper(st, mem_soft_limit, "memory_soft_limit"); + OSContainer::print_container_helper(st, mem_throttle_limit, "memory_throttle_limit"); + OSContainer::print_container_helper(st, mem_usage, "memory_usage"); + OSContainer::print_container_helper(st, mem_max_usage, "memory_max_usage"); + OSContainer::print_container_helper(st, rss_usage, "rss_usage"); + OSContainer::print_container_helper(st, cache_usage, "cache_usage"); OSContainer::print_version_specific_info(st); supported = OSContainer::pids_max(j); - st->print("maximum number of tasks: "); if (supported && j != value_unlimited) { - st->print_cr(UINT64_FORMAT, j); + OSContainer::print_container_metric(st, "maximum number of tasks", j); } else { - st->print_cr("%s", !supported ? "not supported" : "unlimited"); + OSContainer::print_container_metric(st, "maximum number of tasks", !supported ? "not supported" : "unlimited"); } supported = OSContainer::pids_current(j); - st->print("current number of tasks: "); if (supported && j > 0) { - st->print_cr(UINT64_FORMAT, j); + OSContainer::print_container_metric(st, "current number of tasks", j); } else { - st->print_cr("%s", !supported ? "not supported" : "no current tasks"); + OSContainer::print_container_metric(st, "current number of tasks", !supported ? "not supported" : "no tasks"); } return true; diff --git a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java index a5579aa9528..5e7a0000cf5 100644 --- a/test/hotspot/jtreg/containers/docker/TestContainerInfo.java +++ b/test/hotspot/jtreg/containers/docker/TestContainerInfo.java @@ -73,23 +73,11 @@ public class TestContainerInfo { checkContainerInfo(out); } - private static void shouldMatchWithValue(OutputAnalyzer output, String match, String value) { - output.shouldContain(match); - String str = output.getOutput(); - for (String s : str.split(System.lineSeparator())) { - if (s.contains(match)) { - if (!s.contains(value)) { - throw new RuntimeException("memory_swap_current_in_bytes NOT " + value + "! Line was : " + s); - } - } - } - } - private static void checkContainerInfo(OutputAnalyzer out) throws Exception { String str = out.getOutput(); if (str.contains("cgroupv2")) { - shouldMatchWithValue(out, "memory_swap_max_limit_in_bytes", "0"); - shouldMatchWithValue(out, "memory_swap_current_in_bytes", "0"); + DockerTestUtils.shouldMatchWithValue(out, "memory_swap_max_limit", "0"); + DockerTestUtils.shouldMatchWithValue(out, "memory_swap_current", "0"); } else { throw new SkippedException("This test is cgroups v2 specific, skipped on cgroups v1"); } diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index df8ba5b6161..db8f4fd1826 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -128,12 +128,12 @@ public class TestLimitsUpdating { // Do assertions based on the output in target container OutputAnalyzer targetOut = out[0]; - targetOut.shouldContain("active_processor_count: 2"); // initial value - targetOut.shouldContain("active_processor_count: 3"); // updated value - targetOut.shouldContain("memory_limit_in_bytes: 512000 k"); // initial value - targetOut.shouldContain("memory_and_swap_limit_in_bytes: 512000 k"); // initial value - targetOut.shouldContain("memory_limit_in_bytes: 307200 k"); // updated value - targetOut.shouldContain("memory_and_swap_limit_in_bytes: 307200 k"); // updated value + DockerTestUtils.shouldMatchWithValue(targetOut, "active_processor_count", "2"); // initial value + DockerTestUtils.shouldMatchWithValue(targetOut, "active_processor_count", "3"); // updated value + DockerTestUtils.shouldMatchWithValue(targetOut, "memory_limit", "512000 kB"); // initial value + DockerTestUtils.shouldMatchWithValue(targetOut, "memory_and_swap_limit", "512000 kB"); // initial value + DockerTestUtils.shouldMatchWithValue(targetOut, "memory_limit", "307200 kB"); // updated value + DockerTestUtils.shouldMatchWithValue(targetOut, "memory_and_swap_limit", "307200 kB"); // updated value } private static List getContainerUpdate(int cpuQuota, int cpuPeriod, String memory) { diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index 4cf895156fe..6034aefcd6e 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -169,11 +169,11 @@ public class TestMemoryAwareness { opts.addDockerOpts("--memory-swap=" + swapToSet); Common.run(opts) - .shouldMatch("memory_limit_in_bytes:.*" + expectedMem) - .shouldNotMatch("memory_and_swap_limit_in_bytes:.*not supported") + .shouldMatch("memory_limit:.*" + expectedMem) + .shouldNotMatch("memory_and_swap_limit:.*not supported") // On systems with swapaccount=0 this returns the memory limit. // On systems with swapaccount=1 this returns the set memory+swap value. - .shouldMatch("memory_and_swap_limit_in_bytes:.*(" + expectedMem + "|" + expectedSwap + ")"); + .shouldMatch("memory_and_swap_limit:.*(" + expectedMem + "|" + expectedSwap + ")"); } /* diff --git a/test/hotspot/jtreg/containers/docker/TestMisc.java b/test/hotspot/jtreg/containers/docker/TestMisc.java index fca3cef5513..794bbc7b355 100644 --- a/test/hotspot/jtreg/containers/docker/TestMisc.java +++ b/test/hotspot/jtreg/containers/docker/TestMisc.java @@ -127,10 +127,10 @@ public class TestMisc { // mapping function. if (numberMatch) { int valueExpected = isCgroupV2 ? expected : cpuShares; - out.shouldContain("cpu_shares: " + valueExpected); + DockerTestUtils.shouldMatchWithValue(out, "cpu_shares", String.valueOf(valueExpected)); } else { // must not print "no shares" - out.shouldNotContain("cpu_shares: no shares"); + DockerTestUtils.shouldNotMatchWithValue(out, "cpu_shares", "no shares"); } } @@ -141,7 +141,7 @@ public class TestMisc { Common.addWhiteBoxOpts(opts); OutputAnalyzer out = Common.run(opts); - out.shouldContain("but overridden by -XX:ActiveProcessorCount 2"); + DockerTestUtils.shouldMatchWithValue(out, "active_processor_count", "2 (from -XX:ActiveProcessorCount)"); } private static void checkContainerInfo(OutputAnalyzer out) throws Exception { @@ -158,11 +158,11 @@ public class TestMisc { "Memory Throttle Limit", "Memory Usage", "Maximum Memory Usage", - "memory_max_usage_in_bytes", + "memory_max_usage", "maximum number of tasks", "current number of tasks", - "rss_usage_in_bytes", - "cache_usage_in_bytes" + "rss_usage", + "cache_usage" }; for (String s : expectedToContain) { @@ -170,13 +170,13 @@ public class TestMisc { } String str = out.getOutput(); if (str.contains("cgroupv1")) { - out.shouldContain("kernel_memory_usage_in_bytes"); - out.shouldContain("kernel_memory_max_usage_in_bytes"); - out.shouldContain("kernel_memory_limit_in_bytes"); + out.shouldContain("kernel_memory_usage"); + out.shouldContain("kernel_memory_max_usage"); + out.shouldContain("kernel_memory_limit"); } else { if (str.contains("cgroupv2")) { - out.shouldContain("memory_swap_current_in_bytes"); - out.shouldContain("memory_swap_max_limit_in_bytes"); + out.shouldContain("memory_swap_current"); + out.shouldContain("memory_swap_max_limit"); } else { throw new RuntimeException("Output has to contain information about cgroupv1 or cgroupv2"); } diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index ec3e6d773b1..22a8572af46 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -38,6 +38,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.regex.Pattern; import jdk.internal.platform.Metrics; import jdk.test.lib.Container; import jdk.test.lib.Utils; @@ -341,6 +342,16 @@ public class DockerTestUtils { return output; } + public static void shouldMatchWithValue(OutputAnalyzer output, String metric, String value) throws Exception { + String pattern = "^" + Pattern.quote(metric) + ":\\s*" + Pattern.quote(value) + ".*$"; + output.shouldMatch(pattern); + } + + public static void shouldNotMatchWithValue(OutputAnalyzer output, String metric, String value) throws Exception { + String pattern = "^" + Pattern.quote(metric) + ":\\s*" + Pattern.quote(value) + ".*$"; + output.shouldNotMatch(pattern); + } + private static void writeOutputToFile(String output, String fileName) throws Exception { try (FileWriter fw = new FileWriter(fileName)) { From f5187ebf7a4d4241f01612b62c514a1e4e272658 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Mon, 15 Dec 2025 12:57:03 +0000 Subject: [PATCH 098/211] 8373599: Cleanup arguments.hpp includes Reviewed-by: coleenp, kbarrett --- .../compiler/compilerDefinitions.inline.hpp | 1 + .../share/runtime/abstract_vm_version.cpp | 1 + src/hotspot/share/runtime/arguments.cpp | 11 ++++++++++ src/hotspot/share/runtime/arguments.hpp | 21 +++++++----------- src/hotspot/share/runtime/java.cpp | 21 ++++++++++++++++++ src/hotspot/share/runtime/java.hpp | 22 +++++-------------- test/hotspot/gtest/runtime/test_arguments.cpp | 1 + 7 files changed, 48 insertions(+), 30 deletions(-) diff --git a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp index 21bf80549f4..8bf70477cb3 100644 --- a/src/hotspot/share/compiler/compilerDefinitions.inline.hpp +++ b/src/hotspot/share/compiler/compilerDefinitions.inline.hpp @@ -29,6 +29,7 @@ #include "compiler/compiler_globals.hpp" #include "runtime/arguments.hpp" +#include "runtime/globals.hpp" inline bool CompilerConfig::is_interpreter_only() { return Arguments::is_interpreter_only() || TieredStopAtLevel == CompLevel_none; diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 3860307f8df..54c8c917fb3 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -26,6 +26,7 @@ #include "compiler/compilerDefinitions.hpp" #include "jvm_io.h" #include "runtime/arguments.hpp" +#include "runtime/os.hpp" #include "runtime/vm_version.hpp" #include "utilities/globalDefinitions.hpp" diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index d4ba599fa9b..cf0a1ab9757 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1092,6 +1092,13 @@ void Arguments::print_summary_on(outputStream* st) { st->cr(); } +void Arguments::set_jvm_flags_file(const char *value) { + if (_jvm_flags_file != nullptr) { + os::free(_jvm_flags_file); + } + _jvm_flags_file = os::strdup_check_oom(value); +} + void Arguments::print_jvm_flags_on(outputStream* st) { if (_num_jvm_flags > 0) { for (int i=0; i < _num_jvm_flags; i++) { @@ -2844,6 +2851,10 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args, JVMFlagOrigin return JNI_OK; } +void Arguments::set_ext_dirs(char *value) { + _ext_dirs = os::strdup_check_oom(value); +} + void Arguments::add_patch_mod_prefix(const char* module_name, const char* path) { // For java.base check for duplicate --patch-module options being specified on the command line. // This check is only required for java.base, all other duplicate module specifications diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index 3d83959d76a..f2bcc21e123 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -25,18 +25,17 @@ #ifndef SHARE_RUNTIME_ARGUMENTS_HPP #define SHARE_RUNTIME_ARGUMENTS_HPP -#include "logging/logLevel.hpp" -#include "logging/logTag.hpp" +#include "jni.h" #include "memory/allocation.hpp" #include "memory/allStatic.hpp" -#include "runtime/globals.hpp" +#include "runtime/flags/jvmFlag.hpp" #include "runtime/java.hpp" -#include "runtime/os.hpp" -#include "utilities/debug.hpp" -#include "utilities/vmEnums.hpp" +#include "utilities/globalDefinitions.hpp" // Arguments parses the command line and recognizes options +template +class GrowableArray; class JVMFlag; // Invocation API hook typedefs (these should really be defined in jni.h) @@ -412,12 +411,8 @@ class Arguments : AllStatic { // convenient methods to get and set jvm_flags_file static const char* get_jvm_flags_file() { return _jvm_flags_file; } - static void set_jvm_flags_file(const char *value) { - if (_jvm_flags_file != nullptr) { - os::free(_jvm_flags_file); - } - _jvm_flags_file = os::strdup_check_oom(value); - } + static void set_jvm_flags_file(const char *value); + // convenient methods to obtain / print jvm_flags and jvm_args static const char* jvm_flags() { return build_resource_string(_jvm_flags_array, _num_jvm_flags); } static const char* jvm_args() { return build_resource_string(_jvm_args_array, _num_jvm_args); } @@ -479,7 +474,7 @@ class Arguments : AllStatic { static void set_dll_dir(const char *value) { _sun_boot_library_path->set_value(value); } static void set_java_home(const char *value) { _java_home->set_value(value); } static void set_library_path(const char *value) { _java_library_path->set_value(value); } - static void set_ext_dirs(char *value) { _ext_dirs = os::strdup_check_oom(value); } + static void set_ext_dirs(char *value); // Set up the underlying pieces of the boot class path static void add_patch_mod_prefix(const char *module_name, const char *path); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index fb4abdac2ef..c49a9f5d4b8 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -71,6 +71,7 @@ #include "runtime/interfaceSupport.inline.hpp" #include "runtime/java.hpp" #include "runtime/javaThread.hpp" +#include "runtime/os.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stubRoutines.hpp" #include "runtime/task.hpp" @@ -765,3 +766,23 @@ void JDK_Version::to_string(char* buffer, size_t buflen) const { } } } + +void JDK_Version::set_java_version(const char* version) { + _java_version = os::strdup(version); +} + +void JDK_Version::set_runtime_name(const char* name) { + _runtime_name = os::strdup(name); +} + +void JDK_Version::set_runtime_version(const char* version) { + _runtime_version = os::strdup(version); +} + +void JDK_Version::set_runtime_vendor_version(const char* vendor_version) { + _runtime_vendor_version = os::strdup(vendor_version); +} + +void JDK_Version::set_runtime_vendor_vm_bug_url(const char* vendor_vm_bug_url) { + _runtime_vendor_vm_bug_url = os::strdup(vendor_vm_bug_url); +} diff --git a/src/hotspot/share/runtime/java.hpp b/src/hotspot/share/runtime/java.hpp index 67cf3fb686a..f7f1fb5e892 100644 --- a/src/hotspot/share/runtime/java.hpp +++ b/src/hotspot/share/runtime/java.hpp @@ -25,7 +25,6 @@ #ifndef SHARE_RUNTIME_JAVA_HPP #define SHARE_RUNTIME_JAVA_HPP -#include "runtime/os.hpp" #include "utilities/globalDefinitions.hpp" class Handle; @@ -133,38 +132,27 @@ class JDK_Version { static const char* java_version() { return _java_version; } - static void set_java_version(const char* version) { - _java_version = os::strdup(version); - } + static void set_java_version(const char* version); static const char* runtime_name() { return _runtime_name; } - static void set_runtime_name(const char* name) { - _runtime_name = os::strdup(name); - } + static void set_runtime_name(const char* name); static const char* runtime_version() { return _runtime_version; } - static void set_runtime_version(const char* version) { - _runtime_version = os::strdup(version); - } + static void set_runtime_version(const char* version); static const char* runtime_vendor_version() { return _runtime_vendor_version; } - static void set_runtime_vendor_version(const char* vendor_version) { - _runtime_vendor_version = os::strdup(vendor_version); - } + static void set_runtime_vendor_version(const char* vendor_version); static const char* runtime_vendor_vm_bug_url() { return _runtime_vendor_vm_bug_url; } - static void set_runtime_vendor_vm_bug_url(const char* vendor_vm_bug_url) { - _runtime_vendor_vm_bug_url = os::strdup(vendor_vm_bug_url); - } - + static void set_runtime_vendor_vm_bug_url(const char* vendor_vm_bug_url); }; #endif // SHARE_RUNTIME_JAVA_HPP diff --git a/test/hotspot/gtest/runtime/test_arguments.cpp b/test/hotspot/gtest/runtime/test_arguments.cpp index 074636fea0d..17404f45be2 100644 --- a/test/hotspot/gtest/runtime/test_arguments.cpp +++ b/test/hotspot/gtest/runtime/test_arguments.cpp @@ -24,6 +24,7 @@ #include "jvm.h" #include "runtime/arguments.hpp" #include "runtime/flags/jvmFlag.hpp" +#include "runtime/os.hpp" #include "utilities/align.hpp" #include "utilities/globalDefinitions.hpp" From 1f47294cd336db34030ea16132490ab51310ace5 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Mon, 15 Dec 2025 13:36:12 +0000 Subject: [PATCH 099/211] 8287062: com/sun/jndi/ldap/LdapPoolTimeoutTest.java failed due to different timeout message Reviewed-by: aefimov --- .../sun/jndi/ldap/LdapPoolTimeoutTest.java | 91 +++++++++++-------- 1 file changed, 53 insertions(+), 38 deletions(-) diff --git a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java index 294e0f5f1a8..b47433ca16f 100644 --- a/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java +++ b/test/jdk/com/sun/jndi/ldap/LdapPoolTimeoutTest.java @@ -35,6 +35,8 @@ import org.testng.annotations.Test; import javax.naming.Context; import javax.naming.NamingException; import javax.naming.directory.InitialDirContext; + +import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.Hashtable; import java.util.List; @@ -82,14 +84,10 @@ public class LdapPoolTimeoutTest { env.put(Context.PROVIDER_URL, "ldap://example.com:1234"); try { - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); - futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + // launch a few concurrent connection attempts + for (int i = 0; i < 8; i++) { + futures.add(executorService.submit(() -> { attemptConnect(env); return null; })); + } } finally { executorService.shutdown(); } @@ -109,38 +107,55 @@ public class LdapPoolTimeoutTest { private static void attemptConnect(Hashtable env) throws Exception { try { - LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, - 2 * CONNECT_MILLIS + TOLERANCE, - () -> new InitialDirContext(env)); - } catch (RuntimeException e) { - final String msg = e.getCause() == null ? e.getMessage() : e.getCause().getMessage(); - // assertCompletion may wrap a CommunicationException in an RTE - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("No route to host") - || msg.contains("Connection timed out"))) { - // got the expected exception - System.out.println("Received expected RuntimeException message: " + msg); - } else { - // propagate the unexpected exception - throw e; - } - } catch (NamingException ex) { - final String msg = ex.getCause() == null ? ex.getMessage() : ex.getCause().getMessage(); - if (msg != null && - (msg.contains("Network is unreachable") - || msg.contains("Timed out waiting for lock") - || msg.contains("Connect timed out") - || msg.contains("Timeout exceeded while waiting for a connection"))) { - // got the expected exception - System.out.println("Received expected NamingException message: " + msg); - } else { - // propagate the unexpected exception - throw ex; - } + final InitialDirContext unexpectedCtx = + LdapTimeoutTest.assertCompletion(CONNECT_MILLIS - 1000, + 2 * CONNECT_MILLIS + TOLERANCE, + () -> new InitialDirContext(env)); + throw new RuntimeException("InitialDirContext construction was expected to fail," + + " but returned " + unexpectedCtx); } catch (Throwable t) { - throw new RuntimeException(t); + final NamingException namingEx = findNamingException(t); + if (namingEx != null) { + // found the NamingException, verify it's the right reason + if (namingEx.getCause() instanceof SocketTimeoutException ste) { + // got the expected exception + System.out.println("Received expected SocketTimeoutException: " + ste); + return; + } + // rely on the exception message to verify the expected exception + final String msg = namingEx.getCause() == null + ? namingEx.getMessage() + : namingEx.getCause().getMessage(); + if (msg != null && + (msg.contains("Network is unreachable") + || msg.contains("No route to host") + || msg.contains("Timed out waiting for lock") + || msg.contains("Connect timed out") + || msg.contains("Timeout exceeded while waiting for a connection"))) { + // got the expected exception + System.out.println("Received expected NamingException with message: " + msg); + return; + } + } + // unexpected exception, propagate it + if (t instanceof Exception e) { + throw e; + } else { + throw new Exception(t); + } } } + // Find and return the NamingException from the given Throwable. Returns null if none found. + private static NamingException findNamingException(final Throwable t) { + Throwable cause = t; + while (cause != null) { + if (cause instanceof NamingException ne) { + return ne; + } + cause = cause.getCause(); + } + return null; + } + } From 34f241317ecd7473cfb6dcc2e6e5cf3a40299e2c Mon Sep 17 00:00:00 2001 From: SendaoYan Date: Mon, 15 Dec 2025 14:18:46 +0000 Subject: [PATCH 100/211] 8371503: RETAIN_IMAGE_AFTER_TEST do not work for some tests Reviewed-by: lmesnik, dholmes --- test/hotspot/jtreg/containers/docker/DockerBasicTest.java | 4 +--- test/hotspot/jtreg/containers/docker/ShareTmpDir.java | 4 +--- test/hotspot/jtreg/containers/docker/TestCPUAwareness.java | 4 +--- test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java | 4 +--- test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java | 4 +--- test/hotspot/jtreg/containers/docker/TestPids.java | 4 +--- .../jdk/internal/platform/docker/TestDockerMemoryMetrics.java | 4 +--- .../internal/platform/docker/TestGetFreeSwapSpaceSize.java | 4 +--- test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java | 4 +--- test/jdk/jdk/internal/platform/docker/TestPidsLimit.java | 4 +--- test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java | 2 ++ 11 files changed, 12 insertions(+), 30 deletions(-) diff --git a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java index e564cae9d8e..403f46f6ab4 100644 --- a/test/hotspot/jtreg/containers/docker/DockerBasicTest.java +++ b/test/hotspot/jtreg/containers/docker/DockerBasicTest.java @@ -54,9 +54,7 @@ public class DockerBasicTest { testHelloDocker(); testJavaVersionWithCgMounts(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageNameAndTag); - } + DockerTestUtils.removeDockerImage(imageNameAndTag); } } diff --git a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java index a84cdacefa1..b7f807d76a3 100644 --- a/test/hotspot/jtreg/containers/docker/ShareTmpDir.java +++ b/test/hotspot/jtreg/containers/docker/ShareTmpDir.java @@ -57,9 +57,7 @@ public class ShareTmpDir { try { test(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java index 26f160ab27d..6b0a536e4d4 100644 --- a/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestCPUAwareness.java @@ -85,9 +85,7 @@ public class TestCPUAwareness { } } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java index db8f4fd1826..32436cec1d7 100644 --- a/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java +++ b/test/hotspot/jtreg/containers/docker/TestLimitsUpdating.java @@ -63,9 +63,7 @@ public class TestLimitsUpdating { try { testLimitUpdates(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java index 6034aefcd6e..522b2904c43 100644 --- a/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java +++ b/test/hotspot/jtreg/containers/docker/TestMemoryAwareness.java @@ -102,9 +102,7 @@ public class TestMemoryAwareness { testMetricsSwapExceedingPhysical(); testContainerMemExceedsPhysical(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/hotspot/jtreg/containers/docker/TestPids.java b/test/hotspot/jtreg/containers/docker/TestPids.java index 0e39268184e..2bc5f8c03c2 100644 --- a/test/hotspot/jtreg/containers/docker/TestPids.java +++ b/test/hotspot/jtreg/containers/docker/TestPids.java @@ -63,9 +63,7 @@ public class TestPids { try { testPids(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java index 818c2c04a1d..12f90d65516 100644 --- a/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java +++ b/test/jdk/jdk/internal/platform/docker/TestDockerMemoryMetrics.java @@ -81,9 +81,7 @@ public class TestDockerMemoryMetrics { testMemorySoftLimit("500m","200m"); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java index 1e5160330de..6e07d2e9ed5 100644 --- a/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java +++ b/test/jdk/jdk/internal/platform/docker/TestGetFreeSwapSpaceSize.java @@ -53,9 +53,7 @@ public class TestGetFreeSwapSpaceSize { "150M", Integer.toString(0) ); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java index a3df580fed1..a42eee358c3 100644 --- a/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java +++ b/test/jdk/jdk/internal/platform/docker/TestLimitsUpdating.java @@ -62,9 +62,7 @@ public class TestLimitsUpdating { try { testLimitUpdates(); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java index 87ecae7ee62..0313fcc582d 100644 --- a/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java +++ b/test/jdk/jdk/internal/platform/docker/TestPidsLimit.java @@ -59,9 +59,7 @@ public class TestPidsLimit { testPidsLimit("2000"); testPidsLimit("Unlimited"); } finally { - if (!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { - DockerTestUtils.removeDockerImage(imageName); - } + DockerTestUtils.removeDockerImage(imageName); } } diff --git a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java index 22a8572af46..b013561be0b 100644 --- a/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java +++ b/test/lib/jdk/test/lib/containers/docker/DockerTestUtils.java @@ -291,7 +291,9 @@ public class DockerTestUtils { * @throws Exception */ public static void removeDockerImage(String imageNameAndTag) throws Exception { + if(!DockerTestUtils.RETAIN_IMAGE_AFTER_TEST) { execute(Container.ENGINE_COMMAND, "rmi", "--force", imageNameAndTag); + } } From ea6493c4e1de2bc9615beee389b2d335669dc542 Mon Sep 17 00:00:00 2001 From: William Kemper Date: Mon, 15 Dec 2025 15:52:01 +0000 Subject: [PATCH 101/211] 8373100: Genshen: Control thread can miss allocation failure notification Reviewed-by: ysr, kdnilsen, xpeng --- .../shenandoahGenerationalControlThread.cpp | 23 +++++++++---------- .../shenandoahGenerationalControlThread.hpp | 11 ++++----- 2 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp index ece4150f577..dfb28fd9ebb 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.cpp @@ -96,8 +96,7 @@ void ShenandoahGenerationalControlThread::stop_service() { log_debug(gc, thread)("Stopping control thread"); MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); _heap->cancel_gc(GCCause::_shenandoah_stop_vm); - _requested_gc_cause = GCCause::_shenandoah_stop_vm; - notify_cancellation(ml, GCCause::_shenandoah_stop_vm); + notify_control_thread(ml, GCCause::_shenandoah_stop_vm); // We can't wait here because it may interfere with the active cycle's ability // to reach a safepoint (this runs on a java thread). } @@ -140,7 +139,8 @@ void ShenandoahGenerationalControlThread::check_for_request(ShenandoahGCRequest& } ShenandoahGenerationalControlThread::GCMode ShenandoahGenerationalControlThread::prepare_for_allocation_failure_gc(ShenandoahGCRequest &request) { - + // Important: not all paths update the request.generation. This is intentional. + // A degenerated cycle must use the same generation carried over from the previous request. if (_degen_point == ShenandoahGC::_degenerated_unset) { _degen_point = ShenandoahGC::_degenerated_outside_cycle; request.generation = _heap->young_generation(); @@ -633,9 +633,7 @@ void ShenandoahGenerationalControlThread::service_stw_degenerated_cycle(const Sh void ShenandoahGenerationalControlThread::request_gc(GCCause::Cause cause) { if (ShenandoahCollectorPolicy::is_allocation_failure(cause)) { - // GC should already be cancelled. Here we are just notifying the control thread to - // wake up and handle the cancellation request, so we don't need to set _requested_gc_cause. - notify_cancellation(cause); + notify_control_thread(cause); } else if (ShenandoahCollectorPolicy::should_handle_requested_gc(cause)) { handle_requested_gc(cause); } @@ -661,7 +659,7 @@ bool ShenandoahGenerationalControlThread::request_concurrent_gc(ShenandoahGenera log_info(gc)("Preempting old generation mark to allow %s GC", generation->name()); while (gc_mode() == servicing_old) { ShenandoahHeap::heap()->cancel_gc(GCCause::_shenandoah_concurrent_gc); - notify_cancellation(ml, GCCause::_shenandoah_concurrent_gc); + notify_control_thread(ml, GCCause::_shenandoah_concurrent_gc); ml.wait(); } return true; @@ -701,14 +699,15 @@ void ShenandoahGenerationalControlThread::notify_control_thread(MonitorLocker& m ml.notify(); } -void ShenandoahGenerationalControlThread::notify_cancellation(GCCause::Cause cause) { +void ShenandoahGenerationalControlThread::notify_control_thread(GCCause::Cause cause) { MonitorLocker ml(&_control_lock, Mutex::_no_safepoint_check_flag); - notify_cancellation(ml, cause); + notify_control_thread(ml, cause); } -void ShenandoahGenerationalControlThread::notify_cancellation(MonitorLocker& ml, GCCause::Cause cause) { - assert(_heap->cancelled_gc(), "GC should already be cancelled"); - log_debug(gc,thread)("Notify control (%s): %s", gc_mode_name(gc_mode()), GCCause::to_string(cause)); +void ShenandoahGenerationalControlThread::notify_control_thread(MonitorLocker& ml, GCCause::Cause cause) { + assert(_control_lock.is_locked(), "Request lock must be held here"); + log_debug(gc, thread)("Notify control (%s): %s", gc_mode_name(gc_mode()), GCCause::to_string(cause)); + _requested_gc_cause = cause; ml.notify(); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp index b7dbedd5e84..13e69d25268 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalControlThread.hpp @@ -135,16 +135,13 @@ private: // Return printable name for the given gc mode. static const char* gc_mode_name(GCMode mode); - // Takes the request lock and updates the requested cause and generation, then notifies the control thread. - // The overloaded variant should be used when the _control_lock is already held. + // These notify the control thread after updating _requested_gc_cause and (optionally) _requested_generation. + // Updating the requested generation is not necessary for allocation failures nor when stopping the thread. + void notify_control_thread(GCCause::Cause cause); + void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause); void notify_control_thread(GCCause::Cause cause, ShenandoahGeneration* generation); void notify_control_thread(MonitorLocker& ml, GCCause::Cause cause, ShenandoahGeneration* generation); - // Notifies the control thread, but does not update the requested cause or generation. - // The overloaded variant should be used when the _control_lock is already held. - void notify_cancellation(GCCause::Cause cause); - void notify_cancellation(MonitorLocker& ml, GCCause::Cause cause); - // Configure the heap to age objects and regions if the aging period has elapsed. void maybe_set_aging_cycle(); From ad29642d8f4e8e0fb1223b14b85ab7841d7b1b51 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Mon, 15 Dec 2025 16:18:44 +0000 Subject: [PATCH 102/211] 8351889: C2 crash: assertion failed: Base pointers must match (addp 344) Reviewed-by: rcastanedalo, epeter --- src/hotspot/share/opto/addnode.hpp | 7 ++ src/hotspot/share/opto/c2_globals.hpp | 3 +- src/hotspot/share/opto/cfgnode.cpp | 36 +++++++++ src/hotspot/share/opto/cfgnode.hpp | 2 + src/hotspot/share/opto/compile.cpp | 5 +- src/hotspot/share/opto/phaseX.cpp | 21 ++++- src/hotspot/share/opto/phaseX.hpp | 5 ++ .../flags/jvmFlagConstraintsCompiler.cpp | 2 +- .../c2/TestMismatchedAddPAfterMaxUnroll.java | 80 +++++++++++++++++++ .../compiler/c2/TestVerifyIterativeGVN.java | 6 +- 10 files changed, 156 insertions(+), 11 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestMismatchedAddPAfterMaxUnroll.java diff --git a/src/hotspot/share/opto/addnode.hpp b/src/hotspot/share/opto/addnode.hpp index 28ed73121ed..1bbdae92e48 100644 --- a/src/hotspot/share/opto/addnode.hpp +++ b/src/hotspot/share/opto/addnode.hpp @@ -246,6 +246,13 @@ public: // Do not match base-ptr edge virtual uint match_edge(uint idx) const; + +#ifdef ASSERT + bool address_input_has_same_base() const { + Node *addp = in(Address); + return !addp->is_AddP() || addp->in(Base)->is_top() || addp->in(Base) == in(Base); + } +#endif }; //------------------------------OrINode---------------------------------------- diff --git a/src/hotspot/share/opto/c2_globals.hpp b/src/hotspot/share/opto/c2_globals.hpp index 2b2b4db47b1..7fa3ca638c2 100644 --- a/src/hotspot/share/opto/c2_globals.hpp +++ b/src/hotspot/share/opto/c2_globals.hpp @@ -697,7 +697,8 @@ "Print progress during Iterative Global Value Numbering") \ \ develop(uint, VerifyIterativeGVN, 0, \ - "Verify Iterative Global Value Numbering =DCBA, with:" \ + "Verify Iterative Global Value Numbering =EDCBA, with:" \ + " E: verify node specific invariants" \ " D: verify Node::Identity did not miss opportunities" \ " C: verify Node::Ideal did not miss opportunities" \ " B: verify that type(n) == n->Value() after IGVN" \ diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 203aa69ce1b..07657dd0883 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -2096,6 +2096,20 @@ bool PhiNode::is_split_through_mergemem_terminating() const { return true; } +// Is one of the inputs a Cast that has not been processed by igvn yet? +bool PhiNode::wait_for_cast_input_igvn(const PhaseIterGVN* igvn) const { + for (uint i = 1, cnt = req(); i < cnt; ++i) { + Node* n = in(i); + while (n != nullptr && n->is_ConstraintCast()) { + if (igvn->_worklist.member(n)) { + return true; + } + n = n->in(1); + } + } + return false; +} + //------------------------------Ideal------------------------------------------ // Return a node which is more "ideal" than the current node. Must preserve // the CFG, but we can still strip out dead paths. @@ -2154,6 +2168,28 @@ Node *PhiNode::Ideal(PhaseGVN *phase, bool can_reshape) { // If there is a chance that the region can be optimized out do // not add a cast node that we can't remove yet. !wait_for_region_igvn(phase)) { + // If one of the inputs is a cast that has yet to be processed by igvn, delay processing of this node to give the + // inputs a chance to optimize and possibly end up with identical inputs (casts included). + // Say we have: + // (Phi region (Cast#1 c uin) (Cast#2 c uin)) + // and Cast#1 and Cast#2 have not had a chance to common yet + // if the unique_input() transformation below proceeds, then PhiNode::Ideal returns: + // (Cast#3 region uin) (1) + // If PhiNode::Ideal is delayed until Cast#1 and Cast#2 common, then it returns: + // (Cast#1 c uin) (2) + // + // In (1) the resulting cast is conservatively pinned at a later control and while Cast#3 and Cast#1/Cast#2 still + // have a chance to common, that requires proving that c dominates region in ConstraintCastNode::dominating_cast() + // which may not happen if control flow is too complicated and another pass of loop opts doesn't run. Delaying the + // transformation here should allow a more optimal result. + // Beyond the efficiency concern, there is a risk, if the casts are CastPPs, to end up with a chain of AddPs with + // different base inputs (but a unique uncasted base input). This breaks an invariant in the shape of address + // subtrees. + PhaseIterGVN* igvn = phase->is_IterGVN(); + if (wait_for_cast_input_igvn(igvn)) { + igvn->_worklist.push(this); + return nullptr; + } uncasted = true; uin = unique_input(phase, true); } diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index bc0b38e2f97..f3ccf23703f 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -182,6 +182,8 @@ class PhiNode : public TypeNode { bool is_split_through_mergemem_terminating() const; + bool wait_for_cast_input_igvn(const PhaseIterGVN* igvn) const; + public: // Node layout (parallels RegionNode): enum { Region, // Control input is the Phi's region. diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 621ba684da1..16f5be50805 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3418,10 +3418,7 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f case Op_AddP: { // Assert sane base pointers Node *addp = n->in(AddPNode::Address); - assert( !addp->is_AddP() || - addp->in(AddPNode::Base)->is_top() || // Top OK for allocation - addp->in(AddPNode::Base) == n->in(AddPNode::Base), - "Base pointers must match (addp %u)", addp->_idx ); + assert(n->as_AddP()->address_input_has_same_base(), "Base pointers must match (addp %u)", addp->_idx ); #ifdef _LP64 if ((UseCompressedOops || UseCompressedClassPointers) && addp->Opcode() == Op_ConP && diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 4a0933b89f2..1e4cd42e09a 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1076,7 +1076,8 @@ void PhaseIterGVN::verify_optimize() { if (is_verify_Value() || is_verify_Ideal() || - is_verify_Identity()) { + is_verify_Identity() || + is_verify_invariants()) { ResourceMark rm; Unique_Node_List worklist; bool failure = false; @@ -1088,6 +1089,7 @@ void PhaseIterGVN::verify_optimize() { if (is_verify_Ideal()) { failure |= verify_Ideal_for(n, false); } if (is_verify_Ideal()) { failure |= verify_Ideal_for(n, true); } if (is_verify_Identity()) { failure |= verify_Identity_for(n); } + if (is_verify_invariants()) { failure |= verify_node_invariants_for(n); } // traverse all inputs and outputs for (uint i = 0; i < n->req(); i++) { if (n->in(i) != nullptr) { @@ -1102,7 +1104,7 @@ void PhaseIterGVN::verify_optimize() { // We should either make sure that these nodes are properly added back to the IGVN worklist // in PhaseIterGVN::add_users_to_worklist to update them again or add an exception // in the verification code above if that is not possible for some reason (like Load nodes). - assert(!failure, "Missed optimization opportunity in PhaseIterGVN"); + assert(!failure, "Missed optimization opportunity/broken graph in PhaseIterGVN"); } verify_empty_worklist(nullptr); @@ -2058,6 +2060,21 @@ bool PhaseIterGVN::verify_Identity_for(Node* n) { tty->print_cr("%s", ss.as_string()); return true; } + +// Some other verifications that are not specific to a particular transformation. +bool PhaseIterGVN::verify_node_invariants_for(const Node* n) { + if (n->is_AddP()) { + if (!n->as_AddP()->address_input_has_same_base()) { + stringStream ss; // Print as a block without tty lock. + ss.cr(); + ss.print_cr("Base pointers must match for AddP chain:"); + n->dump_bfs(2, nullptr, "", &ss); + tty->print_cr("%s", ss.as_string()); + return true; + } + } + return false; +} #endif /** diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 473231e6af5..3f75aab8980 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -493,6 +493,7 @@ public: bool verify_Value_for(Node* n, bool strict = false); bool verify_Ideal_for(Node* n, bool can_reshape); bool verify_Identity_for(Node* n); + bool verify_node_invariants_for(const Node* n); void verify_empty_worklist(Node* n); #endif @@ -616,6 +617,10 @@ public: // '-XX:VerifyIterativeGVN=1000' return ((VerifyIterativeGVN % 10000) / 1000) == 1; } + static bool is_verify_invariants() { + // '-XX:VerifyIterativeGVN=10000' + return ((VerifyIterativeGVN % 100000) / 10000) == 1; + } protected: // Sub-quadratic implementation of '-XX:VerifyIterativeGVN=1' (Use-Def verification). julong _verify_counter; diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp index d0141c2e6cc..63d3424b3ed 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsCompiler.cpp @@ -306,7 +306,7 @@ JVMFlag::Error TypeProfileLevelConstraintFunc(uint value, bool verbose) { } JVMFlag::Error VerifyIterativeGVNConstraintFunc(uint value, bool verbose) { - const int max_modes = 4; + const int max_modes = 5; uint original_value = value; for (int i = 0; i < max_modes; i++) { if (value % 10 > 1) { diff --git a/test/hotspot/jtreg/compiler/c2/TestMismatchedAddPAfterMaxUnroll.java b/test/hotspot/jtreg/compiler/c2/TestMismatchedAddPAfterMaxUnroll.java new file mode 100644 index 00000000000..2dcafd2cf6a --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestMismatchedAddPAfterMaxUnroll.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. 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 + * @bug 8351889 + * @summary C2 crash: assertion failed: Base pointers must match (addp 344) + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileOnly=TestMismatchedAddPAfterMaxUnroll::test1 + * -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:-UseLoopPredicate + * -XX:+StressIGVN -XX:StressSeed=383593806 -XX:VerifyIterativeGVN=10000 + * TestMismatchedAddPAfterMaxUnroll + * @run main/othervm -XX:-BackgroundCompilation -XX:CompileOnly=TestMismatchedAddPAfterMaxUnroll::test1 + * -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:-UseLoopPredicate + * -XX:+StressIGVN -XX:VerifyIterativeGVN=10000 TestMismatchedAddPAfterMaxUnroll + * @run main/othervm TestMismatchedAddPAfterMaxUnroll + */ + +public class TestMismatchedAddPAfterMaxUnroll { + private static C[] arrayField = new C[4]; + + public static void main(String[] args) { + C c = new C(); + Object lock = new Object(); + for (int i = 0; i < 20_000; i++) { + arrayField[3] = null; + test1(3, c, arrayField, true, true, lock); + arrayField[3] = null; + test1(3, c, arrayField, true, false, lock); + arrayField[3] = null; + test1(3, c, arrayField, false, false, lock); + arrayField[3] = c; + test1(3, c, arrayField, false, false, lock); + } + } + + static class C { + + } + + private static void test1(int j, C c, C[] otherArray, boolean flag, boolean flag2, Object lock) { + C[] array = arrayField; + int i = 0; + for (;;) { + synchronized (lock) {} + if (array[j] == null) { + break; + } + otherArray[i] = c; + i++; + if (i >= 3) { + return; + } + } + if (flag) { + if (flag2) { + } + } + array[j] = c; + } +} diff --git a/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java b/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java index 83f3540226f..4b6215b25bd 100644 --- a/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java +++ b/test/hotspot/jtreg/compiler/c2/TestVerifyIterativeGVN.java @@ -23,11 +23,11 @@ /* * @test - * @bug 8238756 + * @bug 8238756 8351889 * @requires vm.debug == true & vm.flavor == "server" - * @summary Run with -Xcomp to test -XX:VerifyIterativeGVN=1111 in debug builds. + * @summary Run with -Xcomp to test -XX:VerifyIterativeGVN=11111 in debug builds. * - * @run main/othervm/timeout=300 -Xcomp -XX:VerifyIterativeGVN=1111 compiler.c2.TestVerifyIterativeGVN + * @run main/othervm/timeout=300 -Xcomp -XX:VerifyIterativeGVN=11111 compiler.c2.TestVerifyIterativeGVN */ package compiler.c2; From 45ee89c4c8e3d8bb418b8578fb361e7dc1c12be5 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 15 Dec 2025 19:50:46 +0000 Subject: [PATCH 103/211] 8373297: Test com/sun/jdi/AfterThreadDeathTest.java failed with unexpected ObjectCollectedException Reviewed-by: kevinw, sspitsyn, amenkov, lmesnik --- test/jdk/com/sun/jdi/AfterThreadDeathTest.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/test/jdk/com/sun/jdi/AfterThreadDeathTest.java b/test/jdk/com/sun/jdi/AfterThreadDeathTest.java index 27904021442..25987de864c 100644 --- a/test/jdk/com/sun/jdi/AfterThreadDeathTest.java +++ b/test/jdk/com/sun/jdi/AfterThreadDeathTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -93,6 +93,7 @@ public class AfterThreadDeathTest extends TestScaffold { println("Ok; got expected IllegalThreadStateException"); return; } catch (Exception ee) { + ee.printStackTrace(System.err); failure("FAILED: Did not get expected" + " IllegalThreadStateException" + " on a StepRequest.enable(). \n" @@ -133,6 +134,13 @@ public class AfterThreadDeathTest extends TestScaffold { mainThread = bpe.thread(); erm = vm().eventRequestManager(); + /* + * The "main" thread will be referenced during the ThreadDeathEvent, which + * uses SUSPEND_NONE, so the thread might get gc'd and cause an unexpected + * ObjectCollectedException. Disable it from collection to prevent problems. + */ + mainThread.disableCollection(); + /* * Set event requests */ From f52d49925f9c60814a0a34720d7443e748b35c25 Mon Sep 17 00:00:00 2001 From: Sergey Chernyshev Date: Mon, 15 Dec 2025 20:19:05 +0000 Subject: [PATCH 104/211] 8319589: Attach from root to a user java process not supported in Mac Reviewed-by: sspitsyn --- src/hotspot/os/bsd/os_bsd.cpp | 84 +++++++++++++++++ src/hotspot/os/bsd/os_bsd.hpp | 8 +- src/hotspot/os/posix/os_posix.cpp | 4 + src/hotspot/os/posix/os_posix.hpp | 3 + src/hotspot/os/posix/perfMemory_posix.cpp | 18 +++- .../sun/tools/attach/VirtualMachineImpl.java | 56 +++++++++--- .../native/libattach/VirtualMachineImpl.c | 26 +----- .../sun/jvmstat/PlatformSupportImpl.java | 91 +++++++++++++++++++ .../share/classes/module-info.java | 4 +- 9 files changed, 252 insertions(+), 42 deletions(-) create mode 100644 src/jdk.internal.jvmstat/macosx/classes/sun/jvmstat/PlatformSupportImpl.java diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index dc8f5187b5a..61de48bb7fa 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -861,6 +861,90 @@ pid_t os::Bsd::gettid() { } } +// Returns the uid of a process or -1 on error. +uid_t os::Bsd::get_process_uid(pid_t pid) { + struct kinfo_proc kp; + size_t size = sizeof kp; + int mib_kern[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, pid}; + if (sysctl(mib_kern, 4, &kp, &size, nullptr, 0) == 0) { + if (size > 0 && kp.kp_proc.p_pid == pid) { + return kp.kp_eproc.e_ucred.cr_uid; + } + } + return (uid_t)-1; +} + +// Returns true if the process is running as root. +bool os::Bsd::is_process_root(pid_t pid) { + uid_t uid = get_process_uid(pid); + return (uid != (uid_t)-1) ? os::Posix::is_root(uid) : false; +} + +#ifdef __APPLE__ + +// macOS has a secure per-user temporary directory. +// Root can attach to a non-root process, hence it needs +// to lookup /var/folders for the user specific temporary directory +// of the form /var/folders/*/*/T, that contains PERFDATA_NAME_user +// directory. +static const char VAR_FOLDERS[] = "/var/folders/"; +int os::Bsd::get_user_tmp_dir_macos(const char* user, int vmid, char* output_path, int output_size) { + + // read the var/folders directory + DIR* varfolders_dir = os::opendir(VAR_FOLDERS); + if (varfolders_dir != nullptr) { + + // var/folders directory contains 2-characters subdirectories (buckets) + struct dirent* bucket_de; + + // loop until the PERFDATA_NAME_user directory has been found + while ((bucket_de = os::readdir(varfolders_dir)) != nullptr) { + // skip over files and special "." and ".." + if (bucket_de->d_type != DT_DIR || bucket_de->d_name[0] == '.') { + continue; + } + // absolute path to the bucket + char bucket[PATH_MAX]; + int b = os::snprintf(bucket, PATH_MAX, "%s%s/", VAR_FOLDERS, bucket_de->d_name); + + // the total length of the absolute path must not exceed the buffer size + if (b >= PATH_MAX || b < 0) { + continue; + } + // each bucket contains next level subdirectories + DIR* bucket_dir = os::opendir(bucket); + if (bucket_dir == nullptr) { + continue; + } + // read each subdirectory, skipping over regular files + struct dirent* subbucket_de; + while ((subbucket_de = os::readdir(bucket_dir)) != nullptr) { + if (subbucket_de->d_type != DT_DIR || subbucket_de->d_name[0] == '.') { + continue; + } + // If the PERFDATA_NAME_user directory exists in the T subdirectory, + // this means the subdirectory is the temporary directory of the user. + char perfdata_path[PATH_MAX]; + int p = os::snprintf(perfdata_path, PATH_MAX, "%s%s/T/%s_%s/", bucket, subbucket_de->d_name, PERFDATA_NAME, user); + + // the total length must not exceed the output buffer size + if (p >= PATH_MAX || p < 0) { + continue; + } + // check if the subdirectory exists + if (os::file_exists(perfdata_path)) { + // the return value of snprintf is not checked for the second time + return os::snprintf(output_path, output_size, "%s%s/T", bucket, subbucket_de->d_name); + } + } + os::closedir(bucket_dir); + } + os::closedir(varfolders_dir); + } + return -1; +} +#endif + intx os::current_thread_id() { #ifdef __APPLE__ return (intx)os::Bsd::gettid(); diff --git a/src/hotspot/os/bsd/os_bsd.hpp b/src/hotspot/os/bsd/os_bsd.hpp index 82002917f39..da73211b9a7 100644 --- a/src/hotspot/os/bsd/os_bsd.hpp +++ b/src/hotspot/os/bsd/os_bsd.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -61,6 +61,12 @@ class os::Bsd { static pthread_t main_thread(void) { return _main_thread; } static pid_t gettid(); + static uid_t get_process_uid(pid_t pid); + static bool is_process_root(pid_t pid); + +#ifdef __APPLE__ + static int get_user_tmp_dir_macos(const char* user, int vmid, char* output_buffer, int buffer_size); +#endif static intptr_t* ucontext_get_sp(const ucontext_t* uc); static intptr_t* ucontext_get_fp(const ucontext_t* uc); diff --git a/src/hotspot/os/posix/os_posix.cpp b/src/hotspot/os/posix/os_posix.cpp index ef52b946cc6..07e1920c62d 100644 --- a/src/hotspot/os/posix/os_posix.cpp +++ b/src/hotspot/os/posix/os_posix.cpp @@ -1352,6 +1352,10 @@ bool os::Posix::is_root(uid_t uid){ return ROOT_UID == uid; } +bool os::Posix::is_current_user_root(){ + return is_root(geteuid()); +} + bool os::Posix::matches_effective_uid_or_root(uid_t uid) { return is_root(uid) || geteuid() == uid; } diff --git a/src/hotspot/os/posix/os_posix.hpp b/src/hotspot/os/posix/os_posix.hpp index 4b8b75ea07e..424d737cf42 100644 --- a/src/hotspot/os/posix/os_posix.hpp +++ b/src/hotspot/os/posix/os_posix.hpp @@ -76,6 +76,9 @@ public: // Returns true if given uid is root. static bool is_root(uid_t uid); + // Returns true if the current user is root. + static bool is_current_user_root(); + // Returns true if given uid is effective or root uid. static bool matches_effective_uid_or_root(uid_t uid); diff --git a/src/hotspot/os/posix/perfMemory_posix.cpp b/src/hotspot/os/posix/perfMemory_posix.cpp index 2cc0263d291..39bfc72a486 100644 --- a/src/hotspot/os/posix/perfMemory_posix.cpp +++ b/src/hotspot/os/posix/perfMemory_posix.cpp @@ -40,6 +40,9 @@ #if defined(LINUX) #include "os_linux.hpp" #endif +#if defined(BSD) +#include "os_bsd.hpp" +#endif # include # include @@ -142,6 +145,18 @@ static char* get_user_tmp_dir(const char* user, int vmid, int nspid) { jio_snprintf(buffer, TMP_BUFFER_LEN, "/proc/%d/root%s", vmid, tmpdir); tmpdir = buffer; } +#endif +#ifdef __APPLE__ + char buffer[PATH_MAX] = {0}; + // Check if the current user is root and the target VM is running as non-root. + // Otherwise the output of os::get_temp_directory() is used. + // + if (os::Posix::is_current_user_root() && !os::Bsd::is_process_root(vmid)) { + int path_size = os::Bsd::get_user_tmp_dir_macos(user, vmid, buffer, sizeof buffer); + if (path_size > 0 && (size_t)path_size < sizeof buffer) { + tmpdir = buffer; + } + } #endif const char* perfdir = PERFDATA_NAME; size_t nbytes = strlen(tmpdir) + strlen(perfdir) + strlen(user) + 3; @@ -1138,7 +1153,8 @@ static void mmap_attach_shared(int vmid, char** addr, size_t* sizep, TRAPS) { // for linux, determine if vmid is for a containerized process int nspid = LINUX_ONLY(os::Linux::get_namespace_pid(vmid)) NOT_LINUX(-1); - const char* luser = get_user_name(vmid, &nspid, CHECK); + const char* luser = NOT_MACOS(get_user_name(vmid, &nspid, CHECK)) + MACOS_ONLY(get_user_name(os::Bsd::get_process_uid(vmid))); if (luser == nullptr) { THROW_MSG(vmSymbols::java_lang_IllegalArgumentException(), diff --git a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java index 5c786db1366..a7a348affe3 100644 --- a/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java +++ b/src/jdk.attach/macosx/classes/sun/tools/attach/VirtualMachineImpl.java @@ -28,9 +28,13 @@ import com.sun.tools.attach.AgentLoadException; import com.sun.tools.attach.AttachNotSupportedException; import com.sun.tools.attach.spi.AttachProvider; +import sun.jvmstat.PlatformSupport; + import java.io.InputStream; import java.io.IOException; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import static java.nio.charset.StandardCharsets.UTF_8; @@ -39,14 +43,17 @@ import static java.nio.charset.StandardCharsets.UTF_8; */ @SuppressWarnings("restricted") public class VirtualMachineImpl extends HotSpotVirtualMachine { - // "tmpdir" is used as a global well-known location for the files - // .java_pid. and .attach_pid. It is important that this - // location is the same for all processes, otherwise the tools - // will not be able to find all Hotspot processes. - // This is intentionally not the same as java.io.tmpdir, since - // the latter can be changed by the user. - // Any changes to this needs to be synchronized with HotSpot. - private static final String tmpdir; + + /** + * HotSpot PerfData file prefix + */ + private static final String HSPERFDATA_PREFIX = "hsperfdata_"; + + /** + * Use platform specific methods for looking up temporary directories. + */ + private static final PlatformSupport platformSupport = PlatformSupport.getInstance(); + String socket_path; private OperationProperties props = new OperationProperties(VERSION_1); // updated in ctor @@ -67,10 +74,12 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { // Find the socket file. If not found then we attempt to start the // attach mechanism in the target VM by sending it a QUIT signal. // Then we attempt to find the socket file again. - File socket_file = new File(tmpdir, ".java_pid" + pid); + // In macOS the socket file is located in per-user temp directory. + String tempdir = getTempDirFromPid(pid); + File socket_file = new File(tempdir, ".java_pid" + pid); socket_path = socket_file.getPath(); if (!socket_file.exists()) { - File f = createAttachFile(pid); + File f = createAttachFile(tempdir, pid); try { checkCatchesAndSendQuitTo(pid, false); @@ -211,12 +220,34 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { } } - private File createAttachFile(int pid) throws IOException { + private File createAttachFile(String tmpdir, int pid) throws IOException { File f = new File(tmpdir, ".attach_pid" + pid); createAttachFile0(f.getPath()); return f; } + /* + * Returns a platform-specific temporary directory for a given process. + * In VMs running as unprivileged user it returns the default platform-specific + * temporary directory. In VMs running as root it searches over the list of + * temporary directories for one containing HotSpot PerfData directory. + */ + private String getTempDirFromPid(int pid) { + ProcessHandle ph = ProcessHandle.of(pid).orElse(null); + if (ph != null) { + String user = ph.info().user().orElse(null); + if (user != null) { + for (String dir : platformSupport.getTemporaryDirectories(pid)) { + Path fullPath = Path.of(dir, HSPERFDATA_PREFIX + user, String.valueOf(pid)); + if (Files.exists(fullPath)) { + return dir; + } + } + } + } + return PlatformSupport.getTemporaryDirectory(); + } + //-- native methods static native boolean checkCatchesAndSendQuitTo(int pid, boolean throwIfNotReady) throws IOException, AttachNotSupportedException; @@ -235,10 +266,7 @@ public class VirtualMachineImpl extends HotSpotVirtualMachine { static native void createAttachFile0(String path); - static native String getTempDir(); - static { System.loadLibrary("attach"); - tmpdir = getTempDir(); } } diff --git a/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c b/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c index d105d7d3b1b..5b2579eba39 100644 --- a/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c +++ b/src/jdk.attach/macosx/native/libattach/VirtualMachineImpl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2025, 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 @@ -335,27 +335,3 @@ JNIEXPORT void JNICALL Java_sun_tools_attach_VirtualMachineImpl_createAttachFile JNU_ReleaseStringPlatformChars(env, path, _path); } } - -/* - * Class: sun_tools_attach_BSDVirtualMachine - * Method: getTempDir - * Signature: (V)Ljava.lang.String; - */ -JNIEXPORT jstring JNICALL Java_sun_tools_attach_VirtualMachineImpl_getTempDir(JNIEnv *env, jclass cls) -{ - // This must be hard coded because it's the system's temporary - // directory not the java application's temp directory, ala java.io.tmpdir. - -#ifdef __APPLE__ - // macosx has a secure per-user temporary directory. - // Don't cache the result as this is only called once. - char path[PATH_MAX]; - int pathSize = confstr(_CS_DARWIN_USER_TEMP_DIR, path, PATH_MAX); - if (pathSize == 0 || pathSize > PATH_MAX) { - strlcpy(path, "/tmp", sizeof(path)); - } - return JNU_NewStringPlatform(env, path); -#else /* __APPLE__ */ - return (*env)->NewStringUTF(env, "/tmp"); -#endif /* __APPLE__ */ -} diff --git a/src/jdk.internal.jvmstat/macosx/classes/sun/jvmstat/PlatformSupportImpl.java b/src/jdk.internal.jvmstat/macosx/classes/sun/jvmstat/PlatformSupportImpl.java new file mode 100644 index 00000000000..f858fde4dce --- /dev/null +++ b/src/jdk.internal.jvmstat/macosx/classes/sun/jvmstat/PlatformSupportImpl.java @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, BELLSOFT. 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. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * 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 sun.jvmstat; + +import java.io.IOException; +import java.nio.file.DirectoryStream; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +/* + * macOS specific implementation of the PlatformSupport routines + * providing temporary directory support. + */ +public class PlatformSupportImpl extends PlatformSupport { + + private static final String VAR_FOLDERS_PATH = "/var/folders"; + private static final String USER_NAME_SYSTEM_PROPERTY = "user.name"; + private static final String USER_NAME_ROOT = "root"; + private static final String DIRHELPER_TEMP_STR = "T"; + + private static final boolean isCurrentUserRoot = + System.getProperty(USER_NAME_SYSTEM_PROPERTY).equals(USER_NAME_ROOT); + + public PlatformSupportImpl() { + super(); + } + + /* + * Return a list of the temporary directories that the VM uses + * for the attach and perf data files. + * + * This function returns the traditional temp directory. Additionally, + * when called by root, it returns other temporary directories of non-root + * users. + * + * macOS per-user temp directories are located under /var/folders + * and have the form /var/folders///T + */ + @Override + public List getTemporaryDirectories(int pid) { + if (!isCurrentUserRoot) { + // early exit for non-root + return List.of(PlatformSupport.getTemporaryDirectory()); + } + List result = new ArrayList<>(); + try (DirectoryStream bs = Files.newDirectoryStream(Path.of(VAR_FOLDERS_PATH))) { + for (Path bucket : bs) { + try (DirectoryStream encUuids = Files.newDirectoryStream(bucket)) { + for (Path encUuid : encUuids) { + try { + Path tempDir = encUuid.resolve(DIRHELPER_TEMP_STR); + if (Files.isDirectory(tempDir) && Files.isReadable(tempDir)) { + result.add(tempDir.toString()); + } + } catch (Exception ignore) { // ignored unreadable bucket/encUuid, continue + } + } + } catch (IOException ignore) { // IOException ignored, continue to the next bucket + } + } + } catch (Exception ignore) { // var/folders directory is inaccessible / other errors + } + return result.isEmpty() ? List.of(PlatformSupport.getTemporaryDirectory()) : result; + } +} diff --git a/src/jdk.internal.jvmstat/share/classes/module-info.java b/src/jdk.internal.jvmstat/share/classes/module-info.java index 9e12c98b016..d9e1bc68008 100644 --- a/src/jdk.internal.jvmstat/share/classes/module-info.java +++ b/src/jdk.internal.jvmstat/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ module jdk.internal.jvmstat { jdk.jstatd; exports sun.jvmstat.perfdata.monitor to jdk.jstatd; + exports sun.jvmstat to + jdk.attach; uses sun.jvmstat.monitor.MonitoredHostService; From 6aeabd4bfaca168e9c88716b185979cf1e1b85ed Mon Sep 17 00:00:00 2001 From: Kieran Farrell Date: Mon, 15 Dec 2025 20:51:08 +0000 Subject: [PATCH 105/211] 8370910: Cleanup terminology of UUID vs Global Identifiers in UUID Reviewed-by: alanb, rriggs, jpai --- src/java.base/share/classes/java/util/UUID.java | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/java.base/share/classes/java/util/UUID.java b/src/java.base/share/classes/java/util/UUID.java index fa66d199239..f69ca8171cf 100644 --- a/src/java.base/share/classes/java/util/UUID.java +++ b/src/java.base/share/classes/java/util/UUID.java @@ -32,12 +32,11 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.util.ByteArrayLittleEndian; /** - * A class that represents an immutable universally unique identifier (UUID). + * A class that represents an immutable Universally Unique IDentifier (UUID). * A UUID represents a 128-bit value. * - *

    There exist different variants of these global identifiers. The methods - * of this class are for manipulating the Leach-Salz variant, although the - * constructors allow the creation of any variant of UUID (described below). + *

    This class is primarily designed for manipulating Leach-Salz variant UUIDs, + * but it also supports the creation of UUIDs of other variants. * *

    The layout of a variant 2 (Leach-Salz) UUID is as follows: * From 317788ff12ee231bd3c9e8f1a0c9b38c8dad3feb Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Mon, 15 Dec 2025 22:39:09 +0000 Subject: [PATCH 106/211] 8360160: ubuntu-22-04 machine is failing client tests Reviewed-by: prr, azvegint --- test/jdk/java/awt/Frame/FrameVisualTest.java | 73 +++++++++++--------- 1 file changed, 41 insertions(+), 32 deletions(-) diff --git a/test/jdk/java/awt/Frame/FrameVisualTest.java b/test/jdk/java/awt/Frame/FrameVisualTest.java index 767eb0a1896..39853822c44 100644 --- a/test/jdk/java/awt/Frame/FrameVisualTest.java +++ b/test/jdk/java/awt/Frame/FrameVisualTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2025, 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 @@ -46,62 +46,71 @@ import javax.imageio.ImageIO; public class FrameVisualTest { private static GraphicsConfiguration[] gcs; private static volatile Frame[] frames; - private static volatile int index; - private static Frame f; private static Robot robot; + private static volatile int frameNum; private static volatile Point p; private static volatile Dimension d; private static final int TOLERANCE = 5; + private static final int MAX_FRAME_COUNT = 30; public static void main(String[] args) throws Exception { - gcs = GraphicsEnvironment.getLocalGraphicsEnvironment().getDefaultScreenDevice().getConfigurations(); + gcs = GraphicsEnvironment.getLocalGraphicsEnvironment() + .getDefaultScreenDevice().getConfigurations(); robot = new Robot(); robot.setAutoDelay(100); - try { - EventQueue.invokeAndWait(() -> { - createAndShowUI(); - }); - robot.delay(1000); - System.out.println("frames.length: "+frames.length); - for (index = 0; index < frames.length; index++) { + + // Limit the number of frames tested if needed + if (gcs.length > MAX_FRAME_COUNT) { + frames = new Frame[MAX_FRAME_COUNT]; + } else { + frames = new Frame[gcs.length]; + } + System.out.println(gcs.length + " gcs found. Testing " + + frames.length + " frame(s)."); + + for (frameNum = 0; frameNum < frames.length; frameNum++) { + try { EventQueue.invokeAndWait(() -> { - p = frames[index].getLocation(); - d = frames[index].getSize(); + frames[frameNum] = new Frame("Frame w/ gc " + + frameNum, gcs[frameNum]); + frames[frameNum].setSize(100, 100); + frames[frameNum].setUndecorated(true); + frames[frameNum].setBackground(Color.WHITE); + frames[frameNum].setVisible(true); + System.out.println("Frame " + frameNum + " created"); }); + + robot.delay(1000); + + EventQueue.invokeAndWait(() -> { + p = frames[frameNum].getLocation(); + d = frames[frameNum].getSize(); + }); + Rectangle rect = new Rectangle(p, d); BufferedImage img = robot.createScreenCapture(rect); if (chkImgBackgroundColor(img)) { try { - ImageIO.write(img, "png", new File("Frame_" + index + ".png")); + ImageIO.write(img, "png", + new File("Frame_" + + frameNum + ".png")); } catch (IOException ignored) {} - throw new RuntimeException("Frame visual test failed with non-white background color"); + throw new RuntimeException("Frame visual test " + + "failed with non-white background color"); } - } - } finally { - for (index = 0; index < frames.length; index++) { + } finally { EventQueue.invokeAndWait(() -> { - if (frames[index] != null) { - frames[index].dispose(); + if (frames[frameNum] != null) { + frames[frameNum].dispose(); + System.out.println("Frame " + frameNum + " disposed"); } }); } } } - private static void createAndShowUI() { - frames = new Frame[gcs.length]; - for (int i = 0; i < frames.length; i++) { - frames[i] = new Frame("Frame w/ gc " + i, gcs[i]); - frames[i].setSize(100, 100); - frames[i].setUndecorated(true); - frames[i].setBackground(Color.WHITE); - frames[i].setVisible(true); - } - } - private static boolean chkImgBackgroundColor(BufferedImage img) { - // scan for mid-line and if it is non-white color then return true. for (int x = 1; x < img.getWidth() - 1; ++x) { Color c = new Color(img.getRGB(x, img.getHeight() / 2)); From 1748737b99f283f69b4be0910b6623a27d804e68 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 16 Dec 2025 00:19:01 +0000 Subject: [PATCH 107/211] 8372988: Test runtime/Nestmates/membership/TestNestHostErrorWithMultiThread.java failed: Unexpected interrupt Reviewed-by: coleenp, iklam, jsjolen --- src/hotspot/share/classfile/resolutionErrors.cpp | 6 ++---- src/hotspot/share/classfile/systemDictionary.cpp | 15 ++++++++++----- src/hotspot/share/classfile/systemDictionary.hpp | 2 +- src/hotspot/share/oops/instanceKlass.cpp | 10 ++++------ 4 files changed, 17 insertions(+), 16 deletions(-) diff --git a/src/hotspot/share/classfile/resolutionErrors.cpp b/src/hotspot/share/classfile/resolutionErrors.cpp index f5a335f17f3..c41d5d2f052 100644 --- a/src/hotspot/share/classfile/resolutionErrors.cpp +++ b/src/hotspot/share/classfile/resolutionErrors.cpp @@ -127,10 +127,8 @@ ResolutionErrorEntry::~ResolutionErrorEntry() { } void ResolutionErrorEntry::set_nest_host_error(const char* message) { - // If a message is already set, free it. - if (nest_host_error() != nullptr) { - FREE_C_HEAP_ARRAY(char, _nest_host_error); - } + assert(_nest_host_error == nullptr, "caller should have checked"); + assert_lock_strong(SystemDictionary_lock); _nest_host_error = message; } diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index e03d198eb9f..73738412017 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -1859,7 +1859,7 @@ Symbol* SystemDictionary::find_resolution_error(const constantPoolHandle& pool, void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool, int which, - const char* message) { + const stringStream& message) { { MutexLocker ml(Thread::current(), SystemDictionary_lock); ResolutionErrorEntry* entry = ResolutionErrorTable::find_entry(pool, which); @@ -1868,14 +1868,19 @@ void SystemDictionary::add_nest_host_error(const constantPoolHandle& pool, // constant pool index. In this case resolution succeeded but there's an error in this nest host // that we use the table to record. assert(pool->resolved_klass_at(which) != nullptr, "klass should be resolved if there is no entry"); - ResolutionErrorTable::add_entry(pool, which, message); + ResolutionErrorTable::add_entry(pool, which, message.as_string(true /* on C-heap */)); } else { // An existing entry means we had a true resolution failure (LinkageError) with our nest host, but we // still want to add the error message for the higher-level access checks to report. We should // only reach here under the same error condition, so we can ignore the potential race with setting - // the message, and set it again. - assert(entry->nest_host_error() == nullptr || strcmp(entry->nest_host_error(), message) == 0, "should be the same message"); - entry->set_nest_host_error(message); + // the message. + const char* nhe = entry->nest_host_error(); + if (nhe == nullptr) { + entry->set_nest_host_error(message.as_string(true /* on C-heap */)); + } else { + DEBUG_ONLY(const char* msg = message.base();) + assert(strcmp(nhe, msg) == 0, "New message %s, differs from original %s", msg, nhe); + } } } } diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index 99e13fea61e..e32e0082f8f 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -280,7 +280,7 @@ public: // Record a nest host resolution/validation error static void add_nest_host_error(const constantPoolHandle& pool, int which, - const char* message); + const stringStream& message); static const char* find_nest_host_error(const constantPoolHandle& pool, int which); static void add_to_initiating_loader(JavaThread* current, InstanceKlass* k, diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index e74bc80d893..56a80daed60 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -312,12 +312,11 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) { ss.print("Nest host resolution of %s with host %s failed: ", this->external_name(), target_host_class); java_lang_Throwable::print(PENDING_EXCEPTION, &ss); - const char* msg = ss.as_string(true /* on C-heap */); constantPoolHandle cph(THREAD, constants()); - SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg); + SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss); CLEAR_PENDING_EXCEPTION; - log_trace(class, nestmates)("%s", msg); + log_trace(class, nestmates)("%s", ss.base()); } else { // A valid nest-host is an instance class in the current package that lists this // class as a nest member. If any of these conditions are not met the class is @@ -356,10 +355,9 @@ InstanceKlass* InstanceKlass::nest_host(TRAPS) { k->external_name(), k->class_loader_data()->loader_name_and_id(), error); - const char* msg = ss.as_string(true /* on C-heap */); constantPoolHandle cph(THREAD, constants()); - SystemDictionary::add_nest_host_error(cph, _nest_host_index, msg); - log_trace(class, nestmates)("%s", msg); + SystemDictionary::add_nest_host_error(cph, _nest_host_index, ss); + log_trace(class, nestmates)("%s", ss.base()); } } } else { From 3f33eaa42aff45422c94300573c898868189fdfc Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Tue, 16 Dec 2025 04:03:12 +0000 Subject: [PATCH 108/211] 8373649: Convert simple AtomicAccess usage in ConcurrentHashTable to use Atomic Reviewed-by: tschatzl, iwalulya --- .../share/utilities/concurrentHashTable.hpp | 11 +-- .../utilities/concurrentHashTable.inline.hpp | 73 ++++++++++--------- .../concurrentHashTableTasks.inline.hpp | 29 ++++---- 3 files changed, 58 insertions(+), 55 deletions(-) diff --git a/src/hotspot/share/utilities/concurrentHashTable.hpp b/src/hotspot/share/utilities/concurrentHashTable.hpp index a837a56a19a..1a50ecabc3e 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.hpp @@ -26,6 +26,7 @@ #define SHARE_UTILITIES_CONCURRENTHASHTABLE_HPP #include "memory/allocation.hpp" +#include "runtime/atomic.hpp" #include "runtime/mutex.hpp" #include "utilities/globalCounter.hpp" #include "utilities/globalDefinitions.hpp" @@ -246,7 +247,7 @@ class ConcurrentHashTable : public CHeapObj { const size_t _log2_start_size; // Start size. const size_t _grow_hint; // Number of linked items - volatile bool _size_limit_reached; + Atomic _size_limit_reached; // We serialize resizers and other bulk operations which do not support // concurrent resize with this lock. @@ -255,7 +256,7 @@ class ConcurrentHashTable : public CHeapObj { // taking the mutex after a safepoint this bool is the actual state. After // acquiring the mutex you must check if this is already locked. If so you // must drop the mutex until the real lock holder grabs the mutex. - volatile Thread* _resize_lock_owner; + Atomic _resize_lock_owner; // Return true if lock mutex/state succeeded. bool try_resize_lock(Thread* locker); @@ -273,7 +274,7 @@ class ConcurrentHashTable : public CHeapObj { // this field keep tracks if a version of the hash-table was ever been seen. // We the working thread pointer as tag for debugging. The _invisible_epoch // can only be used by the owner of _resize_lock. - volatile Thread* _invisible_epoch; + Atomic _invisible_epoch; // Scoped critical section, which also handles the invisible epochs. // An invisible epoch/version do not need a write_synchronize(). @@ -435,11 +436,11 @@ class ConcurrentHashTable : public CHeapObj { size_t get_size_log2(Thread* thread); static size_t get_node_size() { return sizeof(Node); } static size_t get_dynamic_node_size(size_t value_size); - bool is_max_size_reached() { return _size_limit_reached; } + bool is_max_size_reached() { return _size_limit_reached.load_relaxed(); } // This means no paused bucket resize operation is going to resume // on this table. - bool is_safepoint_safe() { return _resize_lock_owner == nullptr; } + bool is_safepoint_safe() { return _resize_lock_owner.load_relaxed() == nullptr; } // Re-size operations. bool shrink(Thread* thread, size_t size_limit_log2 = 0); diff --git a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp index eeaff0167b2..b96a487324c 100644 --- a/src/hotspot/share/utilities/concurrentHashTable.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTable.inline.hpp @@ -29,6 +29,7 @@ #include "cppstdlib/type_traits.hpp" #include "memory/allocation.inline.hpp" +#include "runtime/atomic.hpp" #include "runtime/atomicAccess.hpp" #include "runtime/orderAccess.hpp" #include "runtime/prefetch.inline.hpp" @@ -221,8 +222,8 @@ inline ConcurrentHashTable:: _cs_context(GlobalCounter::critical_section_begin(_thread)) { // This version is published now. - if (AtomicAccess::load_acquire(&_cht->_invisible_epoch) != nullptr) { - AtomicAccess::release_store_fence(&_cht->_invisible_epoch, (Thread*)nullptr); + if (_cht->_invisible_epoch.load_acquire() != nullptr) { + _cht->_invisible_epoch.release_store_fence(nullptr); } } @@ -282,16 +283,16 @@ template inline void ConcurrentHashTable:: write_synchonize_on_visible_epoch(Thread* thread) { - assert(_resize_lock_owner == thread, "Re-size lock not held"); + assert(_resize_lock_owner.load_relaxed() == thread, "Re-size lock not held"); OrderAccess::fence(); // Prevent below load from floating up. // If no reader saw this version we can skip write_synchronize. - if (AtomicAccess::load_acquire(&_invisible_epoch) == thread) { + if (_invisible_epoch.load_acquire() == thread) { return; } - assert(_invisible_epoch == nullptr, "Two thread doing bulk operations"); + assert(_invisible_epoch.load_relaxed() == nullptr, "Two thread doing bulk operations"); // We set this/next version that we are synchronizing for to not published. // A reader will zero this flag if it reads this/next version. - AtomicAccess::release_store(&_invisible_epoch, thread); + _invisible_epoch.release_store(thread); GlobalCounter::write_synchronize(); } @@ -300,8 +301,8 @@ inline bool ConcurrentHashTable:: try_resize_lock(Thread* locker) { if (_resize_lock->try_lock()) { - if (_resize_lock_owner != nullptr) { - assert(locker != _resize_lock_owner, "Already own lock"); + if (_resize_lock_owner.load_relaxed() != nullptr) { + assert(locker != _resize_lock_owner.load_relaxed(), "Already own lock"); // We got mutex but internal state is locked. _resize_lock->unlock(); return false; @@ -309,8 +310,8 @@ inline bool ConcurrentHashTable:: } else { return false; } - _invisible_epoch = nullptr; - _resize_lock_owner = locker; + _invisible_epoch.store_relaxed(nullptr); + _resize_lock_owner.store_relaxed(locker); return true; } @@ -326,8 +327,8 @@ inline void ConcurrentHashTable:: _resize_lock->lock_without_safepoint_check(); // If holder of lock dropped mutex for safepoint mutex might be unlocked, // and _resize_lock_owner will contain the owner. - if (_resize_lock_owner != nullptr) { - assert(locker != _resize_lock_owner, "Already own lock"); + if (_resize_lock_owner.load_relaxed() != nullptr) { + assert(locker != _resize_lock_owner.load_relaxed(), "Already own lock"); // We got mutex but internal state is locked. _resize_lock->unlock(); yield.wait(); @@ -335,17 +336,17 @@ inline void ConcurrentHashTable:: break; } } while(true); - _resize_lock_owner = locker; - _invisible_epoch = nullptr; + _resize_lock_owner.store_relaxed(locker); + _invisible_epoch.store_relaxed(nullptr); } template inline void ConcurrentHashTable:: unlock_resize_lock(Thread* locker) { - _invisible_epoch = nullptr; - assert(locker == _resize_lock_owner, "Not unlocked by locker."); - _resize_lock_owner = nullptr; + _invisible_epoch.store_relaxed(nullptr); + assert(locker == _resize_lock_owner.load_relaxed(), "Not unlocked by locker."); + _resize_lock_owner.store_relaxed(nullptr); _resize_lock->unlock(); } @@ -477,8 +478,8 @@ inline void ConcurrentHashTable:: { // Here we have resize lock so table is SMR safe, and there is no new // table. Can do this in parallel if we want. - assert((is_mt && _resize_lock_owner != nullptr) || - (!is_mt && _resize_lock_owner == thread), "Re-size lock not held"); + assert((is_mt && _resize_lock_owner.load_relaxed() != nullptr) || + (!is_mt && _resize_lock_owner.load_relaxed() == thread), "Re-size lock not held"); Node* ndel_stack[StackBufferSize]; InternalTable* table = get_table(); assert(start_idx < stop_idx, "Must be"); @@ -696,7 +697,7 @@ inline bool ConcurrentHashTable:: if (!try_resize_lock(thread)) { return false; } - assert(_resize_lock_owner == thread, "Re-size lock not held"); + assert(_resize_lock_owner.load_relaxed() == thread, "Re-size lock not held"); if (_table->_log2_size == _log2_start_size || _table->_log2_size <= log2_size) { unlock_resize_lock(thread); @@ -710,10 +711,10 @@ template inline void ConcurrentHashTable:: internal_shrink_epilog(Thread* thread) { - assert(_resize_lock_owner == thread, "Re-size lock not held"); + assert(_resize_lock_owner.load_relaxed() == thread, "Re-size lock not held"); InternalTable* old_table = set_table_from_new(); - _size_limit_reached = false; + _size_limit_reached.store_relaxed(false); unlock_resize_lock(thread); #ifdef ASSERT for (size_t i = 0; i < old_table->_size; i++) { @@ -767,13 +768,13 @@ inline bool ConcurrentHashTable:: internal_shrink(Thread* thread, size_t log2_size) { if (!internal_shrink_prolog(thread, log2_size)) { - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); return false; } - assert(_resize_lock_owner == thread, "Should be locked by me"); + assert(_resize_lock_owner.load_relaxed() == thread, "Should be locked by me"); internal_shrink_range(thread, 0, _new_table->_size); internal_shrink_epilog(thread); - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); return true; } @@ -787,7 +788,7 @@ inline void ConcurrentHashTable:: delete _table; // Create and publish a new table InternalTable* table = new InternalTable(log2_size); - _size_limit_reached = (log2_size == _log2_size_limit); + _size_limit_reached.store_relaxed(log2_size == _log2_size_limit); AtomicAccess::release_store(&_table, table); } @@ -812,7 +813,7 @@ inline bool ConcurrentHashTable:: } _new_table = new InternalTable(_table->_log2_size + 1); - _size_limit_reached = _new_table->_log2_size == _log2_size_limit; + _size_limit_reached.store_relaxed(_new_table->_log2_size == _log2_size_limit); return true; } @@ -821,7 +822,7 @@ template inline void ConcurrentHashTable:: internal_grow_epilog(Thread* thread) { - assert(_resize_lock_owner == thread, "Should be locked"); + assert(_resize_lock_owner.load_relaxed() == thread, "Should be locked"); InternalTable* old_table = set_table_from_new(); unlock_resize_lock(thread); @@ -840,13 +841,13 @@ inline bool ConcurrentHashTable:: internal_grow(Thread* thread, size_t log2_size) { if (!internal_grow_prolog(thread, log2_size)) { - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); return false; } - assert(_resize_lock_owner == thread, "Should be locked by me"); + assert(_resize_lock_owner.load_relaxed() == thread, "Should be locked by me"); internal_grow_range(thread, 0, _table->_size); internal_grow_epilog(thread); - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); return true; } @@ -961,7 +962,7 @@ template inline void ConcurrentHashTable:: do_scan_locked(Thread* thread, FUNC& scan_f) { - assert(_resize_lock_owner == thread, "Re-size lock not held"); + assert(_resize_lock_owner.load_relaxed() == thread, "Re-size lock not held"); // We can do a critical section over the entire loop but that would block // updates for a long time. Instead we choose to block resizes. InternalTable* table = get_table(); @@ -1020,7 +1021,7 @@ ConcurrentHashTable(size_t log2size, size_t log2size_limit, size_t grow_hint, bo _resize_lock = new Mutex(rank, "ConcurrentHashTableResize_lock"); _table = new InternalTable(log2size); assert(log2size_limit >= log2size, "bad ergo"); - _size_limit_reached = _table->_log2_size == _log2_size_limit; + _size_limit_reached.store_relaxed(_table->_log2_size == _log2_size_limit); } template @@ -1139,11 +1140,11 @@ inline void ConcurrentHashTable:: { assert(!SafepointSynchronize::is_at_safepoint(), "must be outside a safepoint"); - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); lock_resize_lock(thread); do_scan_locked(thread, scan_f); unlock_resize_lock(thread); - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); } template @@ -1205,7 +1206,7 @@ inline bool ConcurrentHashTable:: } do_bulk_delete_locked(thread, eval_f, del_f); unlock_resize_lock(thread); - assert(_resize_lock_owner != thread, "Re-size lock held"); + assert(_resize_lock_owner.load_relaxed() != thread, "Re-size lock held"); return true; } diff --git a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp index 086a548ede5..054008953a8 100644 --- a/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp +++ b/src/hotspot/share/utilities/concurrentHashTableTasks.inline.hpp @@ -27,6 +27,7 @@ // No concurrentHashTableTasks.hpp +#include "runtime/atomic.hpp" #include "runtime/atomicAccess.hpp" #include "utilities/concurrentHashTable.inline.hpp" #include "utilities/globalDefinitions.hpp" @@ -41,7 +42,7 @@ class ConcurrentHashTable::BucketsOperation { ConcurrentHashTable* _cht; class InternalTableClaimer { - volatile size_t _next; + Atomic _next; size_t _limit; size_t _size; @@ -56,14 +57,14 @@ public: void set(size_t claim_size, InternalTable* table) { assert(table != nullptr, "precondition"); - _next = 0; + _next.store_relaxed(0); _limit = table->_size; _size = MIN2(claim_size, _limit); } bool claim(size_t* start, size_t* stop) { - if (AtomicAccess::load(&_next) < _limit) { - size_t claimed = AtomicAccess::fetch_then_add(&_next, _size); + if (_next.load_relaxed() < _limit) { + size_t claimed = _next.fetch_then_add(_size); if (claimed < _limit) { *start = claimed; *stop = MIN2(claimed + _size, _limit); @@ -78,7 +79,7 @@ public: } bool have_more_work() { - return AtomicAccess::load_acquire(&_next) >= _limit; + return _next.load_acquire() >= _limit; } }; @@ -108,13 +109,13 @@ public: } void thread_owns_resize_lock(Thread* thread) { - assert(BucketsOperation::_cht->_resize_lock_owner == thread, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() == thread, "Should be locked by me"); assert(BucketsOperation::_cht->_resize_lock->owned_by_self(), "Operations lock not held"); } void thread_owns_only_state_lock(Thread* thread) { - assert(BucketsOperation::_cht->_resize_lock_owner == thread, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() == thread, "Should be locked by me"); assert(!BucketsOperation::_cht->_resize_lock->owned_by_self(), "Operations lock held"); @@ -122,7 +123,7 @@ public: void thread_do_not_own_resize_lock(Thread* thread) { assert(!BucketsOperation::_cht->_resize_lock->owned_by_self(), "Operations lock held"); - assert(BucketsOperation::_cht->_resize_lock_owner != thread, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != thread, "Should not be locked by me"); } @@ -169,7 +170,7 @@ class ConcurrentHashTable::BulkDeleteTask : template bool do_task(Thread* thread, EVALUATE_FUNC& eval_f, DELETE_FUNC& del_f) { size_t start, stop; - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); if (!this->claim(&start, &stop)) { return false; @@ -177,7 +178,7 @@ class ConcurrentHashTable::BulkDeleteTask : BucketsOperation::_cht->do_bulk_delete_locked_for(thread, start, stop, eval_f, del_f, BucketsOperation::_is_mt); - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); return true; } @@ -210,13 +211,13 @@ class ConcurrentHashTable::GrowTask : // Re-sizes a portion of the table. Returns true if there is more work. bool do_task(Thread* thread) { size_t start, stop; - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); if (!this->claim(&start, &stop)) { return false; } BucketsOperation::_cht->internal_grow_range(thread, start, stop); - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); return true; } @@ -253,13 +254,13 @@ class ConcurrentHashTable::StatisticsTask : template bool do_task(Thread* thread, VALUE_SIZE_FUNC& sz) { size_t start, stop; - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); if (!this->claim(&start, &stop)) { return false; } BucketsOperation::_cht->internal_statistics_range(thread, start, stop, sz, _summary, _literal_bytes); - assert(BucketsOperation::_cht->_resize_lock_owner != nullptr, + assert(BucketsOperation::_cht->_resize_lock_owner.load_relaxed() != nullptr, "Should be locked"); return true; } From b1e8c4e030f42ea3146b2502c9ab030bc79a8147 Mon Sep 17 00:00:00 2001 From: Rui Li Date: Tue, 16 Dec 2025 07:02:15 +0000 Subject: [PATCH 109/211] 8372543: Shenandoah: undercalculated the available size when soft max takes effect Reviewed-by: wkemper, kdnilsen --- .../shenandoahAdaptiveHeuristics.cpp | 13 +- .../shenandoahCompactHeuristics.cpp | 14 +- .../heuristics/shenandoahSpaceInfo.hpp | 2 +- .../heuristics/shenandoahStaticHeuristics.cpp | 16 +-- .../share/gc/shenandoah/shenandoahFreeSet.cpp | 82 +++++------- .../share/gc/shenandoah/shenandoahFreeSet.hpp | 1 + .../gc/shenandoah/shenandoahGeneration.cpp | 4 +- .../gc/shenandoah/shenandoahGeneration.hpp | 2 +- .../shenandoah/shenandoahGlobalGeneration.cpp | 9 -- .../shenandoah/shenandoahGlobalGeneration.hpp | 1 - .../shenandoah/shenandoahYoungGeneration.cpp | 4 +- .../shenandoah/shenandoahYoungGeneration.hpp | 2 +- .../TestSoftMaxHeapSizeAvailableCalc.java | 123 ++++++++++++++++++ 13 files changed, 182 insertions(+), 91 deletions(-) create mode 100644 test/hotspot/jtreg/gc/shenandoah/TestSoftMaxHeapSizeAvailableCalc.java diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp index 6498f0acdb6..41535f302d7 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahAdaptiveHeuristics.cpp @@ -31,7 +31,6 @@ #include "gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" #include "gc/shenandoah/shenandoahCollectorPolicy.hpp" -#include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "logging/log.hpp" @@ -234,11 +233,12 @@ static double saturate(double value, double min, double max) { // allocation rate computation independent. bool ShenandoahAdaptiveHeuristics::should_start_gc() { size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); - size_t available = _space_info->soft_available(); + size_t available = _space_info->soft_mutator_available(); size_t allocated = _space_info->bytes_allocated_since_gc_start(); - log_debug(gc)("should_start_gc? available: %zu, soft_max_capacity: %zu" - ", allocated: %zu", available, capacity, allocated); + log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", " + "allocated_since_gc_start: " PROPERFMT, + PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(allocated)); // Track allocation rate even if we decide to start a cycle for other reasons. double rate = _allocation_rate.sample(allocated); @@ -252,9 +252,8 @@ bool ShenandoahAdaptiveHeuristics::should_start_gc() { size_t min_threshold = min_free_threshold(); if (available < min_threshold) { - log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)", - byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), - byte_size_in_proper_unit(min_threshold), proper_unit_for_byte_size(min_threshold)); + log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", + PROPERFMTARGS(available), PROPERFMTARGS(min_threshold)); accept_trigger_with_type(OTHER); return true; } diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp index f8a77d95d51..28673b28612 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahCompactHeuristics.cpp @@ -26,7 +26,6 @@ #include "gc/shenandoah/heuristics/shenandoahCompactHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" -#include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "logging/log.hpp" @@ -47,26 +46,25 @@ ShenandoahCompactHeuristics::ShenandoahCompactHeuristics(ShenandoahSpaceInfo* sp } bool ShenandoahCompactHeuristics::should_start_gc() { - size_t max_capacity = _space_info->max_capacity(); size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); - size_t available = _space_info->available(); + size_t available = _space_info->soft_mutator_available(); + size_t bytes_allocated = _space_info->bytes_allocated_since_gc_start(); - // Make sure the code below treats available without the soft tail. - size_t soft_tail = max_capacity - capacity; - available = (available > soft_tail) ? (available - soft_tail) : 0; + log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", " + "allocated_since_gc_start: " PROPERFMT, + PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(bytes_allocated)); size_t threshold_bytes_allocated = capacity / 100 * ShenandoahAllocationThreshold; size_t min_threshold = capacity / 100 * ShenandoahMinFreeThreshold; if (available < min_threshold) { - log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)", + log_trigger("Free (Soft) (%zu%s) is below minimum threshold (%zu%s)", byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), byte_size_in_proper_unit(min_threshold), proper_unit_for_byte_size(min_threshold)); accept_trigger(); return true; } - size_t bytes_allocated = _space_info->bytes_allocated_since_gc_start(); if (bytes_allocated > threshold_bytes_allocated) { log_trigger("Allocated since last cycle (%zu%s) is larger than allocation threshold (%zu%s)", byte_size_in_proper_unit(bytes_allocated), proper_unit_for_byte_size(bytes_allocated), diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp index 7fb44c7b71b..6ed05abf0b1 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahSpaceInfo.hpp @@ -38,7 +38,7 @@ class ShenandoahSpaceInfo { public: virtual const char* name() const = 0; virtual size_t max_capacity() const = 0; - virtual size_t soft_available() const = 0; + virtual size_t soft_mutator_available() const = 0; virtual size_t available() const = 0; virtual size_t used() const = 0; diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp index 205135751aa..d4d66fef6a1 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahStaticHeuristics.cpp @@ -26,7 +26,6 @@ #include "gc/shenandoah/heuristics/shenandoahStaticHeuristics.hpp" #include "gc/shenandoah/shenandoahCollectionSet.hpp" -#include "gc/shenandoah/shenandoahFreeSet.hpp" #include "gc/shenandoah/shenandoahHeap.inline.hpp" #include "gc/shenandoah/shenandoahHeapRegion.inline.hpp" #include "logging/log.hpp" @@ -41,20 +40,19 @@ ShenandoahStaticHeuristics::ShenandoahStaticHeuristics(ShenandoahSpaceInfo* spac ShenandoahStaticHeuristics::~ShenandoahStaticHeuristics() {} bool ShenandoahStaticHeuristics::should_start_gc() { - size_t max_capacity = _space_info->max_capacity(); size_t capacity = ShenandoahHeap::heap()->soft_max_capacity(); - size_t available = _space_info->available(); + size_t available = _space_info->soft_mutator_available(); + size_t allocated = _space_info->bytes_allocated_since_gc_start(); - // Make sure the code below treats available without the soft tail. - size_t soft_tail = max_capacity - capacity; - available = (available > soft_tail) ? (available - soft_tail) : 0; + log_debug(gc, ergo)("should_start_gc calculation: available: " PROPERFMT ", soft_max_capacity: " PROPERFMT ", " + "allocated_since_gc_start: " PROPERFMT, + PROPERFMTARGS(available), PROPERFMTARGS(capacity), PROPERFMTARGS(allocated)); size_t threshold_available = capacity / 100 * ShenandoahMinFreeThreshold; if (available < threshold_available) { - log_trigger("Free (%zu%s) is below minimum threshold (%zu%s)", - byte_size_in_proper_unit(available), proper_unit_for_byte_size(available), - byte_size_in_proper_unit(threshold_available), proper_unit_for_byte_size(threshold_available)); + log_trigger("Free (Soft) (" PROPERFMT ") is below minimum threshold (" PROPERFMT ")", + PROPERFMTARGS(available), PROPERFMTARGS(threshold_available)); accept_trigger(); return true; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp index eb05bf24028..c03e66e28da 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.cpp @@ -2921,6 +2921,29 @@ void ShenandoahFreeSet::log_status_under_lock() { } } +void ShenandoahFreeSet::log_freeset_stats(ShenandoahFreeSetPartitionId partition_id, LogStream& ls) { + size_t max = 0; + size_t total_free = 0; + size_t total_used = 0; + + for (idx_t idx = _partitions.leftmost(partition_id); + idx <= _partitions.rightmost(partition_id); idx++) { + if (_partitions.in_free_set(partition_id, idx)) { + ShenandoahHeapRegion *r = _heap->get_region(idx); + size_t free = alloc_capacity(r); + max = MAX2(max, free); + total_free += free; + total_used += r->used(); + } + } + + ls.print(" %s freeset stats: Partition count: %zu, Reserved: " PROPERFMT ", Max free available in a single region: " PROPERFMT ";", + partition_name(partition_id), + _partitions.count(partition_id), + PROPERFMTARGS(total_free), PROPERFMTARGS(max) + ); +} + void ShenandoahFreeSet::log_status() { shenandoah_assert_heaplocked(); @@ -3040,20 +3063,18 @@ void ShenandoahFreeSet::log_status() { // retired, the sum of used and capacities within regions that are still in the Mutator free partition may not match // my internally tracked values of used() and free(). assert(free == total_free, "Free memory (%zu) should match calculated memory (%zu)", free, total_free); - ls.print("Free: %zu%s, Max: %zu%s regular, %zu%s humongous, ", - byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free), - byte_size_in_proper_unit(max), proper_unit_for_byte_size(max), - byte_size_in_proper_unit(max_humongous), proper_unit_for_byte_size(max_humongous) - ); + ls.print("Whole heap stats: Total free: " PROPERFMT ", Total used: " PROPERFMT ", Max free in a single region: " PROPERFMT + ", Max humongous: " PROPERFMT "; ", + PROPERFMTARGS(total_free), PROPERFMTARGS(total_used), PROPERFMTARGS(max), PROPERFMTARGS(max_humongous)); - ls.print("Frag: "); + ls.print("Frag stats: "); size_t frag_ext; if (total_free_ext > 0) { frag_ext = 100 - (100 * max_humongous / total_free_ext); } else { frag_ext = 0; } - ls.print("%zu%% external, ", frag_ext); + ls.print("External: %zu%%, ", frag_ext); size_t frag_int; if (_partitions.count(ShenandoahFreeSetPartitionId::Mutator) > 0) { @@ -3062,52 +3083,13 @@ void ShenandoahFreeSet::log_status() { } else { frag_int = 0; } - ls.print("%zu%% internal; ", frag_int); - ls.print("Used: %zu%s, Mutator Free: %zu", - byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used), - _partitions.count(ShenandoahFreeSetPartitionId::Mutator)); - } - - { - size_t max = 0; - size_t total_free = 0; - size_t total_used = 0; - - for (idx_t idx = _partitions.leftmost(ShenandoahFreeSetPartitionId::Collector); - idx <= _partitions.rightmost(ShenandoahFreeSetPartitionId::Collector); idx++) { - if (_partitions.in_free_set(ShenandoahFreeSetPartitionId::Collector, idx)) { - ShenandoahHeapRegion *r = _heap->get_region(idx); - size_t free = alloc_capacity(r); - max = MAX2(max, free); - total_free += free; - total_used += r->used(); - } - } - ls.print(" Collector Reserve: %zu%s, Max: %zu%s; Used: %zu%s", - byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free), - byte_size_in_proper_unit(max), proper_unit_for_byte_size(max), - byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used)); + ls.print("Internal: %zu%%; ", frag_int); } + log_freeset_stats(ShenandoahFreeSetPartitionId::Mutator, ls); + log_freeset_stats(ShenandoahFreeSetPartitionId::Collector, ls); if (_heap->mode()->is_generational()) { - size_t max = 0; - size_t total_free = 0; - size_t total_used = 0; - - for (idx_t idx = _partitions.leftmost(ShenandoahFreeSetPartitionId::OldCollector); - idx <= _partitions.rightmost(ShenandoahFreeSetPartitionId::OldCollector); idx++) { - if (_partitions.in_free_set(ShenandoahFreeSetPartitionId::OldCollector, idx)) { - ShenandoahHeapRegion *r = _heap->get_region(idx); - size_t free = alloc_capacity(r); - max = MAX2(max, free); - total_free += free; - total_used += r->used(); - } - } - ls.print_cr(" Old Collector Reserve: %zu%s, Max: %zu%s; Used: %zu%s", - byte_size_in_proper_unit(total_free), proper_unit_for_byte_size(total_free), - byte_size_in_proper_unit(max), proper_unit_for_byte_size(max), - byte_size_in_proper_unit(total_used), proper_unit_for_byte_size(total_used)); + log_freeset_stats(ShenandoahFreeSetPartitionId::OldCollector, ls); } } } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index a9c5ebe49de..400eb8d25ee 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -629,6 +629,7 @@ private: void establish_old_collector_alloc_bias(); size_t get_usable_free_words(size_t free_bytes) const; + void log_freeset_stats(ShenandoahFreeSetPartitionId partition_id, LogStream& ls); // log status, assuming lock has already been acquired by the caller. void log_status(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp index b9295654b6f..d74ee872cd1 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.cpp @@ -938,8 +938,8 @@ size_t ShenandoahGeneration::available_with_reserve() const { return result; } -size_t ShenandoahGeneration::soft_available() const { - size_t result = available(ShenandoahHeap::heap()->soft_max_capacity()); +size_t ShenandoahGeneration::soft_mutator_available() const { + size_t result = available(ShenandoahHeap::heap()->soft_max_capacity() * (100.0 - ShenandoahEvacReserve) / 100); return result; } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp index 6f393110666..06cf132f946 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGeneration.hpp @@ -126,7 +126,7 @@ private: // The soft max heap size may be adjusted lower than the max heap size to cause the trigger // to believe it has less memory available than is _really_ available. Lowering the soft // max heap size will cause the adaptive heuristic to run more frequent cycles. - size_t soft_available() const override; + size_t soft_mutator_available() const override; void log_status(const char* msg) const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp index c9972e2db81..a072fe2db06 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.cpp @@ -78,15 +78,6 @@ size_t ShenandoahGlobalGeneration::available() const { return MIN2(available, ShenandoahHeap::heap()->free_set()->available()); } -size_t ShenandoahGlobalGeneration::soft_available() const { - size_t available = this->available(); - - // Make sure the code below treats available without the soft tail. - assert(max_capacity() >= ShenandoahHeap::heap()->soft_max_capacity(), "Max capacity must be greater than soft max capacity."); - size_t soft_tail = max_capacity() - ShenandoahHeap::heap()->soft_max_capacity(); - return (available > soft_tail) ? (available - soft_tail) : 0; -} - void ShenandoahGlobalGeneration::set_concurrent_mark_in_progress(bool in_progress) { ShenandoahHeap* heap = ShenandoahHeap::heap(); if (in_progress && heap->mode()->is_generational()) { diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp index 5ceba8ed50e..9f9e4818a95 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGlobalGeneration.hpp @@ -56,7 +56,6 @@ public: size_t max_capacity() const override; size_t available() const override; - size_t soft_available() const override; void set_concurrent_mark_in_progress(bool in_progress) override; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp index 86be2fc60be..f00ce16136f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.cpp @@ -138,8 +138,8 @@ size_t ShenandoahYoungGeneration::available() const { return MIN2(available, ShenandoahHeap::heap()->free_set()->available()); } -size_t ShenandoahYoungGeneration::soft_available() const { - size_t available = this->ShenandoahGeneration::soft_available(); +size_t ShenandoahYoungGeneration::soft_mutator_available() const { + size_t available = this->ShenandoahGeneration::soft_mutator_available(); return MIN2(available, ShenandoahHeap::heap()->free_set()->available()); } diff --git a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp index 6b2794b12c3..930c5ff1747 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahYoungGeneration.hpp @@ -83,7 +83,7 @@ public: size_t max_capacity() const override; size_t available() const override; - size_t soft_available() const override; + size_t soft_mutator_available() const override; void prepare_gc() override; }; diff --git a/test/hotspot/jtreg/gc/shenandoah/TestSoftMaxHeapSizeAvailableCalc.java b/test/hotspot/jtreg/gc/shenandoah/TestSoftMaxHeapSizeAvailableCalc.java new file mode 100644 index 00000000000..e70f2f0849f --- /dev/null +++ b/test/hotspot/jtreg/gc/shenandoah/TestSoftMaxHeapSizeAvailableCalc.java @@ -0,0 +1,123 @@ +/* + * Copyright Amazon.com Inc. 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=satb-adaptive + * @requires vm.gc.Shenandoah + * @library /test/lib + * @bug 8372543 + * @summary When soft max heap size < Xmx, we had a bug reported in JBS-8372543 where available size was undercalculated. + * This caused excessive GC runs. + * + * @run main/othervm -XX:SoftMaxHeapSize=512m -Xmx2g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=adaptive + * TestSoftMaxHeapSizeAvailableCalc + */ + +/** + * @test id=satb-static + * @requires vm.gc.Shenandoah + * @library /test/lib + * + * @run main/othervm -XX:SoftMaxHeapSize=512m -Xmx2g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info + * -XX:ShenandoahGCMode=satb + * -XX:+ShenandoahDegeneratedGC + * -XX:ShenandoahGCHeuristics=static + * TestSoftMaxHeapSizeAvailableCalc + */ + +/** + * @test id=generational + * @requires vm.gc.Shenandoah + * @library /test/lib + * + * @run main/othervm -XX:SoftMaxHeapSize=512m -Xmx2g -XX:+UnlockDiagnosticVMOptions -XX:+UnlockExperimentalVMOptions + * -XX:+UseShenandoahGC -Xlog:gc=info + * -XX:ShenandoahGCMode=generational + * -XX:ShenandoahGCHeuristics=adaptive + * TestSoftMaxHeapSizeAvailableCalc + * + */ +import java.lang.management.ManagementFactory; + +import jdk.test.lib.Asserts; +import jdk.test.lib.Utils; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.dcmd.PidJcmdExecutor; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import com.sun.management.GarbageCollectorMXBean; + +public class TestSoftMaxHeapSizeAvailableCalc { + public static void main(String[] args) throws Exception { + Allocate.test(); + } + + // This test runs an app that has a stable heap of ~300M and allocates temporary garbage at ~100M/s + // Soft max: 512M, ShenandoahMinFreeThreshold: 10 (default), ShenandoahEvacReserve: 5 (default) + // Soft max for mutator: 512M * (100.0 - 5) / 100 = 486.4M + // Threshold to trigger gc: 486.4M - 512 * 10 / 100.0 = 435.2M, just above (300 + 100)M. + // Expect gc count to be less than 1 / sec. + public static class Allocate { + static final List longLived = new ArrayList<>(); + + public static void test() throws Exception { + final int expectedMaxGcCount = Integer.getInteger("expectedMaxGcCount", 30); + List collectors = ManagementFactory.getGarbageCollectorMXBeans(); + java.lang.management.GarbageCollectorMXBean cycleCollector = null; + for (java.lang.management.GarbageCollectorMXBean bean : collectors) { + if (bean.getName().contains("Cycles")) { + cycleCollector = bean; + } + } + + // Allocate ~300MB of long-lived objects + for (int i = 0; i < 300; i++) { + longLived.add(new byte[1_000_000]); + } + + // allocate short-lived garbage to the heap + long end = System.currentTimeMillis() + 30_000; // 30 seconds + + while (System.currentTimeMillis() < end) { + byte[] garbage = new byte[1_000_000]; + garbage[0] = 1; // prevent optimization + + Thread.sleep(10); // Pace to generate garbage at speed of ~100M/s + } + + long gcCount = cycleCollector.getCollectionCount(); + Asserts.assertLessThan(gcCount, (long) expectedMaxGcCount, "GC was triggered too many times. Expected to be less than: " + expectedMaxGcCount + ", triggered: " + gcCount); + } + } +} From 78c2d57259ad829a2cfc1370efbb2a5913df4661 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 16 Dec 2025 07:38:26 +0000 Subject: [PATCH 110/211] 8373668: Add override keyword to *Klass classes Reviewed-by: jwaters, dholmes, kbarrett, tschatzl --- src/hotspot/share/oops/arrayKlass.hpp | 36 ++++----- src/hotspot/share/oops/instanceKlass.hpp | 78 +++++++++---------- .../share/oops/instanceMirrorKlass.hpp | 2 +- src/hotspot/share/oops/instanceRefKlass.hpp | 2 +- src/hotspot/share/oops/klass.hpp | 13 +--- src/hotspot/share/oops/objArrayKlass.hpp | 40 +++++----- src/hotspot/share/oops/typeArrayKlass.hpp | 28 +++---- 7 files changed, 97 insertions(+), 102 deletions(-) diff --git a/src/hotspot/share/oops/arrayKlass.hpp b/src/hotspot/share/oops/arrayKlass.hpp index 6ee783fb510..b9b100f18a8 100644 --- a/src/hotspot/share/oops/arrayKlass.hpp +++ b/src/hotspot/share/oops/arrayKlass.hpp @@ -51,15 +51,15 @@ class ArrayKlass: public Klass { public: // Testing operation - DEBUG_ONLY(bool is_array_klass_slow() const { return true; }) + DEBUG_ONLY(bool is_array_klass_slow() const override { return true; }) // Returns the ObjArrayKlass for n'th dimension. - ArrayKlass* array_klass(int n, TRAPS); - ArrayKlass* array_klass_or_null(int n); + ArrayKlass* array_klass(int n, TRAPS) override; + ArrayKlass* array_klass_or_null(int n) override; // Returns the array class with this class as element type. - ArrayKlass* array_klass(TRAPS); - ArrayKlass* array_klass_or_null(); + ArrayKlass* array_klass(TRAPS) override; + ArrayKlass* array_klass_or_null() override; // Instance variables int dimension() const { return _dimension; } @@ -79,7 +79,7 @@ class ArrayKlass: public Klass { // type of elements (T_OBJECT for both oop arrays and array-arrays) BasicType element_type() const { return layout_helper_element_type(layout_helper()); } - virtual InstanceKlass* java_super() const; + InstanceKlass* java_super() const override; // Allocation // Sizes points to the first dimension of the array, subsequent dimensions @@ -87,13 +87,13 @@ class ArrayKlass: public Klass { virtual oop multi_allocate(int rank, jint* sizes, TRAPS); // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined - Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; + Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const override; // Lookup operations Method* uncached_lookup_method(const Symbol* name, const Symbol* signature, OverpassLookupMode overpass_mode, - PrivateLookupMode private_mode = PrivateLookupMode::find) const; + PrivateLookupMode private_mode = PrivateLookupMode::find) const override; static ArrayKlass* cast(Klass* k) { return const_cast(cast(const_cast(k))); @@ -105,38 +105,38 @@ class ArrayKlass: public Klass { } GrowableArray* compute_secondary_supers(int num_extra_slots, - Array* transitive_interfaces); + Array* transitive_interfaces) override; // Sizing static int static_size(int header_size); - virtual void metaspace_pointers_do(MetaspaceClosure* iter); + void metaspace_pointers_do(MetaspaceClosure* iter) override; // Return a handle. static void complete_create_array_klass(ArrayKlass* k, Klass* super_klass, ModuleEntry* module, TRAPS); // JVMTI support - jint jvmti_class_status() const; + jint jvmti_class_status() const override; #if INCLUDE_CDS // CDS support - remove and restore oops from metadata. Oops are not shared. - virtual void remove_unshareable_info(); - virtual void remove_java_mirror(); + void remove_unshareable_info() override; + void remove_java_mirror() override; void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS); void cds_print_value_on(outputStream* st) const; #endif void log_array_class_load(Klass* k); // Printing - void print_on(outputStream* st) const; - void print_value_on(outputStream* st) const; + void print_on(outputStream* st) const override; + void print_value_on(outputStream* st) const override; - void oop_print_on(oop obj, outputStream* st); + void oop_print_on(oop obj, outputStream* st) override; // Verification - void verify_on(outputStream* st); + void verify_on(outputStream* st) override; - void oop_verify_on(oop obj, outputStream* st); + void oop_verify_on(oop obj, outputStream* st) override; }; #endif // SHARE_OOPS_ARRAYKLASS_HPP diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index a03e6c05b54..23a59d26093 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -313,8 +313,8 @@ class InstanceKlass: public Klass { bool is_public() const { return _access_flags.is_public(); } bool is_final() const { return _access_flags.is_final(); } - bool is_interface() const { return _access_flags.is_interface(); } - bool is_abstract() const { return _access_flags.is_abstract(); } + bool is_interface() const override { return _access_flags.is_interface(); } + bool is_abstract() const override { return _access_flags.is_abstract(); } bool is_super() const { return _access_flags.is_super(); } bool is_synthetic() const { return _access_flags.is_synthetic(); } void set_is_synthetic() { _access_flags.set_is_synthetic(); } @@ -494,8 +494,8 @@ public: }; // package - PackageEntry* package() const { return _package_entry; } - ModuleEntry* module() const; + PackageEntry* package() const override { return _package_entry; } + ModuleEntry* module() const override; bool in_javabase_module() const; bool in_unnamed_package() const { return (_package_entry == nullptr); } void set_package(ClassLoaderData* loader_data, PackageEntry* pkg_entry, TRAPS); @@ -552,11 +552,11 @@ public: void set_is_marked_dependent(bool value) { _misc_flags.set_is_marked_dependent(value); } // initialization (virtuals from Klass) - bool should_be_initialized() const; // means that initialize should be called + bool should_be_initialized() const override; // means that initialize should be called void initialize_with_aot_initialized_mirror(TRAPS); void assert_no_clinit_will_run_for_aot_initialized_class() const NOT_DEBUG_RETURN; - void initialize(TRAPS); - void initialize_preemptable(TRAPS); + void initialize(TRAPS) override; + void initialize_preemptable(TRAPS) override; void link_class(TRAPS); bool link_class_or_fail(TRAPS); // returns false on failure void rewrite_class(TRAPS); @@ -578,7 +578,7 @@ public: // find field in direct superinterfaces, returns the interface in which the field is defined Klass* find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined - Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; + Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const override; // find instance or static fields according to JVM spec 5.4.3.2, returns the klass in which the field is defined Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const; @@ -637,7 +637,7 @@ public: Method* uncached_lookup_method(const Symbol* name, const Symbol* signature, OverpassLookupMode overpass_mode, - PrivateLookupMode private_mode = PrivateLookupMode::find) const; + PrivateLookupMode private_mode = PrivateLookupMode::find) const override; // lookup a method in all the interfaces that this class implements // (returns null if not found) @@ -660,7 +660,7 @@ public: void set_constants(ConstantPool* c) { _constants = c; } // protection domain - oop protection_domain() const; + oop protection_domain() const override; // signers objArrayOop signers() const; @@ -834,7 +834,7 @@ public: // Check whether reflection/jni/jvm code is allowed to instantiate this class; // if not, throw either an Error or an Exception. - virtual void check_valid_for_instantiation(bool throwError, TRAPS); + void check_valid_for_instantiation(bool throwError, TRAPS) override; // initialization void call_class_initializer(TRAPS); @@ -901,12 +901,12 @@ public: public: // virtual operations from Klass GrowableArray* compute_secondary_supers(int num_extra_slots, - Array* transitive_interfaces); - bool can_be_primary_super_slow() const; - size_t oop_size(oop obj) const { return size_helper(); } + Array* transitive_interfaces) override; + bool can_be_primary_super_slow() const override; + size_t oop_size(oop obj) const override { return size_helper(); } // slow because it's a virtual call and used for verifying the layout_helper. // Using the layout_helper bits, we can call is_instance_klass without a virtual call. - DEBUG_ONLY(bool is_instance_klass_slow() const { return true; }) + DEBUG_ONLY(bool is_instance_klass_slow() const override { return true; }) // Iterators void do_local_static_fields(FieldClosure* cl); @@ -932,7 +932,7 @@ public: return (Klass::super() == nullptr) ? nullptr : InstanceKlass::cast(Klass::super()); } - virtual InstanceKlass* java_super() const { + InstanceKlass* java_super() const override { return InstanceKlass::super(); } @@ -949,10 +949,10 @@ public: (is_interface ? (int)sizeof(Klass*)/wordSize : 0)); } - int size() const { return size(vtable_length(), - itable_length(), - nonstatic_oop_map_size(), - is_interface()); + int size() const override { return size(vtable_length(), + itable_length(), + nonstatic_oop_map_size(), + is_interface()); } @@ -1008,15 +1008,15 @@ public: void static deallocate_record_components(ClassLoaderData* loader_data, Array* record_component); - virtual bool on_stack() const; + bool on_stack() const override; // callbacks for actions during class unloading static void unload_class(InstanceKlass* ik); - virtual void release_C_heap_structures(bool release_sub_metadata = true); + void release_C_heap_structures(bool release_sub_metadata = true) override; // Naming - const char* signature_name() const; + const char* signature_name() const override; // Oop fields (and metadata) iterators // @@ -1095,12 +1095,12 @@ public: oop init_lock() const; // Returns the array class for the n'th dimension - virtual ArrayKlass* array_klass(int n, TRAPS); - virtual ArrayKlass* array_klass_or_null(int n); + ArrayKlass* array_klass(int n, TRAPS) override; + ArrayKlass* array_klass_or_null(int n) override; // Returns the array class with this class as element type - virtual ArrayKlass* array_klass(TRAPS); - virtual ArrayKlass* array_klass_or_null(); + ArrayKlass* array_klass(TRAPS) override; + ArrayKlass* array_klass_or_null() override; static void clean_initialization_error_table(); private: @@ -1139,9 +1139,9 @@ public: #if INCLUDE_CDS // CDS support - remove and restore oops from metadata. Oops are not shared. - virtual void remove_unshareable_info(); + void remove_unshareable_info() override; void remove_unshareable_flags(); - virtual void remove_java_mirror(); + void remove_java_mirror() override; void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, PackageEntry* pkg_entry, TRAPS); void init_shared_package_entry(); bool can_be_verified_at_dumptime() const; @@ -1154,22 +1154,22 @@ public: _misc_flags.set_has_init_deps_processed(true); } - u2 compute_modifier_flags() const; + u2 compute_modifier_flags() const override; public: // JVMTI support - jint jvmti_class_status() const; + jint jvmti_class_status() const override; - virtual void metaspace_pointers_do(MetaspaceClosure* iter); + void metaspace_pointers_do(MetaspaceClosure* iter) override; public: // Printing - void print_on(outputStream* st) const; - void print_value_on(outputStream* st) const; + void print_on(outputStream* st) const override; + void print_value_on(outputStream* st) const override; - void oop_print_value_on(oop obj, outputStream* st); + void oop_print_value_on(oop obj, outputStream* st) override; - void oop_print_on (oop obj, outputStream* st); + void oop_print_on (oop obj, outputStream* st) override; #ifndef PRODUCT void print_dependent_nmethods(bool verbose = false); @@ -1177,12 +1177,12 @@ public: bool verify_itable_index(int index); #endif - const char* internal_name() const; + const char* internal_name() const override; // Verification - void verify_on(outputStream* st); + void verify_on(outputStream* st) override; - void oop_verify_on(oop obj, outputStream* st); + void oop_verify_on(oop obj, outputStream* st) override; // Logging void print_class_load_logging(ClassLoaderData* loader_data, diff --git a/src/hotspot/share/oops/instanceMirrorKlass.hpp b/src/hotspot/share/oops/instanceMirrorKlass.hpp index 4546f904eca..a89e573503d 100644 --- a/src/hotspot/share/oops/instanceMirrorKlass.hpp +++ b/src/hotspot/share/oops/instanceMirrorKlass.hpp @@ -67,7 +67,7 @@ class InstanceMirrorKlass: public InstanceKlass { } // Returns the size of the instance including the extra static fields. - virtual size_t oop_size(oop obj) const; + size_t oop_size(oop obj) const override; // Static field offset is an offset into the Heap, should be converted by // based on UseCompressedOop for traversal diff --git a/src/hotspot/share/oops/instanceRefKlass.hpp b/src/hotspot/share/oops/instanceRefKlass.hpp index c372b83a267..57126156dd8 100644 --- a/src/hotspot/share/oops/instanceRefKlass.hpp +++ b/src/hotspot/share/oops/instanceRefKlass.hpp @@ -126,7 +126,7 @@ class InstanceRefKlass: public InstanceKlass { public: // Verification - void oop_verify_on(oop obj, outputStream* st); + void oop_verify_on(oop obj, outputStream* st) override; }; #endif // SHARE_OOPS_INSTANCEREFKLASS_HPP diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index 25fb900e7d6..b6974762209 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -215,7 +215,7 @@ protected: enum class StaticLookupMode { find, skip }; enum class PrivateLookupMode { find, skip }; - virtual bool is_klass() const { return true; } + bool is_klass() const override { return true; } // super() cannot be InstanceKlass* -- Java arrays are covariant, and _super is used // to implement that. NB: the _super of "[Ljava/lang/Integer;" is "[Ljava/lang/Number;" @@ -649,9 +649,6 @@ public: // actual oop size of obj in memory in word size. virtual size_t oop_size(oop obj) const = 0; - // Size of klass in word size. - virtual int size() const = 0; - // Returns the Java name for a class (Resource allocated) // For arrays, this returns the name of the element with a leading '['. // For classes, this returns the name with the package separators @@ -728,8 +725,8 @@ public: JFR_ONLY(DEFINE_TRACE_ID_METHODS;) - virtual void metaspace_pointers_do(MetaspaceClosure* iter); - virtual MetaspaceObj::Type type() const { return ClassType; } + void metaspace_pointers_do(MetaspaceClosure* iter) override; + MetaspaceObj::Type type() const override { return ClassType; } inline bool is_loader_alive() const; inline bool is_loader_present_and_alive() const; @@ -764,15 +761,13 @@ public: virtual jint jvmti_class_status() const; // Printing - virtual void print_on(outputStream* st) const; + void print_on(outputStream* st) const override; virtual void oop_print_value_on(oop obj, outputStream* st); virtual void oop_print_on (oop obj, outputStream* st); void print_secondary_supers_on(outputStream* st) const; - virtual const char* internal_name() const = 0; - // Verification virtual void verify_on(outputStream* st); void verify() { verify_on(tty); } diff --git a/src/hotspot/share/oops/objArrayKlass.hpp b/src/hotspot/share/oops/objArrayKlass.hpp index 1a4f7f657d2..12db56351ed 100644 --- a/src/hotspot/share/oops/objArrayKlass.hpp +++ b/src/hotspot/share/oops/objArrayKlass.hpp @@ -72,29 +72,29 @@ class ObjArrayKlass : public ArrayKlass { void set_bottom_klass(Klass* k) { _bottom_klass = k; } Klass** bottom_klass_addr() { return &_bottom_klass; } - ModuleEntry* module() const; - PackageEntry* package() const; + ModuleEntry* module() const override; + PackageEntry* package() const override; // Dispatched operation - bool can_be_primary_super_slow() const; + bool can_be_primary_super_slow() const override; GrowableArray* compute_secondary_supers(int num_extra_slots, - Array* transitive_interfaces); - DEBUG_ONLY(bool is_objArray_klass_slow() const { return true; }) - size_t oop_size(oop obj) const; + Array* transitive_interfaces) override; + DEBUG_ONLY(bool is_objArray_klass_slow() const override { return true; }) + size_t oop_size(oop obj) const override; // Allocation static ObjArrayKlass* allocate_objArray_klass(ClassLoaderData* loader_data, int n, Klass* element_klass, TRAPS); - oop multi_allocate(int rank, jint* sizes, TRAPS); + oop multi_allocate(int rank, jint* sizes, TRAPS) override; // Copying - void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS); + void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) override; // Compute protection domain - oop protection_domain() const { return bottom_klass()->protection_domain(); } + oop protection_domain() const override { return bottom_klass()->protection_domain(); } - virtual void metaspace_pointers_do(MetaspaceClosure* iter); + virtual void metaspace_pointers_do(MetaspaceClosure* iter) override; private: // Either oop or narrowOop depending on UseCompressedOops. @@ -114,10 +114,10 @@ class ObjArrayKlass : public ArrayKlass { // Sizing static int header_size() { return sizeof(ObjArrayKlass)/wordSize; } - int size() const { return ArrayKlass::static_size(header_size()); } + int size() const override { return ArrayKlass::static_size(header_size()); } // Initialization (virtual from Klass) - void initialize(TRAPS); + void initialize(TRAPS) override; // Oop fields (and metadata) iterators // @@ -150,24 +150,24 @@ class ObjArrayKlass : public ArrayKlass { inline void oop_oop_iterate_elements_bounded(objArrayOop a, OopClosureType* closure, void* low, void* high); public: - u2 compute_modifier_flags() const; + u2 compute_modifier_flags() const override; public: // Printing - void print_on(outputStream* st) const; - void print_value_on(outputStream* st) const; + void print_on(outputStream* st) const override; + void print_value_on(outputStream* st) const override; - void oop_print_value_on(oop obj, outputStream* st); + void oop_print_value_on(oop obj, outputStream* st) override; #ifndef PRODUCT - void oop_print_on (oop obj, outputStream* st); + void oop_print_on (oop obj, outputStream* st) override; #endif //PRODUCT - const char* internal_name() const; + const char* internal_name() const override; // Verification - void verify_on(outputStream* st); + void verify_on(outputStream* st) override; - void oop_verify_on(oop obj, outputStream* st); + void oop_verify_on(oop obj, outputStream* st) override; }; #endif // SHARE_OOPS_OBJARRAYKLASS_HPP diff --git a/src/hotspot/share/oops/typeArrayKlass.hpp b/src/hotspot/share/oops/typeArrayKlass.hpp index 22600702fe2..87a41a6d4b3 100644 --- a/src/hotspot/share/oops/typeArrayKlass.hpp +++ b/src/hotspot/share/oops/typeArrayKlass.hpp @@ -56,10 +56,10 @@ class TypeArrayKlass : public ArrayKlass { jint max_length() { return _max_length; } void set_max_length(jint m) { _max_length = m; } - u2 compute_modifier_flags() const; + u2 compute_modifier_flags() const override; // testers - DEBUG_ONLY(bool is_typeArray_klass_slow() const { return true; }) + DEBUG_ONLY(bool is_typeArray_klass_slow() const override { return true; }) // klass allocation static TypeArrayKlass* create_klass(BasicType type, const char* name_str, @@ -68,15 +68,15 @@ class TypeArrayKlass : public ArrayKlass { return create_klass(type, external_name(type), THREAD); } - size_t oop_size(oop obj) const; + size_t oop_size(oop obj) const override; // Allocation - oop multi_allocate(int rank, jint* sizes, TRAPS); + oop multi_allocate(int rank, jint* sizes, TRAPS) override; - oop protection_domain() const { return nullptr; } + oop protection_domain() const override { return nullptr; } // Copying - void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS); + void copy_array(arrayOop s, int src_pos, arrayOop d, int dst_pos, int length, TRAPS) override; // Oop iterators. Since there are no oops in TypeArrayKlasses, // these functions only return the size of the object. @@ -113,23 +113,23 @@ class TypeArrayKlass : public ArrayKlass { // Sizing static int header_size() { return sizeof(TypeArrayKlass)/wordSize; } - int size() const { return ArrayKlass::static_size(header_size()); } + int size() const override { return ArrayKlass::static_size(header_size()); } // Initialization (virtual from Klass) - void initialize(TRAPS); + void initialize(TRAPS) override; public: // Printing - void oop_print_on(oop obj, outputStream* st); + void oop_print_on(oop obj, outputStream* st) override; void oop_print_elements_on(typeArrayOop ta, outputStream* st); - void print_on(outputStream* st) const; - void print_value_on(outputStream* st) const; + void print_on(outputStream* st) const override; + void print_value_on(outputStream* st) const override; public: - const char* internal_name() const; + const char* internal_name() const override; - ModuleEntry* module() const; - PackageEntry* package() const; + ModuleEntry* module() const override; + PackageEntry* package() const override; }; #endif // SHARE_OOPS_TYPEARRAYKLASS_HPP From 8402891889c29894555eca6449ba63f7b7458124 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 16 Dec 2025 09:34:42 +0000 Subject: [PATCH 111/211] 8373355: C2: CompileCommand PrintIdealPhase should also print nodes that are not "reachable from below" Reviewed-by: rcastanedalo, mchevalier, bmaillard --- src/hotspot/share/opto/compile.cpp | 4 +- .../compiler/c2/irTests/ModDNodeTests.java | 94 ++++++++++++++----- .../compiler/c2/irTests/ModFNodeTests.java | 94 ++++++++++++++----- .../compiler/lib/ir_framework/IRNode.java | 10 -- .../tests/TestIRFindFromAbove.java | 63 +++++++++++++ 5 files changed, 210 insertions(+), 55 deletions(-) create mode 100644 test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRFindFromAbove.java diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 16f5be50805..cea2b09e142 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -595,7 +595,9 @@ void Compile::print_ideal_ir(const char* phase_name) { if (_output == nullptr) { ss.print_cr("AFTER: %s", phase_name); // Print out all nodes in ascending order of index. - root()->dump_bfs(MaxNodeLimit, nullptr, "+S$", &ss); + // It is important that we traverse both inputs and outputs of nodes, + // so that we reach all nodes that are connected to Root. + root()->dump_bfs(MaxNodeLimit, nullptr, "-+S$", &ss); } else { // Dump the node blockwise if we have a scheduling _output->print_scheduling(&ss); diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java index 7eed798871e..6b20b782923 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModDNodeTests.java @@ -63,17 +63,29 @@ public class ModDNodeTests { Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1d, 2.2d), 0.d); } + // Note: we used to check for ConD nodes in the IR. But that is a bit brittle: + // Constant nodes can appear during IR transformations, and then lose their outputs. + // During IGNV, the constants stay in the graph even if they lose the inputs. But + // CCP cleans them out because they are not in the useful set. So for now, we do not + // rely on any constant counting, just on counting the operation nodes. + @Test - @IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double constant() { // All constants available during parsing return q % 72.0d % 30.0d; } @Test - @IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double alsoConstant() { // Make sure value is only available after second loop opts round double val = 0; @@ -86,8 +98,12 @@ public class ModDNodeTests { } @Test - @IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double nanLeftConstant() { // Make sure value is only available after second loop opts round double val = 134.18d; @@ -100,8 +116,12 @@ public class ModDNodeTests { } @Test - @IR(failOn = {"drem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double nanRightConstant() { // Make sure value is only available after second loop opts round double val = 134.18d; @@ -114,29 +134,41 @@ public class ModDNodeTests { } @Test - @IR(counts = {"drem", "1"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*drem.*", "1"}, + phase = CompilePhase.BEFORE_MATCHING) // no constant folding public double notConstant(double x) { return x % 32.0d; } @Test - @IR(counts = {"drem", "2"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_D, "1"}) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*drem.*", "2"}, + phase = CompilePhase.BEFORE_MATCHING) // no constant folding public double veryNotConstant(double x, double y) { return x % 32.0d % y; } @Test - @IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1) - @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "0"}, + phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public void unusedResult(double x, double y) { double unused = x % y; } @Test - @IR(failOn = IRNode.MOD_D, phase = CompilePhase.ITER_GVN1) - @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "0"}, + phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public void repeatedlyUnused(double x, double y) { double unused = 1.d; for (int i = 0; i < 100_000; i++) { @@ -149,8 +181,14 @@ public class ModDNodeTests { // and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is // used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not. @Test - @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.ITER_GVN2) - @IR(failOn = IRNode.MOD_D, phase = CompilePhase.BEFORE_MACRO_EXPANSION) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.ITER_GVN2) + @IR(counts = {IRNode.MOD_D, "0"}, + phase = CompilePhase.BEFORE_MACRO_EXPANSION) + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double unusedResultAfterLoopOpt1(double x, double y) { double unused = x % y; @@ -168,8 +206,14 @@ public class ModDNodeTests { } @Test - @IR(counts = {IRNode.MOD_D, "1"}, phase = CompilePhase.AFTER_CLOOPS) - @IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "1"}, + phase = CompilePhase.AFTER_CLOOPS) + @IR(counts = {IRNode.MOD_D, "0"}, + phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double unusedResultAfterLoopOpt2(double x, double y) { int a = 77; int b = 0; @@ -187,8 +231,14 @@ public class ModDNodeTests { } @Test - @IR(counts = {IRNode.MOD_D, "2"}, phase = CompilePhase.AFTER_CLOOPS) - @IR(failOn = IRNode.MOD_D, phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {IRNode.MOD_D, "3"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_D, "2"}, + phase = CompilePhase.AFTER_CLOOPS) // drop the useless one + @IR(counts = {IRNode.MOD_D, "0"}, + phase = CompilePhase.PHASEIDEALLOOP1) // drop the rest + @IR(counts = {".*CallLeaf.*drem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public double unusedResultAfterLoopOpt3(double x, double y) { double unused = x % y; diff --git a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java index 886efe57124..2f69578c2f0 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/ModFNodeTests.java @@ -63,17 +63,29 @@ public class ModFNodeTests { Asserts.assertEQ(unusedResultAfterLoopOpt3(1.1f, 2.2f), 0.f); } + // Note: we used to check for ConF nodes in the IR. But that is a bit brittle: + // Constant nodes can appear during IR transformations, and then lose their outputs. + // During IGNV, the constants stay in the graph even if they lose the inputs. But + // CCP cleans them out because they are not in the useful set. So for now, we do not + // rely on any constant counting, just on counting the operation nodes. + @Test - @IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float constant() { // All constants available during parsing return q % 72.0f % 30.0f; } @Test - @IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float alsoConstant() { // Make sure value is only available after second loop opts round float val = 0; @@ -86,8 +98,12 @@ public class ModFNodeTests { } @Test - @IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float nanLeftConstant() { // Make sure value is only available after second loop opts round float val = 134.18f; @@ -100,8 +116,12 @@ public class ModFNodeTests { } @Test - @IR(failOn = {"frem"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.PHASEIDEALLOOP1) // Only constant fold after some loop opts + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float nanRightConstant() { // Make sure value is only available after second loop opts round float val = 134.18f; @@ -114,29 +134,41 @@ public class ModFNodeTests { } @Test - @IR(counts = {"frem", "1"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*frem.*", "1"}, + phase = CompilePhase.BEFORE_MATCHING) // no constant folding public float notConstant(float x) { return x % 32.0f; } @Test - @IR(counts = {"frem", "2"}, phase = CompilePhase.BEFORE_MATCHING) - @IR(counts = {IRNode.CON_F, "1"}) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {".*CallLeaf.*frem.*", "2"}, + phase = CompilePhase.BEFORE_MATCHING) // no constant folding public float veryNotConstant(float x, float y) { return x % 32.0f % y; } @Test - @IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1) - @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "0"}, + phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public void unusedResult(float x, float y) { float unused = x % y; } @Test - @IR(failOn = IRNode.MOD_F, phase = CompilePhase.ITER_GVN1) - @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "0"}, + phase = CompilePhase.ITER_GVN1) // IGVN removes unused nodes + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public void repeatedlyUnused(float x, float y) { float unused = 1.f; for (int i = 0; i < 100_000; i++) { @@ -149,8 +181,14 @@ public class ModFNodeTests { // and thus a different execution path. In unusedResultAfterLoopOpt1 the modulo is // used in the traps of the parse predicates. In unusedResultAfterLoopOpt2, it is not. @Test - @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.ITER_GVN2) - @IR(failOn = IRNode.MOD_F, phase = CompilePhase.BEFORE_MACRO_EXPANSION) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.ITER_GVN2) + @IR(counts = {IRNode.MOD_F, "0"}, + phase = CompilePhase.BEFORE_MACRO_EXPANSION) + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float unusedResultAfterLoopOpt1(float x, float y) { float unused = x % y; @@ -168,8 +206,14 @@ public class ModFNodeTests { } @Test - @IR(counts = {IRNode.MOD_F, "1"}, phase = CompilePhase.AFTER_CLOOPS) - @IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "1"}, + phase = CompilePhase.AFTER_CLOOPS) + @IR(counts = {IRNode.MOD_F, "0"}, + phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float unusedResultAfterLoopOpt2(float x, float y) { int a = 77; int b = 0; @@ -187,8 +231,14 @@ public class ModFNodeTests { } @Test - @IR(counts = {IRNode.MOD_F, "2"}, phase = CompilePhase.AFTER_CLOOPS) - @IR(failOn = IRNode.MOD_F, phase = CompilePhase.PHASEIDEALLOOP1) + @IR(counts = {IRNode.MOD_F, "3"}, + phase = CompilePhase.AFTER_PARSING) + @IR(counts = {IRNode.MOD_F, "2"}, + phase = CompilePhase.AFTER_CLOOPS) // drop the useless one + @IR(counts = {IRNode.MOD_F, "0"}, + phase = CompilePhase.PHASEIDEALLOOP1) // drop the rest + @IR(counts = {".*CallLeaf.*frem.*", "0"}, + phase = CompilePhase.BEFORE_MATCHING) public float unusedResultAfterLoopOpt3(float x, float y) { float unused = x % y; diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index d5799e5aa05..3fd8e2eceb4 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -690,16 +690,6 @@ public class IRNode { beforeMatchingNameRegex(CON_L, "ConL"); } - public static final String CON_D = PREFIX + "CON_D" + POSTFIX; - static { - beforeMatchingNameRegex(CON_D, "ConD"); - } - - public static final String CON_F = PREFIX + "CON_F" + POSTFIX; - static { - beforeMatchingNameRegex(CON_F, "ConF"); - } - public static final String COUNTED_LOOP = PREFIX + "COUNTED_LOOP" + POSTFIX; static { String regex = START + "CountedLoop\\b" + MID + END; diff --git a/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRFindFromAbove.java b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRFindFromAbove.java new file mode 100644 index 00000000000..23e46428460 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/ir_framework/tests/TestIRFindFromAbove.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2025, 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 ir_framework.tests; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8373355 + * @summary Test that IR matching happens on the whole graph, not just nodes + * that can be found by traversing up from the Root. + * @library /test/lib / + * @run main ${test.main.class} + */ + +public class TestIRFindFromAbove { + public static boolean flag = false; + public static int fld = 0; + + public static void main(String[] args) { + TestFramework.run(); + } + + @Test + @Warmup(0) + // Simulate Xcomp with no warmup: ensure the flag branch is not an unstable if + // but that we compile the infinite loop. + @IR(counts = {IRNode.LOAD_I, "1", IRNode.STORE_I, "1", ".*NeverBranch.*", "0"}, + phase = CompilePhase.ITER_GVN1) + @IR(counts = {IRNode.LOAD_I, "1", IRNode.STORE_I, "1", ".*NeverBranch.*", "1"}, + phase = CompilePhase.PHASEIDEALLOOP1) + public static void test() { + if (flag) { + // This loop has no exit. So it is at first not connected down to Root. + while (true) { + // During PHASEIDEALLOOP1, we insert a NeverBranch here, with a fake + // exit, that connects the loop down to Root. + fld++; // LoadI and StoreI + } + } + } +} From 43d4456181fcd759e3f1de7ca4f6d74827a3c644 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Tue, 16 Dec 2025 10:01:13 +0000 Subject: [PATCH 112/211] 8373570: Javac stack overflow on method-local class with nested record referring to enclosing type Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Resolve.java | 5 +- .../javac/SuperInit/NewLocalNotInInner.java | 72 +++++++++++++++++++ .../javac/SuperInit/NewLocalNotInInner.out | 6 ++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/SuperInit/NewLocalNotInInner.java create mode 100644 test/langtools/tools/javac/SuperInit/NewLocalNotInInner.out diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java index 07f2a742bcb..d88180bb15c 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Resolve.java @@ -3843,12 +3843,15 @@ public class Resolve { Env env1 = env; boolean staticOnly = false; while (env1.outer != null) { + // If the local class is defined inside a static method, and the instance creation expression + // occurs in that same method, the creation occurs (technically) inside a static context, but that's ok. if (env1.info.scope.owner == owner) { return (staticOnly) ? new BadLocalClassCreation(c) : owner; + } else if (isStatic(env1) || env1.enclClass.sym.isStatic()) { + staticOnly = true; } - if (isStatic(env1)) staticOnly = true; env1 = env1.outer; } return owner.kind == MTH ? diff --git a/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.java b/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.java new file mode 100644 index 00000000000..8a69bc37667 --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.java @@ -0,0 +1,72 @@ +/* + * @test /nodynamiccopyright/ + * @bug 8373570 + * @summary Javac stack overflow on method-local class with nested record referring to enclosing type + * @compile/fail/ref=NewLocalNotInInner.out -XDrawDiagnostics NewLocalNotInInner.java + */ +class NewLocalNotInInner { + void m() { + class Local { + static class Foo { + void m() { + new Local(); // error + } + } + } + } + + void m_anon() { + class Local { + static class Foo { + void m() { + new Local() { }; // error + } + } + } + } + + void m_record() { + class Local { + record Foo() { + void m() { + new Local(); // error + } + } + } + } + + void m_intf() { + class Local { + interface Foo { + default void m() { + new Local(); // error + } + } + } + } + + void sup() { + class Local { + static class Foo { + void m() { + class Sub extends Local { }; // error + new Sub(); + } + } + } + } + + static void staticLocal() { + class Local { } + new Local(); // ok + } + + static void staticLocalFromAnon() { + class Local { } + new Object() { + Local local() { + return new Local(); // ok + } + }; + } +} diff --git a/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.out b/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.out new file mode 100644 index 00000000000..dd816f2ab0e --- /dev/null +++ b/test/langtools/tools/javac/SuperInit/NewLocalNotInInner.out @@ -0,0 +1,6 @@ +NewLocalNotInInner.java:12:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +NewLocalNotInInner.java:22:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +NewLocalNotInInner.java:32:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +NewLocalNotInInner.java:42:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +NewLocalNotInInner.java:52:21: compiler.err.local.cant.be.inst.static: kindname.class, Local +5 errors From 41d28c1838bcd7a69f78c9799b449af2a33c11c3 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Tue, 16 Dec 2025 10:08:08 +0000 Subject: [PATCH 113/211] 8373561: Replace usages of -verify java launcher option with -Xverify:all JVM option Reviewed-by: serb, prr, dholmes, jlahoda --- test/hotspot/jtreg/runtime/verifier/TestANewArray.java | 6 +++--- test/hotspot/jtreg/runtime/verifier/TraceClassRes.java | 2 +- .../verifier/stackMapTableTests/StackMapTableTest.java | 4 ++-- test/jdk/javax/swing/JFileChooser/6520101/bug6520101.java | 4 ++-- .../langtools/tools/javac/VarDeclarationWithAssignment.java | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/test/hotspot/jtreg/runtime/verifier/TestANewArray.java b/test/hotspot/jtreg/runtime/verifier/TestANewArray.java index e1b0dcf764c..f7b133868d4 100644 --- a/test/hotspot/jtreg/runtime/verifier/TestANewArray.java +++ b/test/hotspot/jtreg/runtime/verifier/TestANewArray.java @@ -69,7 +69,7 @@ public class TestANewArray { byte[] classFile_254 = dumpClassFile(cfv, test_Dimension_254, array_Dimension_254); writeClassFileFromByteArray(classFile_254); System.err.println("Running with cfv: " + cfv + ", test_Dimension_254"); - ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder("-verify", "-cp", ".", classCName); + ProcessBuilder pb = ProcessTools.createTestJavaProcessBuilder("-Xverify:all", "-cp", ".", classCName); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldNotContain("java.lang.VerifyError"); output.shouldHaveExitValue(0); @@ -78,7 +78,7 @@ public class TestANewArray { byte[] classFile_255 = dumpClassFile(cfv, test_Dimension_255, array_Dimension_255); writeClassFileFromByteArray(classFile_255); System.err.println("Running with cfv: " + cfv + ", test_Dimension_255"); - pb = ProcessTools.createTestJavaProcessBuilder("-verify", "-cp", ".", classCName); + pb = ProcessTools.createTestJavaProcessBuilder("-Xverify:all", "-cp", ".", classCName); output = new OutputAnalyzer(pb.start()); // If anewarray has an operand with 255 array dimensions then VerifyError should // be thrown because the resulting array would have 256 dimensions. @@ -95,7 +95,7 @@ public class TestANewArray { byte[] classFile_264 = dumpClassFile(cfv, test_Dimension_264, array_Dimension_264); writeClassFileFromByteArray(classFile_264); System.err.println("Running with cfv: " + cfv + ", test_Dimension_264"); - pb = ProcessTools.createTestJavaProcessBuilder("-verify", "-cp", ".", classCName); + pb = ProcessTools.createTestJavaProcessBuilder("-Xverify:all", "-cp", ".", classCName); output = new OutputAnalyzer(pb.start()); output.shouldContain("java.lang.ClassFormatError"); output.shouldHaveExitValue(1); diff --git a/test/hotspot/jtreg/runtime/verifier/TraceClassRes.java b/test/hotspot/jtreg/runtime/verifier/TraceClassRes.java index ddb5e68e1d3..e9be98fea17 100644 --- a/test/hotspot/jtreg/runtime/verifier/TraceClassRes.java +++ b/test/hotspot/jtreg/runtime/verifier/TraceClassRes.java @@ -39,7 +39,7 @@ public class TraceClassRes { public static void main(String[] args) throws Exception { ProcessBuilder pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-Xlog:class+resolve=debug", "-verify", "-Xshare:off", "-version"); + "-Xlog:class+resolve=debug", "-Xverify:all", "-Xshare:off", "-version"); OutputAnalyzer output = new OutputAnalyzer(pb.start()); output.shouldContain("[class,resolve] java.lang.ClassLoader java.lang.Throwable ClassLoader.java (verification)"); diff --git a/test/hotspot/jtreg/runtime/verifier/stackMapTableTests/StackMapTableTest.java b/test/hotspot/jtreg/runtime/verifier/stackMapTableTests/StackMapTableTest.java index f7f2ca1e881..08ddad6464f 100644 --- a/test/hotspot/jtreg/runtime/verifier/stackMapTableTests/StackMapTableTest.java +++ b/test/hotspot/jtreg/runtime/verifier/stackMapTableTests/StackMapTableTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -28,7 +28,7 @@ * @summary Test that the JVM does not assert when printing a stack map table * containing a stack map with a bad verification type. * @compile badStackMapTable.jcod - * @run main/othervm -verify StackMapTableTest + * @run main/othervm -Xverify:all StackMapTableTest */ public class StackMapTableTest { diff --git a/test/jdk/javax/swing/JFileChooser/6520101/bug6520101.java b/test/jdk/javax/swing/JFileChooser/6520101/bug6520101.java index f6671872ba8..131ccc0e348 100644 --- a/test/jdk/javax/swing/JFileChooser/6520101/bug6520101.java +++ b/test/jdk/javax/swing/JFileChooser/6520101/bug6520101.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, 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,7 +27,7 @@ * @bug 6520101 * @summary JFileChooser throws OOM in 1.4.2, 5.0u4 and 1.6.0 * @author Praveen Gupta - * @run main/othervm/timeout=600 -Xmx8m -verify bug6520101 + * @run main/othervm/timeout=600 -Xmx8m -Xverify:all bug6520101 */ import javax.swing.*; diff --git a/test/langtools/tools/javac/VarDeclarationWithAssignment.java b/test/langtools/tools/javac/VarDeclarationWithAssignment.java index 7ee81cbc0e2..171c49274e0 100644 --- a/test/langtools/tools/javac/VarDeclarationWithAssignment.java +++ b/test/langtools/tools/javac/VarDeclarationWithAssignment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2025, 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 @@ -29,7 +29,7 @@ * @author turnidge * * @compile VarDeclarationWithAssignment.java - * @run main/othervm -verify VarDeclarationWithAssignment + * @run main/othervm -Xverify:all VarDeclarationWithAssignment */ public From 53ebcdbd029a1c78f8429574b78cecce70c11af2 Mon Sep 17 00:00:00 2001 From: Serguei Spitsyn Date: Tue, 16 Dec 2025 10:28:27 +0000 Subject: [PATCH 114/211] 8373627: assert(!is_vthread_transition_disabler()) failed: no suspend allowed for vthread transition disablers Reviewed-by: pchilanomate, dholmes --- src/hotspot/share/runtime/mountUnmountDisabler.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/mountUnmountDisabler.cpp b/src/hotspot/share/runtime/mountUnmountDisabler.cpp index 5bf00323f10..261bbfb9c18 100644 --- a/src/hotspot/share/runtime/mountUnmountDisabler.cpp +++ b/src/hotspot/share/runtime/mountUnmountDisabler.cpp @@ -367,7 +367,7 @@ MountUnmountDisabler::enable_transition_for_all() { OrderAccess::release(); MonitorLocker ml(VThreadTransition_lock); - if (exclusive_operation_ongoing()) { + if (_is_exclusive) { set_exclusive_operation_ongoing(false); } dec_active_disablers(); From a61394b1da40cfbb617fec35553da2d3c3e27d37 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Tue, 16 Dec 2025 13:18:59 +0000 Subject: [PATCH 115/211] 8373789: No PCH release build failure after JDK-8372543 Reviewed-by: tschatzl --- src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp index 400eb8d25ee..95f9fbe6856 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahFreeSet.hpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahHeap.hpp" #include "gc/shenandoah/shenandoahHeapRegionSet.hpp" #include "gc/shenandoah/shenandoahSimpleBitMap.hpp" +#include "logging/logStream.hpp" // Each ShenandoahHeapRegion is associated with a ShenandoahFreeSetPartitionId. enum class ShenandoahFreeSetPartitionId : uint8_t { From 89e77512fd44b6a0299ab36db15142e7544899f3 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Tue, 16 Dec 2025 13:33:02 +0000 Subject: [PATCH 116/211] 8370922: Template Framework Library: Float16 type and operations Reviewed-by: galder, thartmann, bmaillard --- .../jtreg/compiler/igvn/ExpressionFuzzer.java | 39 ++++-- .../library/CodeGenerationDataNameType.java | 22 +++ .../library/Float16Type.java | 62 +++++++++ .../library/Operations.java | 94 +++++++++++-- .../library/PrimitiveType.java | 1 + .../jtreg/compiler/lib/verify/Verify.java | 36 +++++ .../examples/TestExpressions.java | 17 ++- .../verify/tests/TestVerify.java | 4 +- .../verify/tests/TestVerifyFloat16.java | 129 ++++++++++++++++++ 9 files changed, 376 insertions(+), 28 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/lib/template_framework/library/Float16Type.java create mode 100644 test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerifyFloat16.java diff --git a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java index 570c59f0da2..875ef57c865 100644 --- a/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java +++ b/test/hotspot/jtreg/compiler/igvn/ExpressionFuzzer.java @@ -23,10 +23,11 @@ /* * @test - * @bug 8359412 + * @bug 8359412 8370922 * @key randomness * @summary Use the template framework library to generate random expressions. * @modules java.base/jdk.internal.misc + * @modules jdk.incubator.vector * @library /test/lib / * @compile ../lib/verify/Verify.java * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:CompileTaskTimeout=10000 compiler.igvn.ExpressionFuzzer @@ -55,6 +56,7 @@ import compiler.lib.template_framework.library.Operations; import compiler.lib.template_framework.library.PrimitiveType; import compiler.lib.template_framework.library.TestFrameworkClass; import static compiler.lib.template_framework.library.CodeGenerationDataNameType.PRIMITIVE_TYPES; +import static compiler.lib.template_framework.library.CodeGenerationDataNameType.SCALAR_NUMERIC_TYPES; // We generate random Expressions from primitive type operators. // @@ -84,10 +86,14 @@ public class ExpressionFuzzer { comp.addJavaSourceCode("compiler.igvn.templated.ExpressionFuzzerInnerTest", generate(comp)); // Compile the source file. - comp.compile(); + comp.compile("--add-modules=jdk.incubator.vector"); // compiler.igvn.templated.InnterTest.main(new String[] {}); - comp.invoke("compiler.igvn.templated.ExpressionFuzzerInnerTest", "main", new Object[] {new String[] {}}); + 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" + }}); } // Generate a Java source file as String @@ -189,10 +195,10 @@ public class ExpressionFuzzer { case "byte", "short", "char", "int", "long" -> List.of("val", Collections.nCopies(20, integralCmpTemplate.asToken(expression.returnType))); // Float/Double have no range, just return the value: - case "float", "double" -> "val"; + case "float", "double", "Float16" -> "val"; // Check if the boolean constant folded: case "boolean" -> "val, val == true, val == false"; - default -> throw new RuntimeException("should only be primitive types"); + default -> throw new RuntimeException("type not supported yet: " + expression.returnType.name()); } , "};\n", """ @@ -224,7 +230,7 @@ public class ExpressionFuzzer { // Booleans do have an int-range, but restricting it would just make it constant, which // is not very useful: we would like to keep it variable here. We already mix in variable // arguments and constants in the testTemplate. - case "boolean", "float", "double" -> "return v;\n"; + case "boolean", "float", "double", "Float16" -> "return v;\n"; case "byte", "short", "char", "int", "long" -> List.of( // Sometimes constrain the signed range // v = min(max(v, CON1), CON2) @@ -241,7 +247,7 @@ public class ExpressionFuzzer { : List.of(), // FUTURE: we could also constrain the unsigned bounds. "return v;\n"); - default -> throw new RuntimeException("should only be primitive types"); + default -> throw new RuntimeException("type not supported yet: " + type.name()); }, """ } @@ -325,6 +331,7 @@ public class ExpressionFuzzer { // Generate expressions with the primitive types. for (PrimitiveType type : PRIMITIVE_TYPES) { + // Prmitive expressions are most important, so let's create many expressions per output type. for (int i = 0; i < 10; i++) { // The depth determines roughly how many operations are going to be used in the expression. int depth = RANDOM.nextInt(1, 20); @@ -333,6 +340,21 @@ public class ExpressionFuzzer { } } + // Generate expressions with any scalar numeric types. + for (CodeGenerationDataNameType type : SCALAR_NUMERIC_TYPES) { + // The extended set of scalar numeric expressions (incl. special types such as Float16) are relevant + // but don't currently warrant the same number amount of testing time, so we only create 2 cases + // per type. Note: this still produces a lot of expressions, given that we have a lot of output + // types, and even if the output type is "float", we can still use other types in the expression, + // such as "float -> Float16 -> float". We can consider adjusting this arbitrary count in the future. + for (int i = 0; i < 2; i++) { + // The depth determines roughly how many operations are going to be used in the expression. + int depth = RANDOM.nextInt(1, 20); + Expression expression = Expression.nestRandomly(type, Operations.SCALAR_NUMERIC_OPERATIONS, depth); + tests.add(testTemplate.asToken(expression)); + } + } + // Create the test class, which runs all tests. return TestFrameworkClass.render( // package and class name. @@ -341,7 +363,8 @@ public class ExpressionFuzzer { Set.of("compiler.lib.verify.*", "java.util.Random", "jdk.test.lib.Utils", - "compiler.lib.generators.*"), + "compiler.lib.generators.*", + "jdk.incubator.vector.Float16"), // classpath, so the Test VM has access to the compiled class files. comp.getEscapedClassPathOfCompiledClasses(), // The list of tests. 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 56f7afcbaeb..b461e3e857f 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/CodeGenerationDataNameType.java @@ -100,6 +100,13 @@ public interface CodeGenerationDataNameType extends DataName.Type { */ static PrimitiveType booleans() { return PrimitiveType.BOOLEANS; } + /** + * The Float16 type. + * + * @return The Float16 type. + */ + static CodeGenerationDataNameType float16() { return Float16Type.FLOAT16; } + /** * List of all {@link PrimitiveType}s. */ @@ -154,4 +161,19 @@ public interface CodeGenerationDataNameType extends DataName.Type { floats(), doubles() ); + + /** + * List of all scalar numeric types. + */ + List SCALAR_NUMERIC_TYPES = List.of( + bytes(), + chars(), + shorts(), + ints(), + longs(), + floats(), + doubles(), + booleans(), + float16() + ); } diff --git a/test/hotspot/jtreg/compiler/lib/template_framework/library/Float16Type.java b/test/hotspot/jtreg/compiler/lib/template_framework/library/Float16Type.java new file mode 100644 index 00000000000..e591fe4e045 --- /dev/null +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/Float16Type.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2025, 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 compiler.lib.generators.Generators; +import compiler.lib.generators.Generator; + +import compiler.lib.template_framework.DataName; + +/** + * The {@link Float16Type} models Java's {@link Float16} type. + */ +final class Float16Type implements CodeGenerationDataNameType { + private static final Generator GEN_FLOAT16 = Generators.G.float16s(); + + // We only need one static instance of the class. + static final Float16Type FLOAT16 = new Float16Type(); + + // Private constructor so nobody can create duplicate instances. + private Float16Type() {} + + @Override + public boolean isSubtypeOf(DataName.Type other) { + return other instanceof Float16Type; + } + + @Override + public String name() { + return "Float16"; + } + + @Override + public String toString() { + return name(); + } + + @Override + public Object con() { + return "Float16.shortBitsToFloat16((short)" + GEN_FLOAT16.next() + ")"; + } +} 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 53acf943b20..7d353a8c610 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/Operations.java @@ -23,9 +23,12 @@ package compiler.lib.template_framework.library; -import java.util.List; 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; @@ -35,6 +38,7 @@ 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; +import static compiler.lib.template_framework.library.Float16Type.FLOAT16; /** * This class provides various lists of {@link Expression}s, that represent Java operators or library @@ -45,18 +49,39 @@ public final class Operations { // private constructor to avoid instantiation. 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 void addComparisonOperations(List ops, String operatorName, CodeGenerationDataNameType type) { + for (String mask : List.of("==", "!=", "<", ">", "<=", ">=")) { + ops.add(Expression.make(BOOLEANS, "(" + operatorName + "(", type, ", ", type, ")" + mask + "0)")); + } + } + private static List generatePrimitiveOperations() { List ops = new ArrayList<>(); - Expression.Info withArithmeticException = new Expression.Info().withExceptions(Set.of("ArithmeticException")); - Expression.Info withNondeterministicResult = new Expression.Info().withNondeterministicResult(); - // Cast between all primitive types. Except for Boolean, we cannot cast from and to. CodeGenerationDataNameType.INTEGRAL_AND_FLOATING_TYPES.stream().forEach(src -> { CodeGenerationDataNameType.INTEGRAL_AND_FLOATING_TYPES.stream().forEach(dst -> { @@ -75,8 +100,8 @@ public final class Operations { ops.add(Expression.make(type, "(", type, " + ", type, ")")); ops.add(Expression.make(type, "(", type, " - ", type, ")")); ops.add(Expression.make(type, "(", type, " * ", type, ")")); - ops.add(Expression.make(type, "(", type, " / ", type, ")", withArithmeticException)); - ops.add(Expression.make(type, "(", type, " % ", type, ")", withArithmeticException)); + ops.add(Expression.make(type, "(", type, " / ", type, ")", WITH_ARITHMETIC_EXCEPTION)); + ops.add(Expression.make(type, "(", type, " % ", type, ")", WITH_ARITHMETIC_EXCEPTION)); // Bitwise Operators (non short-circuit) ops.add(Expression.make(type, "(~(", type, "))")); @@ -94,6 +119,8 @@ public final class Operations { ops.add(Expression.make(BOOLEANS, "(", type, " < ", type, ")")); ops.add(Expression.make(BOOLEANS, "(", type, " >= ", type, ")")); ops.add(Expression.make(BOOLEANS, "(", type, " <= ", type, ")")); + addComparisonOperations(ops, type.boxedTypeName() + ".compare", type); + addComparisonOperations(ops, type.boxedTypeName() + ".compareUnsigned", type); // ugt, uge, ule, ult }); CodeGenerationDataNameType.FLOATING_TYPES.stream().forEach(type -> { @@ -112,6 +139,7 @@ public final class Operations { ops.add(Expression.make(BOOLEANS, "(", type, " < ", type, ")")); ops.add(Expression.make(BOOLEANS, "(", type, " >= ", type, ")")); ops.add(Expression.make(BOOLEANS, "(", type, " <= ", type, ")")); + addComparisonOperations(ops, type.boxedTypeName() + ".compare", type); }); // ------------ byte ------------- @@ -152,7 +180,7 @@ public final class Operations { ops.add(Expression.make(INTS, "Integer.compare(", INTS, ", ", INTS, ")")); ops.add(Expression.make(INTS, "Integer.compareUnsigned(", INTS, ", ", INTS, ")")); ops.add(Expression.make(INTS, "Integer.compress(", INTS, ", ", INTS, ")")); - ops.add(Expression.make(INTS, "Integer.divideUnsigned(", INTS, ", ", INTS, ")", withArithmeticException)); + ops.add(Expression.make(INTS, "Integer.divideUnsigned(", INTS, ", ", INTS, ")", WITH_ARITHMETIC_EXCEPTION)); ops.add(Expression.make(INTS, "Integer.expand(", INTS, ", ", INTS, ")")); ops.add(Expression.make(INTS, "Integer.highestOneBit(", INTS, ")")); ops.add(Expression.make(INTS, "Integer.lowestOneBit(", INTS, ")")); @@ -160,7 +188,7 @@ public final class Operations { ops.add(Expression.make(INTS, "Integer.min(", INTS, ", ", INTS, ")")); ops.add(Expression.make(INTS, "Integer.numberOfLeadingZeros(", INTS, ")")); ops.add(Expression.make(INTS, "Integer.numberOfTrailingZeros(", INTS, ")")); - ops.add(Expression.make(INTS, "Integer.remainderUnsigned(", INTS, ", ", INTS, ")", withArithmeticException)); + ops.add(Expression.make(INTS, "Integer.remainderUnsigned(", INTS, ", ", INTS, ")", WITH_ARITHMETIC_EXCEPTION)); ops.add(Expression.make(INTS, "Integer.reverse(", INTS, ")")); ops.add(Expression.make(INTS, "Integer.reverseBytes(", INTS, ")")); ops.add(Expression.make(INTS, "Integer.rotateLeft(", INTS, ", ", INTS, ")")); @@ -178,7 +206,7 @@ public final class Operations { ops.add(Expression.make(INTS, "Long.compare(", LONGS, ", ", LONGS, ")")); ops.add(Expression.make(INTS, "Long.compareUnsigned(", LONGS, ", ", LONGS, ")")); ops.add(Expression.make(LONGS, "Long.compress(", LONGS, ", ", LONGS, ")")); - ops.add(Expression.make(LONGS, "Long.divideUnsigned(", LONGS, ", ", LONGS, ")", withArithmeticException)); + ops.add(Expression.make(LONGS, "Long.divideUnsigned(", LONGS, ", ", LONGS, ")", WITH_ARITHMETIC_EXCEPTION)); ops.add(Expression.make(LONGS, "Long.expand(", LONGS, ", ", LONGS, ")")); ops.add(Expression.make(LONGS, "Long.highestOneBit(", LONGS, ")")); ops.add(Expression.make(LONGS, "Long.lowestOneBit(", LONGS, ")")); @@ -186,7 +214,7 @@ public final class Operations { ops.add(Expression.make(LONGS, "Long.min(", LONGS, ", ", LONGS, ")")); ops.add(Expression.make(INTS, "Long.numberOfLeadingZeros(", LONGS, ")")); ops.add(Expression.make(INTS, "Long.numberOfTrailingZeros(", LONGS, ")")); - ops.add(Expression.make(LONGS, "Long.remainderUnsigned(", LONGS, ", ", LONGS, ")", withArithmeticException)); + ops.add(Expression.make(LONGS, "Long.remainderUnsigned(", LONGS, ", ", LONGS, ")", WITH_ARITHMETIC_EXCEPTION)); ops.add(Expression.make(LONGS, "Long.reverse(", LONGS, ")")); ops.add(Expression.make(LONGS, "Long.reverseBytes(", LONGS, ")")); ops.add(Expression.make(LONGS, "Long.rotateLeft(", LONGS, ", ", INTS, ")")); @@ -201,7 +229,7 @@ public final class Operations { // ------------ Float ------------- ops.add(Expression.make(INTS, "Float.compare(", FLOATS, ", ", FLOATS, ")")); ops.add(Expression.make(INTS, "Float.floatToIntBits(", FLOATS, ")")); - ops.add(Expression.make(INTS, "Float.floatToRawIntBits(", FLOATS, ")", withNondeterministicResult)); + ops.add(Expression.make(INTS, "Float.floatToRawIntBits(", FLOATS, ")", WITH_NONDETERMINISTIC_RESULT)); // Note: there are multiple NaN values with different bit representations. ops.add(Expression.make(FLOATS, "Float.float16ToFloat(", SHORTS, ")")); ops.add(Expression.make(FLOATS, "Float.intBitsToFloat(", INTS, ")")); @@ -220,7 +248,7 @@ public final class Operations { ops.add(Expression.make(INTS, "Double.compare(", DOUBLES, ", ", DOUBLES, ")")); ops.add(Expression.make(LONGS, "Double.doubleToLongBits(", DOUBLES, ")")); // Note: there are multiple NaN values with different bit representations. - ops.add(Expression.make(LONGS, "Double.doubleToRawLongBits(", DOUBLES, ")", withNondeterministicResult)); + ops.add(Expression.make(LONGS, "Double.doubleToRawLongBits(", DOUBLES, ")", WITH_NONDETERMINISTIC_RESULT)); ops.add(Expression.make(DOUBLES, "Double.longBitsToDouble(", LONGS, ")")); ops.add(Expression.make(BOOLEANS, "Double.isFinite(", DOUBLES, ")")); ops.add(Expression.make(BOOLEANS, "Double.isInfinite(", DOUBLES, ")")); @@ -250,4 +278,46 @@ public final class Operations { // Make sure the list is not modifiable. return List.copyOf(ops); } + + private static List generateFloat16Operations() { + List ops = new ArrayList<>(); + + // Casts. + CodeGenerationDataNameType.INTEGRAL_AND_FLOATING_TYPES.stream().forEach(type -> { + if (type == CHARS) { return; } + ops.add(Expression.make(FLOAT16, "Float16.valueOf(", type, ")")); + ops.add(Expression.make(type, "", FLOAT16, "." + type.name() + "Value()")); + }); + + ops.add(Expression.make(FLOAT16, "Float16.abs(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.add(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(INTS, "Float16.compare(", FLOAT16, ",", FLOAT16, ")")); + addComparisonOperations(ops, "Float16.compare", FLOAT16); + ops.add(Expression.make(INTS, "(", FLOAT16, ").compareTo(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.copySign(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.divide(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(BOOLEANS, "", FLOAT16, ".equals(", FLOAT16, ")")); + ops.add(Expression.make(SHORTS, "Float16.float16ToRawShortBits(", FLOAT16, ")")); + ops.add(Expression.make(SHORTS, "Float16.float16ToShortBits(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.fma(", FLOAT16, ",", FLOAT16, ", ", FLOAT16, ")")); + ops.add(Expression.make(INTS, "Float16.getExponent(", FLOAT16, ")")); + ops.add(Expression.make(BOOLEANS, "Float16.isFinite(", FLOAT16, ")")); + ops.add(Expression.make(BOOLEANS, "Float16.isInfinite(", FLOAT16, ")")); + ops.add(Expression.make(BOOLEANS, "Float16.isNaN(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.max(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.min(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.multiply(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.negate(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.nextDown(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.nextUp(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.scalb(", FLOAT16, ", ", INTS, ")")); + ops.add(Expression.make(FLOAT16, "Float16.shortBitsToFloat16(", SHORTS, ")")); + ops.add(Expression.make(FLOAT16, "Float16.signum(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.sqrt(", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.subtract(", FLOAT16, ",", FLOAT16, ")")); + ops.add(Expression.make(FLOAT16, "Float16.ulp(", FLOAT16, ")")); + + // Make sure the list is not modifiable. + return List.copyOf(ops); + } } 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 c0db3d51545..b789da45d44 100644 --- a/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java +++ b/test/hotspot/jtreg/compiler/lib/template_framework/library/PrimitiveType.java @@ -93,6 +93,7 @@ public final class PrimitiveType implements CodeGenerationDataNameType { return name(); } + @Override public Object con() { return switch (kind) { case BYTE -> "(byte)" + GEN_BYTE.next(); diff --git a/test/hotspot/jtreg/compiler/lib/verify/Verify.java b/test/hotspot/jtreg/compiler/lib/verify/Verify.java index 7b5e554b0e3..c79ad2c55a0 100644 --- a/test/hotspot/jtreg/compiler/lib/verify/Verify.java +++ b/test/hotspot/jtreg/compiler/lib/verify/Verify.java @@ -150,6 +150,8 @@ public final class Verify { default -> { if (isVectorAPIClass(ca)) { checkEQForVectorAPIClass(a, b, field, aParent, bParent); + } else if (isFloat16Class(ca)) { + checkEQForFloat16Class(a, b, field, aParent, bParent); } else { checkEQArbitraryClasses(a, b); } @@ -456,6 +458,40 @@ public final class Verify { checkEQdispatch(va, vb, field + ".toArray", aParent, bParent); } + private static boolean isFloat16Class(Class c) { + return c.getName().equals("jdk.incubator.vector.Float16"); + } + + /** + * We do not want to import jdk.incubator.vector.Float16 explicitly, because it would mean we would + * also have to add "--add-modules=jdk.incubator.vector" to the command-line of every test that uses + * the Verify class. So we hack this via reflection. + * + * An additional challenge is the boxing and NaNs, see also isFloatEQ. + */ + private void checkEQForFloat16Class(Object a, Object b, String field, Object aParent, Object bParent) { + Class ca = a.getClass(); + short bitsA; + short bitsB; + try { + Method m = isFloatCheckWithRawBits ? ca.getMethod("float16ToRawShortBits", ca) + : ca.getMethod("float16ToShortBits", ca); + m.setAccessible(true); + bitsA = (short)m.invoke(null, a); + bitsB = (short)m.invoke(null, b); + } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) { + throw new RuntimeException("Could not invoke float16ToRawShortBits on " + ca.getName(), e); + } + + if (bitsA != bitsB) { + System.err.println("ERROR: Equality matching failed: value mismatch. check raw: " + isFloatCheckWithRawBits); + System.err.println(" Values: " + a + " vs " + b); + System.err.println(" Bits: " + bitsA + " vs " + bitsB); + print(a, b, field, aParent, bParent); + throw new VerifyException("Value mismatch: " + a + " vs " + b); + } + } + private void checkEQArbitraryClasses(Object a, Object b) { Class c = a.getClass(); while (c != Object.class) { diff --git a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java index 6a0a2d3786a..4bec633553b 100644 --- a/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java +++ b/test/hotspot/jtreg/testlibrary_tests/template_framework/examples/TestExpressions.java @@ -23,12 +23,13 @@ /* * @test - * @bug 8359412 + * @bug 8359412 8370922 * @summary Demonstrate the use of Expressions from the Template Library. * @modules java.base/jdk.internal.misc + * @modules jdk.incubator.vector * @library /test/lib / * @compile ../../../compiler/lib/verify/Verify.java - * @run main template_framework.examples.TestExpressions + * @run main ${test.main.class} */ package template_framework.examples; @@ -55,10 +56,14 @@ public class TestExpressions { comp.addJavaSourceCode("p.xyz.InnerTest", generate(comp)); // Compile the source file. - comp.compile(); + comp.compile("--add-modules=jdk.incubator.vector"); // p.xyz.InnterTest.main(new String[] {}); - comp.invoke("p.xyz.InnerTest", "main", new Object[] {new String[] {}}); + comp.invoke("p.xyz.InnerTest", "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" + }}); } // Generate a Java source file as String @@ -121,7 +126,7 @@ public class TestExpressions { ); }); - for (Expression operation : Operations.PRIMITIVE_OPERATIONS) { + for (Expression operation : Operations.SCALAR_NUMERIC_OPERATIONS) { tests.add(withConstantsTemplate.asToken(operation)); } @@ -130,7 +135,7 @@ public class TestExpressions { // package and class name. "p.xyz", "InnerTest", // Set of imports. - Set.of("compiler.lib.verify.*"), + Set.of("compiler.lib.verify.*", "jdk.incubator.vector.Float16"), // classpath, so the Test VM has access to the compiled class files. comp.getEscapedClassPathOfCompiledClasses(), // The list of tests. diff --git a/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerify.java b/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerify.java index 34cff79dd6e..519331b17fd 100644 --- a/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerify.java +++ b/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerify.java @@ -23,10 +23,10 @@ /* * @test - * @summary Test functionality of IntGenerator implementations. + * @summary Test basic functionality of Verify implementations. * @modules java.base/jdk.internal.misc * @library /test/lib / - * @run driver verify.tests.TestVerify + * @run driver ${test.main.class} */ package verify.tests; diff --git a/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerifyFloat16.java b/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerifyFloat16.java new file mode 100644 index 00000000000..8d1d763a250 --- /dev/null +++ b/test/hotspot/jtreg/testlibrary_tests/verify/tests/TestVerifyFloat16.java @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2025, 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 + * @key randomness + * @summary Test functionality of Verify implementations for Float16. + * @modules jdk.incubator.vector + * @library /test/lib / + * @run driver ${test.main.class} + */ + +package verify.tests; + +import java.lang.foreign.*; +import java.util.Random; +import jdk.test.lib.Utils; + +import jdk.incubator.vector.Float16; + +import compiler.lib.verify.*; + +public class TestVerifyFloat16 { + private static final Random RANDOM = Utils.getRandomInstance(); + + public static void main(String[] args) { + testArrayFloat16(); + testRawFloat16(); + testFloat16Random(); + } + + public static void testArrayFloat16() { + Float16[] a = new Float16[1000]; + Float16[] b = new Float16[1001]; + Float16[] c = new Float16[1000]; + + Verify.checkEQ(a, a); + Verify.checkEQ(b, b); + Verify.checkEQ(a, c); + Verify.checkEQ(c, a); + + // Size mismatch + checkNE(a, b); + + c[RANDOM.nextInt(c.length)] = Float16.valueOf(1f); + + // Value mismatch + checkNE(a, c); + } + + public static void testRawFloat16() { + Float16 nan1 = Float16.shortBitsToFloat16((short)0xFFFF); + Float16 nan2 = Float16.shortBitsToFloat16((short)0x7FFF); + if (!Float16.isNaN(nan1)) { throw new RuntimeException("must be NaN"); } + if (!Float16.isNaN(nan2)) { throw new RuntimeException("must be NaN"); } + if (Float16.float16ToRawShortBits(nan1) != (short)0xFFFF) { throw new RuntimeException("wrong bits"); } + if (Float16.float16ToRawShortBits(nan2) != (short)0x7FFF) { throw new RuntimeException("wrong bits"); } + + Float16[] arr1 = new Float16[]{nan1}; + Float16[] arr2 = new Float16[]{nan2}; + + Verify.checkEQ(nan1, Float16.NaN); + Verify.checkEQ(nan1, nan1); + Verify.checkEQWithRawBits(nan1, nan1); + Verify.checkEQ(nan1, nan2); + + Verify.checkEQ(arr1, arr1); + Verify.checkEQWithRawBits(arr1, arr1); + Verify.checkEQ(arr1, arr2); + + checkNEWithRawBits(nan1, nan2); + + checkNEWithRawBits(arr1, arr2); + } + + public static void testFloat16Random() { + // Testing all 2^16 * 2^16 = 2^32 would take a bit long, so we randomly sample instead. + for (int i = 0; i < 10_000; i++) { + short bitsA = (short)RANDOM.nextInt(); + short bitsB = (short)RANDOM.nextInt(); + Float16 a = Float16.shortBitsToFloat16(bitsA); + Float16 b = Float16.shortBitsToFloat16(bitsB); + if (bitsA == bitsB) { + Verify.checkEQWithRawBits(a, b); + } else { + checkNEWithRawBits(a, b); + } + if (a.equals(b)) { + Verify.checkEQ(a, b); + } else { + checkNE(a, b); + } + } + } + + public static void checkNE(Object a, Object b) { + try { + Verify.checkEQ(a, b); + throw new RuntimeException("Should have thrown: " + a + " vs " + b); + } catch (VerifyException e) {} + } + + public static void checkNEWithRawBits(Object a, Object b) { + try { + Verify.checkEQWithRawBits(a, b); + throw new RuntimeException("Should have thrown: " + a + " vs " + b); + } catch (VerifyException e) {} + } +} From 76e79dbb3eca5589aae6852c8f55adf0759c714e Mon Sep 17 00:00:00 2001 From: Marc Chevalier Date: Tue, 16 Dec 2025 14:32:23 +0000 Subject: [PATCH 117/211] 8371716: C2: Phi node fails Value()'s verification when speculative types clash Co-authored-by: Roland Westrelin Reviewed-by: roland, epeter --- src/hotspot/share/opto/cfgnode.cpp | 64 ++++++++ src/hotspot/share/opto/cfgnode.hpp | 1 + .../igvn/ClashingSpeculativeTypePhiNode.java | 153 ++++++++++++++++++ 3 files changed, 218 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/igvn/ClashingSpeculativeTypePhiNode.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 07657dd0883..776a2d4c90b 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -1351,11 +1351,75 @@ const Type* PhiNode::Value(PhaseGVN* phase) const { } #endif //ASSERT + // In rare cases, during an IGVN call to `PhiNode::Value`, `_type` and `t` have incompatible opinion on speculative type, + // resulting into a too small intersection (such as AnyNull), which is removed in cleanup_speculative. + // From that `ft` has no speculative type (ft->speculative() == nullptr). + // After the end of the current `PhiNode::Value` call, `ft` (that is returned) is being store into `_type` + // (see PhaseIterGVN::transform_old -> raise_bottom_type -> set_type). + // + // It is possible that verification happens immediately after, without any change to the current node, or any of its inputs. + // In the verification invocation of `PhiNode::Value`, `t` would be the same as the IGVN `t` (union of input types, that are unchanged), + // but the new `_type` is the value returned by the IGVN invocation of `PhiNode::Value`, the former `ft`, that has no speculative type. + // Thus, the result of `t->filter_speculative(_type)`, the new `ft`, gets the speculative type of `t`, which is not empty. Since the + // result of the verification invocation of `PhiNode::Value` has some speculative type, it is not the same as the previously returned type + // (that had no speculative type), making verification fail. + // + // In such a case, doing the filtering one time more allows to reach a fixpoint. + if (ft->speculative() == nullptr && t->speculative() != nullptr) { + ft = t->filter_speculative(ft); + } + verify_type_stability(phase, t, ft); + // Deal with conversion problems found in data loops. ft = phase->saturate_and_maybe_push_to_igvn_worklist(this, ft); return ft; } +#ifdef ASSERT +// Makes sure that a newly computed type is stable when filtered against the incoming types. +// Otherwise, we may have IGVN verification failures. See PhiNode::Value, and the second +// filtering (enforcing stability), for details. +void PhiNode::verify_type_stability(const PhaseGVN* const phase, const Type* const union_of_input_types, const Type* const new_type) const { + const Type* doubly_filtered_type = union_of_input_types->filter_speculative(new_type); + if (Type::equals(new_type, doubly_filtered_type)) { + return; + } + + stringStream ss; + + ss.print_cr("At node:"); + this->dump("\n", false, &ss); + + const Node* region = in(Region); + for (uint i = 1; i < req(); ++i) { + ss.print("in(%d): ", i); + if (region->in(i) != nullptr && phase->type(region->in(i)) == Type::CONTROL) { + const Type* ti = phase->type(in(i)); + ti->dump_on(&ss); + } + ss.print_cr(""); + } + + ss.print("t: "); + union_of_input_types->dump_on(&ss); + ss.print_cr(""); + + ss.print("_type: "); + _type->dump_on(&ss); + ss.print_cr(""); + + ss.print("Filter once: "); + new_type->dump_on(&ss); + ss.print_cr(""); + ss.print("Filter twice: "); + doubly_filtered_type->dump_on(&ss); + ss.print_cr(""); + tty->print("%s", ss.base()); + tty->flush(); + assert(false, "computed type would not pass verification"); +} +#endif + // Does this Phi represent a simple well-shaped diamond merge? Return the // index of the true path or 0 otherwise. int PhiNode::is_diamond_phi() const { diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index f3ccf23703f..ef799f4c39a 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -182,6 +182,7 @@ class PhiNode : public TypeNode { bool is_split_through_mergemem_terminating() const; + void verify_type_stability(const PhaseGVN* phase, const Type* union_of_input_types, const Type* new_type) const NOT_DEBUG_RETURN; bool wait_for_cast_input_igvn(const PhaseIterGVN* igvn) const; public: diff --git a/test/hotspot/jtreg/compiler/igvn/ClashingSpeculativeTypePhiNode.java b/test/hotspot/jtreg/compiler/igvn/ClashingSpeculativeTypePhiNode.java new file mode 100644 index 00000000000..7d8f9e8d409 --- /dev/null +++ b/test/hotspot/jtreg/compiler/igvn/ClashingSpeculativeTypePhiNode.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025, Red Hat, Inc. + * Copyright (c) 2025, 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 + * @bug 8371716 + * @summary Ranges can be proven to be disjoint but not orderable (thanks to unsigned range) + * Comparing such values in such range with != should always be true. + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:-TieredCompilation + * -XX:-UseOnStackReplacement + * -XX:-BackgroundCompilation + * -XX:CompileOnly=${test.main.class}::test1 + * -XX:CompileCommand=quiet + * -XX:TypeProfileLevel=222 + * -XX:+AlwaysIncrementalInline + * -XX:VerifyIterativeGVN=10 + * -XX:CompileCommand=dontinline,${test.main.class}::notInlined1 + * ${test.main.class} + * + * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions + * -XX:+UnlockDiagnosticVMOptions + * -XX:-TieredCompilation + * -XX:-UseOnStackReplacement + * -XX:-BackgroundCompilation + * -XX:CompileOnly=${test.main.class}::test2 + * -XX:CompileOnly=${test.main.class}::inlined3 + * -XX:CompileCommand=quiet + * -XX:TypeProfileLevel=200 + * -XX:+AlwaysIncrementalInline + * -XX:VerifyIterativeGVN=10 + * -XX:CompileCommand=dontinline,${test.main.class}::notInlined1 + * -XX:+StressIncrementalInlining + * ${test.main.class} + * + * @run main ${test.main.class} + */ + +package compiler.igvn; + +public class ClashingSpeculativeTypePhiNode { + public static void main(String[] args) { + main1(); + main2(); + } + + // 1st case + + static void main1() { + for (int i = 0; i < 20_000; i++) { + test1(false); // returns null + inlined1(true, true); // returns C1 + inlined2(false); // returns C2 + } + } + + private static Object test1(boolean flag1) { + return inlined1(flag1, false); + // When inlined1 is inlined + // return Phi(flag1, inlined2(flag2), null) + // inlined2 is speculatively returning C1, known from the calls `inlined1(true, true)` in main1 + // Phi node gets speculative type C1 + // When inline2 is inlined + // return Phi[C1](flag1, Phi(false, new C1(), notInlined1()), null) + // => Phi[C1](flag1, notInlined1(), null) + // notInlined1 is speculatively returning C2, known from `inline2(false)` in main1 + // return Phi[C1](flag1, notInlined1()[C2], null) + // Clashing speculative type between Phi's _type (C1) and union of inputs (C2). + } + + private static Object inlined1(boolean flag1, boolean flag2) { + if (flag1) { + return inlined2(flag2); // C1 + } + return null; + } + + private static Object inlined2(boolean flag2) { + if (flag2) { + return new C1(); + } + return notInlined1(); // C2 + } + + private static Object notInlined1() { + return new C2(); + } + + // 2nd case + + static void main2() { + for (int i = 0; i < 20_000; i++) { + inlined3(new C1()); + } + for (int i = 0; i < 20_000; i++) { + test2(true, new C2()); + test2(false, new C2()); + } + } + + + private static Object test2(boolean flag1, Object o) { + o = inlined4(o); + if (flag1) { + return inlined3(o); + } + return null; + // We profile only parameters. Param o is speculated to be C2. + // return Phi(flag1, inline3(inline4(o[C2])), null) + // We inline inline3 + // return Phi(flag1, inline4(o[C2])[C1], null) + // As input of inline3, inline4(o) is speculated to be C1. The Phi has C1 as speculative type in _type + // return Phi[C1](flag1, o[C2], null) + // Since o is speculated to be C2 as parameter of test2, we get a clash. + } + + private static Object inlined3(Object o) { + return o; // C1 + } + + private static Object inlined4(Object o) { + return o; + } + + static class C1 { + + } + + static class C2 { + + } +} From 81e375768837e1ae6c34c1d0a8eff06b4e1d2889 Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Tue, 16 Dec 2025 18:11:37 +0000 Subject: [PATCH 118/211] 8373566: Performance regression with java.text.MessageFormat subformat patterns Reviewed-by: liach, rriggs, naoto --- .../classes/java/text/MessageFormat.java | 69 +++++++++---------- .../java/text/MessageFormatterBench.java | 15 ++++ 2 files changed, 48 insertions(+), 36 deletions(-) diff --git a/src/java.base/share/classes/java/text/MessageFormat.java b/src/java.base/share/classes/java/text/MessageFormat.java index 5477d0f881a..1a850ebaa42 100644 --- a/src/java.base/share/classes/java/text/MessageFormat.java +++ b/src/java.base/share/classes/java/text/MessageFormat.java @@ -1713,12 +1713,7 @@ public class MessageFormat extends Format { throw new IllegalArgumentException("unknown format type: " + type); } // Get the style if recognized, otherwise treat style as a SubformatPattern - FormatStyle fStyle; - try { - fStyle = FormatStyle.fromString(style); - } catch (IllegalArgumentException iae) { - fStyle = FormatStyle.SUBFORMATPATTERN; - } + FormatStyle fStyle = FormatStyle.fromString(style); return switch (fType) { case NUMBER -> switch (fStyle) { case DEFAULT -> NumberFormat.getInstance(locale); @@ -1976,41 +1971,43 @@ public class MessageFormat extends Format { } // Corresponding to the FormatStyle pattern + // WARNING: fromString is dependent on ordinal positioning and Enum names. private enum FormatStyle { - DEFAULT(""), - SHORT("short"), - MEDIUM("medium"), - LONG("long"), - FULL("full"), - INTEGER("integer"), - CURRENCY("currency"), - PERCENT("percent"), - COMPACT_SHORT("compact_short"), - COMPACT_LONG("compact_long"), - OR("or"), - UNIT("unit"), - SUBFORMATPATTERN(null); + // Special styles + DEFAULT, + SUBFORMATPATTERN, + // Pre-defined styles + SHORT, + MEDIUM, + LONG, + FULL, + INTEGER, + CURRENCY, + PERCENT, + COMPACT_SHORT, + COMPACT_LONG, + OR, + UNIT; - private final String text; - - // Differs from FormatType in that the text String is - // not guaranteed to match the Enum name, thus a text field is used - FormatStyle(String text) { - this.text = text; - } - - // This method returns a FormatStyle (excluding SUBFORMATPATTERN) - // that matches the passed String. If no FormatStyle is found, - // an IllegalArgumentException is thrown + // Returns a FormatStyle corresponding to the input text. + // DEFAULT is the empty String. + // Pre-defined styles are lower case versions of their enum name + // (but compared case-insensitive for historical compatibility). + // SUBFORMATPATTERN is anything else. private static FormatStyle fromString(String text) { - for (FormatStyle style : values()) { - // Also check trimmed case-insensitive for historical reasons - if (style != FormatStyle.SUBFORMATPATTERN && - text.trim().compareToIgnoreCase(style.text) == 0) { - return style; + var style = text.trim(); + if (style.isEmpty()) { + return FormatStyle.DEFAULT; + } + var styles = values(); + // Match starting at the pre-defined styles -> [SHORT:] + for (int i = SHORT.ordinal(); i < styles.length; i++) { + var fStyle = styles[i]; + if (style.compareToIgnoreCase(fStyle.name()) == 0) { + return fStyle; } } - throw new IllegalArgumentException(); + return FormatStyle.SUBFORMATPATTERN; } } diff --git a/test/micro/org/openjdk/bench/java/text/MessageFormatterBench.java b/test/micro/org/openjdk/bench/java/text/MessageFormatterBench.java index 5d3399cb46d..191634ad299 100644 --- a/test/micro/org/openjdk/bench/java/text/MessageFormatterBench.java +++ b/test/micro/org/openjdk/bench/java/text/MessageFormatterBench.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2024, Alibaba Group Holding Limited. All Rights Reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -51,6 +52,8 @@ import java.util.concurrent.TimeUnit; public class MessageFormatterBench { private Object[][] values; + private String choicePattern; + private String numberPattern; @Setup public void setup() { @@ -60,6 +63,8 @@ public class MessageFormatterBench { new Object[]{Double.valueOf(123.89), "MyDisk3"}, new Object[]{Long.valueOf(1234567), "MyDisk4"}, }; + choicePattern = "{0,choice,0#|1#{1}|2#{1} ({2})}"; + numberPattern = "{0,number,000}"; } private MessageFormat messageFormat = new MessageFormat("There is {0} GB of free space on the {1}.", Locale.ENGLISH); @@ -72,6 +77,16 @@ public class MessageFormatterBench { } } + @Benchmark + public MessageFormat testSubformatChoice() { + return new MessageFormat(choicePattern); + } + + @Benchmark + public MessageFormat testSubformatNumber() { + return new MessageFormat(numberPattern); + } + public static void main(String... args) throws Exception { Options opts = new OptionsBuilder().include(MessageFormatterBench.class.getSimpleName()).shouldDoGC(true).build(); new Runner(opts).run(); From b0b42e7eb14dbe04c9c00e8d1fda139a502f2120 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 16 Dec 2025 18:19:40 +0000 Subject: [PATCH 119/211] 8373615: Improve HotSpot debug functions findclass() and findmethod Reviewed-by: matsaave, asmehra --- src/hotspot/share/classfile/classPrinter.cpp | 159 ++++++++++++++---- src/hotspot/share/classfile/classPrinter.hpp | 4 +- .../gtest/runtime/test_classPrinter.cpp | 61 ++++++- 3 files changed, 178 insertions(+), 46 deletions(-) diff --git a/src/hotspot/share/classfile/classPrinter.cpp b/src/hotspot/share/classfile/classPrinter.cpp index c4b6a024242..3ed0a5e9840 100644 --- a/src/hotspot/share/classfile/classPrinter.cpp +++ b/src/hotspot/share/classfile/classPrinter.cpp @@ -28,9 +28,10 @@ #include "memory/iterator.hpp" #include "memory/resourceArea.hpp" #include "oops/instanceKlass.hpp" -#include "oops/klass.hpp" +#include "oops/klass.inline.hpp" #include "oops/method.hpp" #include "oops/symbol.hpp" +#include "utilities/growableArray.hpp" #include "utilities/ostream.hpp" class ClassPrinter::KlassPrintClosure : public LockedClassesDo { @@ -42,16 +43,15 @@ class ClassPrinter::KlassPrintClosure : public LockedClassesDo { outputStream* _st; int _num; bool _has_printed_methods; + GrowableArray _klasses; + public: KlassPrintClosure(const char* class_name_pattern, const char* method_name_pattern, const char* method_signature_pattern, bool always_print_class_name, int flags, outputStream* st) - : _class_name_pattern(class_name_pattern), - _method_name_pattern(method_name_pattern), - _method_signature_pattern(method_signature_pattern), - _always_print_class_name(always_print_class_name), + : _always_print_class_name(always_print_class_name), _flags(flags), _st(st), _num(0), _has_printed_methods(false) { if (has_mode(_flags, PRINT_METHOD_HANDLE)) { @@ -66,70 +66,150 @@ public: if (has_mode(_flags, PRINT_BYTECODE)) { _flags |= (PRINT_METHOD_NAME); } + + if (has_mode(_flags, PRINT_CLASS_DETAILS)) { + _always_print_class_name = true; + } + + _class_name_pattern = copy_pattern(class_name_pattern); + _method_name_pattern = copy_pattern(method_name_pattern); + _method_signature_pattern = copy_pattern(method_signature_pattern); + } + + static const char* copy_pattern(const char* pattern) { + if (pattern == nullptr) { + return nullptr; + } + char* copy = ResourceArea::strdup(pattern); + for (char* p = copy; *p; p++) { + if (*p == '.') { + *p = '/'; + } + } + return copy; } virtual void do_klass(Klass* k) { if (!k->is_instance_klass()) { return; } - print_instance_klass(InstanceKlass::cast(k)); + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->is_loaded() && ik->name()->is_star_match(_class_name_pattern)) { + _klasses.append(ik); + } } + void print() { + _klasses.sort(compare_klasses_alphabetically); + for (int i = 0; i < _klasses.length(); i++) { + print_instance_klass(_klasses.at(i)); + } + } + + static bool match(const char* pattern, Symbol* sym) { return (pattern == nullptr || sym->is_star_match(pattern)); } + static int compare_klasses_alphabetically(InstanceKlass** a, InstanceKlass** b) { + return compare_symbols_alphabetically((*a)->name(), (*b)->name()); + } + + static int compare_methods_alphabetically(const void* a, const void* b) { + Method* ma = *(Method**)a; + Method* mb = *(Method**)b; + int n = compare_symbols_alphabetically(ma->name(), mb->name()); + if (n == 0) { + n = compare_symbols_alphabetically(ma->signature(), mb->signature()); + } + return n; + } + + static int compare_symbols_alphabetically(Symbol* a, Symbol *b) { + if (a == b) { + return 0; + } + if (a != nullptr && b == nullptr) { + return 1; + } + if (a == nullptr && b != nullptr) { + return -1; + } + + return strcmp(a->as_C_string(), b->as_C_string()); + } + void print_klass_name(InstanceKlass* ik) { - _st->print("[%3d] " INTPTR_FORMAT " class %s ", _num++, p2i(ik), ik->name()->as_C_string()); + _st->print("[%3d] " INTPTR_FORMAT " class: %s mirror: " INTPTR_FORMAT " ", _num++, + p2i(ik), ik->name()->as_C_string(), p2i(ik->java_mirror())); ik->class_loader_data()->print_value_on(_st); _st->cr(); } void print_instance_klass(InstanceKlass* ik) { - if (ik->is_loaded() && ik->name()->is_star_match(_class_name_pattern)) { - ResourceMark rm; - if (_has_printed_methods) { - // We have printed some methods in the previous class. - // Print a new line to separate the two classes - _st->cr(); + ResourceMark rm; + if (_has_printed_methods) { + // We have printed some methods in the previous class. + // Print a new line to separate the two classes + _st->cr(); + } + _has_printed_methods = false; + if (_always_print_class_name) { + print_klass_name(ik); + } + + if (has_mode(_flags, ClassPrinter::PRINT_CLASS_DETAILS)) { + _st->print("InstanceKlass: "); + ik->print_on(_st); + oop mirror = ik->java_mirror(); + if (mirror != nullptr) { + _st->print("\nJava mirror oop for %s: ", ik->name()->as_C_string()); + mirror->print_on(_st); } - _has_printed_methods = false; - if (_always_print_class_name) { - print_klass_name(ik); + } + + if (has_mode(_flags, ClassPrinter::PRINT_METHOD_NAME)) { + bool print_codes = has_mode(_flags, ClassPrinter::PRINT_BYTECODE); + int len = ik->methods()->length(); + int num_methods_printed = 0; + + Method** sorted_methods = NEW_RESOURCE_ARRAY(Method*, len); + for (int index = 0; index < len; index++) { + sorted_methods[index] = ik->methods()->at(index); } - if (has_mode(_flags, ClassPrinter::PRINT_METHOD_NAME)) { - bool print_codes = has_mode(_flags, ClassPrinter::PRINT_BYTECODE); - int len = ik->methods()->length(); - int num_methods_printed = 0; + qsort(sorted_methods, len, sizeof(Method*), compare_methods_alphabetically); - for (int index = 0; index < len; index++) { - Method* m = ik->methods()->at(index); - if (match(_method_name_pattern, m->name()) && - match(_method_signature_pattern, m->signature())) { - if (print_codes && num_methods_printed++ > 0) { - _st->cr(); - } - - if (_has_printed_methods == false) { - if (!_always_print_class_name) { - print_klass_name(ik); - } - _has_printed_methods = true; - } - print_method(m); + for (int index = 0; index < len; index++) { + Method* m = sorted_methods[index]; + if (match(_method_name_pattern, m->name()) && + match(_method_signature_pattern, m->signature())) { + if (print_codes && num_methods_printed++ > 0) { + _st->cr(); } + + if (_has_printed_methods == false) { + if (!_always_print_class_name) { + print_klass_name(ik); + } + _has_printed_methods = true; + } + print_method(m); } } } } void print_method(Method* m) { - bool print_codes = has_mode(_flags, ClassPrinter::PRINT_BYTECODE); _st->print_cr(INTPTR_FORMAT " %smethod %s : %s", p2i(m), m->is_static() ? "static " : "", m->name()->as_C_string(), m->signature()->as_C_string()); - if (print_codes) { + + if (has_mode(_flags, ClassPrinter::PRINT_METHOD_DETAILS)) { + m->print_on(_st); + } + + if (has_mode(_flags, ClassPrinter::PRINT_BYTECODE)) { m->print_codes_on(_st, _flags); } } @@ -142,12 +222,16 @@ void ClassPrinter::print_flags_help(outputStream* os) { os->print_cr(" 0x%02x - print the address of bytecodes", PRINT_BYTECODE_ADDR); os->print_cr(" 0x%02x - print info for invokedynamic", PRINT_DYNAMIC); os->print_cr(" 0x%02x - print info for invokehandle", PRINT_METHOD_HANDLE); + os->print_cr(" 0x%02x - print details of the C++ and Java objects that represent classes", PRINT_CLASS_DETAILS); + os->print_cr(" 0x%02x - print details of the C++ objects that represent methods", PRINT_METHOD_DETAILS); os->cr(); } void ClassPrinter::print_classes(const char* class_name_pattern, int flags, outputStream* os) { + ResourceMark rm; KlassPrintClosure closure(class_name_pattern, nullptr, nullptr, true, flags, os); ClassLoaderDataGraph::classes_do(&closure); + closure.print(); } void ClassPrinter::print_methods(const char* class_name_pattern, @@ -174,4 +258,5 @@ void ClassPrinter::print_methods(const char* class_name_pattern, KlassPrintClosure closure(class_name_pattern, method_name_pattern, method_signature_pattern, false, flags | PRINT_METHOD_NAME, os); ClassLoaderDataGraph::classes_do(&closure); + closure.print(); } diff --git a/src/hotspot/share/classfile/classPrinter.hpp b/src/hotspot/share/classfile/classPrinter.hpp index 0fff372c302..470e82ddc0e 100644 --- a/src/hotspot/share/classfile/classPrinter.hpp +++ b/src/hotspot/share/classfile/classPrinter.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -52,6 +52,8 @@ public: PRINT_BYTECODE_ADDR = 1 << 2, PRINT_DYNAMIC = 1 << 3, // extra information for invokedynamic (and dynamic constant ...) PRINT_METHOD_HANDLE = 1 << 4, // extra information for invokehandle + PRINT_CLASS_DETAILS = 1 << 5, // print details of the C++ and Java objects that represent classes + PRINT_METHOD_DETAILS = 1 << 6, // print details of the C++ objects that represent methods }; static bool has_mode(int flags, Mode mode) { return (flags & static_cast(mode)) != 0; diff --git a/test/hotspot/gtest/runtime/test_classPrinter.cpp b/test/hotspot/gtest/runtime/test_classPrinter.cpp index b13713d7232..9b6d47f09bc 100644 --- a/test/hotspot/gtest/runtime/test_classPrinter.cpp +++ b/test/hotspot/gtest/runtime/test_classPrinter.cpp @@ -28,6 +28,7 @@ #include "utilities/ostream.hpp" #include "unittest.hpp" +using testing::ContainsRegex; using testing::HasSubstr; TEST_VM(ClassPrinter, print_classes) { @@ -35,13 +36,31 @@ TEST_VM(ClassPrinter, print_classes) { ThreadInVMfromNative invm(THREAD); ResourceMark rm; - stringStream ss; - ClassPrinter::print_classes("java/lang/Object", 0x03, &ss); - const char* output = ss.freeze(); + stringStream s1; + ClassPrinter::print_classes("java/lang/Object", 0x03, &s1); + const char* o1 = s1.freeze(); - ASSERT_THAT(output, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object"; - ASSERT_THAT(output, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait"; - ASSERT_THAT(output, HasSubstr("method finalize : ()V\n 0 return")) << "must find java/lang/Object::finalize and disasm"; + ASSERT_THAT(o1, HasSubstr("class: java/lang/Object mirror:")) << "must find java/lang/Object"; + ASSERT_THAT(o1, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait"; + ASSERT_THAT(o1, HasSubstr("method finalize : ()V\n 0 return")) << "must find java/lang/Object::finalize and disasm"; + + // "." should also work as separator in class name + stringStream s2; + ClassPrinter::print_classes("java.lang.Object", 0x03, &s2); + const char* o2 = s2.freeze(); + ASSERT_THAT(o2, HasSubstr("class: java/lang/Object mirror:")) << "must find java/lang/Object"; + + // 0x20 is PRINT_CLASS_DETAILS + stringStream s3; + ClassPrinter::print_classes("java.lang.Integer", 0x20, &s3); + const char* o3 = s3.freeze(); + ASSERT_THAT(o3, HasSubstr("class: java/lang/Integer mirror:")) << "must find java/lang/Integer"; + ASSERT_THAT(o3, HasSubstr("InstanceKlass: java.lang.Integer {0x")) << "must print InstanceKlass"; + ASSERT_THAT(o3, HasSubstr("Java mirror oop for java/lang/Integer:")) << "must print mirror oop"; +#if GTEST_USES_POSIX_RE + // Complex regex not available on Windows + ASSERT_THAT(o3, ContainsRegex("public static final 'MIN_VALUE' 'I'.* -2147483648 [(]0x80000000[)]")) << "must print static fields"; +#endif } TEST_VM(ClassPrinter, print_methods) { @@ -52,7 +71,7 @@ TEST_VM(ClassPrinter, print_methods) { stringStream s1; ClassPrinter::print_methods("*ang/Object*", "wait", 0x1, &s1); const char* o1 = s1.freeze(); - ASSERT_THAT(o1, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object"; + ASSERT_THAT(o1, HasSubstr("class: java/lang/Object mirror:")) << "must find java/lang/Object"; ASSERT_THAT(o1, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait(long)"; ASSERT_THAT(o1, HasSubstr("method wait : ()V")) << "must find java/lang/Object::wait()"; ASSERT_THAT(o1, Not(HasSubstr("method finalize : ()V"))) << "must not find java/lang/Object::finalize"; @@ -60,8 +79,34 @@ TEST_VM(ClassPrinter, print_methods) { stringStream s2; ClassPrinter::print_methods("j*ang/Object*", "wait:(*J*)V", 0x1, &s2); const char* o2 = s2.freeze(); - ASSERT_THAT(o2, HasSubstr("class java/lang/Object loader data:")) << "must find java/lang/Object"; + ASSERT_THAT(o2, HasSubstr("class: java/lang/Object mirror:")) << "must find java/lang/Object"; ASSERT_THAT(o2, HasSubstr("method wait : (J)V")) << "must find java/lang/Object::wait(long)"; ASSERT_THAT(o2, HasSubstr("method wait : (JI)V")) << "must find java/lang/Object::wait(long,int)"; ASSERT_THAT(o2, Not(HasSubstr("method wait : ()V"))) << "must not find java/lang/Object::wait()"; + + // 0x02 is PRINT_BYTECODE + // 0x04 is PRINT_BYTECODE_ADDRESS + // 0x40 is PRINT_METHOD_DETAILS + stringStream s3; + ClassPrinter::print_methods("java.lang.Object", "wait:()V", 0x46, &s3); + const char* o3 = s3.freeze(); + ASSERT_THAT(o3, HasSubstr("method wait : ()V")) << "must find java/lang/Object::wait()"; + +#ifndef PRODUCT + // PRINT_METHOD_DETAILS -- available only in debug builds + ASSERT_THAT(o3, HasSubstr("{method}")) << "must print Method metadata"; +#if GTEST_USES_POSIX_RE + // Complex regex not available on Windows + ASSERT_THAT(o3, ContainsRegex("method holder:.*'java/lang/Object'")) << "must print Method metadata details"; + ASSERT_THAT(o3, ContainsRegex("name: *'wait'")) << "must print Method metadata details"; +#endif +#endif + +#if GTEST_USES_POSIX_RE + // Bytecodes: we should have at least one 'return' bytecide for Object.wait() + // The print out should look like this: + // 0x000000004adf73ad 5 return + ASSERT_THAT(o3, ContainsRegex("0x[0-9a-f]+ +[0-9]+ +return")) << "must print return bytecode"; +#endif + } From a0dd66f92d7f8400b9800847e36d036315628afb Mon Sep 17 00:00:00 2001 From: Saint Wesonga Date: Tue, 16 Dec 2025 18:36:28 +0000 Subject: [PATCH 120/211] 8373630: r18_tls should not be modified on Windows AArch64 Reviewed-by: pchilanomate, aph --- .../cpu/aarch64/c1_Runtime1_aarch64.cpp | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp index 350b6f68196..449ad4f8a4c 100644 --- a/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c1_Runtime1_aarch64.cpp @@ -310,7 +310,18 @@ static void restore_live_registers(StubAssembler* sasm, bool restore_fpu_registe __ add(sp, sp, 32 * wordSize); } +#ifdef R18_RESERVED + /* + Do not modify r18_tls when restoring registers if it is a reserved register. On Windows, + for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS + variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer. + */ + __ pop(RegSet::range(r0, r17), sp); + __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r20, r29), sp); +#else __ pop(RegSet::range(r0, r29), sp); +#endif } static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_fpu_registers = true) { @@ -323,8 +334,20 @@ static void restore_live_registers_except_r0(StubAssembler* sasm, bool restore_f __ add(sp, sp, 32 * wordSize); } +#ifdef R18_RESERVED + /* + Do not modify r18_tls when restoring registers if it is a reserved register. On Windows, + for example, r18_tls is used to store the pointer to the current thread's TEB (where TLS + variables are stored). Therefore, modifying r18_tls would corrupt the TEB pointer. + */ + __ ldp(zr, r1, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r2, r17), sp); + __ ldp(zr, r19, Address(__ post(sp, 2 * wordSize))); + __ pop(RegSet::range(r20, r29), sp); +#else __ ldp(zr, r1, Address(__ post(sp, 16))); __ pop(RegSet::range(r2, r29), sp); +#endif } From 817e3dfde9eaa467ea0dca9b70282e914cdde093 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Tue, 16 Dec 2025 18:38:11 +0000 Subject: [PATCH 121/211] 8350711: [JMH] test Signatures.RSASSAPSS failed for 2 threads config Reviewed-by: hchao, valeriep --- .../bench/java/security/Signatures.java | 197 ++++++++++++------ 1 file changed, 129 insertions(+), 68 deletions(-) diff --git a/test/micro/org/openjdk/bench/java/security/Signatures.java b/test/micro/org/openjdk/bench/java/security/Signatures.java index 1216e253663..b72a4077045 100644 --- a/test/micro/org/openjdk/bench/java/security/Signatures.java +++ b/test/micro/org/openjdk/bench/java/security/Signatures.java @@ -1,4 +1,5 @@ /* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (C) 2022, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -31,84 +32,142 @@ import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.Throughput) @OutputTimeUnit(TimeUnit.SECONDS) -@State(Scope.Thread) @Warmup(iterations = 5, time = 1) @Measurement(iterations = 5, time = 1) @Fork(jvmArgs = {"-Xms1024m", "-Xmx1024m", "-Xmn768m", "-XX:+UseParallelGC"}, value = 3) public class Signatures { - private static Signature signer; - @Param({"64", "512", "2048", "16384"}) - private static int messageLength; - - @Param({"secp256r1", "secp384r1", "secp521r1"}) - private String algorithm; - - private static byte[] message; - - @Setup - public void setup() throws Exception { - message = new byte[messageLength]; - (new Random(System.nanoTime())).nextBytes(message); - - String signName = switch (algorithm) { - case "secp256r1" -> "SHA256withECDSA"; - case "secp384r1" -> "SHA384withECDSA"; - case "secp521r1" -> "SHA512withECDSA"; - default -> throw new RuntimeException(); - }; - - AlgorithmParameters params = - AlgorithmParameters.getInstance("EC", "SunEC"); - params.init(new ECGenParameterSpec(algorithm)); - ECGenParameterSpec ecParams = - params.getParameterSpec(ECGenParameterSpec.class); - - KeyPairGenerator kpg = - KeyPairGenerator.getInstance("EC", "SunEC"); - kpg.initialize(ecParams); - KeyPair kp = kpg.generateKeyPair(); - - signer = Signature.getInstance(signName, "SunEC"); - signer.initSign(kp.getPrivate()); + @State(Scope.Benchmark) + public static class test01 { + @Param({"64", "512", "2048", "16384"}) + private int messageLength; + @Param({"secp256r1", "secp384r1", "secp521r1"}) + private String algorithm; + } + @State(Scope.Benchmark) + public static class test02 { + @Param({"64", "512", "2048", "16384"}) + private int messageLength; + @Param({"Ed25519", "Ed448"}) + private String algorithm; + } + @State(Scope.Benchmark) + public static class test03 { + @Param({"64", "512", "2048", "16384"}) + private int messageLength; + @Param({"SHA256withDSA", "SHA384withDSA", "SHA512withDSA"}) + private String algorithm; + } + @State(Scope.Benchmark) + public static class test04 { + @Param({"64", "512", "2048", "16384"}) + private int messageLength; + @Param({"SHA256withRSA", "SHA384withRSA", "SHA512withRSA"}) + private String algorithm; + } + @State(Scope.Benchmark) + public static class test05 { + @Param({"64", "512", "2048", "16384"}) + private int messageLength; + @Param({"SHA256", "SHA384", "SHA512"}) + private String algorithm; } @Benchmark - public byte[] sign() throws SignatureException { - signer.update(message); - return signer.sign(); + public byte[] ECDSA(s1 state) throws Exception { + state.signer.update(state.message); + return state.signer.sign(); } - public static class EdDSA extends Signatures { - @Param({"Ed25519", "Ed448"}) - private String algorithm; + @Benchmark + public byte[] EdDSA(s2 state) throws Exception { + state.signer.update(state.message); + return state.signer.sign(); + } + + @Benchmark + public byte[] DSA(s3 state) throws Exception { + state.signer.update(state.message); + return state.signer.sign(); + } + + @Benchmark + public byte[] RSA(s4 state) throws Exception { + state.signer.update(state.message); + return state.signer.sign(); + } + + @Benchmark + public byte[] RSASSAPSS(s5 state) throws Exception { + state.signer.update(state.message); + return state.signer.sign(); + } + + @State(Scope.Thread) + public static class s1 { + private Signature signer; + private byte[] message; @Setup - public void setup() throws Exception { - message = new byte[messageLength]; + public void setup(test01 test) throws Exception { + message = new byte[test.messageLength]; (new Random(System.nanoTime())).nextBytes(message); + String signName = switch (test.algorithm) { + case "secp256r1" -> "SHA256withECDSA"; + case "secp384r1" -> "SHA384withECDSA"; + case "secp521r1" -> "SHA512withECDSA"; + default -> throw new RuntimeException(); + }; + + AlgorithmParameters params = + AlgorithmParameters.getInstance("EC", "SunEC"); + params.init(new ECGenParameterSpec(test.algorithm)); + ECGenParameterSpec ecParams = + params.getParameterSpec(ECGenParameterSpec.class); + KeyPairGenerator kpg = - KeyPairGenerator.getInstance(algorithm, "SunEC"); - NamedParameterSpec spec = new NamedParameterSpec(algorithm); - kpg.initialize(spec); + KeyPairGenerator.getInstance("EC", "SunEC"); + kpg.initialize(ecParams); KeyPair kp = kpg.generateKeyPair(); - signer = Signature.getInstance(algorithm, "SunEC"); + signer = Signature.getInstance(signName, "SunEC"); signer.initSign(kp.getPrivate()); } } - public static class DSA extends Signatures { - @Param({"SHA256withDSA", "SHA384withDSA", "SHA512withDSA"}) - private String algorithm; + @State(Scope.Thread) + public static class s2 { + private Signature signer; + private byte[] message; @Setup - public void setup() throws Exception { - message = new byte[messageLength]; + public void setup(test02 test) throws Exception { + message = new byte[test.messageLength]; (new Random(System.nanoTime())).nextBytes(message); - int keyLength = switch (algorithm) { + KeyPairGenerator kpg = + KeyPairGenerator.getInstance(test.algorithm, "SunEC"); + NamedParameterSpec spec = new NamedParameterSpec(test.algorithm); + kpg.initialize(spec); + KeyPair kp = kpg.generateKeyPair(); + + signer = Signature.getInstance(test.algorithm, "SunEC"); + signer.initSign(kp.getPrivate()); + } + } + + @State(Scope.Thread) + public static class s3 { + private Signature signer; + private byte[] message; + + @Setup + public void setup(test03 test) throws Exception { + message = new byte[test.messageLength]; + (new Random(System.nanoTime())).nextBytes(message); + + int keyLength = switch (test.algorithm) { case "SHA256withDSA" -> 2048; case "SHA384withDSA" -> 3072; case "SHA512withDSA" -> 3072; @@ -119,21 +178,22 @@ public class Signatures { kpg.initialize(keyLength); KeyPair kp = kpg.generateKeyPair(); - signer = Signature.getInstance(algorithm); + signer = Signature.getInstance(test.algorithm); signer.initSign(kp.getPrivate()); } } - public static class RSA extends Signatures { - @Param({"SHA256withRSA", "SHA384withRSA", "SHA512withRSA"}) - private String algorithm; + @State(Scope.Thread) + public static class s4 { + private Signature signer; + private byte[] message; @Setup - public void setup() throws Exception { - message = new byte[messageLength]; + public void setup(test04 test) throws Exception { + message = new byte[test.messageLength]; (new Random(System.nanoTime())).nextBytes(message); - int keyLength = switch (algorithm) { + int keyLength = switch (test.algorithm) { case "SHA256withRSA" -> 2048; case "SHA384withRSA" -> 3072; case "SHA512withRSA" -> 4096; @@ -144,28 +204,29 @@ public class Signatures { kpg.initialize(keyLength); KeyPair kp = kpg.generateKeyPair(); - signer = Signature.getInstance(algorithm); + signer = Signature.getInstance(test.algorithm); signer.initSign(kp.getPrivate()); } } - public static class RSASSAPSS extends Signatures { - @Param({"SHA256", "SHA384", "SHA512"}) - private String algorithm; + @State(Scope.Thread) + public static class s5 { + private Signature signer; + private byte[] message; @Setup - public void setup() throws Exception { - message = new byte[messageLength]; + public void setup(test05 test) throws Exception { + message = new byte[test.messageLength]; (new Random(System.nanoTime())).nextBytes(message); - int keyLength = switch (algorithm) { + int keyLength = switch (test.algorithm) { case "SHA256" -> 2048; case "SHA384" -> 3072; case "SHA512" -> 4096; default -> throw new RuntimeException(); }; - PSSParameterSpec spec = switch (algorithm) { + PSSParameterSpec spec = switch (test.algorithm) { case "SHA256" -> new PSSParameterSpec( "SHA-256", "MGF1", From 1e357e9e976bfb0abc9d4e14bfb1572693622af8 Mon Sep 17 00:00:00 2001 From: Roger Riggs Date: Tue, 16 Dec 2025 20:23:58 +0000 Subject: [PATCH 122/211] 8373623: Refactor Serialization tests for Records to JUnit Reviewed-by: jlu --- .../records/AbsentStreamValuesTest.java | 48 +++++----- .../records/BadCanonicalCtrTest.java | 30 +++--- .../io/Serializable/records/BadValues.java | 17 ++-- .../Serializable/records/BasicRecordSer.java | 56 ++++++----- .../records/ConstructorAccessTest.java | 19 ++-- .../io/Serializable/records/CycleTest.java | 33 +++---- .../records/DifferentStreamFieldsTest.java | 95 ++++++++++--------- .../records/ProhibitedMethods.java | 46 +++++---- .../Serializable/records/ReadResolveTest.java | 22 +++-- .../Serializable/records/RecordClassTest.java | 36 +++---- .../records/SerialPersistentFieldsTest.java | 28 +++--- .../records/SerialVersionUIDTest.java | 37 ++++---- .../Serializable/records/StreamRefTest.java | 23 ++--- .../records/ThrowingConstructorTest.java | 33 ++++--- .../io/Serializable/records/UnsharedTest.java | 29 +++--- .../records/WriteReplaceTest.java | 24 +++-- .../records/migration/AbstractTest.java | 9 +- .../records/migration/AssignableFromTest.java | 25 ++--- .../records/migration/DefaultValuesTest.java | 23 +++-- .../migration/SuperStreamFieldsTest.java | 34 ++++--- 20 files changed, 367 insertions(+), 300 deletions(-) diff --git a/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java b/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java index 0f72b9f8f67..02cb35601a9 100644 --- a/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java +++ b/test/jdk/java/io/Serializable/records/AbsentStreamValuesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Checks that the appropriate default value is given to the canonical ctr - * @run testng AbsentStreamValuesTest + * @run junit AbsentStreamValuesTest */ import java.io.ByteArrayInputStream; @@ -34,16 +34,20 @@ import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.io.ObjectStreamConstants.*; import static java.lang.System.out; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Basic test to check that default primitive / reference values are presented * to the record's canonical constructor, for fields not in the stream. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class AbsentStreamValuesTest { record R01(boolean x) implements Serializable { } @@ -61,7 +65,6 @@ public class AbsentStreamValuesTest { record R13(R12 x) implements Serializable { } record R14(R13[] x) implements Serializable { } - @DataProvider(name = "recordTypeAndExpectedValue") public Object[][] recordTypeAndExpectedValue() { return new Object[][] { new Object[] { R01.class, false }, @@ -81,7 +84,8 @@ public class AbsentStreamValuesTest { }; } - @Test(dataProvider = "recordTypeAndExpectedValue") + @ParameterizedTest + @MethodSource("recordTypeAndExpectedValue") public void testWithDifferentTypes(Class clazz, Object expectedXValue) throws Exception { @@ -92,7 +96,7 @@ public class AbsentStreamValuesTest { Object obj = deserialize(bytes); out.println("deserialized: " + obj); Object actualXValue = clazz.getDeclaredMethod("x").invoke(obj); - assertEquals(actualXValue, expectedXValue); + assertEquals(expectedXValue, actualXValue); } // --- all together @@ -107,18 +111,18 @@ public class AbsentStreamValuesTest { R15 obj = (R15)deserialize(bytes); out.println("deserialized: " + obj); - assertEquals(obj.a, false); - assertEquals(obj.b, 0); - assertEquals(obj.c, 0); - assertEquals(obj.d, '\u0000'); - assertEquals(obj.e, 0); - assertEquals(obj.f, 0l); - assertEquals(obj.g, 0f); - assertEquals(obj.h, 0d); - assertEquals(obj.i, null); - assertEquals(obj.j, null); - assertEquals(obj.k, null); - assertEquals(obj.l, null); + assertEquals(false, obj.a); + assertEquals(0, obj.b); + assertEquals(0, obj.c); + assertEquals('\u0000', obj.d); + assertEquals(0, obj.e); + assertEquals(0l, obj.f); + assertEquals(0f, obj.g); + assertEquals(0d, obj.h); + assertEquals(null, obj.i); + assertEquals(null, obj.j); + assertEquals(null, obj.k); + assertEquals(null, obj.l); } // --- generic type @@ -132,8 +136,8 @@ public class AbsentStreamValuesTest { R16 obj = (R16)deserialize(bytes); out.println("deserialized: " + obj); - assertEquals(obj.t, null); - assertEquals(obj.u, null); + assertEquals(null, obj.t); + assertEquals(null, obj.u); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java index 44959eaea87..528a006fc87 100644 --- a/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java +++ b/test/jdk/java/io/Serializable/records/BadCanonicalCtrTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +27,7 @@ * @summary InvalidClassException is thrown when the canonical constructor * cannot be found during deserialization. * @library /test/lib - * @run testng BadCanonicalCtrTest + * @run junit BadCanonicalCtrTest */ import java.io.ByteArrayInputStream; @@ -44,22 +44,25 @@ import java.lang.constant.MethodTypeDesc; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.ByteCodeLoader; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.lang.classfile.ClassFile.ACC_PUBLIC; import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.constant.ConstantDescs.CD_void; import static java.lang.constant.ConstantDescs.INIT_NAME; import static java.lang.constant.ConstantDescs.MTD_void; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Checks that an InvalidClassException is thrown when the canonical * constructor cannot be found during deserialization. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class BadCanonicalCtrTest { // ClassLoader for creating instances of the records to test with. @@ -76,7 +79,7 @@ public class BadCanonicalCtrTest { * the initial bytecode for the record classes using javac, then removes or * modifies the generated canonical constructor. */ - @BeforeTest + @BeforeAll public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("R1", @@ -133,7 +136,6 @@ public class BadCanonicalCtrTest { return c.getConstructor(long.class).newInstance(l); } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() throws Exception { return new Object[][] { new Object[] { newR1() }, @@ -148,13 +150,14 @@ public class BadCanonicalCtrTest { * Tests that InvalidClassException is thrown when no constructor is * present. */ - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void missingConstructorTest(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); byte[] bytes = serialize(objToSerialize); out.println("deserializing"); - InvalidClassException ice = expectThrows(ICE, () -> deserialize(bytes, missingCtrClassLoader)); + InvalidClassException ice = Assertions.assertThrows(ICE, () -> deserialize(bytes, missingCtrClassLoader)); out.println("caught expected ICE: " + ice); assertTrue(ice.getMessage().contains("record canonical constructor not found")); } @@ -164,13 +167,14 @@ public class BadCanonicalCtrTest { * constructor is not present. ( a non-canonical constructor is * present ). */ - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void nonCanonicalConstructorTest(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); byte[] bytes = serialize(objToSerialize); out.println("deserializing"); - InvalidClassException ice = expectThrows(ICE, () -> deserialize(bytes, nonCanonicalCtrClassLoader)); + InvalidClassException ice = Assertions.assertThrows(ICE, () -> deserialize(bytes, nonCanonicalCtrClassLoader)); out.println("caught expected ICE: " + ice); assertTrue(ice.getMessage().contains("record canonical constructor not found")); } diff --git a/test/jdk/java/io/Serializable/records/BadValues.java b/test/jdk/java/io/Serializable/records/BadValues.java index 4e3dbaa200f..9d5e0c7be82 100644 --- a/test/jdk/java/io/Serializable/records/BadValues.java +++ b/test/jdk/java/io/Serializable/records/BadValues.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +24,7 @@ /* * @test * @summary Basic test for ClassNotFoundException - * @run testng BadValues + * @run junit BadValues */ import java.io.ByteArrayInputStream; @@ -32,10 +32,11 @@ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; import java.io.IOException; import java.io.ObjectInputStream; -import org.testng.annotations.Test; import static java.io.ObjectStreamConstants.*; import static java.lang.System.out; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; /** * Not directly related to records but provokes surrounding code, and ensures @@ -73,7 +74,7 @@ public class BadValues { public void testNotFoundSer() throws Exception { out.println("\n---"); byte[] bytes = byteStreamFor("XxYyZz", 0L, (byte)SC_SERIALIZABLE); - Throwable t = expectThrows(CNFE, () -> deserialize(bytes)); + Throwable t = assertThrows(CNFE, () -> deserialize(bytes)); out.println("caught expected CNFE: " + t); } @@ -81,7 +82,7 @@ public class BadValues { public void testNotFoundSerWr() throws Exception { out.println("\n---"); byte[] bytes = byteStreamFor("XxYyZz", 0L, (byte)(SC_SERIALIZABLE | SC_WRITE_METHOD)); - Throwable t = expectThrows(CNFE, () -> deserialize(bytes)); + Throwable t = assertThrows(CNFE, () -> deserialize(bytes)); out.println("caught expected CNFE: " + t); } @@ -89,7 +90,7 @@ public class BadValues { public void testNotFoundExt() throws Exception { out.println("\n---"); byte[] bytes = byteStreamFor("AaBbCc", 0L, (byte)SC_EXTERNALIZABLE); - Throwable t = expectThrows(CNFE, () -> deserialize(bytes)); + Throwable t = assertThrows(CNFE, () -> deserialize(bytes)); out.println("caught expected CNFE: " + t); } @@ -97,7 +98,7 @@ public class BadValues { public void testNotFoundExtWr() throws Exception { out.println("\n---"); byte[] bytes = byteStreamFor("AaBbCc", 0L, (byte)(SC_SERIALIZABLE | SC_WRITE_METHOD)); - Throwable t = expectThrows(CNFE, () -> deserialize(bytes)); + Throwable t = assertThrows(CNFE, () -> deserialize(bytes)); out.println("caught expected CNFE: " + t); } diff --git a/test/jdk/java/io/Serializable/records/BasicRecordSer.java b/test/jdk/java/io/Serializable/records/BasicRecordSer.java index 94a79e85b38..b05d6bd9550 100644 --- a/test/jdk/java/io/Serializable/records/BasicRecordSer.java +++ b/test/jdk/java/io/Serializable/records/BasicRecordSer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Basic test that serializes and deserializes a number of records - * @run testng BasicRecordSer + * @run junit BasicRecordSer */ import java.io.ByteArrayInputStream; @@ -39,19 +39,24 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Serializable; import java.math.BigInteger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.String.format; import static java.lang.System.out; import static java.net.InetAddress.getLoopbackAddress; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Basic test that serializes and deserializes a number of simple records. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class BasicRecordSer { // a mix of a few record and non-record classes @@ -101,7 +106,6 @@ public class BasicRecordSer { record Wubble (Wobble wobble, Wibble wibble, String s) implements ThrowingExternalizable { } - @DataProvider(name = "serializable") public Object[][] serializable() { Foo foo = new Foo(23); return new Object[][] { @@ -121,14 +125,20 @@ public class BasicRecordSer { } /** Tests serializing and deserializing a number of records. */ - @Test(dataProvider = "serializable") + @ParameterizedTest + @MethodSource("serializable") public void testSerializable(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); var objDeserialized = serializeDeserialize(objToSerialize); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize, objDeserialized); - assertEquals(objDeserialized, objToSerialize); + if (objToSerialize.getClass().isArray()) { + assertArrayEquals((Object[]) objDeserialized, (Object[]) objToSerialize); + assertArrayEquals((Object[]) objToSerialize, (Object[]) objDeserialized); + } else { + assertEquals(objDeserialized, objToSerialize); + assertEquals(objToSerialize, objDeserialized); + } } /** Tests serializing and deserializing of local records. */ @@ -154,8 +164,8 @@ public class BasicRecordSer { out.println("serializing : " + objToSerialize); Foo[] objDeserialized = (Foo[])serializeDeserialize(objToSerialize); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize, objDeserialized); - assertEquals(objDeserialized, objToSerialize); + Assertions.assertArrayEquals(objDeserialized, objToSerialize); + Assertions.assertArrayEquals(objToSerialize, objDeserialized); for (Foo f : objDeserialized) assertTrue(objDeserialized[0] == f); @@ -171,8 +181,8 @@ public class BasicRecordSer { out.println("serializing : " + objToSerialize); Wobble[] objDeserialized = (Wobble[])serializeDeserialize(objToSerialize); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize, objDeserialized); - assertEquals(objDeserialized, objToSerialize); + Assertions.assertArrayEquals(objDeserialized, objToSerialize); + Assertions.assertArrayEquals(objToSerialize, objDeserialized); for (Wobble w : objDeserialized) { assertTrue(objDeserialized[0] == w); @@ -192,7 +202,6 @@ public class BasicRecordSer { final NotSer notSer = new NotSer(7); } - @DataProvider(name = "notSerializable") public Object[][] notSerializable() { return new Object[][] { new Object[] { new NotSerEmpty() }, @@ -209,11 +218,12 @@ public class BasicRecordSer { static final Class NSE = NotSerializableException.class; /** Tests that non-Serializable record objects throw NotSerializableException. */ - @Test(dataProvider = "notSerializable") + @ParameterizedTest + @MethodSource("notSerializable") public void testNotSerializable(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); - NotSerializableException expected = expectThrows(NSE, () -> serialize(objToSerialize)); + NotSerializableException expected = Assertions.assertThrows(NSE, () -> serialize(objToSerialize)); out.println("caught expected NSE:" + expected); } @@ -235,9 +245,9 @@ public class BasicRecordSer { out.println("serializing : " + objToSerialize); var objDeserialized = serializeDeserialize(objToSerialize); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize, objDeserialized); assertEquals(objDeserialized, objToSerialize); - assertEquals(e_ctrInvocationCount, 1); + assertEquals(objToSerialize, objDeserialized); + assertEquals(1, e_ctrInvocationCount); } // --- @@ -258,9 +268,9 @@ public class BasicRecordSer { var objToSerialize = new G(); g_ctrInvocationCount = 0; // reset out.println("serializing : " + objToSerialize); - NotSerializableException expected = expectThrows(NSE, () -> serialize(objToSerialize)); + NotSerializableException expected = Assertions.assertThrows(NSE, () -> serialize(objToSerialize)); out.println("caught expected NSE:" + expected); - assertEquals(g_ctrInvocationCount, 0); + assertEquals(0, g_ctrInvocationCount); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java b/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java index 5057fcc7cbb..c84c7c9519e 100644 --- a/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java +++ b/test/jdk/java/io/Serializable/records/ConstructorAccessTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -26,7 +26,7 @@ * @bug 8246774 * @summary Ensures that the serialization implementation can *always* access * the record constructor - * @run testng ConstructorAccessTest + * @run junit ConstructorAccessTest */ import java.io.ByteArrayInputStream; @@ -38,16 +38,19 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.Externalizable; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /*implicit*/ record Aux1 (int x) implements Serializable { } /*implicit*/ record Aux2 (int x) implements Serializable { } +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ConstructorAccessTest { public record A (int x) implements Serializable { } @@ -75,7 +78,6 @@ public class ConstructorAccessTest { private record H (double d) implements ThrowingExternalizable { } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() { return new Object[][] { new Object[] { new A(34) }, @@ -91,7 +93,8 @@ public class ConstructorAccessTest { }; } - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void roundTrip(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); diff --git a/test/jdk/java/io/Serializable/records/CycleTest.java b/test/jdk/java/io/Serializable/records/CycleTest.java index 53d1247e808..7b323a78af8 100644 --- a/test/jdk/java/io/Serializable/records/CycleTest.java +++ b/test/jdk/java/io/Serializable/records/CycleTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Ensures basic behavior of cycles from record components - * @run testng CycleTest + * @run junit CycleTest */ import java.io.ByteArrayInputStream; @@ -34,10 +34,11 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; public class CycleTest { @@ -61,10 +62,10 @@ public class CycleTest { out.println("serializing : " + r); R deserializedObj = serializeDeserialize(r); out.println("deserialized: " + deserializedObj); - assertEquals(deserializedObj.x(), 1); // sanity - assertEquals(deserializedObj.y(), 2); // sanity + assertEquals(1, deserializedObj.x()); // sanity + assertEquals(2, deserializedObj.y()); // sanity assertTrue(deserializedObj.c() instanceof C); // sanity - assertEquals(deserializedObj.c().obj, null); // cycle, expect null + assertEquals(null, deserializedObj.c().obj); // cycle, expect null } /** @@ -84,8 +85,8 @@ public class CycleTest { out.println("deserialized: " + deserializedObj); assertTrue(deserializedObj instanceof C); // sanity assertTrue(deserializedObj.obj != null); // expect non-null, r - assertEquals(((R)deserializedObj.obj).x(), 3); // sanity - assertEquals(((R)deserializedObj.obj).y(), 4); // sanity + assertEquals(3, ((R)deserializedObj.obj).x()); // sanity + assertEquals(4, ((R)deserializedObj.obj).y()); // sanity } record R2 (int x, int y, C c1, C c2) implements Serializable { } @@ -105,8 +106,8 @@ public class CycleTest { out.println("serializing : " + r); R2 deserializedObj = serializeDeserialize(r); out.println("deserialized: " + deserializedObj); - assertEquals(deserializedObj.x(), 5); // sanity - assertEquals(deserializedObj.y(), 6); // sanity + assertEquals(5, deserializedObj.x()); // sanity + assertEquals(6, deserializedObj.y()); // sanity c1 = deserializedObj.c1(); c2 = deserializedObj.c2(); @@ -132,11 +133,11 @@ public class CycleTest { R3 deserializedObj = serializeDeserialize(r3); out.println("deserialized: " + deserializedObj); assertTrue(deserializedObj.r() != null); - assertEquals(deserializedObj.l(), 9); // sanity - assertEquals(deserializedObj.r().x(), 7); // sanity - assertEquals(deserializedObj.r().y(), 8); // sanity + assertEquals(9, deserializedObj.l()); // sanity + assertEquals(7, deserializedObj.r().x()); // sanity + assertEquals(8, deserializedObj.r().y()); // sanity assertTrue(deserializedObj.r().c() instanceof C); // sanity - assertEquals(deserializedObj.r().c().obj, null); // cycle, expect null + assertEquals(null, deserializedObj.r().c().obj); // cycle, expect null } // --- infra diff --git a/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java index 02175c53bb8..2960cc4f723 100644 --- a/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/DifferentStreamFieldsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -26,7 +26,7 @@ * @bug 8246774 * @summary Checks that the appropriate value is given to the canonical ctr * @library /test/lib - * @run testng DifferentStreamFieldsTest + * @run junit DifferentStreamFieldsTest */ import java.io.ByteArrayInputStream; @@ -38,14 +38,19 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; import jdk.test.lib.serial.SerialObjectBuilder; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Checks that the appropriate value is given to the canonical ctr. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class DifferentStreamFieldsTest { record R01(boolean x) implements Serializable {} @@ -76,7 +81,6 @@ public class DifferentStreamFieldsTest { record R14(R13[]x) implements Serializable {} - @DataProvider(name = "recordTypeAndExpectedValue") public Object[][] recordTypeAndExpectedValue() { return new Object[][]{ new Object[]{R01.class, false}, @@ -96,7 +100,8 @@ public class DifferentStreamFieldsTest { }; } - @Test(dataProvider = "recordTypeAndExpectedValue") + @ParameterizedTest + @MethodSource("recordTypeAndExpectedValue") public void testWithDifferentTypes(Class clazz, Object expectedXValue) throws Exception { out.println("\n---"); @@ -108,7 +113,7 @@ public class DifferentStreamFieldsTest { Object obj = deserialize(bytes); out.println("deserialized: " + obj); Object actualXValue = clazz.getDeclaredMethod("x").invoke(obj); - assertEquals(actualXValue, expectedXValue); + assertEquals(expectedXValue, actualXValue); bytes = SerialObjectBuilder .newBuilder(clazz.getName()) @@ -118,7 +123,7 @@ public class DifferentStreamFieldsTest { obj = deserialize(bytes); out.println("deserialized: " + obj); actualXValue = clazz.getDeclaredMethod("x").invoke(obj); - assertEquals(actualXValue, expectedXValue); + assertEquals(expectedXValue, actualXValue); } // --- all together @@ -137,18 +142,18 @@ public class DifferentStreamFieldsTest { R15 obj = deserialize(bytes); out.println("deserialized: " + obj); - assertEquals(obj.a, false); - assertEquals(obj.b, 0); - assertEquals(obj.c, 0); - assertEquals(obj.d, '\u0000'); - assertEquals(obj.e, 0); - assertEquals(obj.f, 0l); - assertEquals(obj.g, 0f); - assertEquals(obj.h, 0d); - assertEquals(obj.i, null); - assertEquals(obj.j, null); - assertEquals(obj.k, null); - assertEquals(obj.l, null); + assertEquals(false, obj.a); + assertEquals(0, obj.b); + assertEquals(0, obj.c); + assertEquals('\u0000', obj.d); + assertEquals(0, obj.e); + assertEquals(0l, obj.f); + assertEquals(0f, obj.g); + assertEquals(0d, obj.h); + assertEquals(null, obj.i); + assertEquals(null, obj.j); + assertEquals(null, obj.k); + assertEquals(null, obj.l); } @Test @@ -166,9 +171,9 @@ public class DifferentStreamFieldsTest { .build(); var deser1 = deserialize(OOSBytes); - assertEquals(deser1, r); + assertEquals(r, deser1); var deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); } { record R(int x, int y) implements Serializable {} @@ -176,7 +181,7 @@ public class DifferentStreamFieldsTest { var r = new R(7, 8); byte[] OOSBytes = serialize(r); var deser1 = deserialize(OOSBytes); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(R.class.getName()) @@ -185,7 +190,7 @@ public class DifferentStreamFieldsTest { .build(); var deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); builderBytes = SerialObjectBuilder .newBuilder(R.class.getName()) @@ -193,7 +198,7 @@ public class DifferentStreamFieldsTest { .addPrimitiveField("x", int.class, 7) .build(); deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); builderBytes = SerialObjectBuilder .newBuilder(R.class.getName()) @@ -203,12 +208,12 @@ public class DifferentStreamFieldsTest { .addPrimitiveField("z", int.class, 9) // additional fields .build(); deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); r = new R(0, 0); OOSBytes = serialize(r); deser1 = deserialize(OOSBytes); - assertEquals(deser1, r); + assertEquals(r, deser1); builderBytes = SerialObjectBuilder .newBuilder(R.class.getName()) @@ -216,13 +221,13 @@ public class DifferentStreamFieldsTest { .addPrimitiveField("x", int.class, 0) .build(); deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); builderBytes = SerialObjectBuilder .newBuilder(R.class.getName()) // no field values .build(); deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); } } @@ -234,7 +239,7 @@ public class DifferentStreamFieldsTest { var r = new Str("Hello", "World!"); var deser1 = deserialize(serialize(r)); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(Str.class.getName()) @@ -243,7 +248,7 @@ public class DifferentStreamFieldsTest { .build(); var deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); builderBytes = SerialObjectBuilder .newBuilder(Str.class.getName()) @@ -254,7 +259,7 @@ public class DifferentStreamFieldsTest { .build(); var deser3 = deserialize(builderBytes); - assertEquals(deser3, deser1); + assertEquals(deser1, deser3); } @Test @@ -264,8 +269,8 @@ public class DifferentStreamFieldsTest { record IntArray(int[]ints, long[]longs) implements Serializable {} IntArray r = new IntArray(new int[]{5, 4, 3, 2, 1}, new long[]{9L}); IntArray deser1 = deserialize(serialize(r)); - assertEquals(deser1.ints(), r.ints()); - assertEquals(deser1.longs(), r.longs()); + Assertions.assertArrayEquals(r.ints(), deser1.ints()); + Assertions.assertArrayEquals(r.longs(), deser1.longs()); byte[] builderBytes = SerialObjectBuilder .newBuilder(IntArray.class.getName()) @@ -274,14 +279,14 @@ public class DifferentStreamFieldsTest { .build(); IntArray deser2 = deserialize(builderBytes); - assertEquals(deser2.ints(), deser1.ints()); - assertEquals(deser2.longs(), deser1.longs()); + Assertions.assertArrayEquals(deser1.ints(), deser2.ints()); + Assertions.assertArrayEquals(deser1.longs(), deser2.longs()); } { record StrArray(String[]stringArray) implements Serializable {} StrArray r = new StrArray(new String[]{"foo", "bar"}); StrArray deser1 = deserialize(serialize(r)); - assertEquals(deser1.stringArray(), r.stringArray()); + Assertions.assertArrayEquals(r.stringArray(), deser1.stringArray()); byte[] builderBytes = SerialObjectBuilder .newBuilder(StrArray.class.getName()) @@ -289,7 +294,7 @@ public class DifferentStreamFieldsTest { .build(); StrArray deser2 = deserialize(builderBytes); - assertEquals(deser2.stringArray(), deser1.stringArray()); + Assertions.assertArrayEquals(deser1.stringArray(), deser2.stringArray()); } } @@ -302,7 +307,7 @@ public class DifferentStreamFieldsTest { var r = new NumberHolder(123); var deser1 = deserialize(serialize(r)); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(NumberHolder.class.getName()) @@ -310,7 +315,7 @@ public class DifferentStreamFieldsTest { .build(); var deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); } { @@ -318,7 +323,7 @@ public class DifferentStreamFieldsTest { var r = new IntegerHolder(123); var deser1 = deserialize(serialize(r)); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(IntegerHolder.class.getName()) @@ -326,7 +331,7 @@ public class DifferentStreamFieldsTest { .build(); var deser2 = deserialize(builderBytes); - assertEquals(deser2, deser1); + assertEquals(deser1, deser2); } } @@ -338,7 +343,7 @@ public class DifferentStreamFieldsTest { var r = new StringHolder("123"); var deser1 = deserialize(serialize(r)); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(StringHolder.class.getName()) @@ -362,7 +367,7 @@ public class DifferentStreamFieldsTest { var r = new IntHolder(123); var deser1 = deserialize(serialize(r)); - assertEquals(deser1, r); + assertEquals(r, deser1); byte[] builderBytes = SerialObjectBuilder .newBuilder(IntHolder.class.getName()) diff --git a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java index d744e9ddbad..815fbacc0f7 100644 --- a/test/jdk/java/io/Serializable/records/ProhibitedMethods.java +++ b/test/jdk/java/io/Serializable/records/ProhibitedMethods.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -26,7 +26,7 @@ * @bug 8246774 * @summary Basic tests for prohibited magic serialization methods * @library /test/lib - * @run testng ProhibitedMethods + * @run junit ProhibitedMethods */ import java.io.ByteArrayInputStream; @@ -49,24 +49,28 @@ import java.math.BigDecimal; import jdk.test.lib.compiler.InMemoryJavaCompiler; import jdk.test.lib.ByteCodeLoader; -import org.testng.Assert; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.lang.classfile.ClassFile.ACC_PRIVATE; +import static java.lang.constant.ConstantDescs.CD_Object; import static java.lang.constant.ConstantDescs.CD_String; import static java.lang.constant.ConstantDescs.CD_void; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; -import static org.testng.Assert.fail; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Checks that the various prohibited Serialization magic methods, and * Externalizable methods, are not invoked ( effectively ignored ) for * record objects. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ProhibitedMethods { public interface ThrowingExternalizable extends Externalizable { @@ -100,7 +104,7 @@ public class ProhibitedMethods { * fail("readObjectNoData should not be invoked"); } * } */ - @BeforeTest + @BeforeAll public void setup() { { byte[] byteCode = InMemoryJavaCompiler.compile("Foo", @@ -165,7 +169,6 @@ public class ProhibitedMethods { } } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() { return new Object[][] { new Object[] { newFoo() }, @@ -177,7 +180,8 @@ public class ProhibitedMethods { }; } - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void roundTrip(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); @@ -245,8 +249,8 @@ public class ProhibitedMethods { return cf.transformClass(cf.parse(classBytes), ClassTransform.endHandler(clb -> { clb.withMethodBody(name, desc, ACC_PRIVATE, cob -> { cob.loadConstant(name + " should not be invoked"); - cob.invokestatic(Assert.class.describeConstable().orElseThrow(), "fail", - MethodTypeDesc.of(CD_void, CD_String)); + cob.invokestatic(Assertions.class.describeConstable().orElseThrow(), "fail", + MethodTypeDesc.of(CD_Object, CD_String)); cob.return_(); }); })); @@ -266,37 +270,37 @@ public class ProhibitedMethods { Method m = obj.getClass().getDeclaredMethod("writeObject", ObjectOutputStream.class); assertTrue((m.getModifiers() & Modifier.PRIVATE) != 0); m.setAccessible(true); - ReflectiveOperationException t = expectThrows(ROE, () -> + ReflectiveOperationException t = Assertions.assertThrows(ROE, () -> m.invoke(obj, new ObjectOutputStream(OutputStream.nullOutputStream()))); Throwable assertionError = t.getCause(); out.println("caught expected AssertionError: " + assertionError); assertTrue(assertionError instanceof AssertionError, "Expected AssertionError, got:" + assertionError); - assertEquals(assertionError.getMessage(), "writeObject should not be invoked"); + assertEquals("writeObject should not be invoked", assertionError.getMessage()); } { // readObject Method m = obj.getClass().getDeclaredMethod("readObject", ObjectInputStream.class); assertTrue((m.getModifiers() & Modifier.PRIVATE) != 0); m.setAccessible(true); - ReflectiveOperationException t = expectThrows(ROE, () -> + ReflectiveOperationException t = Assertions.assertThrows(ROE, () -> m.invoke(obj, new ObjectInputStream() { })); Throwable assertionError = t.getCause(); out.println("caught expected AssertionError: " + assertionError); assertTrue(assertionError instanceof AssertionError, "Expected AssertionError, got:" + assertionError); - assertEquals(assertionError.getMessage(), "readObject should not be invoked"); + assertEquals("readObject should not be invoked", assertionError.getMessage()); } { // readObjectNoData Method m = obj.getClass().getDeclaredMethod("readObjectNoData"); assertTrue((m.getModifiers() & Modifier.PRIVATE) != 0); m.setAccessible(true); - ReflectiveOperationException t = expectThrows(ROE, () -> m.invoke(obj)); + ReflectiveOperationException t = Assertions.assertThrows(ROE, () -> m.invoke(obj)); Throwable assertionError = t.getCause(); out.println("caught expected AssertionError: " + assertionError); assertTrue(assertionError instanceof AssertionError, "Expected AssertionError, got:" + assertionError); - assertEquals(assertionError.getMessage(), "readObjectNoData should not be invoked"); + assertEquals("readObjectNoData should not be invoked", assertionError.getMessage()); } } } diff --git a/test/jdk/java/io/Serializable/records/ReadResolveTest.java b/test/jdk/java/io/Serializable/records/ReadResolveTest.java index 04de34781f9..2eb77bbf663 100644 --- a/test/jdk/java/io/Serializable/records/ReadResolveTest.java +++ b/test/jdk/java/io/Serializable/records/ReadResolveTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Basic tests for readResolve - * @run testng ReadResolveTest + * @run junit ReadResolveTest */ import java.io.ByteArrayInputStream; @@ -35,15 +35,19 @@ import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serial; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.String.format; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests records being used as a serial proxy. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ReadResolveTest { static class C1 implements Serializable { @@ -94,7 +98,6 @@ public class ReadResolveTest { } } - @DataProvider(name = "objectsToSerialize") public Object[][] objectsToSerialize() { return new Object[][] { new Object[] { new C1(3,4) }, @@ -103,13 +106,14 @@ public class ReadResolveTest { }; } - @Test(dataProvider = "objectsToSerialize") + @ParameterizedTest + @MethodSource("objectsToSerialize") public void testSerialize(Object objectToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objectToSerialize); Object deserializedObj = serializeDeserialize(objectToSerialize); out.println("deserialized: " + deserializedObj); - assertEquals(deserializedObj, objectToSerialize); + assertEquals(objectToSerialize, deserializedObj); } // -- null replacement @@ -128,7 +132,7 @@ public class ReadResolveTest { out.println("serializing : " + objectToSerialize); Object deserializedObj = serializeDeserialize(objectToSerialize); out.println("deserialized: " + deserializedObj); - assertEquals(deserializedObj, null); + assertEquals(null, deserializedObj); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/RecordClassTest.java b/test/jdk/java/io/Serializable/records/RecordClassTest.java index 401512056e6..ba920ce92e5 100644 --- a/test/jdk/java/io/Serializable/records/RecordClassTest.java +++ b/test/jdk/java/io/Serializable/records/RecordClassTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Basic tests for serializing and deserializing record classes - * @run testng RecordClassTest + * @run junit RecordClassTest */ import java.io.ByteArrayInputStream; @@ -38,15 +38,18 @@ import java.io.ObjectOutput; import java.io.ObjectOutputStream; import java.io.ObjectStreamClass; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.fail; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.fail; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Serializes and deserializes record classes. Ensures that the SUID is 0. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class RecordClassTest { record Foo () implements Serializable { } @@ -74,7 +77,6 @@ public class RecordClassTest { record Wubble (Wobble wobble, Wibble wibble, String s) implements ThrowingExternalizable { } - @DataProvider(name = "recordClasses") public Object[][] recordClasses() { return new Object[][] { new Object[] { Foo.class , 0L }, @@ -87,7 +89,8 @@ public class RecordClassTest { } /** Tests that the serialized and deserialized instances are equal. */ - @Test(dataProvider = "recordClasses") + @ParameterizedTest + @MethodSource("recordClasses") public void testClassSerialization(Class recordClass, long unused) throws Exception { @@ -95,21 +98,22 @@ public class RecordClassTest { out.println("serializing : " + recordClass); var deserializedClass = serializeDeserialize(recordClass); out.println("deserialized: " + deserializedClass); - assertEquals(recordClass, deserializedClass); assertEquals(deserializedClass, recordClass); + assertEquals(recordClass, deserializedClass); } /** Tests that the SUID is always 0 unless explicitly declared. */ - @Test(dataProvider = "recordClasses") + @ParameterizedTest + @MethodSource("recordClasses") public void testSerialVersionUID(Class recordClass, long expectedUID) { out.println("\n---"); ObjectStreamClass osc = ObjectStreamClass.lookup(recordClass); out.println("ObjectStreamClass::lookup : " + osc); - assertEquals(osc.getSerialVersionUID(), expectedUID); + assertEquals(expectedUID, osc.getSerialVersionUID()); osc = ObjectStreamClass.lookupAny(recordClass); out.println("ObjectStreamClass::lookupAny: " + osc); - assertEquals(osc.getSerialVersionUID(), expectedUID); + assertEquals(expectedUID, osc.getSerialVersionUID()); } // --- not Serializable @@ -120,7 +124,6 @@ public class RecordClassTest { record NotSerializable3(T t) { } - @DataProvider(name = "notSerRecordClasses") public Object[][] notSerRecordClasses() { return new Object[][] { new Object[] { NotSerializable1.class }, @@ -130,16 +133,17 @@ public class RecordClassTest { } /** Tests that the generated SUID is always 0 for all non-Serializable record classes. */ - @Test(dataProvider = "notSerRecordClasses") + @ParameterizedTest + @MethodSource("notSerRecordClasses") public void testSerialVersionUIDNonSer(Class recordClass) { out.println("\n---"); ObjectStreamClass osc = ObjectStreamClass.lookup(recordClass); out.println("ObjectStreamClass::lookup : " + osc); - assertEquals(osc, null); + assertEquals(null, osc); osc = ObjectStreamClass.lookupAny(recordClass); out.println("ObjectStreamClass::lookupAny: " + osc); - assertEquals(osc.getSerialVersionUID(), 0L); + assertEquals(0L, osc.getSerialVersionUID()); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java index 16266806850..471e94b6ed7 100644 --- a/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/SerialPersistentFieldsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -26,7 +26,7 @@ * @bug 8246774 * @summary Basic tests for prohibited magic serialPersistentFields * @library /test/lib - * @run testng SerialPersistentFieldsTest + * @run junit SerialPersistentFieldsTest */ import java.io.ByteArrayInputStream; @@ -52,9 +52,6 @@ import java.math.BigDecimal; import jdk.test.lib.ByteCodeLoader; import jdk.test.lib.compiler.InMemoryJavaCompiler; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; import static java.lang.classfile.ClassFile.ACC_FINAL; import static java.lang.classfile.ClassFile.ACC_PRIVATE; @@ -65,12 +62,18 @@ import static java.lang.constant.ConstantDescs.CD_void; import static java.lang.constant.ConstantDescs.CLASS_INIT_NAME; import static java.lang.constant.ConstantDescs.INIT_NAME; import static java.lang.constant.ConstantDescs.MTD_void; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Checks that the serialPersistentFields declaration is effectively ignored. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SerialPersistentFieldsTest { ClassLoader serializableRecordLoader; @@ -88,7 +91,7 @@ public class SerialPersistentFieldsTest { * }; * } */ - @BeforeTest + @BeforeAll public void setup() { { // R1 byte[] byteCode = InMemoryJavaCompiler.compile("R1", @@ -174,7 +177,6 @@ public class SerialPersistentFieldsTest { return newRecord("R5", new Class[]{int.class}, new Object[]{x}); } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() { return new Object[][] { new Object[] { newR1() }, @@ -185,14 +187,15 @@ public class SerialPersistentFieldsTest { }; } - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void roundTrip(Object objToSerialize) throws Exception { out.println("\n---"); out.println("serializing : " + objToSerialize); var objDeserialized = serializeDeserialize(objToSerialize); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize, objDeserialized); assertEquals(objDeserialized, objToSerialize); + assertEquals(objToSerialize, objDeserialized); } byte[] serialize(T obj) throws IOException { @@ -290,7 +293,8 @@ public class SerialPersistentFieldsTest { // -- infra sanity -- /** Checks to ensure correct operation of the test's generation logic. */ - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void wellFormedGeneratedClasses(Object obj) throws Exception { out.println("\n---"); out.println(obj); diff --git a/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java b/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java index abc0c63b0f2..2c133392dcb 100644 --- a/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java +++ b/test/jdk/java/io/Serializable/records/SerialVersionUIDTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Basic tests for SUID in the serial stream - * @run testng SerialVersionUIDTest + * @run junit SerialVersionUIDTest */ import java.io.ByteArrayInputStream; @@ -39,13 +39,16 @@ import java.io.Serializable; import java.util.ArrayList; import java.util.List; import java.util.stream.LongStream; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.io.ObjectStreamConstants.*; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SerialVersionUIDTest { record R1 () implements Serializable { @@ -64,7 +67,6 @@ public class SerialVersionUIDTest { private static final long serialVersionUID = 5678L; } - @DataProvider(name = "recordObjects") public Object[][] recordObjects() { return new Object[][] { new Object[] { new R1(), 1L }, @@ -78,7 +80,8 @@ public class SerialVersionUIDTest { /** * Tests that a declared SUID for a record class is inserted into the stream. */ - @Test(dataProvider = "recordObjects") + @ParameterizedTest + @MethodSource("recordObjects") public void testSerialize(Object objectToSerialize, long expectedUID) throws Exception { @@ -90,17 +93,16 @@ public class SerialVersionUIDTest { DataInputStream dis = new DataInputStream(bais); // sanity - assertEquals(dis.readShort(), STREAM_MAGIC); - assertEquals(dis.readShort(), STREAM_VERSION); - assertEquals(dis.readByte(), TC_OBJECT); - assertEquals(dis.readByte(), TC_CLASSDESC); - assertEquals(dis.readUTF(), objectToSerialize.getClass().getName()); + assertEquals(STREAM_MAGIC, dis.readShort()); + assertEquals(STREAM_VERSION, dis.readShort()); + assertEquals(TC_OBJECT, dis.readByte()); + assertEquals(TC_CLASSDESC, dis.readByte()); + assertEquals(objectToSerialize.getClass().getName(), dis.readUTF()); // verify that the UID is as expected - assertEquals(dis.readLong(), expectedUID); + assertEquals(expectedUID, dis.readLong()); } - @DataProvider(name = "recordClasses") public Object[][] recordClasses() { List list = new ArrayList<>(); List> recordClasses = List.of(R1.class, R2.class, R3.class, R4.class, R5.class); @@ -115,14 +117,15 @@ public class SerialVersionUIDTest { * Tests that matching of the serialVersionUID values ( stream value * and runtime class value ) is waived for record classes. */ - @Test(dataProvider = "recordClasses") + @ParameterizedTest + @MethodSource("recordClasses") public void testSerializeFromClass(Class cl, long suid) throws Exception { out.println("\n---"); byte[] bytes = byteStreamFor(cl.getName(), suid); Object obj = deserialize(bytes); - assertEquals(obj.getClass(), cl); + assertEquals(cl, obj.getClass()); assertTrue(obj.getClass().isRecord()); } diff --git a/test/jdk/java/io/Serializable/records/StreamRefTest.java b/test/jdk/java/io/Serializable/records/StreamRefTest.java index b0c72ec8a96..d0d3e353bdb 100644 --- a/test/jdk/java/io/Serializable/records/StreamRefTest.java +++ b/test/jdk/java/io/Serializable/records/StreamRefTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Tests for stream references - * @run testng StreamRefTest + * @run junit StreamRefTest */ import java.io.ByteArrayInputStream; @@ -36,11 +36,12 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; /** * Tests for stream references. @@ -123,14 +124,14 @@ public class StreamRefTest { updateIntValue(3, -3, bytes, 40); var byteStream = new ObjectInputStream(new ByteArrayInputStream(bytes)); - InvalidObjectException ioe = expectThrows(IOE, () -> deserializeOne(byteStream)); + InvalidObjectException ioe = Assertions.assertThrows(IOE, () -> deserializeOne(byteStream)); out.println("caught expected IOE: " + ioe); Throwable t = ioe.getCause(); assertTrue(t instanceof IllegalArgumentException, "Expected IAE, got:" + t); out.println("expected cause IAE: " + t); B b1 = (B)deserializeOne(byteStream); - assertEquals(b1.a, null); + assertEquals(null, b1.a); } @Test @@ -144,14 +145,14 @@ public class StreamRefTest { updateIntValue(3, -3, bytes, 96); var byteStream = new ObjectInputStream(new ByteArrayInputStream(bytes)); - InvalidObjectException ioe = expectThrows(IOE, () -> deserializeOne(byteStream)); + InvalidObjectException ioe = Assertions.assertThrows(IOE, () -> deserializeOne(byteStream)); out.println("caught expected IOE: " + ioe); Throwable t = ioe.getCause(); assertTrue(t instanceof IllegalArgumentException, "Expected IAE, got:" + t); out.println("expected cause IAE: " + t); A a1 = (A)deserializeOne(byteStream); - assertEquals(a1, null); + assertEquals(null, a1); } // --- @@ -211,7 +212,7 @@ public class StreamRefTest { throws IOException { ByteArrayInputStream bais = new ByteArrayInputStream(bytes, offset, 4); DataInputStream dis = new DataInputStream(bais); - assertEquals(dis.readInt(), expectedValue); + assertEquals(expectedValue, dis.readInt()); } static void updateIntValue(int expectedValue, int newValue, byte[] bytes, int offset) diff --git a/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java b/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java index 8e43a11a832..ee05930f29e 100644 --- a/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java +++ b/test/jdk/java/io/Serializable/records/ThrowingConstructorTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Tests constructor invocation exceptions are handled appropriately - * @run testng ThrowingConstructorTest + * @run junit ThrowingConstructorTest */ import java.io.ByteArrayInputStream; @@ -35,17 +35,20 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * If the constructor invocation throws an exception, an * `InvalidObjectException` is thrown with that exception as its cause. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ThrowingConstructorTest { /** "big switch" that can be used to allow/disallow record construction @@ -84,7 +87,6 @@ public class ThrowingConstructorTest { static final Class IOE = InvalidObjectException.class; - @DataProvider(name = "exceptionInstances") public Object[][] exceptionInstances() { Object[][] objs = new Object[][] { new Object[] { new R1(), NullPointerException.class, "thrown from R1" }, @@ -98,7 +100,8 @@ public class ThrowingConstructorTest { return objs; } - @Test(dataProvider = "exceptionInstances") + @ParameterizedTest + @MethodSource("exceptionInstances") public void testExceptions(Object objectToSerialize, Class expectedExType, String expectedExMessage) @@ -107,13 +110,13 @@ public class ThrowingConstructorTest { out.println("\n---"); out.println("serializing: " + objectToSerialize); byte[] bytes = serialize(objectToSerialize); - InvalidObjectException ioe = expectThrows(IOE, () -> deserialize(bytes)); + InvalidObjectException ioe = Assertions.assertThrows(IOE, () -> deserialize(bytes)); out.println("caught expected IOE: " + ioe); Throwable t = ioe.getCause(); assertTrue(t.getClass().equals(expectedExType), "Expected:" + expectedExType + ", got:" + t); out.println("expected cause " + expectedExType +" : " + t); - assertEquals(t.getMessage(), expectedExMessage); + assertEquals(expectedExMessage, t.getMessage()); } // -- errors ( pass through unwrapped ) @@ -143,7 +146,6 @@ public class ThrowingConstructorTest { } } - @DataProvider(name = "errorInstances") public Object[][] errorInstances() { Object[][] objs = new Object[][] { new Object[] { new R4(), OutOfMemoryError.class, "thrown from R4" }, @@ -157,7 +159,8 @@ public class ThrowingConstructorTest { return objs; } - @Test(dataProvider = "errorInstances") + @ParameterizedTest + @MethodSource("errorInstances") public void testErrors(Object objectToSerialize, Class expectedExType, String expectedExMessage) @@ -166,11 +169,11 @@ public class ThrowingConstructorTest { out.println("\n---"); out.println("serializing: " + objectToSerialize); byte[] bytes = serialize(objectToSerialize); - Throwable t = expectThrows(expectedExType, () -> deserialize(bytes)); + Throwable t = Assertions.assertThrows(expectedExType, () -> deserialize(bytes)); assertTrue(t.getClass().equals(expectedExType), "Expected:" + expectedExType + ", got:" + t); out.println("caught expected " + expectedExType +" : " + t); - assertEquals(t.getMessage(), expectedExMessage); + assertEquals(expectedExMessage, t.getMessage()); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/UnsharedTest.java b/test/jdk/java/io/Serializable/records/UnsharedTest.java index c96010c83ab..114e2dc6e10 100644 --- a/test/jdk/java/io/Serializable/records/UnsharedTest.java +++ b/test/jdk/java/io/Serializable/records/UnsharedTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,7 +25,7 @@ * @test * @bug 8238763 8246774 * @summary ObjectInputStream readUnshared method handling of Records - * @run testng UnsharedTest + * @run junit UnsharedTest */ import java.io.ByteArrayInputStream; @@ -35,10 +35,11 @@ import java.io.InvalidObjectException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.expectThrows; +import org.junit.jupiter.api.Assertions; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; /** * Tests OOS::writeUnshared and OIS::readUnshared to verify that records @@ -56,16 +57,16 @@ public class UnsharedTest { { // shared - sanity to ensure the second foo is a ref var byteStream = serialize(foo, foo); var foo1 = (Foo) deserializeOne(byteStream); - assertEquals(foo1.x, foo.x); + assertEquals(foo.x, foo1.x); var foo2 = (Foo) deserializeOne(byteStream); - assertEquals(foo2.x, foo.x); + assertEquals(foo.x, foo2.x); assertTrue(foo2 == foo1); } { // unshared var byteStream = serialize(foo, foo); var foo1 = (Foo) deserializeOneUnshared(byteStream); - assertEquals(foo1.x, foo.x); - var expected = expectThrows(IOE, () -> deserializeOne(byteStream)); + assertEquals(foo.x, foo1.x); + var expected = Assertions.assertThrows(IOE, () -> deserializeOne(byteStream)); assertTrue(expected.getMessage().contains("cannot read back reference to unshared object")); } } @@ -76,17 +77,17 @@ public class UnsharedTest { { // shared - sanity to ensure the second foo is NOT a ref var byteStream = serializeUnshared(foo, foo); var foo1 = (Foo) deserializeOne(byteStream); - assertEquals(foo1.x, foo.x); + assertEquals(foo.x, foo1.x); var foo2 = (Foo) deserializeOne(byteStream); - assertEquals(foo2.x, foo.x); + assertEquals(foo.x, foo2.x); assertTrue(foo2 != foo1); } { // unshared var byteStream = serializeUnshared(foo, foo); var foo1 = (Foo) deserializeOneUnshared(byteStream); - assertEquals(foo1.x, foo.x); + assertEquals(foo.x, foo1.x); var foo2 = (Foo) deserializeOneUnshared(byteStream); - assertEquals(foo2.x, foo.x); + assertEquals(foo.x, foo2.x); assertTrue(foo2 != foo1); } } diff --git a/test/jdk/java/io/Serializable/records/WriteReplaceTest.java b/test/jdk/java/io/Serializable/records/WriteReplaceTest.java index c64d6355dd2..2e253c166a0 100644 --- a/test/jdk/java/io/Serializable/records/WriteReplaceTest.java +++ b/test/jdk/java/io/Serializable/records/WriteReplaceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +25,7 @@ * @test * @bug 8246774 * @summary Basic tests for writeReplace - * @run testng WriteReplaceTest + * @run junit WriteReplaceTest */ import java.io.ByteArrayInputStream; @@ -34,11 +34,15 @@ import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.io.Serializable; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class WriteReplaceTest { record R1 () implements Serializable { @@ -71,7 +75,6 @@ public class WriteReplaceTest { } } - @DataProvider(name = "recordObjects") public Object[][] recordObjects() { return new Object[][] { new Object[] { new R1(), R1.class }, @@ -81,7 +84,8 @@ public class WriteReplaceTest { }; } - @Test(dataProvider = "recordObjects") + @ParameterizedTest + @MethodSource("recordObjects") public void testSerialize(Object objectToSerialize, Class expectedType) throws Exception { @@ -90,9 +94,9 @@ public class WriteReplaceTest { Object deserializedObj = serializeDeserialize(objectToSerialize); out.println("deserialized: " + deserializedObj); if (objectToSerialize.getClass().equals(expectedType)) - assertEquals(deserializedObj, objectToSerialize); + assertEquals(objectToSerialize, deserializedObj); else - assertEquals(deserializedObj.getClass(), expectedType); + assertEquals(expectedType, deserializedObj.getClass()); } // -- null replacement @@ -108,7 +112,7 @@ public class WriteReplaceTest { out.println("serializing : " + objectToSerialize); Object deserializedObj = serializeDeserialize(objectToSerialize); out.println("deserialized: " + deserializedObj); - assertEquals(deserializedObj, null); + assertEquals(null, deserializedObj); } // --- infra diff --git a/test/jdk/java/io/Serializable/records/migration/AbstractTest.java b/test/jdk/java/io/Serializable/records/migration/AbstractTest.java index e0bbc574500..488f4a33acd 100644 --- a/test/jdk/java/io/Serializable/records/migration/AbstractTest.java +++ b/test/jdk/java/io/Serializable/records/migration/AbstractTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,8 +34,9 @@ import java.net.URL; import java.net.URLClassLoader; import java.nio.file.Path; import jdk.test.lib.compiler.CompilerUtils; -import org.testng.annotations.BeforeTest; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; /** * An abstract superclass for tests that require to serialize and deserialize @@ -54,7 +55,7 @@ public class AbstractTest { static final Path RECORD_SRC_DIR = Path.of(TEST_SRC, "record"); static final Path RECORD_DEST_DIR = Path.of("record"); - @BeforeTest + @BeforeAll public void setup() throws IOException { assertTrue(CompilerUtils.compile(PLAIN_SRC_DIR, PLAIN_DEST_DIR, "--class-path", TEST_CLASSES_DIR.toString())); diff --git a/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java b/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java index 6097e2477df..117a8474c67 100644 --- a/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java +++ b/test/jdk/java/io/Serializable/records/migration/AssignableFromTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -29,24 +29,26 @@ * @modules jdk.compiler * @compile AssignableFrom.java Point.java * DefaultValues.java SuperStreamFields.java - * @run testng AssignableFromTest + * @run junit AssignableFromTest */ import java.math.BigDecimal; import java.math.BigInteger; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Basic test to check that stream field values that are not the exact * declared param/field type, but assignable to a declared supertype, * are bound/assigned correctly. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class AssignableFromTest extends AbstractTest { - @DataProvider(name = "plainInstances") public Object[][] plainInstances() { return new Object[][] { new Object[] { newPlainAssignableFrom(Byte.valueOf((byte)11)) }, @@ -59,7 +61,8 @@ public class AssignableFromTest extends AbstractTest { } /** Serialize non-record (plain) instances, deserialize as a record. */ - @Test(dataProvider = "plainInstances") + @ParameterizedTest + @MethodSource("plainInstances") public void testPlainToRecord(AssignableFrom objToSerialize) throws Exception { assert !objToSerialize.getClass().isRecord(); out.println("serialize : " + objToSerialize); @@ -68,13 +71,12 @@ public class AssignableFromTest extends AbstractTest { assert objDeserialized.getClass().isRecord(); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize.number(), objDeserialized.number()); assertEquals(objDeserialized.number(), objToSerialize.number()); + assertEquals(objToSerialize.number(), objDeserialized.number()); assertEquals(objDeserialized.number().getClass(), objDeserialized.number().getClass()); } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() { return new Object[][] { new Object[] { newRecordAssignableFrom(Byte.valueOf((byte)21)) }, @@ -87,7 +89,8 @@ public class AssignableFromTest extends AbstractTest { } /** Serialize record instances, deserialize as non-record (plain). */ - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void testRecordToPlain(AssignableFrom objToSerialize) throws Exception { assert objToSerialize.getClass().isRecord(); out.println("serialize : " + objToSerialize); @@ -96,8 +99,8 @@ public class AssignableFromTest extends AbstractTest { assert !objDeserialized.getClass().isRecord(); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize.number(), objDeserialized.number()); assertEquals(objDeserialized.number(), objToSerialize.number()); + assertEquals(objToSerialize.number(), objDeserialized.number()); assertEquals(objDeserialized.number().getClass(), objDeserialized.number().getClass()); } diff --git a/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java b/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java index 4af684156c6..357c9400777 100644 --- a/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java +++ b/test/jdk/java/io/Serializable/records/migration/DefaultValuesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -28,21 +28,24 @@ * @library /test/lib * @modules jdk.compiler * @compile AssignableFrom.java Point.java DefaultValues.java SuperStreamFields.java - * @run testng DefaultValuesTest + * @run junit DefaultValuesTest */ import java.io.ByteArrayOutputStream; import java.io.DataOutputStream; -import org.testng.annotations.Test; import static java.io.ObjectStreamConstants.*; import static java.lang.System.out; -import static org.testng.Assert.*; + +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; /** * Basic test to check that default primitive / reference values are * presented to the record's canonical constructor, for fields not in * the stream. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class DefaultValuesTest extends AbstractTest { /** @@ -77,13 +80,13 @@ public class DefaultValuesTest extends AbstractTest { Point point = deserializeAsPlain(bytes); out.println("deserialized: " + point); - assertEquals(point.x(), 0); - assertEquals(point.y(), 0); + assertEquals(0, point.x()); + assertEquals(0, point.y()); point = deserializeAsRecord(bytes); out.println("deserialized: " + point); - assertEquals(point.x(), 0); - assertEquals(point.y(), 0); + assertEquals(0, point.x()); + assertEquals(0, point.y()); } // --- @@ -115,8 +118,8 @@ public class DefaultValuesTest extends AbstractTest { DefaultValues o1 = deserializeAsRecord(bytes); out.println("deserialized: " + o1); - assertEquals(o1.point().x(), point.x()); // sanity - assertEquals(o1.point().y(), point.y()); // sanity + assertEquals(point.x(), o1.point().x()); // sanity + assertEquals(point.y(), o1.point().y()); // sanity assertTrue(o1.bool() == Defaults.bool); assertTrue(o1.by() == Defaults.by); assertTrue(o1.ch() == Defaults.ch); diff --git a/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java b/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java index 6090d71003e..35e75341dbf 100644 --- a/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java +++ b/test/jdk/java/io/Serializable/records/migration/SuperStreamFieldsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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 @@ -28,20 +28,23 @@ * @library /test/lib * @modules jdk.compiler * @compile AssignableFrom.java Point.java DefaultValues.java SuperStreamFields.java - * @run testng SuperStreamFieldsTest + * @run junit SuperStreamFieldsTest */ -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static java.lang.System.out; -import static org.testng.Assert.assertEquals; + +import org.junit.jupiter.api.Assertions; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * Tests that superclass fields in the stream are discarded. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SuperStreamFieldsTest extends AbstractTest { - @DataProvider(name = "plainInstances") public Object[][] plainInstances() { return new Object[][] { new Object[] { newPlainSuperStreamFields("cat", new int[] { 1 }, 1) }, @@ -51,7 +54,8 @@ public class SuperStreamFieldsTest extends AbstractTest { } /** Serializes non-record (plain) instance, deserializes as a record. */ - @Test(dataProvider = "plainInstances") + @ParameterizedTest + @MethodSource("plainInstances") public void testPlainToRecord(SuperStreamFields objToSerialize) throws Exception { assert !objToSerialize.getClass().isRecord(); out.println("serialize : " + objToSerialize); @@ -60,12 +64,11 @@ public class SuperStreamFieldsTest extends AbstractTest { assert objDeserialized.getClass().isRecord(); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize.str(), objDeserialized.str()); - assertEquals(objToSerialize.x(), objDeserialized.x()); - assertEquals(objToSerialize.y(), objDeserialized.y()); + assertEquals(objDeserialized.str(), objToSerialize.str()); + Assertions.assertArrayEquals(objDeserialized.x(), objToSerialize.x()); + assertEquals(objDeserialized.y(), objToSerialize.y()); } - @DataProvider(name = "recordInstances") public Object[][] recordInstances() { return new Object[][] { new Object[] { newRecordSuperStreamFields("goat", new int[] { 56 }, 66) }, @@ -75,7 +78,8 @@ public class SuperStreamFieldsTest extends AbstractTest { } /** Serializes record instance, deserializes as non-record (plain). */ - @Test(dataProvider = "recordInstances") + @ParameterizedTest + @MethodSource("recordInstances") public void testRecordToPlain(SuperStreamFields objToSerialize) throws Exception { assert objToSerialize.getClass().isRecord(); out.println("serialize : " + objToSerialize); @@ -84,9 +88,9 @@ public class SuperStreamFieldsTest extends AbstractTest { assert !objDeserialized.getClass().isRecord(); out.println("deserialized: " + objDeserialized); - assertEquals(objToSerialize.str(), objDeserialized.str()); - assertEquals(objToSerialize.x(), objDeserialized.x()); - assertEquals(objToSerialize.y(), objDeserialized.y()); + assertEquals(objDeserialized.str(), objToSerialize.str()); + Assertions.assertArrayEquals(objDeserialized.x(), objToSerialize.x()); + assertEquals(objDeserialized.y(), objToSerialize.y()); } From d02abfe765a1e67c5e37f3450aa5a0d8fb97a208 Mon Sep 17 00:00:00 2001 From: Khalid Boulanouare Date: Tue, 16 Dec 2025 20:37:57 +0000 Subject: [PATCH 123/211] 8158801: [TEST_BUG] Mixing tests fail because of focus workaround trick Reviewed-by: aivanov, prr, psadhukhan --- test/jdk/ProblemList.txt | 29 +------- .../GlassPaneOverlappingTestBase.java | 69 +++++++++---------- .../AWT_Mixing/JComboBoxOverlapping.java | 4 +- .../JInternalFrameMoveOverlapping.java | 4 +- .../AWT_Mixing/JInternalFrameOverlapping.java | 3 +- .../AWT_Mixing/JMenuBarOverlapping.java | 7 +- .../AWT_Mixing/JPopupMenuOverlapping.java | 6 +- .../AWT_Mixing/JScrollPaneOverlapping.java | 3 +- .../AWT_Mixing/JSplitPaneOverlapping.java | 3 +- .../AWT_Mixing/MixingFrameResizing.java | 5 +- .../AWT_Mixing/MixingPanelsResizing.java | 27 ++++++-- .../Mixing/AWT_Mixing/OpaqueOverlapping.java | 7 +- .../AWT_Mixing/OverlappingTestBase.java | 13 +++- .../AWT_Mixing/SimpleOverlappingTestBase.java | 59 +++++++++++----- 14 files changed, 132 insertions(+), 107 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 974e719c1c9..a81e48f3883 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -152,7 +152,6 @@ java/awt/event/InputEvent/EventWhenTest/EventWhenTest.java 8168646 generic-all java/awt/List/KeyEventsTest/KeyEventsTest.java 8201307 linux-all java/awt/List/NoEvents/ProgrammaticChange.java 8201307 linux-all java/awt/Paint/ListRepaint.java 8201307 linux-all -java/awt/Mixing/AWT_Mixing/HierarchyBoundsListenerMixingTest.java 8049405 macosx-all java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8370584 windows-x64 java/awt/Mixing/AWT_Mixing/OpaqueOverlappingChoice.java 8048171 generic-all java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java 8159451 linux-all,windows-all,macosx-all @@ -161,33 +160,7 @@ java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java 6986109 windows-al java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java 8049405 generic-all java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java 8049405 macosx-all java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java 8049405 macosx-all -java/awt/Mixing/AWT_Mixing/JButtonInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JButtonOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JColorChooserOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JEditorPaneInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JEditorPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JLabelInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JLabelOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JListInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JListOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JPanelInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JPanelOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JProgressBarInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JProgressBarOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JScrollBarInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JScrollBarOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JSliderInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JSliderOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JSpinnerInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JSpinnerOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java 8158801,8357360 windows-all,linux-all -java/awt/Mixing/AWT_Mixing/JTableOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JTextAreaInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JTextAreaOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JTextFieldInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JTextFieldOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JToggleButtonInGlassPaneOverlapping.java 8158801 windows-all -java/awt/Mixing/AWT_Mixing/JToggleButtonOverlapping.java 8158801 windows-all +java/awt/Mixing/AWT_Mixing/JTableInGlassPaneOverlapping.java 8357360 windows-all,linux-all java/awt/Mixing/NonOpaqueInternalFrame.java 7124549 macosx-all java/awt/Focus/ActualFocusedWindowTest/ActualFocusedWindowRetaining.java 6829264 generic-all java/awt/datatransfer/DragImage/MultiResolutionDragImageTest.java 8080982 generic-all diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/GlassPaneOverlappingTestBase.java b/test/jdk/java/awt/Mixing/AWT_Mixing/GlassPaneOverlappingTestBase.java index f67e71b1b19..f5dd838eff2 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/GlassPaneOverlappingTestBase.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/GlassPaneOverlappingTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,12 +25,11 @@ import java.awt.Container; import java.awt.Point; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; -import java.awt.event.InputEvent; import java.lang.reflect.InvocationTargetException; + import javax.swing.JFrame; import javax.swing.SpringLayout; import javax.swing.SwingUtilities; -import test.java.awt.regtesthelpers.Util; /** * Base class for testing overlapping of Swing and AWT component put into GlassPane. @@ -46,7 +45,6 @@ public abstract class GlassPaneOverlappingTestBase extends SimpleOverlappingTest */ protected boolean testResize = true; private JFrame f = null; - private volatile Point ancestorLoc; /** * Setups GlassPane with lightweight component returned by {@link SimpleOverlappingTestBase#getSwingComponent() } @@ -83,6 +81,7 @@ public abstract class GlassPaneOverlappingTestBase extends SimpleOverlappingTest testedComponent.setBounds(0, 0, testedComponent.getPreferredSize().width, testedComponent.getPreferredSize().height); glassPane.add(testedComponent); + f.setLocationRelativeTo(null); f.setVisible(true); } @@ -94,6 +93,11 @@ public abstract class GlassPaneOverlappingTestBase extends SimpleOverlappingTest super(defaultClickValidation); } + @Override + protected final boolean isMultiFramesTest() { + return false; + } + /** * Run test by {@link OverlappingTestBase#clickAndBlink(java.awt.Robot, java.awt.Point) } validation for current lightweight component. *

    Also resize component and repeat validation in the resized area. @@ -106,40 +110,33 @@ public abstract class GlassPaneOverlappingTestBase extends SimpleOverlappingTest if (!super.performTest()) { return false; } - if (testResize) { - wasLWClicked = false; - try { - SwingUtilities.invokeAndWait(new Runnable() { - public void run() { - testedComponent.setBounds(0, 0, testedComponent.getPreferredSize().width, testedComponent.getPreferredSize().height + 20); - ancestorLoc = f.getLocationOnScreen(); - } - }); - } catch (InterruptedException ex) { - fail(ex.getMessage()); - } catch (InvocationTargetException ex) { - fail(ex.getMessage()); - } - Point lLoc = testedComponent.getLocationOnScreen(); - lLoc.translate(1, testedComponent.getPreferredSize().height + 1); - - /* this is a workaround for certain jtreg(?) focus issue: - tests fail starting after failing mixing tests but always pass alone. - */ - Util.waitForIdle(robot); - ancestorLoc.translate(isOel7orLater() ? 5 : f.getWidth() / 2 - 15, 2); - robot.mouseMove(ancestorLoc.x, ancestorLoc.y); - Util.waitForIdle(robot); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(50); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - Util.waitForIdle(robot); - - clickAndBlink(robot, lLoc); - return wasLWClicked; - } else { + if (!testResize) { return true; } + + wasLWClicked = false; + try { + SwingUtilities.invokeAndWait(new Runnable() { + + public void run() { + testedComponent.setBounds(0, 0, + testedComponent.getPreferredSize().width, + testedComponent.getPreferredSize().height + 20); + } + }); + } catch (InterruptedException | InvocationTargetException ex) { + fail(ex.getMessage()); + } + Point lLoc = testedComponent.getLocationOnScreen(); + lLoc.translate(1, testedComponent.getPreferredSize().height + 1); + clickAndBlink(robot, lLoc); + + return wasLWClicked; + } + + @Override + protected void cleanup() { + f.dispose(); } } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java index cc02e9afbeb..d71fa7b3522 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JComboBoxOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -64,7 +64,6 @@ public class JComboBoxOverlapping extends OverlappingTestBase { frame = new JFrame("Mixing : Dropdown Overlapping test"); frame.getContentPane().setLayout(new BoxLayout(frame.getContentPane(), BoxLayout.Y_AXIS)); frame.setSize(200, 200); - frame.setVisible(true); cb = new JComboBox(petStrings); cb.setPreferredSize(new Dimension(frame.getContentPane().getWidth(), 20)); @@ -79,6 +78,7 @@ public class JComboBoxOverlapping extends OverlappingTestBase { frame.add(cb); propagateAWTControls(frame); + frame.setLocationRelativeTo(null); frame.setVisible(true); } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java index 443ff70727d..6f27aba85da 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameMoveOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,7 +34,6 @@ import test.java.awt.regtesthelpers.Util; /** * AWT/Swing overlapping test for {@link javax.swing.JInternalFrame } component during move. - *

    See CR6768230 for details and base class for test info. */ /* * @test @@ -117,6 +116,7 @@ public class JInternalFrameMoveOverlapping extends OverlappingTestBase { JFrame frame = new JFrame("Test Window"); frame.setSize(300, 300); frame.setContentPane(desktopPane); + frame.setLocationRelativeTo(null); frame.setVisible(true); locTopFrame = topFrame.getLocationOnScreen(); diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java index 4cb9425abe7..8d619e34c35 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JInternalFrameOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -75,6 +75,7 @@ public class JInternalFrameOverlapping extends OverlappingTestBase { JFrame frame = new JFrame("Test Window"); frame.setSize(300, 300); frame.setContentPane(desktopPane); + frame.setLocationRelativeTo(null); frame.setVisible(true); JInternalFrame bottomFrame = new JInternalFrame("bottom frame", false, false, false, false); bottomFrame.setSize(220, 220); diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java index 792831c2d8d..f3a213e5144 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JMenuBarOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -22,7 +22,6 @@ */ -import java.awt.Color; import java.awt.GridLayout; import java.awt.Point; import java.awt.Robot; @@ -30,12 +29,14 @@ import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; + import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JSeparator; import javax.swing.SwingUtilities; + import test.java.awt.regtesthelpers.Util; /** @@ -72,7 +73,6 @@ public class JMenuBarOverlapping extends OverlappingTestBase { frame = new JFrame("Mixing : Dropdown Overlapping test"); frame.setLayout(new GridLayout(0,1)); frame.setSize(200, 200); - frame.setVisible(true); menuBar = new JMenuBar(); JMenu menu = new JMenu("Test Menu"); @@ -104,6 +104,7 @@ public class JMenuBarOverlapping extends OverlappingTestBase { frame.setJMenuBar(menuBar); propagateAWTControls(frame); + frame.setLocationRelativeTo(null); frame.setVisible(true); } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java index d4b50287dc6..e80475088ac 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JPopupMenuOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -22,17 +22,18 @@ */ -import java.awt.Color; import java.awt.Point; import java.awt.Robot; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.lang.reflect.InvocationTargetException; + import javax.swing.JFrame; import javax.swing.JMenuItem; import javax.swing.JPopupMenu; import javax.swing.SpringLayout; import javax.swing.SwingUtilities; + import test.java.awt.regtesthelpers.Util; /** @@ -82,6 +83,7 @@ public class JPopupMenuOverlapping extends OverlappingTestBase { item.addActionListener(menuListener); } propagateAWTControls(frame); + frame.setLocationRelativeTo(null); frame.setVisible(true); loc = frame.getContentPane().getLocationOnScreen(); } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JScrollPaneOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JScrollPaneOverlapping.java index f22eacba82d..91538b75c13 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JScrollPaneOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JScrollPaneOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -95,6 +95,7 @@ public class JScrollPaneOverlapping extends OverlappingTestBase { }); f.getContentPane().add(scrollPane); + f.setLocationRelativeTo(null); f.setVisible(true); propagateAWTControls(p); // JButton b = new JButton("Space extender"); diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java index 7e1cb9434e4..5875a04b62b 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/JSplitPaneOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -89,6 +89,7 @@ public class JSplitPaneOverlapping extends OverlappingTestBase { frame.getContentPane().add(splitPane); frame.pack(); + frame.setLocationRelativeTo(null); frame.setVisible(true); } diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java b/test/jdk/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java index 545566970f8..8c19a80bd43 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/MixingFrameResizing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -26,9 +26,11 @@ import java.awt.Dimension; import java.awt.Point; import java.awt.Robot; import java.awt.event.InputEvent; + import javax.swing.JFrame; import javax.swing.SpringLayout; import javax.swing.SwingUtilities; + import test.java.awt.regtesthelpers.Util; /** @@ -65,6 +67,7 @@ public class MixingFrameResizing extends OverlappingTestBase { frame = new JFrame("Mixing : Frame Resizing test"); frame.setLayout(new SpringLayout()); frame.setSize(50, 50); + frame.setLocationRelativeTo(null); frame.setVisible(true); propagateAWTControls(frame); Util.waitTillShown(frame); diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java b/test/jdk/java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java index 39a59dc2a5c..1bb9b442dd8 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/MixingPanelsResizing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -22,10 +22,23 @@ */ -import java.awt.*; +import java.awt.BorderLayout; +import java.awt.Button; +import java.awt.Color; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; -import javax.swing.*; -import java.io.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + import test.java.awt.regtesthelpers.Util; /** @@ -130,6 +143,7 @@ public class MixingPanelsResizing { frame.add(jPanel, BorderLayout.NORTH); frame.pack(); + frame.setLocationRelativeTo(null); frame.setVisible(true); } }); @@ -298,6 +312,7 @@ public class MixingPanelsResizing { failureMessage = whyFailed; mainThread.interrupt(); }//fail() + + static class TestPassedException extends RuntimeException { + } }// class JButtonInGlassPane -class TestPassedException extends RuntimeException { -} diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java b/test/jdk/java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java index 4975cc165c2..03abb58f673 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -56,13 +56,13 @@ public class OpaqueOverlapping extends OverlappingTestBase { { useClickValidation = false; - failMessage = "Opacity test mismatchs"; + failMessage = "Opacity test mismatches"; // CR 6994264 (Choice autohides dropdown on Solaris 10) skipClassNames = new String[] { "Choice" }; } private String testSeq; - private final static String checkSeq = "010000101"; + private static final String checkSeq = "010000101"; private Point heavyLoc; private JButton light; private Frame frame = null; @@ -89,6 +89,7 @@ public class OpaqueOverlapping extends OverlappingTestBase { panel.add(light); frame.add(panel); frame.setBounds(50, 50, 400, 400); + frame.setLocationRelativeTo(null); frame.setVisible(true); currentAwtControl.addMouseListener(new MouseAdapter() { diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java b/test/jdk/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java index 794578a5907..3d4adecbd17 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/OverlappingTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,6 +34,7 @@ import java.awt.Robot; import java.awt.Scrollbar; import java.awt.TextField; import java.awt.Toolkit; +import java.awt.Window; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; @@ -171,6 +172,7 @@ public abstract class OverlappingTestBase { frame.getContentPane().setBackground(AWT_BACKGROUND_COLOR); frame.setSize(size, size); frame.setUndecorated(true); + frame.setLocationRelativeTo(null); frame.setVisible(true); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); p[0] = frame.getLocation(); @@ -259,6 +261,9 @@ public abstract class OverlappingTestBase { embedder.setBackground(Color.RED); embedder.setPreferredSize(new Dimension(150, 150)); container.add(embedder); + if (container instanceof Window) { + ((Window) container).setLocationRelativeTo(null); + } container.setVisible(true); // create peer long frameWindow = 0; @@ -301,6 +306,7 @@ public abstract class OverlappingTestBase { EmbeddedFrame eframe = (EmbeddedFrame) eframeCtor.newInstance(frameWindow); setupControl(eframe); eframe.setSize(new Dimension(150, 150)); + eframe.setLocationRelativeTo(null); eframe.setVisible(true); // System.err.println(eframe.getSize()); } catch (Exception ex) { @@ -682,6 +688,7 @@ public abstract class OverlappingTestBase { failureMessage = whyFailed; mainThread.interrupt(); }//fail() + + static class TestPassedException extends RuntimeException { + } }// class LWComboBox -class TestPassedException extends RuntimeException { -} diff --git a/test/jdk/java/awt/Mixing/AWT_Mixing/SimpleOverlappingTestBase.java b/test/jdk/java/awt/Mixing/AWT_Mixing/SimpleOverlappingTestBase.java index 928a5c437cb..0dd42a36cd0 100644 --- a/test/jdk/java/awt/Mixing/AWT_Mixing/SimpleOverlappingTestBase.java +++ b/test/jdk/java/awt/Mixing/AWT_Mixing/SimpleOverlappingTestBase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,10 +21,21 @@ * questions. */ -import java.awt.*; -import java.awt.event.*; -import java.util.regex.*; -import javax.swing.*; +import java.awt.Point; +import java.awt.Robot; +import java.awt.event.FocusAdapter; +import java.awt.event.FocusEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.swing.JComponent; +import javax.swing.JFrame; +import javax.swing.SpringLayout; + import test.java.awt.regtesthelpers.Util; /** @@ -55,6 +66,10 @@ public abstract class SimpleOverlappingTestBase extends OverlappingTestBase { this.useDefaultClickValidation = defaultClickValidation; } + protected boolean isMultiFramesTest(){ + return true; + } + public SimpleOverlappingTestBase() { this(true); } @@ -114,6 +129,7 @@ public abstract class SimpleOverlappingTestBase extends OverlappingTestBase { propagateAWTControls(f); + f.setLocationRelativeTo(null); f.setVisible(true); } @@ -140,21 +156,29 @@ public abstract class SimpleOverlappingTestBase extends OverlappingTestBase { /* this is a workaround for certain jtreg(?) focus issue: tests fail starting after failing mixing tests but always pass alone. */ - JFrame ancestor = (JFrame)(testedComponent.getTopLevelAncestor()); - if( ancestor != null ) { - Point ancestorLoc = ancestor.getLocationOnScreen(); - ancestorLoc.translate(isOel7orLater() ? 5 : - ancestor.getWidth() / 2 - 15, 2); - robot.mouseMove(ancestorLoc.x, ancestorLoc.y); - Util.waitForIdle(robot); - robot.mousePress(InputEvent.BUTTON1_MASK); - robot.delay(50); - robot.mouseRelease(InputEvent.BUTTON1_MASK); - Util.waitForIdle(robot); + JFrame ancestor = (JFrame) (testedComponent.getTopLevelAncestor()); + if (ancestor != null) { + final CountDownLatch latch = new CountDownLatch(1); + ancestor.addFocusListener(new FocusAdapter() { + @Override public void focusGained(FocusEvent e) { + latch.countDown(); + } + }); + ancestor.requestFocus(); + try { + if (!latch.await(1L, TimeUnit.SECONDS)) { + throw new RuntimeException( + "Ancestor frame didn't receive focus"); + } + } catch (InterruptedException e) { + throw new RuntimeException(e); + } } clickAndBlink(robot, lLoc); - Util.waitForIdle(robot); + if (ancestor != null && isMultiFramesTest()) { + ancestor.dispose(); + } return wasLWClicked; } @@ -172,5 +196,4 @@ public abstract class SimpleOverlappingTestBase extends OverlappingTestBase { } return false; } - } From fb99ba6ccd6e6d7a0e717a1b9f2a80402af5c661 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Tue, 16 Dec 2025 21:19:33 +0000 Subject: [PATCH 124/211] 8373119: JDK 26 RDP1 L10n resource files update Reviewed-by: jlu, asemenyuk, almatvee --- .../launcher/resources/launcher_de.properties | 5 +- .../launcher/resources/launcher_ja.properties | 6 +- .../resources/launcher_zh_CN.properties | 8 +- .../keytool/resources/keytool_de.properties | 2 +- .../keytool/resources/keytool_ja.properties | 2 +- .../resources/keytool_zh_CN.properties | 2 +- .../util/resources/security_de.properties | 5 +- .../util/resources/security_ja.properties | 3 + .../util/resources/security_zh_CN.properties | 3 + .../javac/resources/compiler_de.properties | 69 ++++--- .../javac/resources/compiler_ja.properties | 69 ++++--- .../javac/resources/compiler_zh_CN.properties | 69 ++++--- .../tools/javac/resources/javac_de.properties | 24 ++- .../tools/javac/resources/javac_ja.properties | 26 +-- .../javac/resources/javac_zh_CN.properties | 26 +-- .../javac/resources/launcher_de.properties | 3 + .../javac/resources/launcher_ja.properties | 3 + .../javac/resources/launcher_zh_CN.properties | 3 + .../resources/jarsigner_de.properties | 1 + .../resources/jarsigner_ja.properties | 1 + .../resources/jarsigner_zh_CN.properties | 1 + .../sun/tools/jar/resources/jar_de.properties | 2 + .../sun/tools/jar/resources/jar_ja.properties | 2 + .../tools/jar/resources/jar_zh_CN.properties | 2 + .../html/resources/standard_de.properties | 6 + .../html/resources/standard_ja.properties | 6 + .../html/resources/standard_zh_CN.properties | 6 + .../toolkit/resources/doclets_de.properties | 8 +- .../toolkit/resources/doclets_ja.properties | 4 + .../resources/doclets_zh_CN.properties | 4 + .../tool/resources/javadoc_de.properties | 2 +- .../tools/jlink/resources/jlink_de.properties | 3 +- .../tools/jlink/resources/jlink_ja.properties | 3 +- .../jlink/resources/jlink_zh_CN.properties | 3 +- .../jlink/resources/plugins_de.properties | 12 +- .../jlink/resources/plugins_ja.properties | 12 +- .../jlink/resources/plugins_zh_CN.properties | 12 +- .../resources/LinuxResources_de.properties | 6 - .../resources/LinuxResources_ja.properties | 6 - .../resources/LinuxResources_zh_CN.properties | 6 - .../resources/MacResources_de.properties | 31 ++- .../resources/MacResources_ja.properties | 31 ++- .../resources/MacResources_zh_CN.properties | 33 ++-- .../resources/HelpResources_de.properties | 176 +++++++++++++++-- .../resources/HelpResources_ja.properties | 179 ++++++++++++++++-- .../resources/HelpResources_zh_CN.properties | 177 +++++++++++++++-- .../resources/MainResources_de.properties | 106 ++++++----- .../resources/MainResources_ja.properties | 106 ++++++----- .../resources/MainResources_zh_CN.properties | 106 ++++++----- .../resources/WinResources_de.properties | 8 - .../resources/WinResources_ja.properties | 8 - .../resources/WinResources_zh_CN.properties | 8 - 52 files changed, 976 insertions(+), 429 deletions(-) diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties index 79b5968b210..e80869b868c 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_de.properties @@ -30,8 +30,8 @@ java.launcher.opt.vmselect =\ {0}\t zur Auswahl der "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t ist ein Synonym für die "{1}" VM [verworfen]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch "{0}" getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --upgrade-module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist,\n um upgradefähige Module im Laufzeitimage zu ersetzen. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --add-modules [,...]\n Root-Module, die zusätzlich zum anfänglichen Modul aufgelöst werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n Damit kann der Code in Modulen auf Code und Daten außerhalb der JRE zugreifen.\n kann auch ALL-UNNAMED sein, um den Code im Classpath anzugeben.\n --illegal-native-access=\n Zugriff auf Code und Daten außerhalb der JRE\n durch Code in Modulen zulassen oder verweigern, für die der native Zugriff nicht explizit aktiviert ist.\n ist "deny", "warn" oder "allow". Der Standardwert ist "warn".\n Diese Option wird in einem zukünftigen Release entfernt.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und lädt die Hauptklasse, führt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann nützlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann nützlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Aktiviert die Verbose-Ausgabe für das angegebene Subsystem\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulauflösungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zusätzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zusätzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener \ -Granularität\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n +java.launcher.opt.footer = \ -cp \n -classpath \n --class-path \n Eine durch "{0}" getrennte Liste mit Verzeichnissen, JAR-Archiven\n und ZIP-Archiven, in denen nach Klassendateien gesucht wird.\n -p \n --module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --upgrade-module-path ...\n Eine durch "{0}" getrennte Liste mit Elementen, von denen jedes Element ein Dateipfad ist\n zu einem Modul oder einem Verzeichnis mit Modulen ist,\n um upgradefähige Module im Laufzeitimage zu ersetzen. Jedes Modul ist entweder\n ein modulares JAR oder ein entpacktes Modulverzeichnis.\n --add-modules [,...]\n Root-Module, die zusätzlich zum anfänglichen Modul aufgelöst werden sollen.\n kann auch wie folgt lauten: ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n Damit kann der Code in Modulen auf Code und Daten außerhalb der JRE zugreifen.\n kann auch ALL-UNNAMED sein, um den Code im Classpath anzugeben.\n --illegal-native-access=\n Zugriff auf Code und Daten außerhalb der JRE\n durch Code in Modulen zulassen oder verweigern, für die der native Zugriff nicht explizit aktiviert ist.\n ist "deny", "warn" oder "allow". Der Standardwert ist "warn".\n Diese Option wird in einem zukünftigen Release entfernt.\n --enable-final-field-mutation [,...]\n Zulassen, dass die endgültigen Instanzfelder durch Code in den angegebenen Modulen mutiert werden.\n kann auch ALL-UNNAMED sein, um den Code im Classpath anzugeben.\n --illegal-final-field-mutation=\n Erlauben oder verweigern Sie die Mutation von endgültigen Feldern durch Code in Modulen, für die die Mutation\n von endgültigen Feldern nicht explizit aktiviert ist.\n ist "deny", "warn", "debug" oder "allow". Der Standardwert ist "warn".\n Diese Option wird in einem zukünftigen Release entfernt.\n --list-modules\n Listet beobachtbare Module auf und beendet den Vorgang\n -d \n --describe-module \n Beschreibt ein Modul und beendet den Vorgang\n --dry-run Erstellt eine VM und lädt die Hauptklasse, führt aber nicht die Hauptmethode aus.\n Die Option "--dry-run" kann nützlich sein, um die\n Befehlszeilenoptionen, wie die Modulsystemkonfiguration, zu validieren.\n --validate-modules\n Validiert alle Module und beendet den Vorgang\n Die Option "--validate-modules" kann nützlich sein, um\n Konflikte und andere Fehler mit Modulen auf dem Modulpfad zu ermitteln.\n -D=\n Legt eine Systemeigenschaft fest\n -verbose:[class|module|gc|jni]\n Aktiviert die Verbose-Ausgabe für das angegebene Subsystem\n -version Gibt die Produktversion an den Fehlerstream aus und beendet den Vorgang\n --version Gibt die Produktversion an den Outputstream aus und beendet den Vorgang\n -showversion Gibt die Produktversion an den Fehlerstream aus und \ +setzt den Vorgang fort\n --show-version\n Gibt die Produktversion an den Outputstream aus und setzt den Vorgang fort\n --show-module-resolution\n Zeigt die Modulauflösungsausgabe beim Start an\n -? -h -help\n Gibt diese Hilfemeldung an den Fehlerstream aus\n --help Gibt diese Hilfemeldung an den Outputstream aus\n -X Gibt Hilfe zu zusätzlichen Optionen an den Fehlerstream aus\n --help-extra Gibt Hilfe zu zusätzlichen Optionen an den Outputstream aus\n -ea[:...|:]\n -enableassertions[:...|:]\n Aktiviert Assertions mit angegebener Granularität\n -da[:...|:]\n -disableassertions[:...|:]\n Deaktiviert Assertions mit angegebener Granularität\n -esa | -enablesystemassertions\n Aktiviert System-Assertions\n -dsa | -disablesystemassertions\n Deaktiviert System-Assertions\n -agentlib:[=]\n Lädt die native Agent Library . Beispiel: -agentlib:jdwp\n siehe auch -agentlib:jdwp=help\n -agentpath:[=]\n Lädt die native Agent Library mit dem vollständigen Pfadnamen\n -javaagent:[=]\n Lädt den Java-Programmiersprachen-Agent, siehe java.lang.instrument\n -splash:\n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterstützt und verwendet,\n falls verfügbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" übergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgewählt.\n Weitere Informationen finden Sie in der Dokumentation zur SplashScreen-API\n @argument files\n Eine oder mehrere Argumentdateien mit Optionen\n --disable-@files\n Verhindert die weitere Erweiterung von Argumentdateien\n --enable-preview\n Lässt zu, das Klassen von Vorschaufeatures dieses Release abhängig sind\nUm ein Argument für eine lange Option anzugeben, können Sie --= oder\n-- verwenden.\n # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anhängen\n -Xcheck:jni Führt zusätzliche Prüfungen für JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug Führt keine Aktion aus. Ist veraltet und wird in einem zukünftigen Release entfernt.\n -Xdiag Zeigt zusätzliche Diagnosemeldungen an\n -Xint Nur Ausführung im interpretierten Modus\n -Xinternalversion\n Zeigt detailliertere JVM-Versionsinformationen an als die\n Option -version\n -Xlog: Konfiguriert oder aktiviert Logging mit dem einheitlichen Java Virtual\n Machine-(JVM-)Logging-Framework. Verwenden Sie -Xlog:help\n für weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zukünftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausführung im gemischten Modus (Standard)\n -Xmn Legt die anfängliche und maximale Größe (in Byte) des Heaps\n für die Young Generation (Nursery) fest\n -Xms Legt die minimale und die anfängliche Java-Heap-Größe fest\n -Xmx Legt die maximale Java-Heap-Größe fest\n -Xnoclassgc Deaktiviert die Klassen-Garbage Collection\n -Xrs Reduziert die Verwendung von BS-Signalen durch Java/VM (siehe Dokumentation)\n -Xshare:auto Verwendet freigegebene Klassendaten, wenn möglich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verläuft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern führen. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und fährt fort\n -XshowSettings:all\n Zeigt alle Einstellungen als Verbose-Ausgabe an und fährt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und fährt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und fährt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und fährt fort\n -XshowSettings:security\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:all\n Zeigt alle Sicherheitseinstellungen an und fährt fort\n -XshowSettings:security:properties\n Zeigt Sicherheitseigenschaften an und fährt fort\n -XshowSettings:security:providers\n Zeigt statische Sicherheitsprovidereinstellungen an und fährt fort\n -XshowSettings:security:tls\n Zeigt TLS-bezogene Sicherheitseinstellungen an und fährt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und fährt fort\n -Xss Legt die Stackgröße des Java-Threads fest\n Die tatsächliche Größe kann auf ein Vielfaches der\n Systemseitengröße aufgerundet werden, wenn für das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n \ @@ -58,6 +58,7 @@ java.launcher.jar.error3=kein Hauptmanifestattribut, in {0} java.launcher.jar.error4=Fehler beim Laden des Java-Agents in {0} java.launcher.jar.error5=Fehler: Beim Versuch, Datei {0} zu schließen, ist ein unerwarteter Fehler aufgetreten java.launcher.jar.error.illegal.ena.value=Fehler: Ungültiger Wert "{0}" für das Manifestattribut "Enable-Native-Access". Nur ''ALL-UNNAMED'' ist zulässig +java.launcher.jar.error.illegal.effm.value=Fehler: Ungültiger Wert "{0}" für das Manifestattribut "Enable-Final-Field-Mutation". Nur "ALL-UNNAMED" ist zulässig java.launcher.init.error=Initialisierungsfehler java.launcher.javafx.error1=Fehler: Die JavaFX-Methode launchApplication hat die falsche Signatur, sie\nmuss als statisch deklariert werden und einen Wert vom Typ VOID zurückgeben java.launcher.module.error1=Modul {0} weist kein ModuleMainClass-Attribut auf. Verwenden Sie -m / diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties index 04b68db3a8e..49712b21c52 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_ja.properties @@ -31,8 +31,9 @@ java.launcher.opt.hotspot =\ {0}\t は"{1}" VMのシノニムです [非 # Translators please note do not translate the options themselves java.launcher.opt.footer = \ -cp <ディレクトリおよびzip/jarファイルのクラス検索パス>\n -classpath <ディレクトリおよびzip/jarファイルのクラス検索パス>\n --class-path <ディレクトリおよびzip/jarファイルのクラス検索パス>\n "{0}"区切りリスト(ディレクトリ、JARアーカイブ、\n ZIPアーカイブ)で、クラス・ファイルの検索用。\n -p \n --module-path ...\n 要素を"{0}"で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリ。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --upgrade-module-path ...\n 要素を"{0}"で区切ったリストで、各要素は次へのファイル・パスです:\n モジュール、またはモジュールが格納されているディレクトリで、次のものを置き換えます:\n ランタイム・イメージのアップグレード可能なモジュール。各モジュールは次のいずれかです:\n モジュラJARまたは展開形式のモジュール・ディレクトリ。\n --add-modules [,...]\n 初期モジュールに加えて解決するルート・モジュール。\n には次も指定できます: ALL-DEFAULT、ALL-SYSTEM、\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n モジュール内のコードをJavaランタイムの外のコードおよびデータにアクセスさせることができます。\n は、クラス・パス上のコードを指定するためにALL-UNNAMEDにもできます。\n --illegal-native-access=\n Javaランタイムの外のコードおよびデータへのアクセスを許可または拒否します\n (ネイティブ・アクセスが明示的に有効化されていないモジュール内のコードによる)。\n \ -は、"deny"、"warn"または"allow"のいずれかです。デフォルト値は"warn"です。\n このオプションは、将来のリリースで削除される予定です。\n --list-modules\n 参照可能なモジュールをリストし終了します\n -d \n --describe-module \n モジュールを説明し終了します\n --dry-run VMを作成しメイン・クラスをロードしますが、メイン・メソッドは実行しません。\n --dry-runオプションは、次の検証に役立つ場合があります:\n モジュール・システム構成などのコマンド行オプション。\n --validate-modules\n すべてのモジュールを検証し終了します\n --validate-modulesオプションは、次の検索に役立つ場合があります:\n モジュール・パス上のモジュールでの競合およびその他のエラー。\n -D=\n システム・プロパティを設定します\n -verbose:[class|module|gc|jni]\n 特定のサブシステムで詳細出力を有効にする\n -version 製品バージョンをエラー・ストリームに出力して終了します\n --version 製品バージョンを出力ストリームに出力して終了します\n -showversion 製品バージョンをエラー・ストリームに出力して続行します\n --show-version\n 製品バージョンを出力ストリームに出力して続行します\n --show-module-resolution\n 起動時にモジュール解決出力を表示します\n -? -h -help\n このヘルプ・メッセージをエラー・ストリームに出力します\n --help このヘルプ・メッセージを出力ストリームに出力します\n -X 追加オプションのヘルプをエラー・ストリームに出力します\n --help-extra 追加オプションのヘルプを出力ストリームに出力します\n -ea[:...|:]\n -enableassertions[:...|:]\n 指定した粒度でアサーションを有効にします\n -da[:...|:]\n \ --disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n +は、"deny"、"warn"または"allow"のいずれかです。デフォルト値は"warn"です。\n このオプションは、将来のリリースで削除される予定です。\n --enable-final-field-mutation [,...]\n 指定されたモジュールのコードで、finalインスタンス・フィールドを変更できます。\n は、クラス・パス上のコードを指定するためにALL-UNNAMEDにもできます。\n --illegal-final-field-mutation=\n finalのモジュール内のコードによるfinalフィールド変更を許可または拒否します\n フィールド変更は明示的に有効化されていません。\n は、"deny"、"warn"、"debug"または"allow"のいずれかです。デフォルト値は"warn"です。\n このオプションは、将来のリリースで削除される予定です。\n --list-modules\n 参照可能なモジュールをリストし終了します\n -d \n --describe-module \n モジュールを説明し終了します\n --dry-run VMを作成しメイン・クラスをロードしますが、メイン・メソッドは実行しません。\n --dry-runオプションは、次の検証に役立つ場合があります:\n モジュール・システム構成などのコマンド行オプション。\n --validate-modules\n すべてのモジュールを検証し終了します\n --validate-modulesオプションは、次の検索に役立つ場合があります:\n モジュール・パス上のモジュールでの競合およびその他のエラー。\n -D=\n システム・プロパティを設定します\n -verbose:[class|module|gc|jni]\n 特定のサブシステムで詳細出力を有効にする\n -version 製品バージョンをエラー・ストリームに出力して終了します\n --version 製品バージョンを出力ストリームに出力して終了します\n -showversion 製品バージョンをエラー・ストリームに出力して続行します\n --show-version\n \ + 製品バージョンを出力ストリームに出力して続行します\n --show-module-resolution\n 起動時にモジュール解決出力を表示します\n -? -h -help\n このヘルプ・メッセージをエラー・ストリームに出力します\n --help このヘルプ・メッセージを出力ストリームに出力します\n -X 追加オプションのヘルプをエラー・ストリームに出力します\n --help-extra 追加オプションのヘルプを出力ストリームに出力します\n -ea[:...|:]\n -enableassertions[:...|:]\n 指定した粒度でアサーションを有効にします\n -da[:...|:]\n -disableassertions[:...|:]\n 指定した粒度でアサーションを無効にします\n -esa | -enablesystemassertions\n システム・アサーションを有効にします\n -dsa | -disablesystemassertions\n システム・アサーションを無効にします\n -agentlib:[=]\n ネイティブ・エージェント・ライブラリをロードします。例: -agentlib:jdwp\n -agentlib:jdwp=helpも参照してください\n -agentpath:[=]\n フルパス名を使用して、ネイティブ・エージェント・ライブラリをロードします\n -javaagent:[=]\n Javaプログラミング言語エージェントをロードします。java.lang.instrumentを参照してください\n -splash:\n 指定されたイメージを含むスプラッシュ画面を表示します\n HiDPIスケールのイメージが自動的にサポートされて使用されます\n (可能な場合)。スケーリングされないイメージのファイル名(image.extなど)を\n 引数として-splashオプションに必ず渡す必要があります。\n 指定された最も適切なスケーリング済イメージが選択されます\n (自動的)。\n 詳細は、SplashScreen APIのドキュメントを参照してください\n @argumentファイル\n \ +オプションを含む1つ以上の引数ファイル\n --disable-@files\n さらなる引数ファイル拡張を無効にします\n --enable-preview\n クラスをこのリリースのプレビュー機能に依存させることができます\n長いオプションの引数を指定する場合、--=または\n-- を使用できます。\n # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch バックグラウンド・コンパイルを無効にします\n -Xbootclasspath/a:\n ブートストラップ・クラス・パスの最後に追加します\n -Xcheck:jni JNI関数に対する追加のチェックを実行します\n -Xcomp 初回呼出し時にメソッドのコンパイルを強制します\n -Xdebug 何も実行されません。将来のリリースで削除されるため、非推奨になりました。\n -Xdiag 追加の診断メッセージを表示します\n -Xint インタプリタ・モードの実行のみ\n -Xinternalversion\n -versionオプションより詳細なJVMバージョン情報を\n 表示します\n -Xlog: Java Virtual Machine (JVM)統合ロギング・フレームワークでの\n ロギングを構成または有効化します。詳細は、-Xlog:helpを\n 使用してください。\n -Xloggc: タイムスタンプが付いたファイルにGCステータスのログを記録します\n このオプションは非推奨であり、将来のリリースで削除される\n 可能性があります。-Xlog:gc:で置換されています。\n -Xmixed 混合モードの実行(デフォルト)\n -Xmn 若い世代(ナーサリ)のヒープの初期サイズおよび最大サイズ\n (バイト単位)を設定します\n -Xms Javaの最小および初期のヒープ・サイズを設定します\n -Xmx Javaの最大ヒープ・サイズを設定します\n -Xnoclassgc クラスのガベージ・コレクションを無効にします\n -Xrs Java/VMによるOSシグナルの使用を削減します(ドキュメントを参照)\n -Xshare:auto 可能であれば共有クラス・データを使用します(デフォルト)\n -Xshare:off 共有クラス・データの使用を試みません\n -Xshare:on 共有クラス・データの使用を必須にし、できなければ失敗します。\n \ @@ -60,6 +61,7 @@ java.launcher.jar.error3={0}にメイン・マニフェスト属性がありま java.launcher.jar.error4={0}内のJavaエージェントのロード中にエラーが発生しました java.launcher.jar.error5=エラー: ファイル{0}を閉じるときに、予期しないエラーが発生しました java.launcher.jar.error.illegal.ena.value=エラー: Enable-Native-Accessマニフェスト属性の値"{0}"が不正です。''ALL-UNNAMED''のみ許可されます +java.launcher.jar.error.illegal.effm.value=エラー: Enable-Final-Field-Mutationマニフェスト属性の値"{0}"が不正です。''ALL-UNNAMED''のみ許可されます java.launcher.init.error=初期化エラー java.launcher.javafx.error1=エラー: JavaFX launchApplicationメソッドに誤ったシグネチャがあり、\nstaticを宣言してvoid型の値を返す必要があります java.launcher.module.error1=モジュール{0}にModuleMainClass属性がありません。-m /を使用してください diff --git a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties index ec466bf3019..b3c0268f953 100644 --- a/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties +++ b/src/java.base/share/classes/sun/launcher/resources/launcher_zh_CN.properties @@ -30,8 +30,9 @@ java.launcher.opt.vmselect =\ {0}\t 选择 "{1}" VM\n java.launcher.opt.hotspot =\ {0}\t 是 "{1}" VM 的同义词 [已过时]\n # Translators please note do not translate the options themselves -java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径>\n -classpath <目录和 zip/jar 文件的类搜索路径>\n --class-path <目录和 zip/jar 文件的类搜索路径>\n 以 "{0}" 分隔的用于搜索类文件的目录、JAR 档案\n 和 ZIP 档案列表。\n -p <模块路径>\n --module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --upgrade-module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块(用于替换运行时映像中的\n 可升级模块)的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --add-modules <模块名称>[,<模块名称>...]\n 除了初始模块之外要解析的根模块。\n <模块名称> 还可以为 ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n 允许模块中的代码访问 Java 运行时之外的代码和数据。\n 也可以是 ALL-UNNAMED,以指示类路径上的代码。\n --illegal-native-access=\n 允许或拒绝模块中没有明确为其启用本机访问的\n 代码访问 Java 运行时之外的代码和数据。\n 为 "deny"、"warn" 或 "allow" 之一。默认值为 "warn"。\n 此选项将在未来发行版中删除。\n --list-modules\n 列出可观察模块并退出\n -d \n --describe-module <模块名称>\n 描述模块并退出\n --dry-run 创建 VM 并加载主类, 但不执行 main 方法。\n 此 --dry-run 选项对于验证诸如\n 模块系统配置这样的命令行选项可能非常有用。\n --validate-modules\n 验证所有模块并退出\n --validate-modules 选项对于查找\n 模块路径中模块的冲突及其他错误可能非常有用。\n -D<名称>=<值>\n 设置系统属性\n -verbose:[class|module|gc|jni]\n 为给定子系统启用详细输出\n -version 将产品版本输出到错误流并退出\n --version \ -将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n 允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n +java.launcher.opt.footer = \ -cp <目录和 zip/jar 文件的类搜索路径>\n -classpath <目录和 zip/jar 文件的类搜索路径>\n --class-path <目录和 zip/jar 文件的类搜索路径>\n 以 "{0}" 分隔的用于搜索类文件的目录、JAR 档案\n 和 ZIP 档案列表。\n -p <模块路径>\n --module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --upgrade-module-path <模块路径>...\n 以 "{0}" 分隔的元素列表,每个元素都是\n 模块或包含模块(用于替换运行时映像中的\n 可升级模块)的目录的文件路径。每个模块都是\n 模块化 JAR 或展开的模块目录。\n --add-modules <模块名称>[,<模块名称>...]\n 除了初始模块之外要解析的根模块。\n <模块名称> 还可以为 ALL-DEFAULT, ALL-SYSTEM,\n ALL-MODULE-PATH.\n --enable-native-access [,...]\n 允许模块中的代码访问 Java 运行时之外的代码和数据。\n 也可以是 ALL-UNNAMED,以指示类路径上的代码。\n --illegal-native-access=\n 允许或拒绝模块中没有明确为其启用本机访问的\n 代码访问 Java 运行时之外的代码和数据。\n 为 "deny"、"warn" 或 "allow" 之一。默认值为 "warn"。\n 此选项将在未来发行版中删除。\n --enable-final-field-mutation [,...]\n 允许指定模块中的代码变更最终实例字段。\n 也可以是 ALL-UNNAMED,以指示类路径上的代码。\n --illegal-final-field-mutation=\n 允许或拒绝模块中的代码在未明确启用最终字段变更时\n 变更最终字段。\n 为 "deny"、"warn"、"debug" 或 "allow" 之一。默认值为 "warn"。\n 此选项将在未来发行版中删除。\n --list-modules\n 列出可观察模块并退出\n -d \n --describe-module <模块名称>\n 描述模块并退出\n --dry-run 创建 VM 并加载主类, 但不执行 main 方法。\n 此 --dry-run \ +选项对于验证诸如\n 模块系统配置这样的命令行选项可能非常有用。\n --validate-modules\n 验证所有模块并退出\n --validate-modules 选项对于查找\n 模块路径中模块的冲突及其他错误可能非常有用。\n -D<名称>=<值>\n 设置系统属性\n -verbose:[class|module|gc|jni]\n 为给定子系统启用详细输出\n -version 将产品版本输出到错误流并退出\n --version 将产品版本输出到输出流并退出\n -showversion 将产品版本输出到错误流并继续\n --show-version\n 将产品版本输出到输出流并继续\n --show-module-resolution\n 在启动过程中显示模块解析输出\n -? -h -help\n 将此帮助消息输出到错误流\n --help 将此帮助消息输出到输出流\n -X 将额外选项的帮助输出到错误流\n --help-extra 将额外选项的帮助输出到输出流\n -ea[:<程序包名称>...|:<类名>]\n -enableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度启用断言\n -da[:<程序包名称>...|:<类名>]\n -disableassertions[:<程序包名称>...|:<类名>]\n 按指定的粒度禁用断言\n -esa | -enablesystemassertions\n 启用系统断言\n -dsa | -disablesystemassertions\n 禁用系统断言\n -agentlib:<库名>[=<选项>]\n 加载本机代理库 <库名>, 例如 -agentlib:jdwp\n 另请参阅 -agentlib:jdwp=help\n -agentpath:<路径名>[=<选项>]\n 按完整路径名加载本机代理库\n -javaagent:[=<选项>]\n 加载 Java 编程语言代理, 请参阅 java.lang.instrument\n -splash:<图像路径>\n 使用指定的图像显示启动屏幕\n 自动支持和使用 HiDPI 缩放图像\n (如果可用)。应始终将未缩放的图像文件名 (例如, image.ext)\n 作为参数传递给 -splash 选项。\n 将自动选取提供的最合适的缩放\n 图像。\n 有关详细信息, 请参阅 SplashScreen API 文档\n @argument 文件\n 一个或多个包含选项的参数文件\n --disable-@files\n 阻止进一步扩展参数文件\n --enable-preview\n \ +允许类依赖于此发行版的预览功能\n要为长选项指定参数, 可以使用 --<名称>=<值> 或\n--<名称> <值>。\n # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch 禁用后台编译\n -Xbootclasspath/a:<以 {0} 分隔的目录和 zip/jar 文件>\n 附加在引导类路径末尾\n -Xcheck:jni 对 JNI 函数执行其他检查\n -Xcomp 强制在首次调用时编译方法\n -Xdebug 不执行任何操作;已过时,将在未来发行版中删除。\n -Xdiag 显示附加诊断消息\n -Xint 仅解释模式执行\n -Xinternalversion\n 显示比 -version 选项更详细的\n JVM 版本信息\n -Xlog: 配置或启用采用 Java 虚拟\n 机 (Java Virtual Machine, JVM) 统一记录框架进行事件记录。使用 -Xlog:help\n 可了解详细信息。\n -Xloggc: 将 GC 状态记录在文件中(带时间戳)。\n 此选项已过时,可能会在\n 将来的发行版中删除。它将替换为 -Xlog:gc:。\n -Xmixed 混合模式执行(默认值)\n -Xmn 为年轻代(新生代)设置初始和最大堆大小\n (以字节为单位)\n -Xms 设置最小和初始 Java 堆大小\n -Xmx 设置最大 Java 堆大小\n -Xnoclassgc 禁用类垃圾收集\n -Xrs 减少 Java/VM 对操作系统信号的使用(请参见文档)\n -Xshare:auto 在可能的情况下使用共享类数据(默认值)\n -Xshare:off 不尝试使用共享类数据\n -Xshare:on 要求使用共享类数据,否则将失败。\n 这是一个测试选项,可能导致间歇性\n 故障。不应在生产环境中使用它。\n -XshowSettings 显示所有设置并继续\n -XshowSettings:all\n 详细显示所有设置并继续\n -XshowSettings:locale\n 显示所有与区域设置相关的设置并继续\n -XshowSettings:properties\n 显示所有属性设置并继续\n -XshowSettings:vm\n 显示所有与 vm 相关的设置并继续\n -XshowSettings:security\n 显示所有安全设置并继续\n -XshowSettings:security:all\n 显示所有安全设置并继续\n -XshowSettings:security:properties\n 显示安全属性并继续\n -XshowSettings:security:providers\n 显示静态安全提供方设置并继续\n -XshowSettings:security:tls\n 显示与 TLS \ @@ -49,7 +50,7 @@ java.launcher.cls.error2=错误: 在类 {0} 中找不到 main 方法, 请将 mai java.launcher.cls.error3=错误: 缺少 JavaFX 运行时组件, 需要使用该组件来运行此应用程序 java.launcher.cls.error4=错误: 加载主类 {0} 时出现 LinkageError\n\t{1} java.launcher.cls.error5=错误: 无法初始化主类 {0}\n原因: {1}: {2} -java.launcher.cls.error6=错误:在类 {0} 中未找到非专用零参数构造器\n请从现有构造器中删除专用,或者定义为:\n public {0}() +java.launcher.cls.error6=错误:在类 {0} 中未找到非专用零参数构造器\n请从现有构造器中删除 private,或者定义为:\n public {0}() java.launcher.cls.error7=错误:无法调用非静态内部类 {0} 构造器\n请将内部类设为静态或将内部类移出到单独的源文件 java.launcher.cls.error8=错误:无法实例化抽象类 {0}\n请使用具体类 java.launcher.jar.error1=错误: 尝试打开文件{0}时出现意外错误 @@ -58,6 +59,7 @@ java.launcher.jar.error3={0}中没有主清单属性 java.launcher.jar.error4=在 {0} 中加载 Java 代理时出错 java.launcher.jar.error5=错误:尝试关闭文件 {0} 时出现意外错误 java.launcher.jar.error.illegal.ena.value=错误:Enable-Native-Access 清单属性的值 "{0}" 非法。仅允许使用 ''ALL-UNNAMED'' +java.launcher.jar.error.illegal.effm.value=错误:Enable-Final-Field-Mutation 清单属性的值 "{0}" 非法。仅允许使用 ''ALL-UNNAMED'' java.launcher.init.error=初始化错误 java.launcher.javafx.error1=错误: JavaFX launchApplication 方法具有错误的签名, 必须\n将方法声明为静态方法并返回空类型的值 java.launcher.module.error1=模块 {0} 不具有 ModuleMainClass 属性,请使用 -m <模块>/<主类> diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties index 1c7a9cd17cf..a452dd34e9d 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_de.properties @@ -313,7 +313,7 @@ Unable.to.parse.denyAfter.string.in.exception.message=denyAfter-Datumszeichenfol whose.sigalg.weak=%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko. whose.key.disabled=%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert. whose.key.weak=%1$s verwendet %2$s. Das gilt als Sicherheitsrisiko. Dieser Schlüssel wird in einem zukünftigen Update deaktiviert. -jks.storetype.warning=Der %1$s-Keystore verwendet ein proprietäres Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" ist. +jks.storetype.warning=%1$s verwendet veraltete kryptografische Algorithmen und wird in einer zukünftigen Version entfernt. Migrieren Sie zu PKCS12 mit:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 migrate.keystore.warning="%1$s" zu %4$s migriert. Der %2$s-Keystore wurde als "%3$s" gesichert. backup.keystore.warning=Der ursprüngliche Keystore "%1$s" wird als "%3$s" gesichert... importing.keystore.status=Keystore %1$s wird in %2$s importiert... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties index 63ba4f220dd..a3d7771eb38 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_ja.properties @@ -313,7 +313,7 @@ Unable.to.parse.denyAfter.string.in.exception.message=例外メッセージのde whose.sigalg.weak=%1$sは%2$s署名アルゴリズムを使用しており、これはセキュリティ・リスクとみなされます。 whose.key.disabled=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされ、無効化されています。 whose.key.weak=%1$sは%2$sを使用しており、これはセキュリティ・リスクとみなされます。これは将来の更新で無効化されます。 -jks.storetype.warning=%1$sキーストアは独自の形式を使用しています。"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12"を使用する業界標準の形式であるPKCS12に移行することをお薦めします。 +jks.storetype.warning=%1$sは古い暗号化アルゴリズムを使用しているため、将来のリリースで削除されます。次を使用してPKCS12に移行します:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 migrate.keystore.warning="%1$s"が%4$sに移行されました。%2$sキーストアは"%3$s"としてバックアップされます。 backup.keystore.warning=元のキーストア"%1$s"は"%3$s"としてバックアップされます... importing.keystore.status=キーストア%1$sを%2$sにインポートしています... diff --git a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties index 1f96aa12c57..435e74e468f 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/tools/keytool/resources/keytool_zh_CN.properties @@ -313,7 +313,7 @@ Unable.to.parse.denyAfter.string.in.exception.message=无法解析异常错误 whose.sigalg.weak=%1$s 使用的 %2$s 签名算法存在安全风险。 whose.key.disabled=%1$s 使用的 %2$s 被视为存在安全风险而且被禁用。 whose.key.weak=%1$s 使用的 %2$s 被视为存在安全风险。它将在未来的更新中被禁用。 -jks.storetype.warning=%1$s 密钥库使用专用格式。建议使用 "keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12" 迁移到行业标准格式 PKCS12。 +jks.storetype.warning=%1$s 使用的加密算法已过时,将在未来发行版中删除。请使用以下命令迁移到 PKCS12:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 migrate.keystore.warning=已将 "%1$s" 迁移到 %4$s。将 %2$s 密钥库作为 "%3$s" 进行了备份。 backup.keystore.warning=已将原始密钥库 "%1$s" 备份为 "%3$s"... importing.keystore.status=正在将密钥库 %1$s 导入到 %2$s... diff --git a/src/java.base/share/classes/sun/security/util/resources/security_de.properties b/src/java.base/share/classes/sun/security/util/resources/security_de.properties index a431268831b..63c7fdca472 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_de.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_de.properties @@ -43,7 +43,7 @@ provided.null.OID.map=Null-OID-Zuordnung angegeben NEWLINE=\n invalid.null.action.provided=Ungültige Nullaktion angegeben invalid.null.Class.provided=Ungültige Nullklasse angegeben -Subject.=Subjekt:\n +Subject.=Subject:\n .Principal.=\tPrincipal:\u0020 .Public.Credential.=\tÖffentliche Zugangsdaten:\u0020 .Private.Credential.=\tPrivate Zugangsdaten:\u0020 @@ -74,3 +74,6 @@ line.number.expected.expect.found.actual.=Zeile {0}: [{1}] erwartet, [{2}] gefun # sun.security.pkcs11.SunPKCS11 PKCS11.Token.providerName.Password.=Kennwort für PKCS11-Token [{0}]:\u0020 + +# sun.security.util.Password +warning.input.may.be.visible.on.screen=[Warnung: Eingabe ist möglicherweise auf dem Bildschirm sichtbar]\u0020 diff --git a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties index ff13b37cf3b..00d22e054a5 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_ja.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_ja.properties @@ -74,3 +74,6 @@ line.number.expected.expect.found.actual.=行{0}: [{1}]ではなく[{2}]が検 # sun.security.pkcs11.SunPKCS11 PKCS11.Token.providerName.Password.=PKCS11トークン[{0}]パスワード:\u0020 + +# sun.security.util.Password +warning.input.may.be.visible.on.screen=[警告: 入力が画面に表示される場合があります]\u0020 diff --git a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties index 6a4ec11de77..a322cb7b1e8 100644 --- a/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties +++ b/src/java.base/share/classes/sun/security/util/resources/security_zh_CN.properties @@ -74,3 +74,6 @@ line.number.expected.expect.found.actual.=行号 {0}: 应为 [{1}], 找到 [{2}] # sun.security.pkcs11.SunPKCS11 PKCS11.Token.providerName.Password.=PKCS11 标记 [{0}] 密码:\u0020 + +# sun.security.util.Password +warning.input.may.be.visible.on.screen=[警告:输入可能显示在屏幕上]\u0020 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties index 0787c839cb4..b8fa413adba 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_de.properties @@ -292,10 +292,10 @@ compiler.err.annotation.decl.not.allowed.here=Annotationsschnittstellendeklarati compiler.err.cant.inherit.from.final=Erben aus finalem {0}-Element nicht möglich # 0: symbol or name -compiler.err.cant.ref.before.ctor.called={0} kann nicht referenziert werden, bevor der Supertypkonstruktor aufgerufen wurde +compiler.err.cant.ref.before.ctor.called=Referenz zu {0} darf nur nach einem expliziten Konstruktoraufruf angezeigt werden # 0: symbol or name -compiler.err.cant.assign.initialized.before.ctor.called=Initialisiertes Feld "{0}" kann nicht zugewiesen werden, bevor der Supertypkonstruktor aufgerufen wurde +compiler.err.cant.assign.initialized.before.ctor.called=Zuweisung zu initialisiertem Feld "{0}" darf nur nach einem expliziten Konstruktoraufruf angezeigt werden compiler.err.cant.select.static.class.from.param.type=Statische Klasse kann nicht aus einem parametrisierten Typ ausgewählt werden @@ -649,11 +649,14 @@ compiler.err.limit.string.overflow=UTF8-Darstellung für Zeichenfolge "{0}..." i compiler.err.malformed.fp.lit=Nicht wohlgeformtes Gleitkommaliteral -compiler.err.method.does.not.override.superclass=Methode überschreibt oder implementiert keine Methode aus einem Supertyp +# 0: symbol, 1: symbol +compiler.err.method.does.not.override.superclass={0} in {1} überschreibt oder implementiert keine Methode aus einem Supertyp -compiler.err.static.methods.cannot.be.annotated.with.override=Statische Methoden können nicht mit @Override-Annotation versehen werden +# 0: symbol, 1: symbol +compiler.err.static.methods.cannot.be.annotated.with.override=Statische Methode {0} in {1} kann nicht mit @Override-Annotation versehen werden -compiler.err.missing.meth.body.or.decl.abstract=Methodenbody fehlt oder als abstrakt deklarieren +# 0: symbol, 1: symbol +compiler.err.missing.meth.body.or.decl.abstract=In Methode {0} in {1} fehlt ein Methodenbody, oder sie muss als abstrakt deklariert werden compiler.err.missing.ret.stmt=Rückgabeanweisung fehlt @@ -1139,6 +1142,7 @@ compiler.err.multi-module.outdir.cannot.be.exploded.module=Im Modus für mehrere # 0: path # lint: path +# flags: default-enabled compiler.warn.outdir.is.in.exploded.module=Das Ausgabeverzeichnis befindet sich in einem entpackten Modul: {0} # 0: file object @@ -1198,6 +1202,7 @@ compiler.warn.output.file.clash=Ausgabedatei mehrmals geschrieben: {0} ## The following string will appear before all messages keyed as: ## "compiler.note". +# flags: mandatory compiler.note.compressed.diags=Einige Meldungen wurden vereinfacht. Wiederholen Sie die Kompilierung mit -Xdiags:verbose, um die vollständige Ausgabe abzurufen # 0: boolean, 1: symbol @@ -1378,17 +1383,17 @@ compiler.warn.incubating.modules=Inkubatormodul(e) verwendet: {0} # 0: symbol, 1: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated={0} in {1} ist veraltet # 0: symbol, 1: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal={0} in {1} ist veraltet und wurde zum Entfernen markiert # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview={0} ist eine Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol @@ -1396,7 +1401,7 @@ compiler.err.is.preview={0} ist eine Vorschau-API, die standardmäßig deaktivie # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview.reflective={0} ist eine reflektive Vorschau-API, die in einem zukünftigen Release entfernt werden kann. # 0: symbol, 1: symbol @@ -1405,12 +1410,12 @@ compiler.warn.restricted.method={0}.{1} ist eine eingeschränkte Methode.\n(Eing # 0: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.module=Modul {0} ist veraltet # 0: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal.module=Modul {0} ist veraltet und wurde zum Entfernen markiert # 0: symbol @@ -1583,10 +1588,12 @@ compiler.warn.static.not.qualified.by.type2={0} (statisch) darf nicht als Member # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.bootclasspath=Bootstrap Classpath ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.system.modules.path=Systemmodulpfad ist nicht zusammen mit -source {0} festgelegt\n{1} # 0: string @@ -1603,10 +1610,12 @@ compiler.misc.source.no.system.modules.path.with.target=Wenn Sie den Speicherort # 0: string # lint: options +# flags: default-enabled compiler.warn.option.obsolete.source=Quellwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: target # lint: options +# flags: default-enabled compiler.warn.option.obsolete.target=Zielwert {0} ist veraltet und wird in einem zukünftigen Release entfernt # 0: string, 1: string @@ -1616,12 +1625,17 @@ compiler.err.option.removed.source=Quelloption {0} wird nicht mehr unterstützt. compiler.err.option.removed.target=Zieloption {0} wird nicht mehr unterstützt. Verwenden Sie {1} oder höher. # lint: options +# flags: default-enabled compiler.warn.option.obsolete.suppression=Verwenden Sie -Xlint:-options, um Warnungen zu veralteten Optionen zu unterdrücken. # 0: name, 1: number, 2: number, 3: number, 4: number # lint: classfile compiler.warn.future.attr={0}-Attribut, das in Klassendateien der Version {1}.{2} eingeführt wurde, wird in Klassendateien der Version {3}.{4} ignoriert +# 0: symbol, 1: file object +# lint: classfile +compiler.warn.inconsistent.inner.classes=InnerClasses-Attribut für {0} in {1} inkonsistent mit Quellcode\n({1} muss möglicherweise mit {0} neu kompiliert werden) + # lint: requires-automatic compiler.warn.requires.automatic=Erfordert Direktive für ein automatisches Modul @@ -1706,17 +1720,21 @@ compiler.warn.try.resource.not.referenced=Automatisch schließbare Ressource {0} # lint: try compiler.warn.try.resource.throws.interrupted.exc=Automatisch schließbare Ressource {0} umfasst die Mitgliedsmethode close(), die InterruptedException auslösen könnte +# 0: type +# lint: try +compiler.warn.try.resource.can.throw.interrupted.exc=close()-Methode kann InterruptedException in automatisch schließbarer Klasse {0} auslösen + # lint: unchecked compiler.warn.unchecked.assign=Nicht geprüfte Zuweisung: {0} zu {1} # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.assign.to.var=Nicht geprüfte Zuweisung zu Variable {0} als Mitglied des Raw-Typs {1} # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.call.mbr.of.raw.type=Nicht geprüfter Aufruf von {0} als Mitglied des Raw-Typs {1} # lint: unchecked @@ -1724,17 +1742,17 @@ compiler.warn.unchecked.cast.to.type=Nicht geprüftes Casting zu Typ {0} # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.meth.invocation.applied=Nicht geprüfter Methodenaufruf: {0} {1} in {4} {5} wird auf die angegebenen Typen angewendet\nErforderlich: {2}\nErmittelt: {3} # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.generic.array.creation=Nicht geprüfte Erstellung eines generischen Arrays für varargs-Parameter des Typs {0} # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.varargs.non.reifiable.type=Möglich Heap-Beschädigung aus parametrisiertem vararg-Typ {0} # 0: symbol @@ -1772,6 +1790,10 @@ compiler.err.no.zipfs.for.archive=Kein Dateisystemprovider zur Verarbeitung dies # lint: divzero compiler.warn.div.zero=Division durch Null +# 0: type, 1: long, 2: number +# lint: lossy-conversions +compiler.warn.bit.shift.out.of.range=Das Verschieben von {0} um {1} Bit entspricht einer Verschiebung um {2} Bit + # lint: empty compiler.warn.empty.if=Leere Anweisung nach "if" @@ -2023,7 +2045,7 @@ compiler.misc.prob.found.req=Inkompatible Typen: {0} # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} # 0: type, 1: type @@ -2297,12 +2319,12 @@ compiler.err.override.incompatible.ret={0}\nRückgabetyp {1} ist nicht mit {2} k # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.ret={0}\nRückgabetyp erfordert eine nicht geprüfte Konvertierung von {1} in {2} # 0: message segment, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.thrown={0}\nAußer Kraft gesetzte Methode löst nicht {1} aus # 0: symbol @@ -2377,16 +2399,17 @@ compiler.err.preview.feature.disabled.classfile=Klassendatei für {0} verwendet # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use={0} ist ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use.plural={0} sind ein Vorschaufeature, das in einem zukünftigen Release entfernt werden kann. # 0: file object (classfile), 1: string (expected version) # lint: preview +# flags: mandatory compiler.warn.preview.feature.use.classfile=Klassendatei für {0} verwendet Vorschaufeatures von Java SE {1}. compiler.misc.feature.modules=Module @@ -2783,6 +2806,7 @@ compiler.err.bad.name.for.option=Ungültiger Name im Wert für {0}-Option: "{1}" # 0: option name, 1: symbol # lint: options +# flags: default-enabled compiler.warn.module.for.option.not.found=Modulname in {0}-Option nicht gefunden: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH kann nur beim Kompilieren des unbenannten Moduls oder beim Kompilieren im Kontext eines automatischen Moduls verwendet werden @@ -2794,6 +2818,7 @@ compiler.err.add.exports.with.release=Export eines Packages aus Systemmodul {0} compiler.err.add.reads.with.release=Hinzufügen von Lese-Edges für Systemmodul {0} ist mit --release nicht zulässig # lint: options +# flags: default-enabled compiler.warn.addopens.ignored=--add-opens hat zur Kompilierungszeit keine Auswirkungen compiler.misc.locn.module_source_path=Modulquellpfad @@ -3060,7 +3085,7 @@ compiler.err.incorrect.number.of.nested.patterns=Falsche Anzahl verschachtelter # 0: kind name, 1: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zukünftigen Release entfernt werden kann. # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties index 291d8aeeec5..89bdc893a43 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_ja.properties @@ -292,10 +292,10 @@ compiler.err.annotation.decl.not.allowed.here=ここでは注釈インタフェ compiler.err.cant.inherit.from.final=final {0}からは継承できません # 0: symbol or name -compiler.err.cant.ref.before.ctor.called=スーパータイプのコンストラクタの呼出し前は{0}を参照できません +compiler.err.cant.ref.before.ctor.called={0}への参照は、明示的なコンストラクタの呼出しの後にのみ表示されます # 0: symbol or name -compiler.err.cant.assign.initialized.before.ctor.called=スーパータイプのコンストラクタの呼出し前は、初期化されたフィールド''{0}''を割り当てられません +compiler.err.cant.assign.initialized.before.ctor.called=初期化されたフィールド''{0}''への割当ては、明示的なコンストラクタの呼出しの後にのみ表示されます compiler.err.cant.select.static.class.from.param.type=パラメータにされた型からstaticクラスを選択することはできません @@ -649,11 +649,14 @@ compiler.err.limit.string.overflow=文字列"{0}..."のUTF8表現が、定数プ compiler.err.malformed.fp.lit=浮動小数点リテラルが不正です -compiler.err.method.does.not.override.superclass=メソッドはスーパータイプのメソッドをオーバーライドまたは実装しません +# 0: symbol, 1: symbol +compiler.err.method.does.not.override.superclass={1}の{0}はスーパータイプのメソッドをオーバーライドまたは実装しません -compiler.err.static.methods.cannot.be.annotated.with.override=staticメソッドは@Overrideで注釈付けすることはできません +# 0: symbol, 1: symbol +compiler.err.static.methods.cannot.be.annotated.with.override={1}のstaticメソッド{0}は@Overrideで注釈付けすることはできません -compiler.err.missing.meth.body.or.decl.abstract=メソッド本体がないか、abstractとして宣言されています +# 0: symbol, 1: symbol +compiler.err.missing.meth.body.or.decl.abstract={1}のメソッド{0}にメソッド本体がないか、abstractを宣言する必要があります compiler.err.missing.ret.stmt=return文が指定されていません @@ -1139,6 +1142,7 @@ compiler.err.multi-module.outdir.cannot.be.exploded.module=複数モジュール # 0: path # lint: path +# flags: default-enabled compiler.warn.outdir.is.in.exploded.module=出力ディレクトリは展開したモジュール内です: {0} # 0: file object @@ -1198,6 +1202,7 @@ compiler.warn.output.file.clash=出力ファイルへの書込みが複数回あ ## The following string will appear before all messages keyed as: ## "compiler.note". +# flags: mandatory compiler.note.compressed.diags=一部のメッセージは簡略化されています。-Xdiags:verboseで再コンパイルして完全な出力を取得してください # 0: boolean, 1: symbol @@ -1378,17 +1383,17 @@ compiler.warn.incubating.modules=実験的なモジュールを使用してい # 0: symbol, 1: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated={1}の{0}は推奨されません # 0: symbol, 1: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal={1}の{0}は推奨されておらず、削除用にマークされています # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview={0}はプレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol @@ -1396,7 +1401,7 @@ compiler.err.is.preview={0}はプレビューAPIであり、デフォルトで # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview.reflective={0}はリフレクティブ・プレビューAPIであり、今後のリリースで削除される可能性があります。 # 0: symbol, 1: symbol @@ -1405,12 +1410,12 @@ compiler.warn.restricted.method={0}.{1}は制限されたメソッドです。\n # 0: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.module=モジュール{0}は推奨されません # 0: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal.module=モジュール{0}は推奨されておらず、削除用にマークされています # 0: symbol @@ -1583,10 +1588,12 @@ compiler.warn.static.not.qualified.by.type2=static {0}を匿名クラスのメ # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.bootclasspath=ブートストラップ・クラス・パスが-source {0}と一緒に設定されていません\n{1} # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.system.modules.path=システム・モジュールの場所が-source {0}と一緒に設定されていません\n{1} # 0: string @@ -1603,10 +1610,12 @@ compiler.misc.source.no.system.modules.path.with.target=システム・モジュ # 0: string # lint: options +# flags: default-enabled compiler.warn.option.obsolete.source=ソース値{0}は廃止されていて、今後のリリースで削除される予定です # 0: target # lint: options +# flags: default-enabled compiler.warn.option.obsolete.target=ターゲット値{0}は廃止されていて、今後のリリースで削除される予定です # 0: string, 1: string @@ -1616,12 +1625,17 @@ compiler.err.option.removed.source=ソース・オプション{0}は現在サポ compiler.err.option.removed.target=ターゲット・オプション{0}は現在サポートされていません。{1}以降を使用してください。 # lint: options +# flags: default-enabled compiler.warn.option.obsolete.suppression=廃止されたオプションについての警告を表示しないようにするには、-Xlint:オプションを使用します。 # 0: name, 1: number, 2: number, 3: number, 4: number # lint: classfile compiler.warn.future.attr=バージョン{1}.{2}のクラス・ファイルで導入された{0}属性は、バージョン{3}.{4}のクラス・ファイルでは無視されます +# 0: symbol, 1: file object +# lint: classfile +compiler.warn.inconsistent.inner.classes={1}の{0}のInnerClasses属性はソース・コードと一貫性がありません\n({1}は{0}で再コンパイルする必要がある場合があります) + # lint: requires-automatic compiler.warn.requires.automatic=自動モジュールにはディレクティブが必要です @@ -1706,17 +1720,21 @@ compiler.warn.try.resource.not.referenced=自動クローズ可能なリソー # lint: try compiler.warn.try.resource.throws.interrupted.exc=自動クローズ可能なリソース{0}に、InterruptedExceptionをスローする可能性があるメンバー・メソッドclose()があります +# 0: type +# lint: try +compiler.warn.try.resource.can.throw.interrupted.exc=close()メソッドは、自動クローズ可能なクラス{0}でInterruptedExceptionをスローできます + # lint: unchecked compiler.warn.unchecked.assign={0}から{1}への無検査代入です # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.assign.to.var=raw型{1}のメンバーとして変数{0}への無検査代入です # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.call.mbr.of.raw.type=raw型{1}のメンバーとしての{0}への無検査呼出しです # lint: unchecked @@ -1724,17 +1742,17 @@ compiler.warn.unchecked.cast.to.type=型{0}への無検査キャストです # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.meth.invocation.applied=無検査メソッド呼出し: {4} {5}の{0} {1}は指定された型に適用されます\n期待値: {2}\n検出値: {3} # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.generic.array.creation=型{0}の可変引数パラメータに対する総称型配列の無検査作成です # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.varargs.non.reifiable.type=パラメータ化された可変引数型{0}からのヒープ汚染の可能性があります # 0: symbol @@ -1772,6 +1790,10 @@ compiler.err.no.zipfs.for.archive=このファイルの処理に使用できる # lint: divzero compiler.warn.div.zero=ゼロで除算 +# 0: type, 1: long, 2: number +# lint: lossy-conversions +compiler.warn.bit.shift.out.of.range={0}を{1}ビットでシフトすることは、{2}ビットでシフトすることと同等です + # lint: empty compiler.warn.empty.if=if以降が空の文です @@ -2023,7 +2045,7 @@ compiler.misc.prob.found.req=不適合な型: {0} # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.prob.found.req={0}\n期待値: {2}\n検出値: {1} # 0: type, 1: type @@ -2297,12 +2319,12 @@ compiler.err.override.incompatible.ret={0}\n戻り値の型{1}は{2}と互換性 # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.ret={0}\n戻り値の型は{1}から{2}への無検査変換が必要です # 0: message segment, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.thrown={0}\nオーバーライドされたメソッドは{1}をスローしません # 0: symbol @@ -2377,16 +2399,17 @@ compiler.err.preview.feature.disabled.classfile={0}のクラス・ファイル # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use.plural={0}はプレビュー機能であり、今後のリリースで削除される可能性があります。 # 0: file object (classfile), 1: string (expected version) # lint: preview +# flags: mandatory compiler.warn.preview.feature.use.classfile={0}のクラス・ファイルはJava SE {1}のプレビュー機能を使用します。 compiler.misc.feature.modules=モジュール @@ -2783,6 +2806,7 @@ compiler.err.bad.name.for.option={0}オプションの値に含まれる名前 # 0: option name, 1: symbol # lint: options +# flags: default-enabled compiler.warn.module.for.option.not.found={0}オプション内にモジュール名が見つかりません: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATHは、名前のないモジュールのコンパイル時または自動モジュールのコンテキストでのコンパイル時のみ使用できます @@ -2794,6 +2818,7 @@ compiler.err.add.exports.with.release=システム・モジュール{0}からの compiler.err.add.reads.with.release=システム・モジュール{0}の読取りエッジの追加は--releaseを指定して実行できません # lint: options +# flags: default-enabled compiler.warn.addopens.ignored=--add-opensは、コンパイル時には無効です compiler.misc.locn.module_source_path=モジュール・ソース・パス @@ -3060,7 +3085,7 @@ compiler.err.incorrect.number.of.nested.patterns=ネスト・パターンの数 # 0: kind name, 1: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.declared.using.preview={0} {1}はプレビュー機能を使用して宣言されており、今後のリリースで削除される可能性があります。 # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties index 268ce26bd49..861f371632d 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler_zh_CN.properties @@ -292,10 +292,10 @@ compiler.err.annotation.decl.not.allowed.here=此处不允许批注接口声明 compiler.err.cant.inherit.from.final=无法从最终{0}进行继承 # 0: symbol or name -compiler.err.cant.ref.before.ctor.called=无法在调用超类型构造器之前引用{0} +compiler.err.cant.ref.before.ctor.called=对 {0} 的引用只能在显式调用构造器后显示 # 0: symbol or name -compiler.err.cant.assign.initialized.before.ctor.called=无法在调用超类型构造器之前分配初始化字段 ''{0}'' +compiler.err.cant.assign.initialized.before.ctor.called=对初始化字段 ''{0}'' 的分配只能在显式调用构造器后显示 compiler.err.cant.select.static.class.from.param.type=无法从参数化的类型中选择静态类 @@ -649,11 +649,14 @@ compiler.err.limit.string.overflow=对于常量池来说, 字符串 "{0}..." 的 compiler.err.malformed.fp.lit=浮点文字的格式错误 -compiler.err.method.does.not.override.superclass=方法不会覆盖或实现超类型的方法 +# 0: symbol, 1: symbol +compiler.err.method.does.not.override.superclass={1} 中的 {0} 不会覆盖或实现超类型中的方法 -compiler.err.static.methods.cannot.be.annotated.with.override=不能使用 @Override 对静态方法进行批注 +# 0: symbol, 1: symbol +compiler.err.static.methods.cannot.be.annotated.with.override=不能使用 @Override 对 {1} 中的静态方法 {0} 进行批注 -compiler.err.missing.meth.body.or.decl.abstract=缺少方法主体, 或声明抽象 +# 0: symbol, 1: symbol +compiler.err.missing.meth.body.or.decl.abstract={1} 中的方法 {0} 缺少方法主体,或者应声明为抽象方法 compiler.err.missing.ret.stmt=缺少返回语句 @@ -1139,6 +1142,7 @@ compiler.err.multi-module.outdir.cannot.be.exploded.module=在多模块模式下 # 0: path # lint: path +# flags: default-enabled compiler.warn.outdir.is.in.exploded.module=输出目录位于展开的模块中: {0} # 0: file object @@ -1198,6 +1202,7 @@ compiler.warn.output.file.clash=多次写入输出文件:{0} ## The following string will appear before all messages keyed as: ## "compiler.note". +# flags: mandatory compiler.note.compressed.diags=某些消息已经过简化; 请使用 -Xdiags:verbose 重新编译以获得完整输出 # 0: boolean, 1: symbol @@ -1378,17 +1383,17 @@ compiler.warn.incubating.modules=使用 incubating 模块: {0} # 0: symbol, 1: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated={1}中的{0}已过时 # 0: symbol, 1: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal={1} 中的 {0} 已过时, 且标记为待删除 # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview={0} 是预览 API,可能会在未来发行版中删除。 # 0: symbol @@ -1396,7 +1401,7 @@ compiler.err.is.preview={0} 是预览 API,默认情况下处于禁用状态。 # 0: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.is.preview.reflective={0} 是反射预览 API,可能会在未来发行版中删除。 # 0: symbol, 1: symbol @@ -1405,12 +1410,12 @@ compiler.warn.restricted.method={0}.{1} 是受限制的方法。\n(受限制 # 0: symbol # lint: deprecation -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.module=模块 {0} 已过时 # 0: symbol # lint: removal -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.has.been.deprecated.for.removal.module=模块 {0} 已过时, 且标记为待删除 # 0: symbol @@ -1583,10 +1588,12 @@ compiler.warn.static.not.qualified.by.type2=static {0} 不应用作匿名类的 # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.bootclasspath=未与 -source {0} 一起设置引导类路径\n{1} # 0: string, 1: fragment # lint: options +# flags: default-enabled compiler.warn.source.no.system.modules.path=未与 -source {0} 一起设置系统模块的位置\n{1} # 0: string @@ -1603,10 +1610,12 @@ compiler.misc.source.no.system.modules.path.with.target=不设置系统模块的 # 0: string # lint: options +# flags: default-enabled compiler.warn.option.obsolete.source=源值 {0} 已过时,将在未来发行版中删除 # 0: target # lint: options +# flags: default-enabled compiler.warn.option.obsolete.target=目标值 {0} 已过时,将在未来发行版中删除 # 0: string, 1: string @@ -1616,12 +1625,17 @@ compiler.err.option.removed.source=不再支持源选项 {0}。请使用 {1} 或 compiler.err.option.removed.target=不再支持目标选项 {0}。请使用 {1} 或更高版本。 # lint: options +# flags: default-enabled compiler.warn.option.obsolete.suppression=要隐藏有关已过时选项的警告, 请使用 -Xlint:-options。 # 0: name, 1: number, 2: number, 3: number, 4: number # lint: classfile compiler.warn.future.attr={1}.{2} 版类文件中引入的 {0} 属性在 {3}.{4} 版类文件中被忽略 +# 0: symbol, 1: file object +# lint: classfile +compiler.warn.inconsistent.inner.classes={1} 中 {0} 的 InnerClasses 属性与源代码不一致\n(可能需要使用 {0} 重新编译 {1}) + # lint: requires-automatic compiler.warn.requires.automatic=需要自动模块的指令 @@ -1706,17 +1720,21 @@ compiler.warn.try.resource.not.referenced=不能在相应的 try 语句的正文 # lint: try compiler.warn.try.resource.throws.interrupted.exc=可自动关闭的资源{0}包含的成员方法 close() 可能抛出 InterruptedException +# 0: type +# lint: try +compiler.warn.try.resource.can.throw.interrupted.exc=在可自动关闭的类 {0} 中,close() 方法可能抛出 InterruptedException + # lint: unchecked compiler.warn.unchecked.assign=未经检查的分配: 将{0}分配给{1} # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.assign.to.var=对作为原始类型{1}的成员的变量{0}的分配未经过检查 # 0: symbol, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.call.mbr.of.raw.type=对作为原始类型{1}的成员的{0}的调用未经过检查 # lint: unchecked @@ -1724,17 +1742,17 @@ compiler.warn.unchecked.cast.to.type=向类型{0}的转换未经过检查 # 0: kind name, 1: name, 2: object, 3: object, 4: kind name, 5: symbol # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.meth.invocation.applied=方法调用未经过检查: 将{4} {5}中的{0} {1}应用到给定的类型\n需要: {2}\n找到: {3} # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.generic.array.creation=对于类型为{0}的 varargs 参数, 泛型数组创建未经过检查 # 0: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.unchecked.varargs.non.reifiable.type=参数化 vararg 类型{0}的堆可能已受污染 # 0: symbol @@ -1772,6 +1790,10 @@ compiler.err.no.zipfs.for.archive=没有任何文件系统提供方可处理此 # lint: divzero compiler.warn.div.zero=除数为零 +# 0: type, 1: long, 2: number +# lint: lossy-conversions +compiler.warn.bit.shift.out.of.range=按 {1} 位移动 {0} 相当于按 {2} 位移动 + # lint: empty compiler.warn.empty.if=if 之后没有语句 @@ -2023,7 +2045,7 @@ compiler.misc.prob.found.req=不兼容的类型: {0} # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.prob.found.req={0}\n需要: {2}\n找到: {1} # 0: type, 1: type @@ -2297,12 +2319,12 @@ compiler.err.override.incompatible.ret={0}\n返回类型{1}与{2}不兼容 # 0: message segment, 1: type, 2: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.ret={0}\n返回类型需要从{1}到{2}的未经检查的转换 # 0: message segment, 1: type # lint: unchecked -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.override.unchecked.thrown={0}\n被覆盖的方法未抛出{1} # 0: symbol @@ -2377,16 +2399,17 @@ compiler.err.preview.feature.disabled.classfile={0} 的类文件使用 Java SE { # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use={0} 是预览功能,可能会在未来发行版中删除。 # 0: message segment (feature) # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.preview.feature.use.plural={0} 是预览功能,可能会在未来发行版中删除。 # 0: file object (classfile), 1: string (expected version) # lint: preview +# flags: mandatory compiler.warn.preview.feature.use.classfile={0} 的类文件使用 Java SE {1} 的预览功能。 compiler.misc.feature.modules=模块 @@ -2783,6 +2806,7 @@ compiler.err.bad.name.for.option={0} 选项的值中有错误的名称: ''{1}'' # 0: option name, 1: symbol # lint: options +# flags: default-enabled compiler.warn.module.for.option.not.found=找不到 {0} 选项中的模块名称: {1} compiler.err.addmods.all.module.path.invalid=--add-modules ALL-MODULE-PATH 只能在编译未命名模块或在自动模块的上下文中编译时使用 @@ -2794,6 +2818,7 @@ compiler.err.add.exports.with.release=不允许在使用 --release 时从系统 compiler.err.add.reads.with.release=不允许在使用 --release 时为系统模块 {0} 添加读取维边: # lint: options +# flags: default-enabled compiler.warn.addopens.ignored=--add-opens 在编译时没有任何效果 compiler.misc.locn.module_source_path=模块源路径 @@ -3060,7 +3085,7 @@ compiler.err.incorrect.number.of.nested.patterns=嵌套模式数不正确\n需 # 0: kind name, 1: symbol # lint: preview -# flags: aggregate +# flags: aggregate, mandatory, default-enabled compiler.warn.declared.using.preview={0} {1} 是使用预览功能声明的,可能会在未来发行版中删除。 # lint: identity diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties index 1a00fad1dd0..b36ad3d00ac 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_de.properties @@ -60,6 +60,8 @@ javac.opt.target=Generiert Klassendateien, die sich für das angegebene Java SE- javac.opt.release=Kompiliert für das angegebene Java SE-Release.\nUnterstützte Releases: \n {0} javac.opt.source=Liefert Quellkompatibilität mit dem angegebenen Release von Java SE.\nUnterstützte Releases: \n {0} javac.opt.Werror=Kompilierung beenden, wenn Warnungen auftreten +javac.opt.arg.Werror=(,)* +javac.opt.Werror.custom=Geben Sie Lint-Kategorien, für die die Kompilierung durch Warnungen beendet werden soll,\ndurch Komma getrennt an. \nStellen Sie einem Schlüssel "-" voran, um die angegebene Kategorie auszuschließen. Verwenden Sie --help-lint, um die unterstützten Schlüssel anzuzeigen. javac.opt.A=Optionen zur Übergabe an die Annotationsprozessoren javac.opt.implicit=Gibt an, ob Klassendateien für implizit referenzierte Dateien generiert werden javac.opt.pkginfo=Gibt an, wie package-info-Dateien behandelt werden sollen @@ -97,12 +99,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=Dem Bootstrap Classpath voranstellen javac.opt.Xbootclasspath.a=An Bootstrap Classpath anhängen -javac.opt.Xlint=Empfohlene Warnungskategorien aktivieren -javac.opt.Xlint.all=Alle Warnungskategorien aktivieren -javac.opt.Xlint.none=Alle Warnungskategorien deaktivieren +javac.opt.Xlint=Aktivieren Sie empfohlene Lint-Warnungskategorien. In diesem Release werden alle\nverfügbaren Lint-Warnungskategorien empfohlen. +javac.opt.Xlint.all=Alle Lint-Warnungskategorien aktivieren +javac.opt.Xlint.none=Alle Lint-Warnungskategorien deaktivieren #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=Durch Komma getrennte Warnungskategorien, die aktiviert oder deaktiviert werden sollen.\nStellen Sie einem Schlüssel "-" voran, um die angegebene Warnung zu deaktivieren.\nVerwenden Sie "--help-lint", um die unterstützten Schlüssel anzuzeigen. +javac.opt.Xlint.custom=Lint-Warnungskategorien, die aktiviert oder deaktiviert werden sollen, durch Komma getrennt. \nStellen Sie einem Schlüssel "-" voran, um die angegebene Kategorie zu deaktivieren. Verwenden Sie\n''--help-lint'', um unterstützte Schlüssel und die standardmäßig aktivierten\nKategorien anzuzeigen. javac.opt.Xlint.desc.auxiliaryclass=Warnt vor Auxiliary-Klassen, die in einer Quelldatei verborgen sind und aus anderen Dateien heraus verwendet werden. javac.opt.Xlint.desc.cast=Warnt vor unnötigen Umwandlungen mit Cast. @@ -129,7 +131,7 @@ javac.opt.Xlint.desc.finally=Warnt vor Finally-Klauseln, die nicht normal beende javac.opt.Xlint.desc.incubating=Warnt vor der Verwendung von Inkubatormodulen. -javac.opt.Xlint.desc.lossy-conversions=Warnung über möglichen Verlust von Konvertierungen in zusammengesetzten Zuweisungen. +javac.opt.Xlint.desc.lossy-conversions=Warnung über möglichen Verlust von Konvertierungen in zusammengesetzten Zuweisungen und Bitverschiebungsvorgängen. javac.opt.Xlint.desc.module=Warnt vor Problemen im Zusammenhang mit dem Modulsystem. @@ -175,11 +177,10 @@ javac.opt.Xlint.desc.preview=Warnt vor Verwendung von Vorschausprachfeatures. javac.opt.Xlint.desc.restricted=Warnt vor der Verwendung eingeschränkter Methoden. -# L10N: do not localize: identity synchronization -javac.opt.Xlint.desc.synchronization=Warnt vor Synchronisierungsversuchen mit Instanzen wertbasierter Klassen.\n Dieser Schlüssel ist ein veralteter Alias für die Kategorie "identity", die dieselben Verwendungen und\n Effekte hat. Benutzern wird empfohlen, die Kategorie "identity" für alle zukünftigen\n und vorhandenen Verwendungen von "synchronization" zu verwenden. - javac.opt.Xlint.desc.identity=Warnt vor Verwendungen wertbasierter Klassen, wenn eine Identitätsklasse erwartet wird. +javac.opt.Xlint.alias.of=Veralteter Alias für "{0}" mit identischem Effekt. Benutzern wird empfohlen,\n "{0}" anstatt "{1}" für alle aktuellen und zukünftigen Verwendungen zu nutzen. + javac.opt.Xdoclint=Empfohlene Prüfungen für Probleme in javadoc-Kommentaren aktivieren # L10N: do not localize: all none javac.opt.Xdoclint.subopts = (all|none|[-])[/] @@ -195,14 +196,17 @@ javac.opt.Xdoclint.package.desc=Aktiviert oder deaktiviert Prüfungen in bestimm javac.opt.Xstdout=Leitet die Standardausgabe um javac.opt.X=Gibt Hilfe zu zusätzlichen Optionen aus javac.opt.help=Gibt diese Hilfemeldung aus -javac.opt.help.lint=Gibt die unterstützten Schlüssel für -Xlint aus +javac.opt.help.lint=Gibt die unterstützten Schlüssel für -Xlint und -Werror aus javac.opt.help.lint.header=Die unterstützten Schlüssel für -Xlint sind: +javac.opt.help.lint.enabled.by.default=Die folgenden Lint-Warnungskategorien sind standardmäßig aktiviert: +javac.opt.help.lint.footer=Kategorien und die zugehörigen Aliasnamen können austauschbar verwendet werden. Beispiel: Das Kennzeichen\n"-Xlint:{0},{1}" wäre redundant. javac.opt.print=Gibt eine Textdarstellung der angegebenen Typen aus javac.opt.printRounds=Gibt Informationen zu Durchläufen der Annotationsverarbeitung aus javac.opt.printProcessorInfo=Gibt Informationen dazu aus, welche Annotationen ein Prozessor\nverarbeiten soll javac.opt.userpathsfirst=Durchsucht classpath und sourcepath vor anstatt nach bootclasspath nach Klassen javac.opt.prefer=Gibt an, welche Datei gelesen werden soll, wenn sowohl eine Quell- als auch eine Klassendatei für eine implizit kompilierte Klasse gefunden werden -javac.opt.preview=Aktiviert Vorschausprachfeatures.\nWird in Verbindung mit -source oder --release verwendet. +# L10N: do not localize: ''preview'' +javac.opt.preview=Aktiviert Vorschausprachfeatures. \nDeaktiviert auch die Lint-Kategorie ''preview''. \nWird in Verbindung mit -source oder --release verwendet. javac.opt.AT=Liest Optionen und Dateinamen aus Datei javac.opt.diags=Wählt einen Diagnosemodus aus javac.opt.addExports=Gibt an, dass ein Package als aus seinem definierenden Modul in\nweitere Module oder, wenn ALL-UNNAMED lautet, in alle unbenannten Module\nexportiert betrachtet werden soll. diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties index 3b967d368ae..0ea1796a8e6 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_ja.properties @@ -59,7 +59,9 @@ javac.opt.profile=使用されているAPIが、指定したプロファイル javac.opt.target=指定されたJava SEリリースに適したクラス・ファイルを生成します。サポートされているリリース: \n {0} javac.opt.release=指定されたJava SEリリースに対してコンパイルします。サポートされているリリース: \n {0} javac.opt.source=指定されたJava SEリリースとソースの互換性を保持します。サポートされているリリース: \n {0} -javac.opt.Werror=警告が発生した場合にコンパイルを終了する +javac.opt.Werror=警告が発生した場合にコンパイルを終了します +javac.opt.arg.Werror=(,)* +javac.opt.Werror.custom=コンパイルを終了する警告のlintカテゴリを\nコンマで区切って指定します。\n指定したカテゴリを除外するには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 javac.opt.A=注釈プロセッサに渡されるオプション javac.opt.implicit=暗黙的に参照されるファイルについてクラス・ファイルを生成するかどうかを指定する javac.opt.pkginfo=package-infoファイルの処理を指定する @@ -97,12 +99,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=ブートストラップ・クラス・パスの先頭に付加する javac.opt.Xbootclasspath.a=ブートストラップ・クラス・パスに追加する -javac.opt.Xlint=推奨の警告カテゴリを有効にします -javac.opt.Xlint.all=すべての警告カテゴリを有効にします -javac.opt.Xlint.none=すべての警告カテゴリを無効にします +javac.opt.Xlint=推奨lint警告カテゴリを有効にします。このリリースでは、\n使用可能なすべてのlint警告カテゴリが推奨されます。 +javac.opt.Xlint.all=すべてのlint警告カテゴリを有効にします +javac.opt.Xlint.none=すべてのlint警告カテゴリを無効にします #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=有効または無効にする警告カテゴリ(カンマ区切り)。\n指定した警告を無効にするには、キーの前に''-''を指定します。\nサポートされているキーを表示するには--help-lintを使用します。 +javac.opt.Xlint.custom=有効または無効にするLint警告カテゴリ(カンマ区切り)。\n指定されたカテゴリを無効にするには、キーの前に''-''を指定します。サポートされているキーと\nデフォルトで有効になっているカテゴリを表示するには、\n''--help-lint''を使用します。 javac.opt.Xlint.desc.auxiliaryclass=ソース・ファイルで非表示になっているが他のファイルから使用されている補助クラスについて警告します。 javac.opt.Xlint.desc.cast=不要なキャストの使用について警告します。 @@ -129,7 +131,7 @@ javac.opt.Xlint.desc.finally=正常に完了しないfinally節について警 javac.opt.Xlint.desc.incubating=実験的なモジュールの使用について警告します。 -javac.opt.Xlint.desc.lossy-conversions=複合代入における精度が失われる可能性がある変換についての警告。 +javac.opt.Xlint.desc.lossy-conversions=複合代入およびビット・シフト操作における精度が失われている可能性がある変換についての警告。 javac.opt.Xlint.desc.module=モジュール・システム関連の問題について警告します。 @@ -175,11 +177,10 @@ javac.opt.Xlint.desc.preview=プレビュー言語機能の使用について警 javac.opt.Xlint.desc.restricted=制限されたメソッドの使用について警告します。 -# L10N: do not localize: identity synchronization -javac.opt.Xlint.desc.synchronization=値ベース・クラスのインスタンスでの同期の試行について警告します。\n このキーは、''identity''の非推奨のエイリアスであり、同じ使用方法と効果を\n 持ちます。ユーザーには、今後および既存の''synchronization''の使用に対して''identity''カテゴリを\n 使用することをお薦めします。 - javac.opt.Xlint.desc.identity=アイデンティティ・クラスが必要な場所での値ベース・クラスの使用について警告します。 +javac.opt.Xlint.alias.of=同じ効果を持つ''{0}''の非推奨の別名。ユーザーは現在および将来のすべての使用で\n ''{1}''のかわりに''{0}''の使用が推奨されます。 + javac.opt.Xdoclint=javadocコメントの問題に関する推奨チェックを有効にします # L10N: do not localize: all none javac.opt.Xdoclint.subopts = (all|none|[-])[/] @@ -195,14 +196,17 @@ javac.opt.Xdoclint.package.desc=特定のパッケージのチェックを有効 javac.opt.Xstdout=標準出力をリダイレクトする javac.opt.X=追加オプションのヘルプを出力します javac.opt.help=このヘルプ・メッセージを出力します -javac.opt.help.lint=-Xlintにサポートされているキーを出力します +javac.opt.help.lint=-Xlintおよび-Werrorにサポートされているキーを出力します javac.opt.help.lint.header=-Xlintにサポートされているキーは次のとおりです: +javac.opt.help.lint.enabled.by.default=次のlint警告カテゴリはデフォルトで有効になっています: +javac.opt.help.lint.footer=カテゴリとその別名は同じ意味で使用できます。たとえば、フラグ\n''-Xlint:{0},{1}''は冗長です。 javac.opt.print=指定した型のテキスト表示を出力する javac.opt.printRounds=注釈処理の往復についての情報を印刷する javac.opt.printProcessorInfo=プロセッサが処理を依頼される注釈についての情報を印刷する javac.opt.userpathsfirst=ブート・クラスパスの後ではなく、ブート・クラスパスの前にクラスのクラスパスおよびソース・パスを検索する javac.opt.prefer=暗黙的にコンパイルされるクラスについて、ソース・ファイルとクラス・ファイルの両方が見つかった際どちらを読み込むか指定する -javac.opt.preview=プレビュー言語機能を有効にします。-sourceまたは--releaseとともに使用されます。 +# L10N: do not localize: ''preview'' +javac.opt.preview=プレビュー言語機能を有効にします。\nまた、''preview'' lintカテゴリも無効にします。\n-sourceまたは--releaseとともに使用されます。 javac.opt.AT=ファイルからの読取りオプションおよびファイル名 javac.opt.diags=診断モードの選択 javac.opt.addExports=がALL-UNNAMEDである場合、その定義モジュールから、追加モジュールまたは\n すべての名前のないモジュールにエクスポート済とみなされるようにパッケージを指定します。 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties index a24b5511c9c..0cbfac7e778 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/javac_zh_CN.properties @@ -59,7 +59,9 @@ javac.opt.profile=检查使用的 API 在指定的配置文件中是否可用。 javac.opt.target=生成适合指定的 Java SE 发行版的类文件。支持的发行版:{0} javac.opt.release=为指定的 Java SE 发行版编译。支持的发行版:{0} javac.opt.source=提供与指定的 Java SE 发行版的源兼容性。支持的发行版:{0} -javac.opt.Werror=出现警告时终止编译 +javac.opt.Werror=出现任何警告时终止编译 +javac.opt.arg.Werror=(,)* +javac.opt.Werror.custom=指定出现警告时应终止编译的 lint 类别,\n以逗号分隔。\n在关键字前面加上 ''-'' 可排除指定的类别。\n使用 --help-lint 可查看支持的关键字。 javac.opt.A=传递给批注处理程序的选项 javac.opt.implicit=指定是否为隐式引用文件生成类文件 javac.opt.pkginfo=指定 package-info 文件的处理 @@ -97,12 +99,12 @@ javac.opt.arg.pathname= javac.opt.arg.file= javac.opt.Xbootclasspath.p=置于引导类路径之前 javac.opt.Xbootclasspath.a=置于引导类路径之后 -javac.opt.Xlint=启用建议的警告类别 -javac.opt.Xlint.all=启用所有警告类别 -javac.opt.Xlint.none=禁用所有警告类别 +javac.opt.Xlint=启用建议的 lint 警告类别。在此发行版中,\n建议使用所有可用的 lint 警告类别。 +javac.opt.Xlint.all=启用所有 lint 警告类别 +javac.opt.Xlint.none=禁用所有 lint 警告类别 #L10N: do not localize: -Xlint javac.opt.arg.Xlint=(,)* -javac.opt.Xlint.custom=要启用或禁用的警告类别(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的警告。\n使用 --help-lint 可查看受支持的关键字。 +javac.opt.Xlint.custom=要启用或禁用的 lint 警告类别(以逗号分隔)。\n在关键字前面加上 ''-'' 可禁用指定的类别。\n使用 ''--help-lint'' 可显示支持的关键字和\n默认情况下启用的类别。 javac.opt.Xlint.desc.auxiliaryclass=有关辅助类在源文件中隐藏, 但在其他文件中使用的警告。 javac.opt.Xlint.desc.cast=有关使用了不必要转换的警告。 @@ -129,7 +131,7 @@ javac.opt.Xlint.desc.finally=有关 finally 子句未正常终止的警告。 javac.opt.Xlint.desc.incubating=有关使用 incubating 模块的警告。 -javac.opt.Xlint.desc.lossy-conversions=有关复合赋值中的转换可能会有损失的警告。 +javac.opt.Xlint.desc.lossy-conversions=有关复合赋值和移位操作中的转换可能会有损失的警告。 javac.opt.Xlint.desc.module=有关模块系统相关问题的警告。 @@ -175,11 +177,10 @@ javac.opt.Xlint.desc.preview=有关使用预览语言功能的警告。 javac.opt.Xlint.desc.restricted=有关使用受限制方法的警告。 -# L10N: do not localize: identity synchronization -javac.opt.Xlint.desc.synchronization=有关尝试在基于值的类的实例上同步的警告。\n 此密钥是 ''identity'' 的已过时别名,具有相同的用法和\n 效果。建议用户在 ''synchronization'' 的所有未来和现有\n 用法中使用 ''identity'' 类别。 - javac.opt.Xlint.desc.identity=有关在需要身份类的情况下使用基于值的类的警告。 +javac.opt.Xlint.alias.of=具有相同效果的 ''{0}'' 的别名已过时。建议用户当前和将来\n 都使用 ''{0}'' 而不是 ''{1}''。 + javac.opt.Xdoclint=为 javadoc 注释中的问题启用建议的检查 # L10N: do not localize: all none javac.opt.Xdoclint.subopts = (all|none|[-])[/] @@ -195,14 +196,17 @@ javac.opt.Xdoclint.package.desc=在特定的程序包中启用或禁用检查。 javac.opt.Xstdout=重定向标准输出 javac.opt.X=输出额外选项的帮助 javac.opt.help=输出此帮助消息 -javac.opt.help.lint=输出 -Xlint 支持的关键字 +javac.opt.help.lint=输出 -Xlint 和 -Werror 支持的关键字 javac.opt.help.lint.header=-Xlint 支持的关键字包括: +javac.opt.help.lint.enabled.by.default=默认情况下会启用以下 lint 警告类别: +javac.opt.help.lint.footer=类别及其别名可以互换使用;例如,标记\n''-Xlint:{0},{1}'' 将是冗余的。 javac.opt.print=输出指定类型的文本表示 javac.opt.printRounds=输出有关批注处理循环的信息 javac.opt.printProcessorInfo=输出有关请求处理程序处理哪些批注的信息 javac.opt.userpathsfirst=在引导类路径之前而不是之后搜索类的类路径和源路径 javac.opt.prefer=指定读取文件, 当同时找到隐式编译类的源文件和类文件时 -javac.opt.preview=启用预览语言功能。要与 -source 或 --release 一起使用。 +# L10N: do not localize: ''preview'' +javac.opt.preview=启用预览语言功能。\n还禁用''preview''lint 类别。\n要与 -source 或 --release 一起使用。 javac.opt.AT=从文件读取选项和文件名 javac.opt.diags=选择诊断模式 javac.opt.addExports=指定被视为已从其定义模块导出到其他模块或者导出到所有\n 未命名模块 (如果 为 ALL-UNNAMED) 的程序包。 diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties index 1edda5da22f..bb0f14ab833 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_de.properties @@ -111,6 +111,9 @@ launcher.err.cant.access.main.method=kein Zugriff auf Methode "main" in Klasse: # 0: string launcher.err.cant.find.constructor=No-Argument-Konstruktor nicht gefunden in Klasse: {0} +# 0: string +launcher.err.cant.use.private.constructor=Kein nicht privater Null-Argument-Konstruktor in Klasse {0} gefunden\nEntfernen Sie die Eigenschaft "private" aus dem vorhandenen Konstruktor, oder definieren Sie ihn als:\n public {0}() + # 0: string launcher.err.cant.access.constructor=Kein Zugriff auf No-Argument-Konstruktor in Klasse: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties index be1feb4a8a9..ed940e731bd 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_ja.properties @@ -111,6 +111,9 @@ launcher.err.cant.access.main.method=クラスのメイン・メソッドにア # 0: string launcher.err.cant.find.constructor=クラスに引数なしのコンストラクタが見つかりません: {0} +# 0: string +launcher.err.cant.use.private.constructor=非privateのゼロ引数コンストラクタがクラス{0}に見つかりません\n既存のコンストラクタからprivateを削除するか、次のように定義してください:\n public {0}() + # 0: string launcher.err.cant.access.constructor=クラスの引数なしのコンストラクタにアクセスできません: {0} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties index 5367036d82f..1fafa95c146 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/launcher_zh_CN.properties @@ -111,6 +111,9 @@ launcher.err.cant.access.main.method=无法访问类 {0} 中的 main 方法 # 0: string launcher.err.cant.find.constructor=在类 {0} 中找不到无参数构造器 +# 0: string +launcher.err.cant.use.private.constructor=在类 {0} 中未找到 non-private 零参数构造器\n请从现有构造器中删除 private,或者定义为:\n public {0}() + # 0: string launcher.err.cant.access.constructor=无法访问类 {0} 中的无参数构造器 diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties index c5d9f41ee85..2b76f1408fa 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_de.properties @@ -220,3 +220,4 @@ entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=Eintrag %s ist jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=Diese JAR-Datei enthält interne Inkonsistenzen, die zu anderem Inhalt beim Lesen über JarFile als beim Lesen über JarInputStream führen können: signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=Signaturverifizierung war für Eintrag %s beim Lesen über JarInputStream nicht erfolgreich signature.verification.failed.on.entry.1.when.reading.via.jarfile=Signaturverifizierung war für Eintrag %s beim Lesen über JarFile nicht erfolgreich +jks.storetype.warning=%1$s verwendet veraltete kryptografische Algorithmen und wird in einer zukünftigen Version entfernt. Migrieren Sie zu PKCS12 mit:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties index 97ab6a918cb..f2a5ce39be3 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_ja.properties @@ -220,3 +220,4 @@ entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=エントリ%s jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=このJARファイルには内部的な不整合があるため、JarFileとJarInputStreamから読み取る場合にコンテンツが異なる可能性があります: signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=JarInputStreamを介して読み取るときに署名検証がエントリ%sで失敗しました signature.verification.failed.on.entry.1.when.reading.via.jarfile=JarFileを介して読み取るときに署名検証がエントリ%sで失敗しました +jks.storetype.warning=%1$sは古い暗号化アルゴリズムを使用しているため、将来のリリースで削除されます。次を使用してPKCS12に移行します:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 diff --git a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties index 378cc3ba9fc..f780bd1f1c3 100644 --- a/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/security/tools/jarsigner/resources/jarsigner_zh_CN.properties @@ -220,3 +220,4 @@ entry.1.is.signed.in.jarinputstream.but.is.not.signed.in.jarfile=条目 %s 已 jar.contains.internal.inconsistencies.result.in.different.contents.via.jarfile.and.jarinputstream=此 JAR 文件包含内部不一致,通过 JarFile 和 JarInputStream 读取时可能会导致内容不同: signature.verification.failed.on.entry.1.when.reading.via.jarinputstream=通过 JarInputStream 读取时,条目 %s 的签名验证失败 signature.verification.failed.on.entry.1.when.reading.via.jarfile=通过 JarFile 读取时,条目 %s 的签名验证失败 +jks.storetype.warning=%1$s 使用的加密算法已过时,将在未来发行版中删除。请使用以下命令迁移到 PKCS12:\nkeytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12 diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties index 2a5786e10b4..292ec9c963d 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_de.properties @@ -80,6 +80,8 @@ error.validator.info.opens.notequal=module-info.class in einem versionierten Ver error.validator.info.provides.notequal=module-info.class in einem versionierten Verzeichnis enthält unterschiedliche "provides" error.validator.info.version.notequal={0}: module-info.class in einem versionierten Verzeichnis enthält unterschiedlichen "version"-Wert error.validator.info.manclass.notequal={0}: module-info.class in einem versionierten Verzeichnis enthält unterschiedlichen "main-class"-Wert +error.validator.metainf.wrong.position=Eintrag META-INF/ an Position 0 erwartet, aber an Position {0} gefunden +error.validator.manifest.wrong.position=Eintrag META-INF/MANIFEST.MF an Position 0 oder 1 erwartet, aber an Position {0} gefunden warn.validator.identical.entry=Warnung: Eintrag {0} enthält eine Klasse, die mit\neinem bereits in der JAR-Datei enthaltenen Eintrag identisch ist warn.validator.resources.with.same.name=Warnung: Eintrag {0}, mehrere Ressourcen mit demselben Namen warn.validator.concealed.public.class=Warnung: Eintrag {0} ist eine öffentliche Klasse\nin einem verdeckten Package. Wenn Sie diese JAR-Datei in den Classpath einfügen, kommt es\nzu nicht kompatiblen öffentlichen Schnittstellen diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties index c7d7c14613a..0d0f91ad791 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_ja.properties @@ -80,6 +80,8 @@ error.validator.info.opens.notequal=バージョニング・ディレクトリ error.validator.info.provides.notequal=バージョニングされたディレクトリのmodule-info.classに異なる"provides"が含まれています error.validator.info.version.notequal={0}: バージョニングされたディレクトリのmodule-info.classに異なる"version"が含まれています error.validator.info.manclass.notequal={0}: バージョニングされたディレクトリのmodule-info.classに異なる"main-class"が含まれています +error.validator.metainf.wrong.position=エントリMETA-INF/は0の位置にある必要がありますが、見つかりました: {0} +error.validator.manifest.wrong.position=エントリMETA-INF/MANIFEST.MFは0または1の位置にある必要がありますが、位置: {0}で見つかりました warn.validator.identical.entry=警告 : エントリ{0}には、jarにすでに存在する\nエントリと同じクラスが含まれます warn.validator.resources.with.same.name=警告 : エントリ{0}、同じ名前を持つ複数のリソース warn.validator.concealed.public.class=警告 : エントリ{0}は、隠しパッケージ内のpublicクラスです。\nクラスパスにこのjarを配置すると、互換性のない\npublicインタフェースが生成されます diff --git a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties index 1979f3e2386..41833d28bfc 100644 --- a/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties +++ b/src/jdk.jartool/share/classes/sun/tools/jar/resources/jar_zh_CN.properties @@ -80,6 +80,8 @@ error.validator.info.opens.notequal=版本化目录中的 module-info.class 包 error.validator.info.provides.notequal=版本化目录中的 module-info.class 包含不同的 "provides" error.validator.info.version.notequal={0}: 版本化目录中的 module-info.class 包含不同的 "version" error.validator.info.manclass.notequal={0}: 版本化目录中的 module-info.class 包含不同的 "main-class" +error.validator.metainf.wrong.position=条目 META-INF/ 应位于位置 0 处,但发现:{0} +error.validator.manifest.wrong.position=条目 META-INF/MANIFEST.MF 应位于位置 0 或 1 处,但发现该条目位于位置 {0} 处 warn.validator.identical.entry=警告: 条目 {0} 包含与 jar 中的\n现有条目相同的类 warn.validator.resources.with.same.name=警告: 条目 {0}, 多个资源具有相同名称 warn.validator.concealed.public.class=警告: 条目 {0} 是已隐藏程序包中的\n公共类, 将此 jar 放置在类路径中\n将导致公共接口不兼容 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties index 4cbb4b97774..a380b29d553 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_de.properties @@ -190,6 +190,10 @@ doclet.Window_Help_title=API-Hilfe doclet.references={0} Referenzen doclet.Window_Search_title=Suchen doclet.search.main_heading=Suchen +doclet.theme.select_theme=Theme auswählen +doclet.theme.light=Hell +doclet.theme.dark=Dunkel +doclet.theme.system=Systemeinstellung # label for link/button element to show the information below doclet.search.show_more=Zusätzliche Ressourcen @@ -539,3 +543,5 @@ doclet.NoFrames_specified=Die Option --no-frames wird nicht mehr benötigt und w # L10N: do not localize the option name -footer doclet.footer_specified=Die Option -footer wird nicht mehr unterstützt und wird ignoriert.\nSie wird möglicherweise in einem zukünftigen Release entfernt. + +doclet.selectModule=Wählen Sie das Modul aus, in dem gesucht werden soll. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties index 2151b3f4a2e..69cdc862b4c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_ja.properties @@ -190,6 +190,10 @@ doclet.Window_Help_title=APIヘルプ doclet.references={0}の参照 doclet.Window_Search_title=検索 doclet.search.main_heading=検索 +doclet.theme.select_theme=テーマを選択 +doclet.theme.light=明るい +doclet.theme.dark=暗い +doclet.theme.system=システム設定 # label for link/button element to show the information below doclet.search.show_more=その他のリソース @@ -539,3 +543,5 @@ doclet.NoFrames_specified=--no-framesオプションは必須ではなくなり # L10N: do not localize the option name -footer doclet.footer_specified=-footerオプションはサポートされなくなったため、無視されます。\n将来のリリースで削除される可能性があります。 + +doclet.selectModule=検索するモジュールを選択します。 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties index 66620d158bb..b3a0a3a1197 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/standard_zh_CN.properties @@ -190,6 +190,10 @@ doclet.Window_Help_title=API 帮助 doclet.references={0} 个引用 doclet.Window_Search_title=搜索 doclet.search.main_heading=搜索 +doclet.theme.select_theme=选择主题 +doclet.theme.light=浅色 +doclet.theme.dark=深色 +doclet.theme.system=系统设置 # label for link/button element to show the information below doclet.search.show_more=其他资源 @@ -539,3 +543,5 @@ doclet.NoFrames_specified=--no-frames 选项不再是必需的,可能\n会在 # L10N: do not localize the option name -footer doclet.footer_specified=-footer 选项不再受支持并将被忽略。\n可能会在未来发行版中删除此选项。 + +doclet.selectModule=选择要在其中搜索的模块。 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties index 0ee34071c93..a6dbf050bf3 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_de.properties @@ -65,6 +65,7 @@ doclet.JavaScript_in_comment=JavaScript in Dokumentationskommentar gefunden.\nVe doclet.JavaScript_in_option=Option {0} enthält JavaScript.\nVerwenden Sie --allow-script-in-comments, um die Verwendung von JavaScript zuzulassen. doclet.Link_icon=Linksymbol doclet.Link_to_section=Link zu diesem Abschnitt +doclet.Toggle_member_listing=Zwischen kurzer und detaillierter Listenansicht umschalten doclet.Packages=Packages doclet.All_Packages=Alle Packages doclet.Modules=Module @@ -114,7 +115,7 @@ doclet.inheritDocWithinInappropriateTag=@inheritDoc kann in diesem Tag nicht ver doclet.inheritDocNoDoc=überschriebene Methoden dokumentieren Ausnahmetyp {0} nicht doclet.throwsInheritDocUnsupported=@inheritDoc wird für Parameter vom Typ Ausnahme, die nicht von einer Methode deklariert werden, nicht unterstützt. Dokumentieren Sie solche Ausnahmetypen direkt. doclet.noInheritedDoc=@inheritDoc wurde verwendet, aber mit {0} wird keine Methode außer Kraft gesetzt oder implementiert. -doclet.tag_misuse=Tag {0} kann nicht in {1}-Dokumentation verwendet werden. Es kann nur in folgenden Dokumentationstypen verwendet werden: {2}. +doclet.tag_misuse=Tag {0} kann nicht in Dokumentation {1} verwendet werden. Es kann nur in folgenden Dokumentationstypen verwendet werden: {2}. doclet.Package_Summary=Packageübersicht doclet.Requires_Summary=Erfordernisse doclet.Indirect_Requires_Summary=Indirekte Erfordernisse @@ -226,7 +227,7 @@ doclet.search=Suchen doclet.search_placeholder=In Dokumentation suchen ("/" eingeben) doclet.search_in_documentation=In Dokumentation suchen doclet.search_reset=Zurücksetzen -doclet.Member=Mitglied +doclet.Member=Member doclet.Field=Feld doclet.Property=Eigenschaft doclet.Constructor=Konstruktor @@ -240,11 +241,14 @@ doclet.Description=Beschreibung doclet.ConstantField=Konstantenfeld doclet.Value=Wert doclet.table_of_contents=Inhaltsverzeichnis +doclet.Sort_lexicographically=Member-Details lexikographisch sortieren +doclet.Sort_by_source_order=Member-Details nach Quellreihenfolge sortieren doclet.hide_sidebar=Randleiste ausblenden doclet.show_sidebar=Randleiste einblenden doclet.filter_label=Inhalt filtern ("." eingeben) doclet.filter_table_of_contents=Inhaltsverzeichnis filtern doclet.filter_reset=Zurücksetzen +doclet.sort_table_of_contents=Member-Details in lexikographischer Reihenfolge sortieren doclet.linkMismatch_PackagedLinkedtoModule=Der Code, der dokumentiert wird, verwendet Packages im unbenannten Modul, aber die in {0} definierten Packages befinden sich in benannten Modulen. doclet.linkMismatch_ModuleLinkedtoPackage=Der Code, der dokumentiert wird, verwendet Module, aber die in {0} definierten Packages befinden sich im unbenannten Modul. doclet.urlRedirected=URL {0} wurde umgeleitet an {1} - Aktualisieren Sie die Befehlszeilenoptionen, um diese Warnung zu unterdrücken. diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties index 2b10f4e6e9a..1970203da38 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_ja.properties @@ -65,6 +65,7 @@ doclet.JavaScript_in_comment=ドキュメント・コメントにJavaScriptが doclet.JavaScript_in_option=オプション{0}にJavaScriptが含まれています。\n--allow-script-in-commentsを使用して、JavaScriptの使用を許可してください。 doclet.Link_icon=リンク・アイコン doclet.Link_to_section=このセクションにリンク +doclet.Toggle_member_listing=短いリスト・ビューと詳細リスト・ビューの切替え doclet.Packages=パッケージ doclet.All_Packages=すべてのパッケージ doclet.Modules=モジュール @@ -240,11 +241,14 @@ doclet.Description=説明 doclet.ConstantField=定数フィールド doclet.Value=値 doclet.table_of_contents=目次 +doclet.Sort_lexicographically=メンバー詳細を辞書順にソート +doclet.Sort_by_source_order=メンバー詳細をソース順序にソート doclet.hide_sidebar=サイドバーの非表示 doclet.show_sidebar=サイドバーの表示 doclet.filter_label=コンテンツのフィルタ(.と入力) doclet.filter_table_of_contents=目次のフィルタ doclet.filter_reset=リセット +doclet.sort_table_of_contents=メンバー詳細を辞書順にソート doclet.linkMismatch_PackagedLinkedtoModule=ドキュメント化しようとしているコードでは名前のないモジュールのパッケージが使用されていますが、{0}で定義されているパッケージは名前のあるモジュールのものです。 doclet.linkMismatch_ModuleLinkedtoPackage=ドキュメント化しようとしているコードではモジュールが使用されていますが、{0}で定義されているパッケージは名前のないモジュールのものです。 doclet.urlRedirected=URL {0}は{1}にリダイレクトされました -- コマンドライン・オプションを更新してこの警告を表示しないようにしてください。 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties index f2c8762b283..62e51c2c1c4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/resources/doclets_zh_CN.properties @@ -65,6 +65,7 @@ doclet.JavaScript_in_comment=文档注释中发现 JavaScript。\n使用 --allow doclet.JavaScript_in_option=选项 {0} 包含 JavaScript。\n使用 --allow-script-in-comments 可允许使用 JavaScript。 doclet.Link_icon=链接图标 doclet.Link_to_section=链接到此节 +doclet.Toggle_member_listing=在简短列表视图和详细列表视图之间切换 doclet.Packages=程序包 doclet.All_Packages=所有程序包 doclet.Modules=模块 @@ -240,11 +241,14 @@ doclet.Description=说明 doclet.ConstantField=常量字段 doclet.Value=值 doclet.table_of_contents=目录 +doclet.Sort_lexicographically=按字典顺序对成员详细信息进行排序 +doclet.Sort_by_source_order=按源顺序对成员详细信息进行排序 doclet.hide_sidebar=隐藏子工具栏 doclet.show_sidebar=显示子工具栏 doclet.filter_label=筛选内容(键入 .) doclet.filter_table_of_contents=筛选目录 doclet.filter_reset=重置 +doclet.sort_table_of_contents=按字典顺序对成员详细信息进行排序 doclet.linkMismatch_PackagedLinkedtoModule=进行文档化的代码使用了未命名模块中的程序包,但在 {0} 中定义的程序包在命名模块中。 doclet.linkMismatch_ModuleLinkedtoPackage=进行文档化的代码使用了模块,但在 {0} 中定义的程序包在未命名模块中。 doclet.urlRedirected=URL {0} 已重定向到 {1} — 更新命令行选项以隐藏此警告。 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties index 7829d2d7e27..57137ffe75d 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_de.properties @@ -52,7 +52,7 @@ main.opt.package.desc=Zeigt Package-/geschützte/öffentliche Typen und Mitglied main.opt.private.desc=Zeigt alle Typen und Mitglieder. Zeigt bei benannten Modulen\nalle Packages und alle Moduldetails. main.opt.show.members.arg= -main.opt.show.members.desc=Gibt an, welche Member (Felder, Methoden oder Konstruktoren) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Member an. "public" zeigt nur\nöffentliche Member, "package" zeigt öffentliche, geschützte und\nPackage-Member, und "private" zeigt alle Member an. +main.opt.show.members.desc=Gibt an, welche Members (Felder, Methoden oder Konstruktoren) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Members an. "public" zeigt nur\nöffentliche Members, "package" zeigt öffentliche, geschützte und\nPackage-Members, und "private" zeigt alle Members an. main.opt.show.types.arg= main.opt.show.types.desc=Gibt an, welche Typen (Klassen, Schnittstellen usw.) dokumentiert\nwerden, wobei der Wert "public", "protected",\n"package" oder "private" lauten kann. Der Standardwert ist "protected"\nund zeigt öffentliche und geschützte Typen, "public" zeigt nur\nöffentliche Typen, "package" zeigt öffentliche, geschützte und\nPackagetypen, und "private" zeigt alle Typen. diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties index 9b776745c66..40022a5532b 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_de.properties @@ -78,7 +78,8 @@ err.runtime.link.patched.module=jlink unterstützt keine Verknüpfung vom Laufze err.no.module.path=Option --module-path muss mit --add-modules ALL-MODULE-PATH angegeben werden err.empty.module.path=Kein Modul im Modulpfad "{0}" mit --add-modules ALL-MODULE-PATH gefunden err.limit.modules=--limit-modules nicht mit --add-modules ALL-MODULE-PATH zulässig -err.jlink.version.mismatch=jlink-Version {0}.{1} stimmt nicht mit Ziel-java.base-Version {2}.{3} überein +err.jlink.version.mismatch=jlink-Build "{0}" stimmt nicht mit dem java.base-Ziel-Build "{1}" überein +err.jlink.version.missing=jlink-Build "{0}" kann die Build-Signatur nicht im Modul java.base finden, das im Modulpfad angegebenen wird. Wahrscheinlich stammt es aus einem früheren Build. err.automatic.module:automatisches Modul kann nicht mit jlink verwendet werden: {0} aus {1} err.unknown.byte.order:unbekannte Bytereihenfolge {0} err.launcher.main.class.empty:Launcher-Hauptklassenname darf nicht leer sein: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties index c925f250c41..9519a24c96e 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_ja.properties @@ -78,7 +78,8 @@ err.runtime.link.patched.module=--patch-moduleを使用してパッチ済ラン err.no.module.path=--module-pathオプションは--add-modules ALL-MODULE-PATHで指定する必要があります err.empty.module.path=モジュール・パス''{0}''に--add-modules ALL-MODULE-PATHを使用したモジュールが見つかりません err.limit.modules=--limit-modulesは--add-modules ALL-MODULE-PATHとともに指定できません -err.jlink.version.mismatch=jlinkバージョン{0}.{1}がターゲットのjava.baseバージョン{2}.{3}と一致しません +err.jlink.version.mismatch=jlinkビルド''{0}''がターゲットのjava.baseビルド''{1}''と一致しません +err.jlink.version.missing=jlinkビルド''{0}''では、モジュール・パスで指定されたjava.baseにビルド署名が見つかりません(おそらく以前のビルドから)。 err.automatic.module:jlinkでは自動モジュールは使用できません: {1}からの{0} err.unknown.byte.order:不明なバイト順{0} err.launcher.main.class.empty:起動ツールのメイン・クラス名は空にできません: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties index b7526c9f57a..81af170ae7f 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/jlink_zh_CN.properties @@ -78,7 +78,8 @@ err.runtime.link.patched.module=当使用 --patch-module 在打补丁的运行 err.no.module.path=--module-path 选项必须与 --add-modules ALL-MODULE-PATH 一起指定 err.empty.module.path=在随 --add-modules ALL-MODULE-PATH 提供的模块路径 ''{0}'' 中找不到模块 err.limit.modules=不允许将 --limit-modules 与 --add-modules ALL-MODULE-PATH 一起使用 -err.jlink.version.mismatch=jlink 版本 {0}.{1} 与目标 java.base 版本 {2}.{3} 不匹配 +err.jlink.version.mismatch=jlink 工作版本 ''{0}'' 与目标 java.base 工作版本 ''{1}'' 不匹配 +err.jlink.version.missing=jlink 工作版本 ''{0}'' 在模块路径中指定的 java.base 中找不到工作版本签名,可能来自早期工作版本。 err.automatic.module:自动模块不能用于来自 {1} 的 jlink: {0} err.unknown.byte.order:未知的字节顺序 {0} err.launcher.main.class.empty:启动程序主类名不能为空: {0} diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_de.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_de.properties index 4713eabed85..80d1ba6e05f 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_de.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, 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 @@ -31,9 +31,9 @@ add-options.usage=\ --add-options Stellt die angegebene release-info.argument=|add:=:=:...|del: -release-info.description=-Option lädt Releaseeigenschaften aus der angegebenen Datei.\nadd: fügt der Datei "release" Eigenschaften hinzu.\nEine beliebige Anzahl von =-Paaren kann übergeben werden.\ndel: löscht die Liste der Schlüssel in der Releasedatei. +release-info.description=Option lädt Releaseeigenschaften aus der angegebenen Datei.\n Die angegebene Datei soll erwartungsgemäß in UTF-8 codiert sein.\nadd: fügt der Datei "release" Eigenschaften hinzu.\nEine beliebige Anzahl von =-Paaren kann übergeben werden.\ndel: löscht die Liste der Schlüssel in der Releasedatei. -release-info.usage=\ --release-info |add:=:=:...|del:\n Option löscht Releaseeigenschaften aus\n der angegebenen Datei.\n add: fügt Eigenschaften der Datei "release" hinzu.\n Eine beliebige Anzahl =-Paare kann übergeben werden.\n del: löscht die Liste der Schlüssel in der Releasedatei. +release-info.usage=\ --release-info |add:=:=:...|del:\n Option lädt Releaseeigenschaften aus\n der angegebenen Datei. Die angegebene Datei soll erwartungsgemäß\n in UTF-8 codiert sein.\n add: fügt der Datei "release" Eigenschaften hinzu.\n Eine beliebige Anzahl =-Paare kann übergeben werden.\n del: löscht die Liste der Schlüssel in der Releasedatei. class-for-name.argument= @@ -41,11 +41,11 @@ class-for-name.description=Klassenoptimierung: Konvertiert Class.forName-Aufrufe class-for-name.usage=\ --class-for-name Klassenoptimierung: Konvertiert Class.forName-Aufrufe in Konstantenladevorgänge. -compress.argument=[:filter=] +compress.argument=[:filter=] compress.description= Zu verwendende Komprimierung für Ressourcen. -compress.usage=\ --compress Zu verwendende Komprimierung für Ressourcen:\n Zulässige Werte:\n zip-[0-9], wobei "zip-0" für keine Komprimierung\n und "zip-9" für die beste Komprimierung steht.\n Standardwert ist "zip-6". +compress.usage=\ --compress Zu verwendende Komprimierung für Ressourcen:\n Zulässige Werte:\n zip-'{0-9}', wobei "zip-0" für keine Komprimierung\n und "zip-9" für die beste Komprimierung steht.\n Standardwert ist "zip-6". compress.warn.argumentdeprecated=Warnung: Das Argument {0} für --compress ist veraltet und wird möglicherweise in einem zukünftigen Release entfernt @@ -170,7 +170,7 @@ plugin.opt.resources-last-sorter=\ --resources-last-sorter Das le plugin.opt.disable-plugin=\ --disable-plugin Deaktiviert das angegebene Plug-in -plugin.opt.compress=\ --compress Zu verwendende Komprimierung für Ressourcen:\n Zulässige Werte:\n zip-[0-9], wobei "zip-0" für keine Komprimierung\n und "zip-9" für die beste Komprimierung steht.\n Standardwert ist "zip-6".\n Veraltete Werte, die in einem zukünftigen Release entfernt werden:\n 0: Keine Komprimierung. Entspricht "zip-0".\n 1: Gemeinsame Verwendung konstanter Zeichenfolgen\n 2: Entspricht "zip-6". +plugin.opt.compress=\ --compress Komprimiert alle Ressourcen im Ausgabeimage:\n Zulässige Werte:\n zip-'{0-9}', wobei "zip-0" für keine Komprimierung\n und "zip-9" für die beste Komprimierung steht.\n Standardwert ist "zip-6."\n Veraltete Werte, die in einem zukünftigen Release entfernt werden:\n 0: Keine Komprimierung. Verwenden Sie stattdessen "zip-0".\n 1: Gemeinsame Verwendung konstanter Zeichenfolgen\n 2: ZIP. Verwenden Sie stattdessen "zip-6". plugin.opt.strip-debug=\ -G, --strip-debug Entfernt Debuginformationen diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties index 1cf3ba5b0c0..6ed0a486132 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, 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 @@ -31,9 +31,9 @@ add-options.usage=\ --add-options 指定した文字列を release-info.argument=|add:=:=:...|del: -release-info.description=オプションは指定されたファイルからリリース・プロパティをロードします。\nadd:はリリース・ファイルにプロパティを追加します。\n任意の数の=のペアを渡すことができます。\ndel:はリリース・ファイルのキーのリストを削除します。 +release-info.description=オプションは指定されたファイルからリリース・プロパティをロードします。\n 指定されたファイルはUTF-8でエンコードされる必要があります。\nadd:はリリース・ファイルにプロパティを追加します。\n任意の数の=のペアを渡すことができます。\ndel:はリリース・ファイルのキーのリストを削除します。 -release-info.usage=\ --release-info |add:=:=:...|del:\n オプションは指定されたファイルからリリース・プロパティを\n ロードします。\n add:はリリース・ファイルにプロパティを追加します。\n 任意の数の=ペアを渡すことができます。\n del:はリリース・ファイルのキーのリストを削除します。 +release-info.usage=\ --release-info |add:=:=:...|del:\n オプションは指定されたファイルからリリース・プロパティを\n ロードします。指定されたファイルはUTF-8で\n エンコードされる必要があります。\n add:はリリース・ファイルにプロパティを追加します。\n 任意の数の=ペアを渡すことができます。\n del:はリリース・ファイルのキーのリストを削除します。 class-for-name.argument= @@ -41,11 +41,11 @@ class-for-name.description=クラスの最適化: Class.forName呼出しを定 class-for-name.usage=\ --class-for-name クラスの最適化: Class.forName呼出しを定数のロードに変換します。 -compress.argument=[:filter=] +compress.argument=[:filter=] compress.description= リソースの圧縮に使用する圧縮。 -compress.usage=\ --compress リソースの圧縮に使用する圧縮:\n 使用可能な値は\n zip-[0-9]です。zip-0では圧縮は行われず、\n zip-9では最適な圧縮が行われます。\n デフォルトはzip-6です。 +compress.usage=\ --compress リソースの圧縮に使用する圧縮:\n 使用可能な値は\n zip-'{0-9}'です。zip-0では圧縮は行われず、\n zip-9では最適な圧縮が行われます。\n デフォルトはzip-6です。 compress.warn.argumentdeprecated=警告: --compressの{0}引数は非推奨であり、今後のリリースで削除される可能性があります @@ -170,7 +170,7 @@ plugin.opt.resources-last-sorter=\ --resources-last-sorter 最後 plugin.opt.disable-plugin=\ --disable-plugin 指定したプラグインを無効にします -plugin.opt.compress=\ --compress リソースの圧縮に使用する圧縮:\n 使用可能な値は\n zip-[0-9]です。zip-0では圧縮は行われず、\n zip-9では最適な圧縮が行われます。\n デフォルトはzip-6です。\n 今後のリリースで削除される非推奨の値:\n 0: 圧縮なし。zip-0と同等。\n 1: 定数文字列の共有\n 2: zip-6と同等。 +plugin.opt.compress=\ --compress 出力イメージ内のすべてのリソースを圧縮します:\n 使用可能な値は\n zip-'{0-9}'です。zip-0では圧縮は行われず、\n zip-9では最適な圧縮が行われます。\n デフォルトはzip-6です。\n 今後のリリースで削除される非推奨の値:\n 0: 圧縮なし。かわりにzip-0を使用。\n 1: 定数文字列の共有\n 2: ZIP。かわりにzip-6を使用。 plugin.opt.strip-debug=\ -G, --strip-debug デバッグ情報を削除します diff --git a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties index 819238e7d04..a0480a31fc3 100644 --- a/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties +++ b/src/jdk.jlink/share/classes/jdk/tools/jlink/resources/plugins_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2015, 2025, 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 @@ -31,9 +31,9 @@ add-options.usage=\ --add-options 在生成的映像中调用虚拟 release-info.argument=|add:=:=:...|del: -release-info.description= 选项:从提供的文件加载 release 属性。\nadd:向 'release' 文件中添加属性。\n可以传递任意数量的 = 对。\ndel:删除 release 文件中的关键字列表。 +release-info.description= 选项:从提供的文件加载 release 属性。\n 指定的文件应采用 UTF-8 编码。\nadd:向 'release' 文件中添加属性。\n可以传递任意数量的 = 对。\ndel:删除 release 文件中的关键字列表。 -release-info.usage=\ --release-info |add:=:=:...|del:\n 选项:从提供的文件\n 加载 release 属性。\n add:向 'release' 文件中添加属性。\n 可以传递任意数量的 = 对。\n del:删除 release 文件中的关键字列表。 +release-info.usage=\ --release-info |add:=:=:...|del:\n 选项:从提供的文件\n 加载 release 属性。指定的文件\n 应采用 UTF-8 编码。\n add:向 'release' 文件中添加属性。\n 可以传递任意数量的 = 对。\n del:删除 release 文件中的关键字列表。 class-for-name.argument= @@ -41,11 +41,11 @@ class-for-name.description=类优化:将 Class.forName 调用转换为常量 class-for-name.usage=\ --class-for-name 类优化:将 Class.forName 调用转换为常量负载。 -compress.argument=[:filter=] +compress.argument=[:filter=] compress.description= 要在压缩资源时使用的压缩。 -compress.usage=\ --compress 要在压缩资源时使用的压缩:\n 接受的值为:\n zip-[0-9],其中 zip-0 表示无压缩,\n zip-9 表示最佳压缩。\n 默认值为 zip-6。 +compress.usage=\ --compress 要在压缩资源时使用的压缩:\n 接受的值为:\n zip-'{0-9}',其中 zip-0 表示无压缩,\n zip-9 表示最佳压缩。\n 默认值为 zip-6。 compress.warn.argumentdeprecated=警告:--compress 的 {0} 参数已过时,可能会在未来发行版中删除 @@ -170,7 +170,7 @@ plugin.opt.resources-last-sorter=\ --resources-last-sorter 允许 plugin.opt.disable-plugin=\ --disable-plugin 禁用所提及的插件 -plugin.opt.compress=\ --compress 要在压缩资源时使用的压缩:\n 接受的值为:\n zip-[0-9],其中 zip-0 表示无压缩,\n zip-9 表示最佳压缩。\n 默认值为 zip-6。\n 要在未来发行版中删除的已过时值:\n 0:无压缩。等同于 zip-0。\n 1:常量字符串共享\n 2:等同于 zip-6。 +plugin.opt.compress=\ --compress 在输出映像中压缩所有资源:\n 接受的值包括:\n zip-'{0-9}',其中 zip-0 表示无压缩,\n zip-9 表示最佳压缩。\n 默认值为 zip-6。\n 要在未来发行版中删除的已过时值:\n 0:无压缩。改为使用 zip-0。\n 1:常量字符串共享\n 2:ZIP。改为使用 zip-6。 plugin.opt.strip-debug=\ -G, --strip-debug 去除调试信息 diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties index 2f8fcddff73..345ed36b7be 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_de.properties @@ -23,12 +23,7 @@ # questions. # # -app.bundler.name=Linux-Anwendungsimage -deb.bundler.name=DEB-Bundle -rpm.bundler.name=RPM-Bundle - param.license-type.default=Unbekannt -param.menu-group.default=Unbekannt resource.deb-control-file=DEB-Kontrolldatei resource.deb-preinstall-script=DEB-Preinstall-Skript @@ -59,7 +54,6 @@ message.output-to-location=Package (.deb) gespeichert in: {0}. message.debs-like-licenses=Debian-Packages müssen eine Lizenz angeben. Bei fehlender Lizenz geben einige Linux-Distributionen eine Meldung über eine Beeinträchtigung der Anwendungsqualität aus. message.outputting-bundle-location=RPM für Installationsprogramm wird generiert in: {0}. message.output-bundle-location=Package (.rpm) gespeichert in: {0}. -message.creating-association-with-null-extension=Verknüpfung mit Nullerweiterung wird erstellt. message.ldd-not-available=ldd-Befehl nicht gefunden. Packageabhängigkeiten werden nicht generiert. message.deb-ldd-not-available.advice=Installieren Sie das DEB-Package "libc-bin", um ldd abzurufen. diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties index be2cd00b42c..d0bc4f73407 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_ja.properties @@ -23,12 +23,7 @@ # questions. # # -app.bundler.name=Linuxアプリケーション・イメージ -deb.bundler.name=DEBバンドル -rpm.bundler.name=RPMバンドル - param.license-type.default=不明 -param.menu-group.default=不明 resource.deb-control-file=DEB制御ファイル resource.deb-preinstall-script=DEBインストール前スクリプト @@ -59,7 +54,6 @@ message.output-to-location=パッケージ(.deb)は次に保存されました: message.debs-like-licenses=Debianパッケージではライセンスを指定する必要があります。ライセンスがない場合、一部のLinuxディストリビューションでアプリケーションの品質に問題が発生する場合があります。 message.outputting-bundle-location=インストーラのRPMを次に生成しています: {0} message.output-bundle-location=パッケージ(.rpm)は次に保存されました: {0} -message.creating-association-with-null-extension=null拡張子との関連付けを作成しています。 message.ldd-not-available=lddコマンドが見つかりませんでした。パッケージ依存性は生成されません。 message.deb-ldd-not-available.advice="libc-bin" DEBパッケージをインストールしてlddを取得します。 diff --git a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties index 5b583062ab6..f3d62675c4d 100644 --- a/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties +++ b/src/jdk.jpackage/linux/classes/jdk/jpackage/internal/resources/LinuxResources_zh_CN.properties @@ -23,12 +23,7 @@ # questions. # # -app.bundler.name=Linux 应用程序映像 -deb.bundler.name=DEB 包 -rpm.bundler.name=RPM 包 - param.license-type.default=未知 -param.menu-group.default=未知 resource.deb-control-file=DEB 控制文件 resource.deb-preinstall-script=DEB 安装前脚本 @@ -59,7 +54,6 @@ message.output-to-location=程序包 (.deb) 已保存到: {0}。 message.debs-like-licenses=Debian 程序包应指定许可证。缺少许可证将导致某些 Linux 分发投诉应用程序质量。 message.outputting-bundle-location=正在为安装程序生成 RPM, 位置: {0}。 message.output-bundle-location=程序包 (.rpm) 已保存到: {0}。 -message.creating-association-with-null-extension=正在使用空扩展名创建关联。 message.ldd-not-available=未找到 ldd 命令。将不生成程序包被依赖对象。 message.deb-ldd-not-available.advice=安装 "libc-bin" DEB 程序包以获取 ldd。 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties index 7e36a260c3f..3cc56bb6cdf 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_de.properties @@ -23,24 +23,19 @@ # questions. # # - -app.bundler.name=Mac-Anwendungsimage -store.bundler.name=Mac App Store-fähiger Bundler -dmg.bundler.name=Mac-DMG-Package -pkg.bundler.name=Mac-PKG-Package - error.invalid-cfbundle-version.advice=Legen Sie einen kompatiblen Wert für "app-version" fest. Gültige Versionsnummern sind ein bis drei durch Punkte getrennte Ganzzahlen. error.explicit-sign-no-cert=Signatur wurde explizit angefordert, doch es wurde kein Signaturzertifikat gefunden error.explicit-sign-no-cert.advice=Geben Sie gültige Werte für mac-signing-key-user-name und mac-signing-keychain an -error.must-sign-app-store=Mac App Store-Apps müssen signiert werden. Die Signierung wurde von der Bundler-Konfiguration deaktiviert -error.must-sign-app-store.advice=Verwenden Sie die Option --mac-sign mit entsprechenden Werten für user-name und keychain -error.certificate.expired=Fehler: Zertifikat abgelaufen {0} +error.certificate.expired=Zertifikat abgelaufen {0} error.cert.not.found=Kein Zertifikat gefunden, das [{0}] mit Schlüsselbund [{1}] entspricht -error.multiple.certs.found=WARNUNG: Mehrere Zertifikate gefunden, die [{0}] mit Schlüsselbund [{1}] entsprechen. Es wird das erste Zertifikat verwendet -error.app-image.mac-sign.required=Fehler: Die Option "--mac-sign" ist mit einem vordefinierten Anwendungsimage und Typ [app-image] erforderlich -error.tool.failed.with.output=Fehler: "{0}" nicht erfolgreich mit folgender Ausgabe: -resource.bundle-config-file=Bundle-Konfigurationsdatei +error.multiple.certs.found=Mehrere Zertifikate mit Namen [{0}] in Schlüsselbund [{1}] gefunden +error.app-image.mac-sign.required=Die Option --mac-sign ist mit einem vordefinierten Anwendungsimage und Typ [app-image] erforderlich +error.tool.failed.with.output="{0}" war mit folgender Ausgabe nicht erfolgreich: +error.invalid-runtime-image-missing-file=Im Laufzeitimage "{0}" fehlt die Datei "{1}" +error.invalid-runtime-image-bin-dir=Laufzeitimage "{0}" darf keinen Ordner "bin" enthalten +error.invalid-runtime-image-bin-dir.advice=Verwenden Sie die jlink-Option --strip-native-commands, wenn das Laufzeitimage mit Option {0} generiert wird resource.app-info-plist=Info.plist der Anwendung +resource.app-runtime-info-plist=Eingebettete Info.plist von Java Runtime resource.runtime-info-plist=Info.plist von Java Runtime resource.entitlements=Mac-Berechtigungen resource.dmg-setup-script=DMG-Setupskript @@ -56,21 +51,15 @@ resource.pkg-background-image=PKG-Hintergrundbild resource.pkg-pdf=Projektdefinitionsdatei resource.launchd-plist-file=launchd-PLIST-Datei - message.bundle-name-too-long-warning={0} ist auf "{1}" gesetzt. Dies ist länger als 16 Zeichen. Kürzen Sie den Wert, um die Mac-Nutzungserfahrung zu verbessern. message.preparing-info-plist=Info.plist wird vorbereitet: {0}. message.icon-not-icns= Das angegebene Symbol "{0}" ist keine ICNS-Datei und wird nicht verwendet. Stattdessen wird das Standardsymbol verwendet. message.version-string-too-many-components="app-version" darf ein bis drei Zahlen aufweisen: 1, 1.2, 1.2.3. message.version-string-first-number-not-zero=Die erste Zahl in app-version darf nicht null oder negativ sein. -message.creating-association-with-null-extension=Verknüpfung mit Nullerweiterung wird erstellt. -message.ignoring.symlink=Warnung: codesign überspringt den Symlink {0}. -message.already.signed=Datei ist bereits signiert: {0}. -message.keychain.error=Fehler: Schlüsselbundliste kann nicht abgerufen werden. -message.building-bundle=Mac App Store-Package für {0} wird erstellt. +message.keychain.error=Schlüsselbundliste kann nicht abgerufen werden. message.invalid-identifier=Ungültige Mac-Bundle-ID [{0}]. message.invalid-identifier.advice=Geben Sie die ID mit "--mac-package-identifier" an. message.building-dmg=DMG-Package für {0} wird erstellt. -message.running-script=Shellskript wird auf Anwendungsimage [{0}] ausgeführt. message.preparing-dmg-setup=DMG-Setup wird vorbereitet: {0}. message.creating-dmg-file=DMG-Datei wird erstellt: {0}. message.dmg-cannot-be-overwritten=DMG-Datei [{0}] ist vorhanden und kann nicht entfernt werden. @@ -84,3 +73,5 @@ message.codesign.failed.reason.app.content="codesign" war nicht erfolgreich, und message.codesign.failed.reason.xcode.tools=Möglicher Grund für "codesign"-Fehler ist fehlender Xcode mit Befehlszeilen-Entwicklertools. Installieren Sie Xcode mit Befehlszeilen-Entwicklertools, und prüfen Sie, ob das Problem dadurch beseitigt wird. warning.unsigned.app.image=Warnung: Nicht signiertes app-image wird zum Erstellen von signiertem {0} verwendet. warning.per.user.app.image.signed=Warnung: Konfiguration der installierten Anwendung pro Benutzer wird nicht unterstützt, da "{0}" im vordefinierten signierten Anwendungsimage fehlt. +warning.non.standard.contents.sub.dir=Warnung: Der Dateiname des Verzeichnisses "{0}", das für die Option --app-content angegeben wurde, ist kein Standardunterverzeichnisname im Verzeichnis "Contents" des Anwendungs-Bundles. Möglicherweise verläuft die Codesignierung und/oder Notarisierung im Ergebnisanwendungs-Bundle nicht erfolgreich. +warning.app.content.is.not.dir=Warnung: Der Wert "{0}" der Option --app-content ist kein Verzeichnis. Möglicherweise verläuft die Codesignierung und/oder Notarisierung im Ergebnisanwendungs-Bundle nicht erfolgreich. diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties index 4384d6507f9..d3150a34a86 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_ja.properties @@ -23,24 +23,19 @@ # questions. # # - -app.bundler.name=Macアプリケーション・イメージ -store.bundler.name=Mac App Storeの準備完了バンドラ -dmg.bundler.name=Mac DMGパッケージ -pkg.bundler.name=Mac PKGパッケージ - error.invalid-cfbundle-version.advice=互換性のある'app-version'値を設定します。有効なバージョンは、ドットで区切られた1から3つの整数です。 error.explicit-sign-no-cert=署名が明示的に要求されましたが、署名証明書が見つかりません error.explicit-sign-no-cert.advice=有効なmac-signing-key-user-nameおよびmac-signing-keychainを指定してください -error.must-sign-app-store=Mac App Storeアプリケーションは署名されている必要がありますが、署名はバンドラ構成によって無効化されています -error.must-sign-app-store.advice=--mac-signオプションを適切なuser-nameおよびkeychain付きで使用してください -error.certificate.expired=エラー: 証明書は{0}に期限が切れました +error.certificate.expired=証明書が期限切れです{0} error.cert.not.found=キーチェーン[{1}]を使用する[{0}]と一致する証明書が見つかりません -error.multiple.certs.found=警告: キーチェーン[{1}]を使用する[{0}]と一致する複数の証明書が見つかりました。最初のものを使用します -error.app-image.mac-sign.required=エラー: --mac-signオプションは、事前定義済アプリケーション・イメージおよびタイプ[app-image]で必要です -error.tool.failed.with.output=エラー: "{0}"は次の出力で失敗しました: -resource.bundle-config-file=バンドル構成ファイル +error.multiple.certs.found=名前[{0}]に一致する複数の証明書がキーチェーン[{1}]で見つかりました +error.app-image.mac-sign.required=--mac-signオプションは、事前定義済アプリケーション・イメージおよびタイプ[app-image]で必要です +error.tool.failed.with.output="{0}"は次の出力で失敗しました: +error.invalid-runtime-image-missing-file=ランタイム・イメージ"{0}"に"{1}"ファイルがありません +error.invalid-runtime-image-bin-dir=ランタイム・イメージ"{0}"に"bin"フォルダを含めることはできません +error.invalid-runtime-image-bin-dir.advice={0}オプションとともに使用されるランタイム・イメージを生成する場合は、--strip-native-commands jlinkオプションを使用します resource.app-info-plist=アプリケーションのInfo.plist +resource.app-runtime-info-plist=埋込みJavaランタイムのInfo.plist resource.runtime-info-plist=JavaランタイムのInfo.plist resource.entitlements=Mac権限 resource.dmg-setup-script=DMG設定スクリプト @@ -56,21 +51,15 @@ resource.pkg-background-image=pkg背景イメージ resource.pkg-pdf=プロジェクト定義ファイル resource.launchd-plist-file=launchd plistファイル - message.bundle-name-too-long-warning={0}が16文字を超える''{1}''に設定されています。Macでの操作性をより良くするために短くすることを検討してください。 message.preparing-info-plist=Info.plistを準備しています: {0}。 message.icon-not-icns= 指定したアイコン"{0}"はICNSファイルではなく、使用されません。デフォルト・アイコンがその位置に使用されます。 message.version-string-too-many-components='app-version'には、1、1.2、1.2.3など1から3の数字を使用できます。 message.version-string-first-number-not-zero=pp-versionの最初の数字は、ゼロまたは負の値にできません。 -message.creating-association-with-null-extension=null拡張子との関連付けを作成しています。 -message.ignoring.symlink=警告: codesignがsymlink {0}をスキップしています -message.already.signed=ファイルはすでに署名されています: {0}。 -message.keychain.error=エラー: キーチェーン・リストを取得できません。 -message.building-bundle={0}のMac App Storeパッケージを作成しています。 +message.keychain.error=キーチェーン・リストを取得できません。 message.invalid-identifier=macバンドル識別子[{0}]が無効です。 message.invalid-identifier.advice="--mac-package-identifier"で識別子を指定してください。 message.building-dmg={0}のDMGパッケージを作成しています -message.running-script=アプリケーション・イメージ[{0}]でシェル・スクリプトを実行しています。 message.preparing-dmg-setup=dmgの設定を準備しています: {0} message.creating-dmg-file=DMGファイルを作成しています: {0} message.dmg-cannot-be-overwritten=Dmgファイルは存在し[{0}]、削除できません。 @@ -84,3 +73,5 @@ message.codesign.failed.reason.app.content="codesign"が失敗したため、追 message.codesign.failed.reason.xcode.tools="codesign"失敗の考えられる理由は、Xcodeとコマンドライン・デベロッパ・ツールの欠落です。Xcodeとコマンドライン・デベロッパ・ツールをインストールして、問題が解決されるかを確認してください。 warning.unsigned.app.image=警告: 署名されていないapp-imageを使用して署名された{0}を作成します。 warning.per.user.app.image.signed=警告: 事前定義済の署名付きアプリケーション・イメージに"{0}"がないため、インストール済アプリケーションのユーザーごとの構成はサポートされません。 +warning.non.standard.contents.sub.dir=警告: --app-contentオプションに指定されたディレクトリ"{0}"のファイル名が、アプリケーション・バンドルの"Contents"ディレクトリ内の標準サブディレクトリ名ではありません。結果アプリケーション・バンドルは、コード署名および/または公証に失敗することがあります。 +warning.app.content.is.not.dir=警告: --app-contentオプションの値"{0}"はディレクトリではありません。結果アプリケーション・バンドルは、コード署名または公証(あるいはその両方)に失敗することがあります。 diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties index 09c6d77694a..8ca2219b72f 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/resources/MacResources_zh_CN.properties @@ -23,24 +23,19 @@ # questions. # # - -app.bundler.name=Mac 应用程序映像 -store.bundler.name=支持 Mac App Store 的打包程序 -dmg.bundler.name=Mac DMG 程序包 -pkg.bundler.name=Mac PKG 程序包 - error.invalid-cfbundle-version.advice=设置兼容的 'app-version' 值。有效版本包含一到三个用点分隔的整数。 error.explicit-sign-no-cert=已明确请求签名,但找不到签名证书 error.explicit-sign-no-cert.advice=指定有效的 mac-signing-key-user-name 和 mac-signing-keychain -error.must-sign-app-store=Mac App Store 应用程序必须签名, 而打包程序配置已禁用签名 -error.must-sign-app-store.advice=将 --mac-sign 选项用于适当的用户名和密钥链 -error.certificate.expired=错误: 证书已失效 {0} +error.certificate.expired=证书已到期 {0} error.cert.not.found=使用密钥链 [{1}] 找不到与 [{0}] 匹配的证书 -error.multiple.certs.found=警告:使用密钥链 [{1}] 找到多个与 [{0}] 匹配的证书,将使用第一个证书 -error.app-image.mac-sign.required=错误:预定义的应用程序映像和类型 [app image] 需要 --mac-sign 选项 -error.tool.failed.with.output=错误:"{0}" 失败,显示以下输出: -resource.bundle-config-file=包配置文件 +error.multiple.certs.found=在密钥链 [{1}] 中找到多个与名称 [{0}] 匹配的证书 +error.app-image.mac-sign.required=预定义的应用程序映像和类型 [app-image] 需要 --mac-sign 选项 +error.tool.failed.with.output="{0}" 失败,显示以下输出: +error.invalid-runtime-image-missing-file=运行时映像 "{0}" 缺少 "{1}" 文件 +error.invalid-runtime-image-bin-dir=运行时映像 "{0}" 不应包含 "bin" 文件夹 +error.invalid-runtime-image-bin-dir.advice=生成与 {0} 选项一起使用的运行时映像时,使用 --strip-native-commands jlink 选项 resource.app-info-plist=应用程序 Info.plist +resource.app-runtime-info-plist=嵌入式 Java 运行时 Info.plist resource.runtime-info-plist=Java 运行时 Info.plist resource.entitlements=Mac 权利 resource.dmg-setup-script=DMG 设置脚本 @@ -56,21 +51,15 @@ resource.pkg-background-image=pkg 背景图像 resource.pkg-pdf=项目定义文件 resource.launchd-plist-file=launchd plist 文件 - message.bundle-name-too-long-warning={0}已设置为 ''{1}'', 其长度超过了 16 个字符。为了获得更好的 Mac 体验, 请考虑将其缩短。 message.preparing-info-plist=正在准备 Info.plist: {0}。 message.icon-not-icns= 指定的图标 "{0}" 不是 ICNS 文件, 不会使用。将使用默认图标代替。 message.version-string-too-many-components='app-version' 可以包含 1 到 3 个数字:1、1.2、1.2.3。 message.version-string-first-number-not-zero=app-version 中的第一个数字不能为零或负数。 -message.creating-association-with-null-extension=正在使用空扩展名创建关联。 -message.ignoring.symlink=警告: codesign 正在跳过符号链接 {0}。 -message.already.signed=文件已签名:{0}。 -message.keychain.error=错误:无法获取密钥链列表。 -message.building-bundle=正在为 {0} 构建 Mac App Store 程序包。 -message.invalid-identifier=无效的 Mac 包标识符 [{0}]。 +message.keychain.error=无法获取密钥链列表。 +message.invalid-identifier=mac 包标识符 [{0}] 无效。 message.invalid-identifier.advice=请使用 "--mac-package-identifier" 指定标识符。 message.building-dmg=正在为 {0} 构建 DMG 程序包。 -message.running-script=正在应用程序映像 [{0}] 上运行 shell 脚本。 message.preparing-dmg-setup=正在准备 dmg 设置: {0}。 message.creating-dmg-file=正在创建 DMG 文件: {0}。 message.dmg-cannot-be-overwritten=Dmg 文件已存在 [{0}] 且无法删除。 @@ -84,3 +73,5 @@ message.codesign.failed.reason.app.content="codesign" 失败,并通过 "--app- message.codesign.failed.reason.xcode.tools="codesign" 失败可能是因为缺少带命令行开发人员工具的 Xcode。请安装带命令行开发人员工具的 Xcode,看看是否可以解决问题。 warning.unsigned.app.image=警告:使用未签名的 app-image 生成已签名的 {0}。 warning.per.user.app.image.signed=警告:由于预定义的已签名应用程序映像中缺少 "{0}",不支持对已安装应用程序的每用户配置提供支持。 +warning.non.standard.contents.sub.dir=警告:为 --app-content 选项指定的目录 "{0}" 的文件名不是应用程序包的 "Contents" 目录中的标准子目录名称。结果应用程序包可能会使代码签名和/或公证失败。 +warning.app.content.is.not.dir=警告:--app-content 选项的值 "{0}" 不是目录。结果应用程序包可能会使代码签名和/或公证失败。 diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties index c1cb5bf4283..5b9a5728912 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_de.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2025, 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,19 +24,163 @@ # # -MSG_Help=Verwendung: jpackage \n\nBeispielverwendungen:\n--------------\n Generiert ein für das Hostsystem geeignetes Anwendungspackage:\n Für eine modulare Anwendung:\n jpackage -n name -p modulePath -m moduleName/className\n Für eine nicht modulare Anwendung:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n Aus einem vorab erstellten Anwendungsimage:\n jpackage -n name --app-image appImageDir\n Generiert ein Anwendungsimage:\n Für eine modulare Anwendung:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n Für eine nicht modulare Anwendung:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n Um eigene Optionen für jlink anzugeben, führen Sie jlink separat aus:\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage\n Generiert ein Java Runtime-Package:\n jpackage -n name --runtime-image \n{6}\nAllgemeine Optionen:\n @ \n Liest Optionen und/oder Modus aus einer Datei \n Diese Option kann mehrmals verwendet werden.\n --type -t \n Der zu erstellende Packagetyp\n Gültige Werte: {1} \n Bei fehlender Angabe dieser Option wird ein plattformabhängiger\n Standardtyp erstellt.\n --app-version \n Version der Anwendung und/oder des Packages\n --copyright \n Copyright für die Anwendung\n --description \n Beschreibung der Anwendung\n --help -h \n Gibt den Verwendungstext mit einer Liste und Beschreibung jeder gültigen\n Option für die aktuelle Plattform an den Ausgabestream aus und beendet den Vorgang\n --icon \n Pfad des Symbols für das Anwendungspackage\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n --name -n \n Name der Anwendung und/oder des Packages\n --dest -d \n Pfad, in den die generierte Ausgabedatei abgelegt wird\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Standardmäßig wird das aktuelle Arbeitsverzeichnis verwendet.\n --temp \n Pfad eines neuen oder leeren Verzeichnisses zum Erstellen temporärer Dateien\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Falls angegeben, wird das temporäre Verzeichnis beim Abschließen der Aufgabe\n nicht entfernt und muss manuell entfernt werden.\n Bei fehlender Angabe wird ein temporäres Verzeichnis erstellt und\n beim Abschließen der Aufgabe entfernt.\n --vendor \n Anbieter der Anwendung\n --verbose\n Aktiviert Ausgabe im Verbose-Modus\n --version\n Gibt die Produktversion an den Outputstream aus und beendet den Vorgang.\n\nOptionen für das Erstellen des Laufzeitimages:\n --add-modules [,...]\n Eine per Komma (",") getrennte Liste hinzuzufügender Module\n Diese Modulliste wird zusammen mit dem Hauptmodul (sofern angegeben)\n als Argument --add-module an jlink übergeben.\n Bei fehlender Angabe wird entweder nur das Hauptmodul (sofern --module\n angegeben ist) oder das Standardset an Modulen (sofern --main-jar \n angegeben ist) verwendet.\n Diese Option kann mehrmals verwendet werden.\n --module-path -p ...\n \ -Eine per {0} getrennte Pfadliste\n Jeder Pfad ist entweder ein Verzeichnis mit Modulen oder der Pfad zu einer\n JAR-Datei eines Moduls.\n (Jeder Pfad ist absolut oder relativ zum aktuellen Verzeichnis.)\n Diese Option kann mehrmals verwendet werden.\n --jlink-options \n Eine per Leerzeichen getrennte Liste mit an jlink zu übergebenden Optionen \n Bei fehlender Angabe wird standardmäßig "--strip-native-commands \n --strip-debug --no-man-pages --no-header-files" verwendet. \n Diese Option kann mehrmals verwendet werden.\n --runtime-image \n Pfad des vordefinierten Laufzeitimages, das in\n das Anwendungsimage kopiert wird\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Wenn --runtime-image nicht angegeben wird, führt jpackage jlink aus, um\n das Laufzeitimage mit folgenden Optionen zu erstellen:\n --strip-debug, --no-header-files, --no-man-pages und\n --strip-native-commands.\n\nOptionen für das Erstellen des Anwendungsimages:\n --input -i \n Pfad des Eingabeverzeichnisses mit den zu verpackenden Dateien\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Alle Dateien im Eingabeverzeichnis werden verpackt für das\n Anwendungsimage integriert.\n --app-content [,...]\n Eine per Komma getrennte Liste mit Pfaden zu Dateien und/oder Verzeichnissen,\n die zur Anwendungs-Payload hinzugefügt werden sollen.\n Diese Option kann mehrmals verwendet werden.\n\nOptionen für das Erstellen des Anwendungs-Launchers:\n --add-launcher =\n Name des Launchers sowie ein Pfad zu einer Eigenschaftendatei mit\n einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Die Schlüssel "module", "main-jar", "main-class", "description",\n "arguments", "java-options", "app-version", "icon",\n "launcher-as-service",\n "win-console", "win-shortcut", "win-menu",\n "linux-app-category" und "linux-shortcut" können verwendet werden.\n Diese Optionen werden den ursprünglichen Befehlszeilenoptionen hinzugefügt\n (oder überschreiben diese), um einen zusätzlichen, alternativen Launcher zu erstellen.\n Der Hauptanwendungs-Launcher wird aus den Befehlszeilenoptionen\n erstellt. Mit dieser Option können zusätzliche alternative Launcher\n erstellt werden. Außerdem kann diese Option mehrmals verwendet werden,\n um mehrere zusätzliche Launcher zu erstellen. \n --arguments \n Befehlszeilenargumente, die an die Hauptklasse übergeben werden, falls\n keine Befehlszeilenargumente an den Launcher übergeben werden\n Diese Option kann mehrmals verwendet werden.\n --java-options \n Optionen, die an Java Runtime übergeben werden\n Diese Option kann mehrmals verwendet werden.\n --main-class \n Qualifizierter Name der auszuführenden Anwendungshauptklasse\n Diese Option kann nur bei Angabe von --main-jar verwendet werden.\n --main-jar \n Die Haupt-JAR-Datei der Anwendung, die die Hauptklasse enthält\n (angegeben als Pfad relativ zum Eingabepfad)\n Es kann entweder die Option --module oder die Option --main-jar angegeben werden, nicht jedoch\n beides.\n --module -m [/]\n Das Hauptmodul (und optional die Hauptklasse) der Anwendung\n Dieses Modul muss unter dem Modulpfad gespeichert sein.\n Bei Angabe dieser Option wird das Hauptmodul\n \ -im Java Runtime-Image verknüpft. Es kann entweder die Option --module oder die Option --main-jar\n angegeben werden, nicht jedoch beides.\n{2}\nOptionen für das Erstellen des Anwendungspackages:\n --about-url \n URL der Homepage der Anwendung\n --app-image \n {5} (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n --file-associations \n Pfad zu einer Eigenschaftendatei mit einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Mit den Schlüsseln "extension", "mime-type", "icon" und "description"\n kann die Verknüpfung beschrieben werden.\n Diese Option kann mehrmals verwendet werden.\n --install-dir \n {4} --license-file \n Pfad zur Lizenzdatei\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n --resource-dir \n Pfad zum Überschreiben von jpackage-Ressourcen\n Symbole, Vorlagendateien und weitere Ressourcen von jpackage können\n durch Hinzufügen von Ersetzungsressourcen zu diesem Verzeichnis überschrieben werden.\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n --runtime-image \n Pfad des zu installierenden vordefinierten Laufzeitimages\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Option muss beim Erstellen eines Laufzeitpackages angegeben werden.\n --launcher-as-service\n Anforderung zum Erstellen eines Installationsprogramms, das den\n Hauptanwendungs-Launcher als Hintergrundserviceanwendung registriert.\n\nPlattformabhängige Optionen für das Erstellen des Anwendungspackages:\n{3} +help.header=Verwendung: jpackage + +help.short=Verwenden Sie jpackage --help (oder -h), um eine Liste möglicher Optionen aufzurufen + +help.option-group.sample.create-native-package=\ Generieren Sie ein Anwendungspackage, das für das Hostsystem geeignet ist:\n Für eine modulare Anwendung:\n jpackage -n name -p modulePath -m moduleName/className\n Für eine nicht modulare Anwendung:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n Aus einem vordefinierten Anwendungsimage:\n jpackage -n name --app-image appImageDir + +help.option-group.sample.create-app-image=\ Generieren Sie ein Anwendungspackage:\n Für eine modulare Anwendung:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n Für eine nicht modulare Anwendung:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n Um eigene Optionen für jlink anzugeben, führen Sie jlink separat aus:\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage + +help.option-group.sample.create-runtime-installer=\ Generieren Sie ein Java-Laufzeitpackage:\n jpackage -n name --runtime-image + +help.option-group.sample.sign-app-image=\ Vordefiniertes Anwendungsimage signieren:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n Hinweis: In diesem Modus sind nur die folgenden zusätzlichen Optionen zulässig:\n Das Set der zusätzlichen Mac-Signaturoptionen und --verbose + +help.option-group.sample=Beispielverwendungen +help.option-group.generic=Allgemeine Optionen +help.option-group.runtime-image=Optionen für das Erstellen des Laufzeitimages +help.option-group.app-image=Optionen für das Erstellen des Anwendungsimages +help.option-group.launcher=Optionen für das Erstellen der Anwendungslauncher: +help.option-group.launcher-platform=Plattformabhängige Option für das Erstellen des Anwendungslaunchers +help.option-group.package=Optionen für das Erstellen des Anwendungspackages +help.option-group.package-platform=Plattformabhängige Optionen für das Erstellen des Anwendungspackages + +help.option.argument-file=\ Leseoptionen und/oder -modus aus einer Datei\n Diese Option kann mehrmals verwendet werden. + +help.option.about-url=\ URL der Homepage der Anwendung + +help.option.add-launcher.win=\ Name des Launchers sowie ein Pfad zu einer Eigenschaftendatei mit\n einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Die Schlüssel "arguments", "description", "icon", "java-options",\n "launcher-as-service", "main-class", "main-jar", "module",\n "win-console", "win-menu" und "win-shortcut" können verwendet werden. \n Diese Optionen werden den ursprünglichen\n Befehlszeilenoptionen hinzugefügt (oder überschreiben diese), um einen zusätzlichen, alternativen Launcher zu erstellen.\n Der Hauptanwendungslauncher wird aus den Befehlszeilenoptionen\n erstellt. Mit dieser Option können zusätzliche alternative Launcher\n erstellt werden. Außerdem kann diese Option mehrmals verwendet werden,\n um mehrere zusätzliche Launcher zu erstellen. + +help.option.add-launcher.linux=\ Name des Launchers sowie ein Pfad zu einer Eigenschaftendatei mit\n einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Die Schlüssel "arguments", "description", "icon", "java-options",\n "launcher-as-service", "linux-shortcut", "main-class", "main-jar"\n und "module" können verwendet werden. \n Diese Optionen werden den ursprünglichen Befehlszeilenoptionen hinzugefügt\n (oder überschreiben diese), um einen zusätzlichen, alternativen Launcher zu erstellen. \n Der Hauptanwendungslauncher wird aus den Befehlszeilenoptionen\n erstellt. Mit dieser Option können zusätzliche alternative Launcher\n erstellt werden. Außerdem kann diese Option mehrmals verwendet werden,\n um mehrere zusätzliche Launcher zu erstellen. + +help.option.add-launcher.mac=\ Name des Launchers sowie ein Pfad zu einer Eigenschaftendatei mit\n einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Die Schlüssel "arguments", "description", "icon", "java-options",\n "launcher-as-service", "main-class", "main-jar"\n und "module" können verwendet werden. \n Diese Optionen werden den ursprünglichen Befehlszeilenoptionen hinzugefügt\n (oder überschreiben diese), um einen zusätzlichen, alternativen Launcher zu erstellen. \n Der Hauptanwendungslauncher wird aus den Befehlszeilenoptionen\n erstellt. Mit dieser Option können zusätzliche alternative Launcher\n erstellt werden. Außerdem kann diese Option mehrmals verwendet werden,\n um mehrere zusätzliche Launcher zu erstellen. + +help.option.add-modules=\ Eine per Komma (",") getrennte Liste hinzuzufügender Module\n Diese Modulliste wird zusammen mit dem Hauptmodul (sofern angegeben)\n als Argument --add-module an jlink übergeben. \n Bei fehlender Angabe wird entweder nur das Hauptmodul (sofern --module\n angegeben ist) oder das Standardset an Modulen (sofern --main-jar\n angegeben ist) verwendet. \n Diese Option kann mehrmals verwendet werden. + +help.option.app-content=\ Eine per Komma getrennte Liste mit Pfaden zu Dateien und/oder Verzeichnissen,\n die zur Anwendungs-Payload hinzugefügt werden sollen.\n Diese Option kann mehrmals verwendet werden. + +help.option.app-content.mac=\ Eine per Komma getrennte Liste mit Pfaden zu Dateien und/oder Verzeichnissen,\n die zur Anwendungs-Payload hinzugefügt werden sollen. \n Diese Option kann mehrmals verwendet werden. \n Hinweis: Der Wert muss ein Verzeichnis mit dem Unterverzeichnis "Resources" sein\n Unterverzeichnis (oder ein anderes Verzeichnis, das im Verzeichnis "Contents"\n des Anwendungs-Bundles gültig ist). Andernfalls produziert jpackage möglicherweise ein\n ungültiges Anwendungs-Bundle, bei dem die Codesignatur und/oder Notarisierung nicht erfolgreich\n verläuft. + +help.option.app-image=\ Speicherort des vordefinierten Anwendungsimages, mit dem\n ein installierbares Package erstellt wird\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis) + +help.option.app-image.mac=\ Speicherort des vordefinierten Anwendungsimages, mit dem\n ein installierbares Package erstellt oder das vordefinierte\n Anwendungsimage signiert wird\n (absoluter Pfad bzw. relativ zum aktuellen Verzeichnis) + +help.option.app-version=\ Version der Anwendung und/oder des Packages + +help.option.arguments=\ Befehlszeilenargumente, die an die Hauptklasse übergeben werden, falls\n keine Befehlszeilenargumente an den Launcher übergeben werden\n Diese Option kann mehrmals verwendet werden. + +help.option.copyright=\ Copyright für die Anwendung + +help.option.description=\ Beschreibung der Anwendung + +help.option.dest=\ Pfad, in dem die generierte Ausgabedatei abgelegt wird\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Standardmäßig wird das aktuelle Arbeitsverzeichnis verwendet. + +help.option.file-associations=\ Pfad zu einer Eigenschaftendatei mit einer Liste von Schlüssel/Wert-Paaren\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Mit den Schlüsseln "extension", "mime-type", "icon" und "description"\n kann die Verknüpfung beschrieben werden.\n Diese Option kann mehrmals verwendet werden. + +help.option.help=\ Gibt den Verwendungstext mit einer Liste und Beschreibung jeder gültigen\n Option für die aktuelle Plattform an den Outputstream aus und beendet den Vorgang + +help.option.icon=\ Pfad des Symbols für das Anwendungspackage\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis) + +help.option.input=\ Pfad des Eingabeverzeichnisses mit den zu verpackenden Dateien\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Alle Dateien im Eingabeverzeichnis werden als Package in das\n Anwendungsimage integriert. + +help.option.install-dir=\ Absoluter Pfad des Installationsverzeichnisses der Anwendung + +help.option.install-dir.win=\ Relativer Unterpfad des Installationsverzeichnisses der\n Anwendung, wie "Programme" oder "AppData". + +help.option.installer-runtime-image=\ Pfad des zu installierenden vordefinierten Laufzeitimages\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Option muss beim Erstellen eines Laufzeitpackages angegeben werden. + +help.option.java-options=\ Optionen, die an Java Runtime übergeben werden\n Diese Option kann mehrmals verwendet werden. + +help.option.jlink-options=\ Eine per Leerzeichen getrennte Liste mit an jlink zu übergebenden Optionen\n Bei fehlender Angabe wird standardmäßig "--strip-native-commands\n --strip-debug --no-man-pages --no-header-files" verwendet. \n Diese Option kann mehrmals verwendet werden. + +help.option.launcher-as-service=\ Anforderung zum Erstellen eines Installationsprogramms, das den\n Hauptanwendungslauncher als Hintergrundserviceanwendung registriert. + +help.option.license-file=\ Pfad zur Lizenzdatei\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis) + +help.option.linux-app-category=\ Gruppenwert der RPM-Datei .spec oder\n Abschnittswert der DEB-Kontrolldatei + +help.option.linux-app-release=\ Releasewert der RPM-Datei .spec oder\n Debian-Revisionswert der DEB-Kontrolldatei + +help.option.linux-deb-maintainer=\ Maintainer für DEB-Package + +help.option.linux-menu-group=\ Menügruppe, in der diese Anwendung abgelegt wird + +help.option.linux-package-deps=\ Erforderliche Packages oder Funktionen für die Anwendung + +help.option.linux-package-name=\ Name für das Linux-Package, Standardwert: Anwendungsname + +help.option.linux-rpm-license-type=\ Lizenztyp ("Lizenz: " der RPM-SPEC-Datei) + +help.option.linux-shortcut=\ Erstellt eine Verknüpfung für die Anwendung. + +help.option.mac-app-category=\ Zeichenfolge für das Erstellen von LSApplicationCategoryType in\n Anwendungs-plist. Standardwert: "utilities". + +help.option.mac-app-image-sign-identity=\ Zum Signieren des Anwendungsimages verwendete Identität. Dieser Wert wird direkt\n an die Option --sign des Tools "codesign" übergeben. Diese Option kann nicht\n mit --mac-signing-key-user-name kombiniert werden. + +help.option.mac-app-store=\ Gibt an, dass die jpackage-Ausgabe für den\n Mac App Store vorgesehen ist. + +help.option.mac-dmg-content=\ Nimmt den gesamten referenzierten Inhalt in die DMG-Datei auf.\n Diese Option kann mehrmals verwendet werden. + +help.option.mac-entitlements=\ Pfad zu einer Datei mit Berechtigungen, die beim Signieren von ausführbaren\n Dateien und Librarys im Bundle verwendet werden sollen. + +help.option.mac-installer-sign-identity=\ Zum Signieren des Installationsprogramms "pkg" verwendete Identität. Dieser Wert wird direkt\n an die Option --sign des Tools "productbuild"-übergeben. Diese Option\n kann nicht mit --mac-signing-key-user-name kombiniert werden. + +help.option.mac-package-identifier=\ Eine ID, die die Anwendung für macOS eindeutig identifiziert\n Standardwert ist der Hauptklassenname. \n Es dürfen nur alphanumerische Zeichen (A-Z, a-z, 0-9), Bindestriche (-)\n und Punkte (.) verwendet werden. + +help.option.mac-package-name=\ Name der Anwendung, wie in der Menüleiste angezeigt\n Dieser kann vom Anwendungsnamen abweichen.\n Er darf maximal 15 Zeichen enthalten und muss für die Anzeige\n in der Menüleiste und im Infofenster der Anwendung geeignet sein.\n Standardwert: Anwendungsname. + +help.option.mac-package-signing-prefix=\ Beim Signieren des Anwendungspackages wird dieser Wert\n allen zu signierenden Komponenten ohne vorhandene\n Package-ID als Präfix vorangestellt. + +help.option.mac-sign=\ Anforderung zum Signieren des Packages oder des vordefinierten\n Anwendungsimages. + +help.option.mac-signing-keychain=\ Name des Schlüsselbundes für die Suche nach der Signaturidentität\n Bei fehlender Angabe werden die Standardschlüsselbunde verwendet. + +help.option.mac-signing-key-user-name=\ Team- oder Benutzernamensteil der Apple-Signaturidentitäten. Um direkt zu steuern,\n welche Signaturidentität zum Signieren eines Anwendungsimages oder\n Installationsprogramms verwendet wird, verwenden Sie --mac-app-image-sign-identity und/oder\n --mac-installer-sign-identity. Diese Option kann nicht mit\n --mac-app-image-sign-identity oder --mac-installer-sign-identity kombiniert werden. + +help.option.main-class=\ Qualifizierter Name der auszuführenden Anwendungshauptklasse\n Diese Option kann nur bei Angabe von --main-jar verwendet werden. + +help.option.main-jar=\ Die Haupt-JAR-Datei der Anwendung, die die Hauptklasse enthält\n (angegeben als Pfad relativ zum Eingabepfad)\n Es kann entweder die Option --module oder die Option --main-jar angegeben werden, nicht jedoch\n beides. + +help.option.module=\ Das Hauptmodul (und optional die Hauptklasse) der Anwendung\n Dieses Modul muss unter dem Modulpfad gespeichert sein. \n Bei Angabe dieser Option wird das Hauptmodul\n im Java Runtime-Image verknüpft. Es kann entweder die Option --module oder die Option --main-jar\n angegeben werden, nicht jedoch beides. + +help.option.module-path=\ Eine per Doppelpunkt (:) getrennte Pfadliste\n Jeder Pfad ist entweder ein Verzeichnis mit Modulen oder der Pfad zu einer\n modularen JAR-Datei.\n (Jeder Pfad ist absolut oder relativ zum aktuellen Verzeichnis.)\n Diese Option kann mehrmals verwendet werden. +help.option.module-path.win=\ Eine per Semikolon (;) getrennte Pfadliste\n Jeder Pfad ist entweder ein Verzeichnis mit Modulen oder der Pfad zu einer\n modularen JAR-Datei.\n (Jeder Pfad ist absolut oder relativ zum aktuellen Verzeichnis.)\n Diese Option kann mehrmals verwendet werden. + +help.option.name=\ Name der Anwendung und/oder des Packages + +help.option.resource-dir=\ Pfad zum Überschreiben von jpackage-Ressourcen\n Symbole, Vorlagendateien und weitere Ressourcen von jpackage können\n durch Hinzufügen von Ersetzungsressourcen zu diesem Verzeichnis überschrieben werden.\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis) + +help.option.runtime-image=\ Pfad des vordefinierten Laufzeitimages, das in\n das Anwendungsimage kopiert wird\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Wenn --runtime-image nicht angegeben wird, führt jpackage jlink aus, um\n das Laufzeitimage mit folgenden Optionen zu erstellen:\n --strip-debug, --no-header-files, --no-man-pages und\n --strip-native-commands. + +help.option.temp=\ Pfad eines neuen oder leeren Verzeichnisses zum Erstellen temporärer Dateien\n (absoluter Pfad oder relativ zum aktuellen Verzeichnis)\n Falls angegeben, wird das temporäre Verzeichnis beim Abschließen der Aufgabe\n nicht entfernt und muss manuell entfernt werden. \n Bei fehlender Angabe wird ein temporäres Verzeichnis erstellt und\n beim Abschließen der Aufgabe entfernt. + +help.option.type.win=\ Der zu erstellende Packagetyp\n Gültige Werte sind: {"app-image", "exe", "msi"}\n Bei fehlender Angabe dieser Option wird ein plattformabhängiger\n Standardtyp erstellt. +help.option.type.linux=\ Der zu erstellende Packagetyp\n Gültige Werte sind: {"app-image", "deb", "rpm"}\n Bei fehlender Angabe dieser Option wird ein plattformabhängiger\n Standardtyp erstellt. +help.option.type.mac=\ Der zu erstellende Packagetyp\n Gültige Werte sind: {"app-image", "dmg", "pkg"}\n Bei fehlender Angabe dieser Option wird ein plattformabhängiger\n Standardtyp erstellt. + +help.option.vendor=\ Anbieter der Anwendung + +help.option.verbose=\ Aktiviert Ausgabe im Verbose-Modus + +help.option.version=\ Gibt die Produktversion an den Outputstream aus und beendet den Vorgang. + +help.option.win-console=\ Erstellt einen Konsolenlauncher für die Anwendung. Sollte für\n Anwendungen angegeben werden, die Konsoleninteraktionen erfordern + +help.option.win-dir-chooser=\ Fügt ein Dialogfeld hinzu, in dem der Benutzer das Verzeichnis auswählen kann, in dem\n das Produkt installiert wird. + +help.option.win-help-url=\ URL, unter der der Benutzer weitere Informationen oder technische Unterstützung erhält + +help.option.win-menu=\ Anforderung zum Hinzufügen einer Startmenüverknüpfung für diese Anwendung + +help.option.win-menu-group=\ Startmenügruppe, in der diese Anwendung abgelegt wird + +help.option.win-per-user-install=\ Anforderung zum Ausführen einer Installation pro Benutzer + +help.option.win-shortcut=\ Anforderung zum Hinzufügen einer Desktopverknüpfung für diese Anwendung + +help.option.win-shortcut-prompt=\ Fügt ein Dialogfeld hinzu, in dem der Benutzer auswählen kann, ob Verknüpfungen\n vom Installationsprogramm erstellt werden. + +help.option.win-update-url=\ URL der verfügbaren Anwendungsaktualisierungsinformationen + +help.option.win-upgrade-uuid=\ UUID für Upgrades für dieses Package -MSG_Help_win_launcher=\nPlattformabhängige Option für das Erstellen des Anwendungs-Launchers:\n --win-console\n Erstellt einen Konsolen-Launcher für die Anwendung. Sollte für\n Anwendungen angegeben werden, die Konsoleninteraktionen erfordern\n -MSG_Help_win_install=\ --win-dir-chooser\n Fügt ein Dialogfeld hinzu, in dem der Benutzer das Verzeichnis auswählen kann, in dem\n das Produkt installiert wird.\n --win-help-url \n URL, unter der der Benutzer weitere Informationen oder technische Unterstützung erhält\n --win-menu\n Anforderung zum Hinzufügen einer Startmenüverknüpfung für diese Anwendung\n --win-menu-group \n Startmenügruppe, in der diese Anwendung abgelegt wird\n --win-per-user-install\n Anforderung zum Ausführen einer Installation pro Benutzer\n --win-shortcut\n Anforderung zum Hinzufügen einer Desktopverknüpfung für diese Anwendung\n --win-shortcut-prompt\n Fügt ein Dialogfeld hinzu, in dem der Benutzer auswählen kann, ob Verknüpfungen\n vom Installationsprogramm erstellt werden sollen.\n --win-update-url \n URL verfügbarer Anwendungsupdateinformationen\n --win-upgrade-uuid \n UUID, die mit Upgrades für dieses Package verknüpft ist\n -MSG_Help_win_install_dir=Relativer Unterpfad unter dem Standardinstallationsverzeichnis\n -MSG_Help_mac_install=\ --mac-dmg-content [,...]\n Nimmt den gesamten referenzierten Inhalt in die DMG-Datei auf.\n Diese Option kann mehrmals verwendet werden. \n -MSG_Help_mac_launcher=\ --mac-package-identifier \n Eine ID, die die Anwendung für macOS eindeutig identifiziert\n Standardwert ist der Hauptklassenname.\n Es dürfen nur alphanumerische Zeichen (A-Z, a-z, 0-9), Bindestriche (-)\n und Punkte (.) verwendet werden.\n --mac-package-name \n Name der Anwendung, wie in der Menüleiste angezeigt\n Dieser kann vom Anwendungsnamen abweichen.\n Er darf maximal 15 Zeichen enthalten und muss für die Anzeige\n in der Menüleiste und im Infofenster der Anwendung geeignet sein.\n Standardwert: Anwendungsname.\n --mac-package-signing-prefix \n Beim Signieren des Anwendungspackages wird dieser Wert\n allen zu signierenden Komponenten ohne vorhandene\n Package-ID als Präfix vorangestellt.\n --mac-sign\n Anforderung zum Signieren des Packages oder des vordefinierten\nAnwendungsimages\n --mac-signing-keychain \n Name des Schlüsselbundes für die Suche nach der Signaturidentität\n Bei fehlender Angabe werden die Standardschlüsselbunde verwendet.\n --mac-signing-key-user-name \n Team- oder Benutzernamensteil der Apple-Signaturidentitäten. Um direkt zu steuern,\n welche Signaturidentität zum Signieren eines Anwendungsimages oder\n Installationsprogramms verwendet wird, verwenden Sie --mac-app-image-sign-identity und/oder\n --mac-installer-sign-identity. Diese Option kann nicht mit\n --mac-app-image-sign-identity oder --mac-installer-sign-identity kombiniert werden.\n --mac-app-image-sign-identity \n Zum Signieren des Anwendungsimages verwendete Identität. Dieser Wert wird\n direkt an die Option --sign des Tools "codesign" übergeben. Diese Option kann nicht\n mit --mac-signing-key-user-name kombiniert werden.\n --mac-installer-sign-identity \n Zum Signieren des Installationsprogramms "pkg" verwendete Identität. Dieser Wert wird\n direkt an die Option --sign des Tools "productbuild" übergeben. Diese Option\n kann nicht mit --mac-signing-key-user-name kombiniert werden.\n --mac-app-store\n Gibt an, dass die jpackage-Ausgabe für den\n Mac App Store bestimmt ist.\n --mac-entitlements \n Pfad zu einer Datei mit Berechtigungen, die beim Signieren\n von ausführbaren Dateien und Librarys im Bundle verwendet werden sollen.\n --mac-app-category \n Zeichenfolge für das Erstellen von LSApplicationCategoryType in\n Anwendungs-plist. Standardwert: "utilities".\n -MSG_Help_linux_install=\ --linux-package-name \n Name für das Linux-Package, Standardwert: Anwendungsname\n --linux-deb-maintainer \n Maintainer für .deb-Package\n --linux-menu-group \n Menügruppe, in der diese Anwendung abgelegt wird\n --linux-package-deps \n Erforderliche Packages oder Funktionen für die Anwendung\n --linux-rpm-license-type \n Typ der Lizenz ("License: " der RPM-SPEC-Datei)\n --linux-app-release \n Releasewert der RPM-Datei .spec oder \n Debian-Revisionswert der DEB-Kontrolldatei\n --linux-app-category \n Gruppenwert der RPM-Datei .spec oder \n Abschnittswert der DEB-Kontrolldatei\n --linux-shortcut\n Erstellt einen Shortcut für die Anwendung.\n -MSG_Help_mac_linux_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung\n -MSG_Help_default_install_dir=Absoluter Pfad des Installationsverzeichnisses der Anwendung auf OS X\n oder Linux. Relativer Unterpfad des Installationsverzeichnisses der\n Anwendung wie "Programme" oder "AppData" unter Windows.\n -MSG_Help_no_args=Verwendung: jpackage \nVerwenden Sie jpackage --help (oder -h), um eine Liste möglicher Optionen aufzurufen -MSG_Help_default_app_image=Speicherort des vordefinierten Anwendungsimages, mit dem\n ein installierbares Package erstellt wird\n -MSG_Help_mac_app_image=Speicherort des vordefinierten Anwendungsimages, mit dem\n ein installierbares Package erstellt oder das vordefinierte\n Anwendungsimage signiert wird\n -MSG_Help_mac_sign_sample_usage=\ Vordefiniertes Anwendungsimage signieren:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n Hinweis: In diesem Modus sind nur die folgenden zusätzlichen Optionen zulässig:\n Das Set der zusätzlichen Mac-Signaturoptionen und --verbose\n diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties index cae6ae216d3..ca606dda9f8 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2025, 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,22 +24,163 @@ # # -MSG_Help=使用方法: jpackage \n\n使用例:\n--------------\n ホスト・システムに適したアプリケーション・パッケージを生成します。\n モジュラ・アプリケーションの場合:\n jpackage -n name -p modulePath -m moduleName/className\n 非モジュラ・アプリケーションの場合:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 事前作成されたアプリケーション・イメージから:\n jpackage -n name --app-image appImageDir\n アプリケーション・イメージの生成:\n モジュラ・アプリケーションの場合:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n 非モジュラ・アプリケーションの場合:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n jlinkに独自のオプションを指定するには、jlinkを別個に実行します。\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage\n Javaランタイム・パッケージを生成します。\n jpackage -n name --runtime-image \n{6}\n一般的なオプション:\n @ \n ファイルからの読取りオプションおよびモード \n このオプションは複数回使用できます。\n --type -t \n 作成するパッケージのタイプ\n 有効な値: {1} \n このオプションが指定されていない場合、プラットフォーム依存の\n デフォルト・タイプが作成されます\n --app-version \n アプリケーションおよびパッケージのバージョン\n --copyright \n アプリケーションのコピーライト\n --description \n アプリケーションの説明\n --help -h \n 使用方法テキストと現在のプラットフォームの有効なオプションのリストと説明を\n 出力ストリームに出力して、終了します\n --icon \n アプリケーション・パッケージのアイコンのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n \ ---name -n \n アプリケーションおよびパッケージの名前\n --dest -d \n 生成された出力ファイルが配置されるパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n デフォルトは現在の作業ディレクトリです。\n --temp \n 一時ファイルの作成に使用される新規または空のディレクトリのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n 指定した場合、タスク完了時に一時ディレクトリは削除されないため\n 手動で削除する必要があります\n 指定しなかった場合、一時ディレクトリが作成され\n タスク完了時に削除されます。\n --vendor \n アプリケーションのベンダー\n --verbose\n 詳細な出力を有効にします\n --version\n 製品バージョンを出力ストリームに出力して終了します\n\nランタイム・イメージを作成するためのオプション:\n --add-modules [,...]\n 追加するモジュールのカンマ(",")区切りリスト\n このモジュール・リストとメイン・モジュール(指定した場合)\n が--add-module引数としてjlinkに渡されます。\n 指定しなかった場合、メイン・モジュールのみ(--moduleが\n 指定された場合)、またはデフォルトのモジュール・セット(--main-jarが \n 指定された場合)が使用されます。\n このオプションは複数回使用できます。\n --module-path -p ...\n パスの{0}区切りリスト\n 各パスは、モジュールのディレクトリまたは\n モジュラjarへのパスです。\n (各パスは、絶対パスまたは現在のディレクトリからの相対パスです。)\n このオプションは複数回使用できます。\n --jlink-options \n jlinkに渡すオプションのスペース区切りのリスト \n 指定しない場合、"--strip-native-commands \n --strip-debug \ ---no-man-pages --no-header-files"。 \n このオプションは複数回使用できます。\n --runtime-image \n アプリケーション・イメージにコピーされる、事前定義済みのランタイム・イメージ\n のパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n --runtime-imageが指定されていない場合、jpackageはjlinkを実行し、\n 次のオプションを使用してランタイム・イメージを作成します:\n --strip-debug、--no-header-files、--no-man-pagesおよび\n --strip-native-commands。\n\nアプリケーション・イメージを作成するためのオプション:\n --input -i \n パッケージ化するファイルを含む入力ディレクトリへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n 入力ディレクトリのすべてのファイルは、アプリケーション・イメージに\n パッケージ化されます。\n --app-content [,...]\n ファイルまたはディレクトリ(あるいは両方)のパスのカンマ区切りのリスト\n アプリケーション・ペイロードに追加します。\n このオプションは複数回使用できます。\n\nアプリケーション・ランチャを作成するためのオプション:\n --add-launcher =\n ランチャの名前、およびキー、値のペアのリスト\n を含むプロパティ・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n キー"module"、"main-jar"、"main-class"、"description"、\n "arguments"、"java-options"、"app-version"、"icon"、\n "launcher-as-service"、\n "win-console"、"win-shortcut"、"win-menu"、\n "linux-app-category"および"linux-shortcut"を使用できます。\n これらのオプションを元のコマンドライン・オプションに追加するか、これらのオプションを\n 使用して元のコマンドライン・オプションを上書きして、追加の代替ランチャを作成します。\n \ -メイン・アプリケーション・ランチャはコマンドライン・オプションから作成されます。\n このオプションを使用して追加の代替ランチャを作成でき、\n このオプションを複数回使用して\n 複数の追加のランチャを作成できます。 \n --arguments

    \n ランチャにコマンド・ライン引数が指定されていない場合にメイン・クラスに渡す\n コマンド・ライン引数\n このオプションは複数回使用できます。\n --java-options \n Javaランタイムに渡すオプション\n このオプションは複数回使用できます。\n --main-class \n 実行するアプリケーション・メイン・クラスの修飾名\n このオプションを使用できるのは、--main-jarが指定されている場合だけです。\n --main-jar
    \n メイン・クラスを含む、アプリケーションのメインJAR\n (入力パスからの相対パスとして指定)\n --moduleまたは--main-jarオプションを指定できますが、両方は\n 指定できません。\n --module -m [/
    ]\n アプリケーションのメイン・モジュール(およびオプションでメイン・クラス)\n このモジュールは、モジュール・パスに置かれている必要があります。\n このオプションが指定されている場合、メイン・モジュールは\n Javaランタイム・イメージ内でリンクされます。--moduleまたは--main-jar\n オプションを指定できますが、両方は指定できません。\n{2}\nアプリケーション・パッケージを作成するためのオプション:\n --about-url \n アプリケーションのホームページのURL\n --app-image \n {5} (絶対パスまたは現在のディレクトリからの相対パス)\n --file-associations \n キー、値のペアのリストを含むプロパティ・ファイルへのパス\n \ -(絶対パスまたは現在のディレクトリからの相対パス)\n キー"extension"、"mime-type"、"icon"、"description"\n を使用して関連付けを記述できます。\n このオプションは複数回使用できます。\n --install-dir \n {4} --license-file \n ライセンス・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n --resource-dir \n オーバーライドjpackageリソースへのパス\n アイコン、テンプレート・ファイルおよびjpackageのその他のリソースは、\n このディレクトリに置換リソースを追加することでオーバーライドできます。\n (絶対パスまたは現在のディレクトリからの相対パス)\n --runtime-image \n インストールする事前定義済みのランタイム・イメージのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n ランタイム・パッケージの作成時には、オプションが必要です。\n --launcher-as-service\n 次として登録するインストーラの作成をリクエストします: \n バックグラウンド・サービス・タイプ・アプリケーションとしてのメイン・アプリケーション・ランチャ。\n\nアプリケーション・パッケージを作成するためのプラットフォーム依存オプション:\n{3} +help.header=使用方法: jpackage + +help.short=利用可能なオプションのリストについては、jpackage --help (or -h)を使用します + +help.option-group.sample.create-native-package=\ ホスト・システムに適したアプリケーション・パッケージを生成します:\n モジュラ・アプリケーションの場合:\n jpackage -n name -p modulePath -m moduleName/className\n 非モジュラ・アプリケーションの場合:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 事前作成されたアプリケーション・イメージから:\n jpackage -n name --app-image appImageDir + +help.option-group.sample.create-app-image=\ アプリケーション・イメージの生成:\n モジュラ・アプリケーションの場合:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n 非モジュラ・アプリケーションの場合:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n jlinkに独自のオプションを指定するには、jlinkを別個に実行します:\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage + +help.option-group.sample.create-runtime-installer=\ Javaランタイム・パッケージを生成します:\n jpackage -n name --runtime-image + +help.option-group.sample.sign-app-image=\ 事前定義済みアプリケーション・イメージへの署名:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n ノート: このモードで許可される唯一の追加オプション:\n 追加のmac署名オプションのセットおよび--verbose + +help.option-group.sample=使用例 +help.option-group.generic=一般的なオプション +help.option-group.runtime-image=ランタイム・イメージを作成するためのオプション +help.option-group.app-image=アプリケーション・イメージを作成するためのオプション +help.option-group.launcher=アプリケーション・ランチャを作成するためのオプション +help.option-group.launcher-platform=アプリケーション・ランチャを作成するためのプラットフォーム依存オプション +help.option-group.package=アプリケーション・パッケージを作成するためのオプション +help.option-group.package-platform=アプリケーション・パッケージを作成するためのプラットフォーム依存オプション + +help.option.argument-file=\ ファイルからの読取りオプションまたはモード(あるいはその両方)\n このオプションは複数回使用できます。 + +help.option.about-url=\ アプリケーションのホームページのURL + +help.option.add-launcher.win=\ ランチャの名前、およびキー、値のペアのリスト\n を含むプロパティ・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n キー"arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"main-class"、"main-jar"、"module"、\n "win-console"、"win-menu"、"win-shortcut"が使用できます。\n これらのオプションを元のコマンドライン・オプションに追加するか、これらのオプションを\n 使用して元のコマンドライン・オプションを上書きして、追加の代替ランチャを作成します。\n メイン・アプリケーション・ランチャはコマンドライン・オプションから作成されます。\n このオプションを使用して追加の代替ランチャを作成でき、\n このオプションを複数回使用して\n 複数の追加のランチャを作成できます。 + +help.option.add-launcher.linux=\ ランチャの名前、およびキー、値のペアのリスト\n を含むプロパティ・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n キー"arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"linux-shortcut"、"main-class"、"main-jar"、\n "module"が使用できます。\n これらのオプションを元のコマンドライン・オプションに追加するか、これらのオプションを\n 使用して元のコマンドライン・オプションを上書きして、追加の代替ランチャを作成します。\n メイン・アプリケーション・ランチャはコマンドライン・オプションから作成されます。\n このオプションを使用して追加の代替ランチャを作成でき、\n このオプションを複数回使用して\n 複数の追加のランチャを作成できます。 + +help.option.add-launcher.mac=\ ランチャの名前、およびキー、値のペアのリスト\n を含むプロパティ・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n キー"arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"main-class"、"main-jar"、"module"\n が使用できます。\n これらのオプションを元のコマンドライン・オプションに追加するか、これらのオプションを\n 使用して元のコマンドライン・オプションを上書きして、追加の代替ランチャを作成します。\n メイン・アプリケーション・ランチャはコマンドライン・オプションから作成されます。\n このオプションを使用して追加の代替ランチャを作成でき、\n このオプションを複数回使用して\n 複数の追加のランチャを作成できます。 + +help.option.add-modules=\ 追加するモジュールのカンマ(",")区切りリスト\n このモジュール・リストとメイン・モジュール(指定した場合)\n が--add-module引数としてjlinkに渡されます。\n 指定しなかった場合、メイン・モジュールのみ(--moduleが\n 指定された場合)、またはデフォルトのモジュール・セット(--main-jarが\n 指定された場合)が使用されます。\n このオプションは複数回使用できます。 + +help.option.app-content=\ アプリケーション・ペイロードに追加するファイルまたはディレクトリ(あるいはその両方)\n のパスのカンマ区切りのリスト。\n このオプションは複数回使用できます。 + +help.option.app-content.mac=\ アプリケーション・ペイロードに追加するファイルまたはディレクトリ(あるいはその両方)\n のパスのカンマ区切りのリスト。\n このオプションは複数回使用できます。\n ノート: 値は"Resources"サブディレクトリ\n (またはアプリケーション・バンドルの"Contents"ディレクトリで有効なその他のディレクトリ)\n を含むディレクトリである必要があります。それ以外の場合は、jpackageによって無効なアプリケーション・バンドルが生成される場合があり、\n コード署名または公証(あるいはその両方)に失敗する\n 場合があります。 + +help.option.app-image=\ インストール可能なパッケージの作成に使用する、事前定義済\n アプリケーション・イメージの場所\n (絶対パスまたは現在のディレクトリからの相対パス) + +help.option.app-image.mac=\ インストール可能なパッケージの作成または事前定義済\n アプリケーション・イメージの署名に使用する、事前定義済\n アプリケーション・イメージの場所\n (絶対パスまたは現在のディレクトリからの相対パス) + +help.option.app-version=\ アプリケーションおよびパッケージのバージョン + +help.option.arguments=\ コマンドライン引数がランチャに指定されていない場合に、\n メイン・クラスに渡されるコマンドライン引数\n このオプションは複数回使用できます。 + +help.option.copyright=\ アプリケーションのコピーライト + +help.option.description=\ アプリケーションの説明 + +help.option.dest=\ 生成された出力ファイルが配置されるパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n 現在の作業ディレクトリにデフォルト設定されています。 + +help.option.file-associations=\ キー、値のペアのリストを含むプロパティ・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n キー"extension"、"mime-type"、"icon"、"description"\n を使用して関連付けを記述できます。\n このオプションは複数回使用できます。 + +help.option.help=\ 使用方法テキストと現在のプラットフォームの有効なオプションのリストと説明を\n 出力ストリームに出力して、終了します + +help.option.icon=\ アプリケーション・パッケージのアイコンのパス\n (絶対パスまたは現在のディレクトリからの相対パス) + +help.option.input=\ パッケージ化するファイルを含む入力ディレクトリのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n 入力ディレクトリのすべてのファイルは、アプリケーション・イメージに\n パッケージ化されます。 + +help.option.install-dir=\ アプリケーションのインストール・ディレクトリの絶対パス + +help.option.install-dir.win=\ "プログラム・ファイル"または"AppData"など、\n アプリケーションのインストール場所の相対サブパス。 + +help.option.installer-runtime-image=\ インストールする事前定義済のランタイム・イメージのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n ランタイム・パッケージの作成時には、オプションが必要です。 + +help.option.java-options=\ Javaランタイムに渡すオプション\n このオプションは複数回使用できます。 + +help.option.jlink-options=\ jlinkに渡すオプションのスペース区切りのリスト\n 指定しない場合、"--strip-native-commands\n --strip-debug --no-man-pages --no-header-files"にデフォルト設定されます。\n このオプションは複数回使用できます。 + +help.option.launcher-as-service=\ バックグラウンド・サービス・タイプ・アプリケーションとしてメイン・\n アプリケーション・ランチャを登録するインストーラの作成をリクエストします。 + +help.option.license-file=\ ライセンス・ファイルへのパス\n (絶対パスまたは現在のディレクトリからの相対パス) + +help.option.linux-app-category=\ RPM .specファイルのグループ値または\n DEB制御ファイルのセクション値 + +help.option.linux-app-release=\ RPM .specファイルのリリース値または\n DEB制御ファイルのDebianリビジョン値 + +help.option.linux-deb-maintainer=\ .debパッケージのメンテナ + +help.option.linux-menu-group=\ このアプリケーションを配置するメニュー・グループ + +help.option.linux-package-deps=\ アプリケーションに必要なパッケージまたは機能 + +help.option.linux-package-name=\ Linuxパッケージの名前。アプリケーション名にデフォルト設定されています + +help.option.linux-rpm-license-type=\ ライセンスのタイプ(RPM .specの"License: ") + +help.option.linux-shortcut=\ アプリケーションのショートカットを作成します。 + +help.option.mac-app-category=\ アプリケーションplistのLSApplicationCategoryTypeの構築に\n 使用する文字列。デフォルト値は"utilities"です。 + +help.option.mac-app-image-sign-identity=\ アプリケーション・イメージの署名に使用するアイデンティティ。この値は直接\n "codesign"ツールの--signオプションに渡されます。このオプションは\n --mac-signing-key-user-nameと組み合せることはできません。 + +help.option.mac-app-store=\ jpackage出力がMac App Store用であること\n を示します。 + +help.option.mac-dmg-content=\ dmgに参照されたコンテンツをすべて含めます。\n このオプションは複数回使用できます。 + +help.option.mac-entitlements=\ バンドルの実行可能ファイルおよびライブラリの署名時に\n 使用する権限を含むファイルのパス。 + +help.option.mac-installer-sign-identity=\ "pkg"インストーラの署名に使用するアイデンティティ。この値は直接\n "productbuild"ツールの--signオプションに渡されます。このオプションは\n --mac-signing-key-user-nameと組み合せることはできません。 + +help.option.mac-package-identifier=\ MacOSのアプリケーションを一意に識別する識別子。\n メイン・クラス名にデフォルト設定されています。\n 英数字(A-Z、a-z、0-9)、ハイフン(-)、\n およびピリオド(.)のみを使用できます。 + +help.option.mac-package-name=\ メニュー・バーに表示されるアプリケーションの名前\n アプリケーション名とは異なります。\n この名前は16文字未満にする必要があり、メニュー・バー\n およびアプリケーション情報ウィンドウに表示するのに適している必要があります。\n アプリケーション名にデフォルト設定されています。 + +help.option.mac-package-signing-prefix=\ アプリケーション・パッケージに署名する際、既存のパッケージIDのない\n 署名が必要なすべてのコンポーネントに、\n この値が接頭辞として付けられます。 + +help.option.mac-sign=\ パッケージまたは事前定義済アプリケーション・イメージに署名するよう\n リクエストします。 + +help.option.mac-signing-keychain=\ 署名アイデンティティを検索するキーチェーンの名前\n 指定しなかった場合、標準のキーチェーンが使用されます。 + +help.option.mac-signing-key-user-name=\ Apple署名アイデンティティのチームまたはユーザー名部分。\n アプリケーション・イメージまたはインストーラの署名に使用する署名アイデンティティの\n 直接制御には、--mac-app-image-sign-identityまたは\n --mac-installer-sign-identity(あるいはその両方)を使用します。このオプションは\n --mac-app-image-sign-identityまたは--mac-installer-sign-identityと組み合せることはできません。 + +help.option.main-class=\ 実行するアプリケーション・メイン・クラスの修飾名\n このオプションを使用できるのは、--main-jarが指定されている場合だけです。 + +help.option.main-jar=\ メイン・クラスを含む、アプリケーションのメインJAR\n (入力パスからの相対パスとして指定)\n --moduleまたは--main-jarオプションを指定できますが、両方は\n 指定できません。 + +help.option.module=\ アプリケーションのメイン・モジュール(およびオプションでメイン・クラス)\n このモジュールは、モジュール・パスに置かれている必要があります。\n このオプションが指定されている場合、メイン・モジュールは\n Javaランタイム・イメージ内でリンクされます。--moduleまたは--main-jar\n オプションを指定できますが、両方は指定できません。 + +help.option.module-path=\ :で区切られたパスのリスト\n 各パスは、モジュールのディレクトリまたは\n モジュラjarへのパスです。\n (各パスは、絶対パスまたは現在のディレクトリからの相対パスです。)\n このオプションは複数回使用できます。 +help.option.module-path.win=\ ;で区切られたパスのリスト\n 各パスは、モジュールのディレクトリまたは\n モジュラjarへのパスです。\n (各パスは、絶対パスまたは現在のディレクトリからの相対パスです。)\n このオプションは複数回使用できます。 + +help.option.name=\ アプリケーションおよびパッケージの名前 + +help.option.resource-dir=\ オーバーライドjpackageリソースへのパス\n アイコン、テンプレート・ファイルおよびjpackageのその他のリソースは、\n このディレクトリに置換リソースを追加することでオーバーライドできます。\n (絶対パスまたは現在のディレクトリからの相対パス) + +help.option.runtime-image=\ アプリケーション・イメージにコピーされる、事前定義済のランタイム・イメージ\n のパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n --runtime-imageが指定されていない場合、jpackageはjlinkを実行し、\n 次のオプションを使用してランタイム・イメージを作成します:\n --strip-debug、--no-header-files、--no-man-pagesおよび\n --strip-native-commands。 + +help.option.temp=\ 一時ファイルの作成に使用される新規または空のディレクトリのパス\n (絶対パスまたは現在のディレクトリからの相対パス)\n 指定した場合、タスク完了時に一時ディレクトリは削除されないため\n 手動で削除する必要があります。\n 指定しなかった場合、一時ディレクトリが作成され\n タスク完了時に削除されます。 + +help.option.type.win=\ 作成するパッケージのタイプ\n 有効な値: {"app-image", "exe", "msi"}\n このオプションを指定しない場合、プラットフォーム依存の\n デフォルト・タイプが作成されます。 +help.option.type.linux=\ 作成するパッケージのタイプ\n 有効な値: {"app-image", "deb", "rpm"}\n このオプションを指定しない場合、プラットフォーム依存の\n デフォルト・タイプが作成されます。 +help.option.type.mac=\ 作成するパッケージのタイプ\n 有効な値: {"app-image", "dmg", "pkg"}\n このオプションを指定しない場合、プラットフォーム依存の\n デフォルト・タイプが作成されます。 + +help.option.vendor=\ アプリケーションのベンダー + +help.option.verbose=\ 詳細な出力を有効にします + +help.option.version=\ 製品バージョンを出力ストリームに出力して終了します + +help.option.win-console=\ アプリケーションのコンソール・ランチャを作成します。コンソール・\n インタラクションが必要なアプリケーションに指定する必要があります + +help.option.win-dir-chooser=\ 製品をインストールするディレクトリをユーザーが\n 選択できるダイアログを追加します。 + +help.option.win-help-url=\ ユーザーが詳細情報または技術サポートを取得できるURL + +help.option.win-menu=\ このアプリケーションのスタート・メニューのショートカットを追加するリクエスト + +help.option.win-menu-group=\ このアプリケーションを配置するスタート・メニュー・グループ + +help.option.win-per-user-install=\ ユーザーごとにインストールを実行するリクエスト + +help.option.win-shortcut=\ このアプリケーションのデスクトップのショートカットを追加するリクエスト + +help.option.win-shortcut-prompt=\ ショートカットをインストーラで作成するかどうかをユーザーが\n 選択できるダイアログを追加します。 + +help.option.win-update-url=\ 使用可能なアプリケーション更新情報のURL + +help.option.win-upgrade-uuid=\ このパッケージのアップグレードに関連付けられているUUID -MSG_Help_win_launcher=\nアプリケーション・ランチャを作成するためのプラットフォーム依存オプション:\n --win-console\n アプリケーションのコンソール・ランチャを作成します。コンソール・\n インタラクションが必要なアプリケーションに指定する必要があります\n -MSG_Help_win_install=\ --win-dir-chooser\n ユーザーが製品をインストールするディレクトリを選択するための\n ダイアログを追加します。\n --win-help-url \n ユーザーが詳細情報または技術的なサポートを取得できるURL\n --win-menu\n このアプリケーションのスタート・メニュー・ショートカットを追加するようにリクエストします\n --win-menu-group \n このアプリケーションを配置するスタート・メニュー・グループ\n --win-per-user-install\n ユーザーごとにインストールを実行するようにリクエストします\n --win-shortcut\n このアプリケーションのデスクトップ・ショートカットを追加するようにリクエストします\n --win-shortcut-prompt\n ショートカットをインストーラで作成するかどうかをユーザーが選択できるようにする\n ダイアログを追加します。\n --win-update-url \n 使用可能なアプリケーションの更新情報のURL\n --win-upgrade-uuid \n このパッケージのアップグレードに関連付けられたUUID\n -MSG_Help_win_install_dir=デフォルトのインストール場所の下の相対サブパス\n -MSG_Help_mac_install=\ --mac-dmg-content [,...]\n dmgに参照されたコンテンツをすべて含めます。\n このオプションは複数回使用できます。 \n -MSG_Help_mac_launcher=\ --mac-package-identifier \n macOSのアプリケーションを一意に識別するID\n メイン・クラス名にデフォルト設定されています。\n 英数字(A-Z、a-z、0-9)、ハイフン(-)およびピリオド(.)文字のみ\n 使用できます。\n --mac-package-name \n メニュー・バーに表示されるアプリケーションの名前\n アプリケーション名とは異なります。\n この名前は16文字未満にする必要があり、メニュー・バーおよびアプリケーション情報ウィンドウに\n 表示するのに適している必要があります。\n アプリケーション名にデフォルト設定されています。\n --mac-package-signing-prefix \n アプリケーション・パッケージに署名する際、\n 既存のパッケージIDのない署名が必要なすべてのコンポーネントに、\n この値が接頭辞として付けられます。\n --mac-sign\n パッケージまたは事前定義済アプリケーション・イメージに署名するよう\n リクエストします。\n --mac-signing-keychain \n 署名アイデンティティを検索するキーチェーンの名前\n 指定しなかった場合、標準のキーチェーンが使用されます。\n --mac-signing-key-user-name \n Apple署名アイデンティティのチームまたはユーザー名部分。\n アプリケーション・イメージまたはインストーラの署名に使用する署名アイデンティティの\n 直接制御には、--mac-app-image-sign-identityまたは\n --mac-installer-sign-identity(あるいは両方)を使用します。このオプションは\n --mac-app-image-sign-identityまたは--mac-installer-sign-identityと組み合せることはできません。\n --mac-app-image-sign-identity \n アプリケーション・イメージの署名に使用するアイデンティティ。この値は直接\n "codesign"ツールの--signオプションに渡されます。このオプションは\n \ ---mac-signing-key-user-nameと組み合せることはできません。\n --mac-installer-sign-identity \n "pkg"インストーラの署名に使用するアイデンティティ。この値は直接\n "productbuild"ツールの--signオプションに渡されます。このオプションは\n --mac-signing-key-user-nameと組み合せることはできません。\n --mac-app-store\n jpackage出力がMac App Store用であること\n を示します。\n --mac-entitlements \n バンドルの実行可能ファイルおよびライブラリの署名時に\n 使用する権限を含むファイルのパス。\n --mac-app-category \n アプリケーションのplistのLSApplicationCategoryTypeを生成する際に使用する文字列。\n デフォルト値は"utilities"です。\n -MSG_Help_linux_install=\ --linux-package-name \n Linuxパッケージの名前。アプリケーション名にデフォルト設定されています\n --linux-deb-maintainer \n .debパッケージのMaintainer\n --linux-menu-group \n このアプリケーションが配置されているメニュー・グループ\n --linux-package-deps \n アプリケーションに必要なパッケージまたは機能\n --linux-rpm-license-type \n ライセンスのタイプ(RPM .specの"License: ")\n --linux-app-release \n RPM .specファイルのリリース値または\n DEBコントロール・ファイルのDebianリビジョン値。\n --linux-app-category \n RPM .specファイルのグループ値または \n DEBコントロール・ファイルのセクション値\n --linux-shortcut\n アプリケーションのショートカットを作成します。\n -MSG_Help_mac_linux_install_dir=アプリケーションのインストール・ディレクトリの絶対パス\n -MSG_Help_default_install_dir=OS XまたはLinux上のアプリケーションのインストール・ディレクトリの絶対パス。\n "プログラム・ファイル"や"AppData"など、Windows上のアプリケーションの\n インストール場所の相対サブパス。\n -MSG_Help_no_args=使用方法: jpackage \n利用可能なオプションのリストについては、jpackage --help (or -h)を使用します -MSG_Help_default_app_image=インストール可能なパッケージの作成に使用する、事前定義済み\n アプリケーション・イメージの場所\n -MSG_Help_mac_app_image=インストール可能なパッケージの作成または事前定義済みアプリケーション・\n イメージへの署名に使用する、事前定義済みアプリケーション・\n イメージの場所\n -MSG_Help_mac_sign_sample_usage=\ 事前定義済みアプリケーション・イメージへの署名:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n ノート: このモードで許可される唯一の追加オプション:\n 追加のmac署名オプションのセットおよび--verbose\n diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties index 6adf62ef1f8..ac72c67ee2f 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/HelpResources_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 2017, 2023, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2017, 2025, 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,20 +24,163 @@ # # -MSG_Help=用法:jpackage \n\n示例用法:\n--------------\n 生成适合主机系统的应用程序包:\n 对于模块化应用程序:\n jpackage -n name -p modulePath -m moduleName/className\n 对于非模块化应用程序:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 从预构建的应用程序映像:\n jpackage -n name --app-image appImageDir\n 生成应用程序映像:\n 对于模块化应用程序:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n 对于非模块化应用程序:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 要为 jlink 提供您自己的选项,请单独运行 jlink:\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage\n 生成 Java 运行时程序包:\n jpackage -n name --runtime-image \n{6}\n一般选项:\n @ \n 从文件读取选项和/或模式 \n 可以多次使用此选项。\n --type -t \n 要创建的程序包的类型\n 有效值为:{1} \n 如果未指定此选项,则将创建与平台相关的\n 默认类型。\n --app-version \n 应用程序和/或程序包的版本\n --copyright \n 应用程序的版权\n --description \n 应用程序的说明\n --help -h \n 将用法文本输出到输出流并退出,用法文本中包含\n 适用于当前平台的每个有效选项的列表和说明\n --icon \n 应用程序包图标的路径\n (绝对路径或相对于当前目录的路径)\n --name -n \n 应用程序和/或程序包的名称\n --dest -d \n 用来放置所生成的输出文件的路径\n (绝对路径或相对于当前目录的路径)\n 默认为当前的工作目录。\n --temp \n 用来创建临时文件的新目录或空白目录的路径\n (绝对路径或相对于当前目录的路径)\n 如果指定,则在任务完成时将不删除临时目录,\n 必须手动删除临时目录。\n 如果未指定,则将创建一个临时目录,\n \ -并在任务完成时删除该临时目录。\n --vendor \n 应用程序的供应商\n --verbose\n 启用详细的输出\n --version\n 将产品版本输出到输出流并退出。\n\n用来创建运行时映像的选项:\n --add-modules <模块名称>[,<模块名称>...]\n 要添加的模块的逗号 (",") 分隔列表\n 此模块列表连同主模块(如果指定)\n 将作为 --add-module 参数传递到 jlink。\n 如果未指定,则仅使用主模块(如果指定了 --module),\n 或者使用默认的模块集(如果指定了 \n --main-jar)。\n 可以多次使用此选项。\n --module-path -p ...\n 路径的 {0} 分隔列表\n 每个路径要么是模块的目录,要么是\n 模块化 jar 的路径。\n (每个路径可以是绝对路径,也可以是相对于当前目录的路径。)\n 可以多次使用此选项。\n --jlink-options \n 要传递给 jlink 的选项列表(用空格分隔) \n 如果未指定,则默认为 "--strip-native-commands \n --strip-debug --no-man-pages --no-header-files"。 \n 可以多次使用此选项。\n --runtime-image \n 将复制到应用程序映像的预定义\n 运行时映像的路径\n (绝对路径或相对于当前目录的路径)\n 如果未指定 --runtime-image,jpackage 将运行 jlink 以\n 使用如下选项创建运行时映像:\n --strip-debug、--no-header-files、--no-man-pages 和 \n --strip-native-commands。\n\n用来创建应用程序映像的选项:\n --input -i \n 包含要打包的文件的输入目录的路径\n (绝对路径或相对于当前目录的路径)\n 输入目录中的所有文件将打包到\n 应用程序映像中。\n --app-content [,...]\n 要添加到应用程序有效负载中的文件和/或\n 目录的逗号分隔路径列表。\n 此选项可以多次使用。\n\n用来创建应用程序启动程序的选项:\n --add-launcher =\n 启动程序的名称和包含关键字-值对列表的\n 属性文件的路径\n (绝对路径或相对于当前目录的路径)\n \ -可以使用关键字 "module"、"main-jar"、"main-class"、"description"、\n "arguments"、"java-options"、"app-version"、"icon"、\n "launcher-as-service"、\n "win-console"、"win-shortcut"、"win-menu"、\n "linux-app-category" 和 "linux-shortcut"。\n 这些选项将添加到原始命令行选项中或者用来覆盖\n 原始命令行选项,以构建额外的替代启动程序。\n 将从命令行选项构建主应用程序启动程序。\n 可以使用此选项构建额外的替代启动程序,\n 可以多次使用此选项来构建\n 多个额外的启动程序。 \n --arguments
    \n 在没有为启动程序提供命令行参数时,\n 要传递到主类的命令行参数\n 可以多次使用此选项。\n --java-options \n 要传递到 Java 运行时的选项\n 可以多次使用此选项。\n --main-class \n 要执行的应用程序主类的限定名称\n 只有在指定了 --main-jar 时才能使用此选项。\n --main-jar
    \n 应用程序的主 JAR;包含主类\n (指定为相对于输入路径的路径)\n 可以指定 --module 或 --main-jar 选项,但是不能同时指定\n 两者。\n --module -m [/
    ]\n 应用程序的主模块(以及可选的主类)\n 此模块必须位于模块路径中。\n 如果指定了此选项,则将在 Java 运行时映像中\n 链接主模块。可以指定 --module 或 --main-jar 选项,\n 但是不能同时指定这两个选项。\n{2}\n用来创建应用程序包的选项:\n --about-url \n 应用程序主页的 URL\n --app-image \n {5} (绝对路径或相对于当前目录的路径)\n --file-associations \n 包含关键字-值对列表的属性文件的路径\n (绝对路径或相对于当前目录的路径)\n 可以使用关键字 "extension"、"mime-type"、"icon" 和 "description" \n 来描述此关联。\n 可以多次使用此选项。\n --install-dir \n {4} --license-file \n 许可证文件的路径\n (绝对路径或相对于当前目录的路径)\n --resource-dir \n 覆盖 jpackage 资源的路径\n \ -可以通过向该目录中添加替代资源来覆盖 jpackage 的\n 图标、模板文件和其他资源。\n (绝对路径或相对于当前目录的路径)\n --runtime-image \n 要安装的预定义运行时映像的路径\n (绝对路径或相对于当前目录的路径)\n 在创建运行时程序包时需要使用选项。\n --launcher-as-service\n 请求创建安装程序,以将主\n 应用程序启动程序注册为后台服务类型应用程序。\n\n用来创建应用程序包的与平台相关的选项:\n{3} +help.header=用法:jpackage + +help.short=使用 jpackage --help(或 -h)可获取可能选项的列表 + +help.option-group.sample.create-native-package=\ 生成适用于主机系统的应用程序包:\n 对于模块化应用程序:\n jpackage -n name -p modulePath -m moduleName/className\n 对于非模块化应用程序:\n jpackage -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 从预构建的应用程序映像:\n jpackage -n name --app-image appImageDir + +help.option-group.sample.create-app-image=\ 生成应用程序映像:\n 对于模块化应用程序:\n jpackage --type app-image -n name -p modulePath \\\n -m moduleName/className\n 对于非模块化应用程序:\n jpackage --type app-image -i inputDir -n name \\\n --main-class className --main-jar myJar.jar\n 要向 jlink 提供您自己的选项,请分别运行 jlink:\n jlink --output appRuntimeImage -p modulePath \\\n --add-modules moduleName \\\n --no-header-files [...]\n jpackage --type app-image -n name \\\n -m moduleName/className --runtime-image appRuntimeImage + +help.option-group.sample.create-runtime-installer=\ 生成 Java 运行时程序包:\n jpackage -n name --runtime-image + +help.option-group.sample.sign-app-image=\ 对预定义应用程序映像进行签名:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n 注:此模式下允许的其他选项只有:\n 一组其他 mac 签名选项和 --verbose + +help.option-group.sample=示例用法 +help.option-group.generic=一般选项 +help.option-group.runtime-image=用来创建运行时映像的选项 +help.option-group.app-image=用来创建应用程序映像的选项 +help.option-group.launcher=用来创建应用程序启动程序的选项 +help.option-group.launcher-platform=用来创建应用程序启动程序的平台相关选项 +help.option-group.package=用来创建应用程序包的选项 +help.option-group.package-platform=用来创建应用程序包的与平台相关的选项 + +help.option.argument-file=\ 从文件读取选项和/或模式\n 可以多次使用此选项。 + +help.option.about-url=\ 应用程序主页的 URL + +help.option.add-launcher.win=\ 启动程序的名称,以及包含\n 键值对列表的属性文件的路径\n (绝对路径或相对于当前目录的路径)\n 可以使用键 "arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"main-class"、"main-jar"、"module"、\n "win-console"、"win-menu" 和 "win-shortcut"。\n 这些选项添加到或用于覆盖原始\n 命令行选项以构建其他替代启动程序。\n 将从命令行选项构建主应用程序启动程序。\n 可以使用此选项构建其他替代启动程序,\n 并且可以多次使用此选项\n 构建多个其他启动程序。 + +help.option.add-launcher.linux=\ 启动程序的名称,以及包含\n 键值对列表的属性文件的路径\n (绝对路径或相对于当前目录的路径)\n 可以使用键 "arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"linux-shortcut"、"main-class"、"main-jar" \n 和 "module"。\n 这些选项添加到或用于覆盖原始\n 命令行选项以构建其他替代启动程序。\n 将从命令行选项构建主应用程序启动程序。\n 可以使用此选项构建其他替代启动程序,\n 并且可以多次使用此选项\n 构建多个其他启动程序。 + +help.option.add-launcher.mac=\ 启动程序的名称,以及包含\n 键值对列表的属性文件的路径\n (绝对路径或相对于当前目录的路径)\n 可以使用键 "arguments"、"description"、"icon"、"java-options"、\n "launcher-as-service"、"main-class"、"main-jar" 和\n "module"。\n 这些选项添加到或用于覆盖原始\n 命令行选项以构建其他替代启动程序。\n 将从命令行选项构建主应用程序启动程序。\n 可以使用此选项构建其他替代启动程序,\n 并且可以多次使用此选项\n 构建多个其他启动程序。 + +help.option.add-modules=\ 要添加的模块列表(以逗号 (",") 分隔)\n 此模块列表以及主模块(如果指定)\n 将作为 --add-module 参数传递到 jlink。\n 如果未指定,则仅使用主模块\n (如果指定 --module)或默认模块集\n (如果指定 --main-jar)。\n 可以多次使用此选项。 + +help.option.app-content=\ 要添加到应用程序有效负载中的文件\n 和/或目录路径的逗号分隔列表。\n 可以多次使用此选项。 + +help.option.app-content.mac=\ 要添加到应用程序有效负载中的文件\n 和/或目录路径的逗号分隔列表。\n 可以多次使用此选项。\n 注:该值应为具有 "Resources" 子目录的\n 目录(或应用程序包的 "Contents" 目录中\n 有效的任何其他目录)。否则,jpackage \n 可能会生成无效的应用程序包,此应用程序包\n 可能会使代码签名和/或公证失败。 + +help.option.app-image=\ 用来构建可安装程序包的\n 预定义应用程序映像的位置\n (绝对路径或相对于当前目录的路径) + +help.option.app-image.mac=\ 用来构建可安装程序包或对预定义应用程序\n 映像进行签名的预定义应用程序\n 映像的位置\n (绝对路径或相对于当前目录的路径) + +help.option.app-version=\ 应用程序和/或程序包的版本 + +help.option.arguments=\ 在没有为启动程序提供命令行参数时,\n 要传递到主类的命令行参数\n 可以多次使用此选项。 + +help.option.copyright=\ 应用程序的版权 + +help.option.description=\ 应用程序的说明 + +help.option.dest=\ 放置生成的输出文件的路径\n (绝对路径或相对于当前目录的路径)\n 默认为当前工作目录。 + +help.option.file-associations=\ 包含键值对列表的属性文件的路径\n (绝对路径或相对于当前目录的路径)\n 键 "extension"、"mime-type"、"icon" 和 "description"\n 可用于描述关联。\n 可以多次使用此选项。 + +help.option.help=\ 将用法文本输出到输出流并退出,用法文本中包含\n 适用于当前平台的每个有效选项的列表和说明 + +help.option.icon=\ 应用程序包图标的路径\n (绝对路径或相对于当前目录的路径) + +help.option.input=\ 包含要打包的文件的输入目录的路径\n (绝对路径或相对于当前目录的路径)\n 输入目录中的所有文件将打包到\n 应用程序映像中。 + +help.option.install-dir=\ 应用程序安装目录的绝对路径 + +help.option.install-dir.win=\ 应用程序安装位置的相对子路径\n 例如 "Program Files" 或 "AppData"。 + +help.option.installer-runtime-image=\ 要安装的预定义运行时映像的路径\n (绝对路径或相对于当前目录的路径)\n 创建运行时程序包时需要提供选项。 + +help.option.java-options=\ 传递到 Java 运行时的选项\n 可以多次使用此选项。 + +help.option.jlink-options=\ 要传递到 jlink 的选项列表(以空格分隔)\n 如果未指定,则默认为 "--strip-native-commands\n --strip-debug --no-man-pages --no-header-files"。\n 可以多次使用此选项。 + +help.option.launcher-as-service=\ 请求创建安装程序,以将主应用程序\n 启动程序注册为后台服务类型应用程序。 + +help.option.license-file=\ 许可证文件的路径\n (绝对路径或相对于当前目录的路径) + +help.option.linux-app-category=\ RPM .spec 文件的组值或\n DEB 控制文件的节值 + +help.option.linux-app-release=\ RPM .spec 文件的发行版值或\n DEB 控制文件的 Debian 修订版值 + +help.option.linux-deb-maintainer=\ .deb 程序包的维护程序 + +help.option.linux-menu-group=\ 此应用程序所在的菜单组 + +help.option.linux-package-deps=\ 应用程序所需的程序包或功能 + +help.option.linux-package-name=\ Linux 程序包的名称,默认为应用程序名称 + +help.option.linux-rpm-license-type=\ 许可证类型(RPM .spec 的 "License: ") + +help.option.linux-shortcut=\ 为应用程序创建快捷方式。 + +help.option.mac-app-category=\ 用于构造应用程序 plist 中的 LSApplicationCategoryType 的\n 字符串。默认值为 "utilities"。 + +help.option.mac-app-image-sign-identity=\ 用于对应用程序映像进行签名的身份。此值将\n 直接传递到 "codesign" 工具的 --sign 选项。此选项\n 不能与 --mac-signing-key-user-name 结合使用。 + +help.option.mac-app-store=\ 指示 jpackage 输出面向\n Mac App Store。 + +help.option.mac-dmg-content=\ 包括 dmg 中引用的所有内容。\n 可以多次使用此选项。 + +help.option.mac-entitlements=\ 包含对包中的可执行文件和库进行签名时\n 要使用的权利的文件路径。 + +help.option.mac-installer-sign-identity=\ 用于对 "pkg" 安装程序进行签名的身份。此值将\n 直接传递到 "productbuild" 工具的 --sign 选项。此选项\n 不能与 --mac-signing-key-user-name 结合使用。 + +help.option.mac-package-identifier=\ 唯一标识 macOS 应用程序的标识符\n 默认为主类名称。\n 只能使用字母数字 (A-Z,a-z,0-9)、连字符 (-)\n 和句点 (.) 字符。 + +help.option.mac-package-name=\ 应用程序在菜单栏中显示的名称\n 此名称可以与应用程序名称不同。\n 此名称的长度必须少于 16 个字符,并且\n 适合显示在菜单栏和应用程序“信息”窗口中。\n 默认为应用程序名称。 + +help.option.mac-package-signing-prefix=\ 对应用程序包进行签名时,此值将作为\n 前缀添加到需要签名但当前没有程序包\n 标识符的所有组件。 + +help.option.mac-sign=\ 请求对程序包或预定义的应用程序映像\n 进行签名。 + +help.option.mac-signing-keychain=\ 要用来搜索签名身份的密钥链的名称\n 如果未指定,则使用标准密钥链。 + +help.option.mac-signing-key-user-name=\ Apple 签名身份的团队或用户名称部分。为了直接\n 控制用于对应用程序映像或安装程序进行签名的\n 签名身份,请使用 --mac-app-image-sign-identity 和/或\n --mac-installer-sign-identity。此选项不能与\n --mac-app-image-sign-identity 或 --mac-installer-sign-identity 结合使用。 + +help.option.main-class=\ 要执行的应用程序主类的限定名称\n 只有在指定了 --main-jar 时才能使用此选项。 + +help.option.main-jar=\ 应用程序的主 JAR;包含主类\n (指定为相对于输入路径的路径)\n 可以指定 --module 或 --main-jar 选项,\n 但不能同时指定这两个选项。 + +help.option.module=\ 应用程序的主模块(以及可选的主类)\n 此模块必须位于模块路径中。\n 指定了此选项时,将在 Java 运行时映像中\n 链接主模块。可以指定 --module 或 --main-jar \n 选项,但不能同时指定这两个选项。 + +help.option.module-path=\ 以 : 分隔的路径列表\n 每个路径是模块的目录或\n 模块化 jar 的路径。\n (每个路径可以是绝对路径,也可以是相对于当前目录的路径。)\n 可以多次使用此选项。 +help.option.module-path.win=\ 以 ; 分隔的路径列表\n 每个路径是模块的目录或\n 模块化 jar 的路径。\n (每个路径可以是绝对路径,也可以是相对于当前目录的路径。)\n 可以多次使用此选项。 + +help.option.name=\ 应用程序和/或程序包的名称 + +help.option.resource-dir=\ 覆盖 jpackage 资源的路径\n 可以通过向此目录中添加替换资源来覆盖 jpackage 的\n 图标、模板文件和其他资源。\n (绝对路径或相对于当前目录的路径) + +help.option.runtime-image=\ 将复制到应用程序映像中的预定义\n 运行时映像的路径\n (绝对路径或相对于当前目录的路径)\n 如果未指定 --runtime-image,jpackage 将运行 jlink 以\n 使用以下选项创建运行时映像:\n --strip-debug、--no-header-files、--no-man-pages 和\n --strip-native-commands。 + +help.option.temp=\ 用于创建临时文件的新目录或空目录的路径\n (绝对路径或相对于当前目录的路径)\n 如果指定,则在任务完成时将不删除\n 临时目录,必须手动删除临时目录。\n 如果未指定,将创建临时目录并\n 并在任务完成时删除该临时目录。 + +help.option.type.win=\ 要创建的程序包的类型\n 有效值为:{"app-image", "exe", "msi"}\n 如果未指定此选项,则将创建与平台相关的\n 默认类型。 +help.option.type.linux=\ 要创建的程序包的类型\n 有效值为:{"app-image", "deb", "rpm"}\n 如果未指定此选项,则将创建与平台相关的\n 默认类型。 +help.option.type.mac=\ 要创建的程序包的类型\n 有效值为:{"app-image", "dmg", "pkg"}\n 如果未指定此选项,则将创建与平台相关的\n 默认类型。 + +help.option.vendor=\ 应用程序的供应商 + +help.option.verbose=\ 启用详细的输出 + +help.option.version=\ 将产品版本输出到输出流并退出。 + +help.option.win-console=\ 为应用程序创建控制台启动程序,应当为\n 需要控制台交互的应用程序指定 + +help.option.win-dir-chooser=\ 添加一个对话框以允许用户选择\n 产品的安装目录。 + +help.option.win-help-url=\ 用户可以从中获取更多信息或技术支持的 URL + +help.option.win-menu=\ 请求为此应用程序添加“开始”菜单快捷方式 + +help.option.win-menu-group=\ 此应用程序所在的“开始”菜单组 + +help.option.win-per-user-install=\ 请求基于每个用户执行安装 + +help.option.win-shortcut=\ 请求为此应用程序添加桌面快捷方式 + +help.option.win-shortcut-prompt=\ 添加一个对话框以允许用户选择是否将由安装程序\n 创建快捷方式。 + +help.option.win-update-url=\ 可用应用程序更新信息的 URL + +help.option.win-upgrade-uuid=\ 与此程序包的升级关联的 UUID -MSG_Help_win_launcher=\n用来创建应用程序启动程序的与平台相关的选项:\n --win-console\n 为应用程序创建控制台启动程序,应当为\n 需要控制台交互的应用程序指定\n -MSG_Help_win_install=\ --win-dir-chooser\n 添加一个对话框以允许用户选择\n 产品的安装目录。\n --win-help-url \n 用户可以从中获取更多信息或技术支持的 URL\n --win-menu\n 请求为此应用程序添加开始菜单快捷方式\n --win-menu-group \n 此应用程序所在的开始菜单组\n --win-per-user-install\n 请求基于每个用户执行安装\n --win-shortcut\n 请求为此应用程序添加桌面快捷方式\n --win-shortcut-prompt\n 添加一个对话框以允许用户选择是否将由安装程序\n 创建快捷方式。\n --win-update-url \n 可用应用程序更新信息的 URL\n --win-upgrade-uuid \n 与此程序包的升级相关联的 UUID\n -MSG_Help_win_install_dir=默认安装位置下面的相对子路径\n -MSG_Help_mac_install=\ --mac-dmg-content [,...]\n 包括 DMG 中引用的所有内容。\n 此选项可以使用多次。\n -MSG_Help_mac_launcher=\ --mac-package-identifier \n 用来唯一地标识 macOS 应用程序的标识符\n 默认为主类名称。\n 只能使用字母数字 (A-Z,a-z,0-9)、连字符 (-) 和\n 句点 (.) 字符。\n --mac-package-name \n 出现在菜单栏中的应用程序名称\n 这可以与应用程序名称不同。\n 此名称的长度必须小于 16 个字符,适合\n 显示在菜单栏中和应用程序“信息”窗口中。\n 默认为应用程序名称。\n --mac-package-signing-prefix \n 在对应用程序包签名时,会在所有需要签名\n 但当前没有程序包标识符的组件的\n 前面加上此值。\n --mac-sign\n 请求对程序包或预定义的应用程序映像\n 进行签名。\n --mac-signing-keychain \n 要用来搜索签名身份的密钥链的名称\n 如果未指定,则使用标准的密钥链。\n --mac-signing-key-user-name \n Apple 签名身份的团队或用户名称部分。为了直接\n 控制用于对应用程序映像或安装程序进行签名的\n 签名身份,请使用 --mac-app-image-sign-identity 和/或\n --mac-installer-sign-identity。此选项不能与\n --mac-app-image-sign-identity 或 --mac-installer-sign-identity 结合使用。\n --mac-app-image-sign-identity \n 用于对应用程序映像进行签名的身份。此值将直接\n 传递至 "codesign" 工具的 --sign 选项。此选项不能\n 与 --mac-signing-key-user-name 结合使用。\n --mac-installer-sign-identity \n 用于对 "pkg" 安装程序进行签名的身份。此值将直接\n 传递至 "productbuild" 工具的 --sign 选项。此选项不能\n 与 --mac-signing-key-user-name 结合使用。\n --mac-app-store\n 指示 jpackage 输出面向\n Mac App Store。\n --mac-entitlements \n 包含一些权利的文件的路径,在对捆绑包中的可执行文件\n 和库进行签名时会使用这些权利。\n --mac-app-category \n 用于构造应用程序 plist 中 LSApplicationCategoryType 的\n 字符串。默认值为 "utilities"。\n -MSG_Help_linux_install=\ --linux-package-name \n Linux 程序包的名称,默认为应用程序名称\n --linux-deb-maintainer \n .deb 程序包的维护程序\n --linux-menu-group \n 此应用程序所在的菜单组\n --linux-package-deps \n 应用程序所需的程序包或功能\n --linux-rpm-license-type \n 许可证的类型(RPM .spec 的 "License: ")\n --linux-app-release \n RPM .spec 文件的发行版值或 \n DEB 控制文件的 Debian 修订版值\n --linux-app-category \n RPM .spec 文件的组值或 \n DEB 控制文件的节值\n --linux-shortcut\n 为应用程序创建快捷方式。\n -MSG_Help_mac_linux_install_dir=应用程序安装目录的绝对路径\n -MSG_Help_default_install_dir=OS X 或 Linux 上应用程序安装目录的绝对路径。\n Windows 上应用程序安装位置的相对子路径\n (如 "Program Files" 或 "AppData")。\n -MSG_Help_no_args=用法:jpackage \n使用 jpackage --help(或 -h)可获取可能选项的列表 -MSG_Help_default_app_image=用来构建可安装程序包的\n 预定义应用程序映像的位置\n -MSG_Help_mac_app_image=用来构建可安装程序包的\n 或对预定义应用程序映像进行签名的\n 预定义应用程序映像的位置\n -MSG_Help_mac_sign_sample_usage=\ 对预定义应用程序映像进行签名:\n jpackage --type app-image --app-image \\\n --mac-sign [...]\n 注:此模式下允许的其他选项只有:\n 一组其他 mac 签名选项和 --verbose\n diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties index 2426b97c7e2..7816f8ee71a 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_de.properties @@ -24,25 +24,32 @@ # # -jpackage.description=Eigenständige Java-Anwendung verpacken - param.copyright.default=Copyright (C) {0,date,YYYY} -param.description.default=Kein Wert param.vendor.default=Unbekannt +bundle-type.win-app=Windows-Anwendungsimage +bundle-type.win-exe=EXE-Installationsprogrammpackage +bundle-type.win-msi=MSI-Installationsprogrammpackage +bundle-type.mac-app=Mac-Anwendungsimage +bundle-type.mac-dmg=Mac-DMG-Package +bundle-type.mac-pkg=Mac-PKG-Package +bundle-type.linux-app=Linux-Anwendungsimage +bundle-type.linux-deb=DEB-Bundle +bundle-type.linux-rpm=RPM-Bundle + resource.post-app-image-script=Auszuführendes Skript nach dem Auffüllen des Anwendungsimages message.using-default-resource=Standardpackageressource {0} {1} wird verwendet (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich). -message.no-default-resource=Keine Standardpackageressource {0} {1} (durch Hinzufügen von {2} zu resource-dir ist eine Anpassung möglich). +message.no-default-resource=Keine Standardpackageressource {0} (durch Hinzufügen von {1} zu resource-dir ist eine Anpassung möglich). message.using-custom-resource-from-file=Benutzerdefinierte Packageressource {0} wird verwendet (aus Datei {1} geladen). message.using-custom-resource=Benutzerdefinierte Packageressource {0} wird verwendet (aus {1} geladen). message.creating-app-bundle=Anwendungspackage {0} wird in {1} erstellt -message.runtime-image-dir-does-not-exist=Angegebenes Laufzeitimageverzeichnis {0}: {1} ist nicht vorhanden -message.resource-dir-does-not-exist=Angegebenes Ressourcenverzeichnis {0}: {1} ist nicht vorhanden message.debug-working-directory=Arbeitsverzeichnis für Debug beibehalten: {0} message.bundle-created={0}-Package wurde erfolgreich erstellt message.module-version=Version "{0}" aus Modul "{1}" wird als Anwendungsversion verwendet -message.module-class=Klasse "{0}" aus Modul "{1}" wird als Anwendungshauptklasse verwendet + +message.error-header={0} +message.advice-header=Empfehlung zur Behebung: {0} error.version-string-empty=Version darf keine leere Zeichenfolge sein error.version-string-zero-length-component=Version [{0}] enthält eine Komponente mit Nulllänge @@ -50,64 +57,69 @@ error.version-string-invalid-component=Version [{0}] enthält ungültige Kompone error.cannot-create-output-dir=Zielverzeichnis {0} kann nicht erstellt werden error.cannot-write-to-output-dir=Zielverzeichnis {0} ist schreibgeschützt -error.root-exists=Fehler: Anwendungszielverzeichnis {0} ist bereits vorhanden +error.root-exists=Anwendungszielverzeichnis {0} ist bereits vorhanden error.no-main-class-with-main-jar=Es wurde keine Hauptklasse angegeben oder in der JAR-Datei {0} gefunden error.no-main-class-with-main-jar.advice=Geben Sie eine Hauptklasse an, oder stellen Sie sicher, dass die JAR-Datei {0} eine Hauptklasse im Manifest angibt -error.no-main-class=Es wurde keine Hauptklasse angegeben oder in den angegebenen Anwendungsressourcen gefunden -error.no-main-class.advice=Geben Sie eine Anwendungsklasse an, oder stellen Sie sicher, dass die appResources eine JAR-Datei mit einer Anwendungsklasse im Manifest enthalten error.main-jar-does-not-exist=Die konfigurierte Haupt-JAR-Datei ist im Eingabeverzeichnis nicht vorhanden {0} error.main-jar-does-not-exist.advice=Die Haupt-JAR-Datei muss relativ zum Eingabeverzeichnis (nicht als absoluter Pfad) angegeben werden und muss in diesem Verzeichnis vorhanden sein error.no-module-in-path="{0}-Modul im Modulpfad nicht gefunden" -error.not-path-parameter="Ungültiger Wert für Parameter {0}: {1}" error.no-input-parameter="--input-Parameter für nicht modulare Anwendung fehlt" +error.non-option-arguments={0} Argumente, die keine Option sind, in der Befehlszeile gefunden. Argumente, die keine Option sind, sind nicht zulässig +error.undefined-default-bundling-operation=Standard-Bundling-Vorgang ist nicht definiert +error.undefined-default-bundling-operation.advice=Parameter {0} zur Befehlszeile hinzufügen +error.parameter-not-uuid=Der für Parameter {1} angegebene Wert "{0}" ist keine gültige UUID +error.parameter-not-path=Der für Parameter {1} angegebene Wert "{0}" ist kein gültiger Pfad +error.parameter-not-file=Der für Parameter {1} angegebene Wert "{0}" ist keine Datei +error.parameter-not-directory=Der für Parameter {1} angegebene Wert "{0}" ist kein Verzeichnis +error.parameter-not-empty-directory=Der für Parameter {1} angegebene Wert "{0}" ist kein leeres Verzeichnis oder kein vorhandener Pfad +error.parameter-not-url=Der für Parameter {1} angegebene Wert "{0}" ist keine gültige URL +error.parameter-not-launcher-shortcut-dir=Der für Parameter {1} angegebene Wert "{0}" ist kein gültiges Verknüpfungsstartverzeichnis +error.path-parameter-ioexception=I/O-Fehler beim Zugriff auf Pfadwert "{0}" von Parameter {1} +error.parameter-add-launcher-malformed=Der für Parameter {1} angegebene Wert "{0}" stimmt nicht mit dem Muster = überein +error.parameter-add-launcher-not-file=Der Wert des Pfades zu einer Eigenschaftendatei "{0}", der für den zusätzlichen Launcher "{1}" bereitgestellt wird, ist kein gültiger Dateipfad +error.properties-parameter-not-path=Der für Eigenschaft "{1}" in Datei "{2}" angegebene Wert "{0}" ist kein gültiger Pfad +error.properties-parameter-not-file=Der für Eigenschaft "{1}" in Datei "{2}" angegebene Wert "{0}" ist keine Datei +error.properties-parameter-not-launcher-shortcut-dir=Der für Eigenschaft "{1}" in Datei "{2}" angegebene Wert "{0}" ist kein gültiges Verknüpfungsstartverzeichnis + error.no-content-types-for-file-association=Für Dateiverknüpfungsnummer {0} wurden keine MIME-Typen angegeben error.no-content-types-for-file-association.advice=Geben Sie einen MIME-Typ für Dateiverknüpfungsnummer {0} an error.too-many-content-types-for-file-association=Für Dateiverknüpfungsnummer {0} wurde mehr als ein MIME-Typ angegeben error.too-many-content-types-for-file-association.advice=Geben Sie nur einen MIME-Typ für Dateiverknüpfungsnummer {0} an -error.tool-not-found={0} kann nicht gefunden werden. Grund: {1} -error.tool-not-found.advice=Installieren Sie {0} -error.tool-old-version={0} {1} oder eine neuere Version kann nicht gefunden werden -error.tool-old-version.advice=Installieren Sie {0} {1} oder eine neuere Version +error.launcher-duplicate-name=Mehrere Launcher haben denselben Namen "{0}". Launcher müssen eindeutige Namen haben + +error.tool-error=Validieren von "{0}" nicht möglich. Grund: {1} +error.tool-not-executable="{0}" ist nicht ausführbar +error.tool-not-found="{0}" kann nicht gefunden werden +error.tool-not-found.advice=Installieren Sie "{0}" +error.tool-old-version="{0}" {1} oder eine neuere Version kann nicht gefunden werden +error.tool-old-version.advice=Installieren Sie "{0}" {1} oder eine neuere Version + error.jlink.failed=jlink nicht erfolgreich mit: {0} error.blocked.option=jlink-Option [{0}] ist in --jlink-options nicht zulässig error.no.name=Name nicht mit --name angegeben. Es kann auch kein Name aus app-image abgeleitet werden error.no.name.advice=Geben Sie den Namen mit --name an -warning.no.jdk.modules.found=Warnung: Keine JDK-Module gefunden - -error.foreign-app-image=Fehler : Fehlende .jpackage.xml-Datei in app-image-Verzeichnis "{0}" -error.invalid-app-image=Fehler: app-image-Verzeichnis "{0}" wurde von einer anderen jpackage-Version generiert, oder Datei "{1}" ist nicht wohlgeformt +error.missing-app-image-file=Datei "{0}" fehlt im vordefinierten Anwendungsimage "{1}" +error.invalid-app-image-file=Datei "{0}" im vordefinierten Anwendungsimage "{1}" ist beschädigt oder wurde von einer anderen Version von jpackage erstellt +error.malformed-app-image-file=Datei "{0}" im vordefinierten Anwendungsimage "{1}" enthält nicht wohlgeformte XML-Daten +error.reading-app-image-file=Datei "{0}" konnte im vordefinierten Anwendungsimage "{1}" nicht gelesen werden error.invalid-install-dir=Ungültiges Installationsverzeichnis "{0}" -MSG_BundlerFailed=Fehler: Bundler "{1}" ({0}) konnte kein Package generieren -MSG_BundlerConfigException=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} \nEmpfehlung zur Behebung: {2} -MSG_BundlerConfigExceptionNoAdvice=Bundler {0} aufgrund eines Konfigurationsproblems übersprungen: {1} -MSG_BundlerRuntimeException=Bundler {0} nicht erfolgreich. Grund: {1} +ERR_NoMainClass=Hauptanwendungsklasse fehlt +ERR_UnsupportedOption=Option [{0}] ist auf dieser Plattform ungültig +ERR_InvalidTypeOption=Option [{0}] ist nicht gültig mit Typ [{1}] +ERR_NoInstallerEntryPoint=Option [{0}] ist nicht gültig ohne Einstiegspunktoption --module oder --main-jar +ERR_MutuallyExclusiveOptions=Sich gegenseitig ausschließende Optionen: [{0}] und [{1}] +ERR_InvalidOptionWithAppImageSigning=Option [{0}] ist nicht gültig beim Signieren eines Anwendungsimages -ERR_NoMainClass=Fehler: Hauptanwendungsklasse fehlt -ERR_UnsupportedOption=Fehler: Option [{0}] ist auf dieser Plattform ungültig -ERR_InvalidTypeOption=Fehler: Option [{0}] ist nicht gültig mit Typ [{1}] -ERR_NoInstallerEntryPoint=Fehler: Option [{0}] ist nicht gültig ohne Einstiegspunktoption --module oder --main-jar -ERR_MutuallyExclusiveOptions=Fehler: Optionen [{0}] und [{1}] schließen sich gegenseitig aus -ERR_InvalidOptionWithAppImageSigning=Fehler: Option [{0}] ist nicht gültig beim Signieren eines Anwendungsimages - -ERR_MissingArgument=Fehler: Fehlendes Argument: {0} -ERR_MissingRequiredArgument=Fehler: Für das Argument {0} ist mindestens eines der folgenden Argumente erforderlich: [{1}] -ERR_AppImageNotExist=Fehler: Anwendungsimageverzeichnis "{0}" ist nicht vorhanden -ERR_NoAddLauncherName=Fehler: Für Option --add-launcher müssen ein Name und ein Dateipfad angegeben werden (--add-launcher =) -ERR_NoUniqueName=Fehler: Für --add-launcher = ist ein eindeutiger Name erforderlich -ERR_InvalidAppName=Fehler: Ungültiger Anwendungsname: {0} -ERR_InvalidSLName=Fehler: Ungültiger Name für hinzuzufügenden Launcher: {0} -ERR_IconFileNotExit=Fehler: Die angegebene Symboldatei [{0}] ist nicht vorhanden -ERR_LicenseFileNotExit=Fehler: Die angegebene Lizenzdatei ist nicht vorhanden -ERR_BuildRootInvalid=Fehler: Das temporäre Verzeichnis ({0}) darf nicht vorhanden sein oder muss leer sein -ERR_InvalidOption=Fehler: Ungültige Option: [{0}] -ERR_InvalidInstallerType=Fehler: Ungültiger oder nicht unterstützter Typ: [{0}] -ERR_BothMainJarAndModule=Fehler: Die Optionen --main-jar und --module dürfen nicht beide vorhanden sein -ERR_NoEntryPoint=Fehler: Für das Erstellen des Anwendungsimages muss entweder die Option --main-jar oder die Option --module angegeben werden -ERR_CannotParseOptions=Fehler: Option @filename wird verarbeitet: {0} -ERR_MissingJLinkOptMacAppStore=Fehler: Argument "--mac-app-store" erfordert eine {0}-Option für Argument "--jlink-options" -ERR_MacAppStoreRuntimeBinExists=Fehler: Laufzeitimage "{0}" darf nicht den Ordner "bin" enthalten. Verwenden Sie die jlink-Option "--strip-native-commands" beim Generieren des Laufzeitimages mit dem Argument "--mac-app-store". +ERR_MissingArgument2=Fehlendes Argument: {0} oder {1} +ERR_InvalidAppName=Ungültiger Anwendungsname: {0} +ERR_InvalidSLName=Ungültiger Name für hinzuzufügenden Launcher: {0} +ERR_InvalidOption=Ungültige Option: [{0}] +ERR_InvalidInstallerType=Ungültiger oder nicht unterstützter Typ: [{0}] +ERR_NoEntryPoint=Für das Erstellen des Anwendungsimages muss entweder die Option --main-jar oder die Option --module angegeben werden +ERR_CannotParseOptions=Option @filename wird verarbeitet: {0} +ERR_MissingJLinkOptMacAppStore=Argument "--mac-app-store" erfordert eine {0}-Option für Argument "--jlink-options" diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties index e0faf346973..5db5ead7577 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_ja.properties @@ -24,25 +24,32 @@ # # -jpackage.description=自己完結型Javaアプリケーションをパッケージ化します - param.copyright.default=Copyright (C) {0,date,YYYY} -param.description.default=なし param.vendor.default=不明 +bundle-type.win-app=Windowsアプリケーション・イメージ +bundle-type.win-exe=EXEインストーラ・パッケージ +bundle-type.win-msi=MSIインストーラ・パッケージ +bundle-type.mac-app=Macアプリケーション・イメージ +bundle-type.mac-dmg=Mac DMGパッケージ +bundle-type.mac-pkg=Mac PKGパッケージ +bundle-type.linux-app=Linuxアプリケーション・イメージ +bundle-type.linux-deb=DEBバンドル +bundle-type.linux-rpm=RPMバンドル + resource.post-app-image-script=アプリケーション・イメージを移入した後に実行するスクリプト message.using-default-resource=デフォルトのパッケージ・リソース{0} {1}の使用({2}をresource-dirに追加してカスタマイズ)。 -message.no-default-resource=デフォルトのパッケージ・リソース{0} {1}なし({2}をresource-dirに追加してカスタマイズ)。 +message.no-default-resource=デフォルトのパッケージ・リソース{0}なし({1}をresource-dirに追加してカスタマイズ)。 message.using-custom-resource-from-file=カスタム・パッケージ・リソース{0}の使用(ファイル{1}からロード済) message.using-custom-resource=カスタム・パッケージ・リソース{0}の使用({1}からロード済) message.creating-app-bundle=アプリケーション・パッケージを作成しています: {1}内の{0} -message.runtime-image-dir-does-not-exist=指定されたランタイム・イメージ・ディレクトリ{0}: {1}は存在しません -message.resource-dir-does-not-exist=指定されたリソース・ディレクトリ{0}: {1}は存在しません message.debug-working-directory=デバッグの作業ディレクトリが保持されました: {0} message.bundle-created={0}パッケージの作成に成功しました message.module-version=モジュール"{1}"のバージョン"{0}"をアプリケーション・バージョンとして使用 -message.module-class=モジュール"{1}"のクラス"{0}"をアプリケーション・メイン・クラスとして使用 + +message.error-header={0} +message.advice-header=修正のアドバイス: {0} error.version-string-empty=バージョンを空の文字列にすることはできません error.version-string-zero-length-component=バージョン[{0}]に長さゼロのコンポーネントが含まれます @@ -50,64 +57,69 @@ error.version-string-invalid-component=バージョン[{0}]に無効なコンポ error.cannot-create-output-dir=宛先ディレクトリ{0}を作成できません。 error.cannot-write-to-output-dir=宛先ディレクトリ{0}は書込み不可です -error.root-exists=エラー: アプリケーションの宛先ディレクトリ{0}はすでに存在します +error.root-exists=アプリケーションの宛先ディレクトリ{0}はすでに存在します error.no-main-class-with-main-jar=メイン・クラスが指定されていなかったか、jar {0}に見つかりませんでした error.no-main-class-with-main-jar.advice=メイン・クラスを指定するか、jar {0}がマニフェストで指定していることを確認してください -error.no-main-class=メイン・クラスが指定されていなかったか、指定されたアプリケーション・リソースに見つかりませんでした -error.no-main-class.advice=アプリケーション・クラスを指定するか、マニフェストでappResourcesにアプリケーション・クラスを含むjarがあることを確認してください error.main-jar-does-not-exist=入力ディレクトリで、構成されたメインjarが{0}に存在しません error.main-jar-does-not-exist.advice=入力ディレクトリに対して相対的に(絶対パスではない)メインjarを指定する必要があり、そのディレクトリ内に存在する必要があります error.no-module-in-path="モジュール・パスに{0}モジュールが見つかりませんでした" -error.not-path-parameter="{0}パラメータの無効な値: {1}" error.no-input-parameter="非モジュラ・アプリケーションに--inputパラメータがありません" +error.non-option-arguments=コマンドラインで{0}個の非オプション引数が見つかりました。非オプション引数は使用できません +error.undefined-default-bundling-operation=デフォルトのバンドル操作は未定義です +error.undefined-default-bundling-operation.advice=コマンドラインに{0}パラメータを追加します +error.parameter-not-uuid=パラメータ{1}に指定された値"{0}"は有効なUUIDではありません +error.parameter-not-path=パラメータ{1}に指定された値"{0}"は有効なパスではありません +error.parameter-not-file=パラメータ{1}に指定された値"{0}"はファイルではありません +error.parameter-not-directory=パラメータ{1}に指定された値"{0}"はディレクトリではありません +error.parameter-not-empty-directory=パラメータ{1}に指定された値"{0}"が空のディレクトリでないか、存在しないパスです +error.parameter-not-url=パラメータ{1}に指定された値"{0}"は有効なURLではありません +error.parameter-not-launcher-shortcut-dir=パラメータ{1}に指定された値"{0}"は、有効なショートカット起動ディレクトリではありません +error.path-parameter-ioexception=パラメータ{1}のパス値"{0}"へのアクセス中にI/Oエラーが発生しました +error.parameter-add-launcher-malformed=パラメータ{1}に指定された値"{0}"がパターン=と一致しません +error.parameter-add-launcher-not-file=追加のランチャ"{1}"に指定されたプロパティ・ファイル"{0}"へのパスの値は有効なファイル・パスではありません +error.properties-parameter-not-path="{2}"ファイルのプロパティ"{1}"に指定された値"{0}"は有効なパスではありません +error.properties-parameter-not-file="{2}"ファイルのプロパティ"{1}"に指定された値"{0}"はファイルではありません +error.properties-parameter-not-launcher-shortcut-dir="{2}"ファイルのプロパティ"{1}"に指定された値"{0}"は、有効なショートカット起動ディレクトリではありません + error.no-content-types-for-file-association=ファイル・アソシエーション番号{0}にMIMEタイプが指定されませんでした error.no-content-types-for-file-association.advice=ファイル・アソシエーション番号{0}にMIMEタイプを指定してください error.too-many-content-types-for-file-association=ファイル・アソシエーション番号{0}に複数のMIMEタイプが指定されました error.too-many-content-types-for-file-association.advice=ファイル・アソシエーション番号{0}にMIMEタイプを1つのみ指定してください -error.tool-not-found={0}が見つかりません。理由: {1} -error.tool-not-found.advice={0}をインストールしてください -error.tool-old-version={0} {1}以降が見つかりません -error.tool-old-version.advice={0} {1}以降をインストールしてください +error.launcher-duplicate-name=複数のランチャに同じ名前"{0}"が付いています。ランチャには一意の名前が必要です + +error.tool-error="{0}"を検証できません。理由: {1} +error.tool-not-executable="{0}"は実行可能ではありません +error.tool-not-found="{0}"が見つかりません +error.tool-not-found.advice="{0}"をインストールしてください +error.tool-old-version="{0}" {1}以降が見つかりません +error.tool-old-version.advice="{0}" {1}以降をインストールしてください + error.jlink.failed=jlinkが次で失敗しました: {0} error.blocked.option=jlinkオプション[{0}]は--jlink-optionsでは許可されません error.no.name=名前が--nameで指定されておらず、app-imageから推論できません error.no.name.advice=--nameで名前を指定します -warning.no.jdk.modules.found=警告: JDKモジュールが見つかりません - -error.foreign-app-image=エラー: app-imageディレクトリ"{0}"に.jpackage.xmlファイルがありません -error.invalid-app-image=エラー: app-imageディレクトリ"{0}"は、別のjpackageバージョンまたは不正な"{1}"ファイルで生成されました +error.missing-app-image-file=事前定義済アプリケーション・イメージ"{1}"に"{0}"ファイルがありません +error.invalid-app-image-file=事前定義済アプリケーション・イメージ"{1}"の"{0}"ファイルが破損しているか、別のバージョンのjpackageによって作成されました +error.malformed-app-image-file=事前定義済アプリケーション・イメージ"{1}"の"{0}"ファイルに不正なXMLデータが含まれています +error.reading-app-image-file=事前定義済アプリケーション・イメージ"{1}"の"{0}"ファイルの読取りに失敗しました error.invalid-install-dir=無効なインストール・ディレクトリ"{0}" -MSG_BundlerFailed=エラー: バンドラ"{1}" ({0})がパッケージの生成に失敗しました -MSG_BundlerConfigException=構成の問題のため、バンドラ{0}がスキップされました: {1} \n次の修正を行ってください: {2} -MSG_BundlerConfigExceptionNoAdvice=構成の問題のため、バンドラ{0}がスキップされました: {1} -MSG_BundlerRuntimeException={1}のため、バンドラ{0}が失敗しました +ERR_NoMainClass=メイン・アプリケーション・クラスがありません +ERR_UnsupportedOption=オプション[{0}]は、このプラットフォームでは無効です +ERR_InvalidTypeOption=オプション[{0}]は、タイプ[{1}]では無効です +ERR_NoInstallerEntryPoint=オプション[{0}]は、--moduleまたは--main-jarエントリ・ポイント・オプションなしでは無効です +ERR_MutuallyExclusiveOptions=相互排他的なオプション[{0}]と[{1}] +ERR_InvalidOptionWithAppImageSigning=アプリケーション・イメージへの署名時にオプション[{0}]が有効ではありません -ERR_NoMainClass=エラー: メイン・アプリケーション・クラスがありません -ERR_UnsupportedOption=エラー: オプション[{0}]は、このプラットフォームでは無効です -ERR_InvalidTypeOption=エラー: オプション[{0}]は、タイプ[{1}]では無効です -ERR_NoInstallerEntryPoint=エラー: オプション[{0}]は、--moduleまたは--main-jarエントリ・ポイント・オプションなしでは無効です -ERR_MutuallyExclusiveOptions=エラー: 相互排他的なオプション[{0}]と[{1}] -ERR_InvalidOptionWithAppImageSigning=エラー: アプリケーション・イメージへの署名時にオプション[{0}]が有効ではありません - -ERR_MissingArgument=エラー: 引数がありません: {0} -ERR_MissingRequiredArgument=エラー: {0}引数には少なくとも1つの[{1}]引数が必要です -ERR_AppImageNotExist=エラー: アプリケーション・イメージ・ディレクトリ"{0}"は存在しません -ERR_NoAddLauncherName=エラー: --add-launcherオプションには名前およびファイル・パスが必要です(--add-launcher =) -ERR_NoUniqueName=エラー: --add-launcher =には一意の名前が必要です -ERR_InvalidAppName=エラー: 無効なアプリケーション名: {0} -ERR_InvalidSLName=エラー: 無効な追加ランチャ名: {0} -ERR_IconFileNotExit=エラー: 指定されたアイコン・ファイル[{0}]は存在しません -ERR_LicenseFileNotExit=エラー: 指定されたライセンス・ファイルは存在しません -ERR_BuildRootInvalid=エラー: 一時({0})は存在しないか、空のディレクトリである必要があります -ERR_InvalidOption=エラー: 無効なオプション: [{0}] -ERR_InvalidInstallerType=エラー: 無効またはサポートされていないタイプ: [{0}] -ERR_BothMainJarAndModule=エラー: --main-jarオプションと--moduleオプションの両方を指定することはできません -ERR_NoEntryPoint=エラー: アプリケーション・イメージの作成には--main-jarまたは--moduleオプションが必要です -ERR_CannotParseOptions=エラー: @filenameオプションの処理: {0} -ERR_MissingJLinkOptMacAppStore=エラー: --mac-app-store引数では、--jlink-options引数に{0}オプションが必要です -ERR_MacAppStoreRuntimeBinExists=エラー: ランタイム・イメージ"{0}"に"bin"フォルダを含めることはできません。--mac-app-store引数で使用されるランタイム・イメージを生成する際に、--strip-native-commands jlinkオプションを使用します。 +ERR_MissingArgument2=引数がありません: {0}または{1} +ERR_InvalidAppName=無効なアプリケーション名: {0} +ERR_InvalidSLName=無効な追加ランチャ名: {0} +ERR_InvalidOption=無効なオプション: [{0}] +ERR_InvalidInstallerType=無効またはサポートされていないタイプ: [{0}] +ERR_NoEntryPoint=アプリケーション・イメージの作成には--main-jarまたは--moduleオプションが必要です +ERR_CannotParseOptions=@filenameオプションの処理: {0} +ERR_MissingJLinkOptMacAppStore=--mac-app-store引数では、--jlink-options引数に{0}オプションが必要です diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties index 0236ef34077..23540af7db2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/resources/MainResources_zh_CN.properties @@ -24,25 +24,32 @@ # # -jpackage.description=打包自包含 Java 应用程序 - param.copyright.default=版权所有 (C) {0,date,YYYY} -param.description.default=无 param.vendor.default=未知 +bundle-type.win-app=Windows 应用程序映像 +bundle-type.win-exe=EXE 安装程序包 +bundle-type.win-msi=MSI 安装程序包 +bundle-type.mac-app=Mac 应用程序映像 +bundle-type.mac-dmg=Mac DMG 程序包 +bundle-type.mac-pkg=Mac PKG 程序包 +bundle-type.linux-app=Linux 应用程序映像 +bundle-type.linux-deb=DEB 包 +bundle-type.linux-rpm=RPM 包 + resource.post-app-image-script=要在填充应用程序映像之后运行的脚本 message.using-default-resource=使用默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。 -message.no-default-resource=无默认程序包资源 {0} {1}(将 {2} 添加到 resource-dir 中以进行定制)。 +message.no-default-resource=无默认程序包资源 {0}(将 {1} 添加到 resource-dir 中以进行定制)。 message.using-custom-resource-from-file=使用定制程序包资源 {0} (从文件 {1} 加载)。 message.using-custom-resource=使用定制程序包资源 {0} (从 {1} 加载)。 message.creating-app-bundle=正在 {1} 中创建应用程序包 {0} -message.runtime-image-dir-does-not-exist=指定的运行时映像目录 {0}:{1} 不存在 -message.resource-dir-does-not-exist=指定的资源目录 {0}:{1} 不存在 message.debug-working-directory=用于调试的已保留工作目录: {0} message.bundle-created=已成功地构建 {0} 程序包 message.module-version=正在将模块 "{1}" 中的版本 "{0}" 用作应用程序版本 -message.module-class=正在将模块 "{1}" 中的类 "{0}" 用作应用程序主类 + +message.error-header={0} +message.advice-header=修复建议:{0} error.version-string-empty=版本不能为空字符串 error.version-string-zero-length-component=版本 [{0}] 包含长度为零的组件 @@ -50,64 +57,69 @@ error.version-string-invalid-component=版本 [{0}] 包含无效组件 [{1}] error.cannot-create-output-dir=无法创建目标目录 {0} error.cannot-write-to-output-dir=目标目录 {0} 不可写 -error.root-exists=错误:应用程序目标目录 {0} 已存在 +error.root-exists=应用程序目标目录 {0} 已存在 error.no-main-class-with-main-jar=未指定主类,在 jar {0} 中也未找到主类 error.no-main-class-with-main-jar.advice=请指定主类或确保 jar {0} 在清单中指定一个主类。 -error.no-main-class=未指定主类,在提供的应用程序资源中也未找到主类 -error.no-main-class.advice=请指定应用程序类,或者确保 appResources 中有一个 jar 在清单中包含应用程序类。 error.main-jar-does-not-exist=配置的主 jar 在输入目录中不存在 {0} error.main-jar-does-not-exist.advice=必须使用相对于输入目录的路径(不使用绝对路径)指定主 jar ,并且该目录中存在主 jar error.no-module-in-path="无法在模块路径中找到 {0} 模块" -error.not-path-parameter="{0} 参数的值无效:{1}" error.no-input-parameter="非模块化应用程序缺少 --input 参数" +error.non-option-arguments=在命令行上发现 {0} 个非选项参数。不允许使用非选项参数 +error.undefined-default-bundling-operation=未定义默认绑定操作 +error.undefined-default-bundling-operation.advice=将 {0} 参数添加到命令行 +error.parameter-not-uuid=为参数 {1} 提供的值 "{0}" 不是有效的 UUID +error.parameter-not-path=为参数 {1} 提供的值 "{0}" 不是有效路径 +error.parameter-not-file=为参数 {1} 提供的值 "{0}" 不是文件 +error.parameter-not-directory=为参数 {1} 提供的值 "{0}" 不是目录 +error.parameter-not-empty-directory=为参数 {1} 提供的值 "{0}" 不是空目录或是不存在的路径 +error.parameter-not-url=为参数 {1} 提供的值 "{0}" 不是有效的 URL +error.parameter-not-launcher-shortcut-dir=为参数 {1} 提供的值 "{0}" 不是有效的快捷方式启动目录 +error.path-parameter-ioexception=访问参数 {1} 的路径值 "{0}" 时出现 I/O 错误 +error.parameter-add-launcher-malformed=为参数 {1} 提供的值 "{0}" 与模式 = 不匹配 +error.parameter-add-launcher-not-file=为其他启动程序 "{1}" 提供的属性文件 "{0}" 的路径值不是有效的文件路径 +error.properties-parameter-not-path=为 "{2}" 文件中的属性 "{1}" 提供的值 "{0}" 不是有效路径 +error.properties-parameter-not-file=为 "{2}" 文件中的属性 "{1}" 提供的值 "{0}" 不是文件 +error.properties-parameter-not-launcher-shortcut-dir=为 "{2}" 文件中的属性 "{1}" 提供的值 "{0}" 不是有效的快捷方式启动目录 + error.no-content-types-for-file-association=没有为文件关联号{0}指定 MIME 类型 error.no-content-types-for-file-association.advice=为文件关联号 {0} 指定 MIME 类型 error.too-many-content-types-for-file-association=为文件关联号{0}指定了多个 MIME 类型 error.too-many-content-types-for-file-association.advice=仅为文件关联号 {0} 指定一个 MIME 类型 -error.tool-not-found=找不到 {0}。原因:{1} -error.tool-not-found.advice=请安装 {0} -error.tool-old-version=找不到 {0} {1}或更新版本 -error.tool-old-version.advice=请安装 {0} {1}或更新版本 +error.launcher-duplicate-name=多个启动程序具有相同的名称 "{0}"。启动程序应具有唯一名称 + +error.tool-error=无法验证 "{0}"。原因:{1} +error.tool-not-executable="{0}" 不可执行 +error.tool-not-found=找不到 "{0}" +error.tool-not-found.advice=请安装 "{0}" +error.tool-old-version=找不到 "{0}" {1} 或更新版本 +error.tool-old-version.advice=请安装 "{0}" {1} 或更新版本 + error.jlink.failed=jlink 失败,出现 {0} error.blocked.option=不允许在 --jlink-options 中使用 jlink 选项 [{0}] error.no.name=未使用 --name 指定名称,无法从 app-image 推断名称 error.no.name.advice=使用 --name 指定名称 -warning.no.jdk.modules.found=警告: 未找到 JDK 模块 - -error.foreign-app-image=错误:app-image 目录 "{0}" 中缺少 .jpackage.xml 文件 -error.invalid-app-image=错误:另一个 jpackage 版本或格式错误的 "{1}" 文件生成了 app-image 目录 "{0}" +error.missing-app-image-file=预定义的应用程序映像 "{1}" 中缺少 "{0}" 文件 +error.invalid-app-image-file=预定义的应用程序映像 "{1}" 中的 "{0}" 文件已损坏或由其他版本的 jpackage 创建 +error.malformed-app-image-file=预定义的应用程序映像 "{1}" 中的 "{0}" 文件包含格式错误的 XML 数据 +error.reading-app-image-file=无法在预定义的应用程序映像 "{1}" 中读取 "{0}" 文件 error.invalid-install-dir=安装目录 "{0}" 无效 -MSG_BundlerFailed=错误:打包程序 "{1}" ({0}) 无法生成程序包 -MSG_BundlerConfigException=由于配置问题, 跳过了打包程序{0}: {1} \n修复建议: {2} -MSG_BundlerConfigExceptionNoAdvice=由于配置问题, 跳过了打包程序{0}: {1} -MSG_BundlerRuntimeException=由于{1}, 打包程序{0}失败 +ERR_NoMainClass=缺少主应用程序类 +ERR_UnsupportedOption=选项 [{0}] 在此平台上无效 +ERR_InvalidTypeOption=选项 [{0}] 对于类型 [{1}] 无效 +ERR_NoInstallerEntryPoint=在没有 --module 或 --main-jar 入口点选项时,选项 [{0}] 无效 +ERR_MutuallyExclusiveOptions=选项 [{0}] 和 [{1}] 相互排斥 +ERR_InvalidOptionWithAppImageSigning=对应用程序映像进行签名时,选项 [{0}] 无效 -ERR_NoMainClass=错误:缺少主应用程序类 -ERR_UnsupportedOption=错误:选项 [{0}] 在此平台上无效 -ERR_InvalidTypeOption=错误:选项 [{0}] 对于类型 [{1}] 无效 -ERR_NoInstallerEntryPoint=错误:在没有 --module 或 --main-jar 入口点选项时,选项 [{0}] 无效 -ERR_MutuallyExclusiveOptions=错误:选项 [{0}] 和 [{1}] 相互排斥 -ERR_InvalidOptionWithAppImageSigning=错误:对应用程序映像签名时,选项 [{0}] 无效 - -ERR_MissingArgument=错误: 缺少参数: {0} -ERR_MissingRequiredArgument=错误:{0} 参数至少需要 [{1}] 参数之一 -ERR_AppImageNotExist=错误:应用程序映像目录 "{0}" 不存在 -ERR_NoAddLauncherName=错误:--add-launcher 选项需要一个名称和一个文件路径 (--add-launcher =) -ERR_NoUniqueName=错误:--add-launcher = 需要一个唯一的名称 -ERR_InvalidAppName=错误:应用程序名称 {0} 无效 -ERR_InvalidSLName=错误:添加启动程序名称 {0} 无效 -ERR_IconFileNotExit=错误:指定的图标文件 [{0}] 不存在 -ERR_LicenseFileNotExit=错误:指定的许可证文件不存在 -ERR_BuildRootInvalid=错误:临时目录 ({0}) 必须是不存在的目录或空白目录 -ERR_InvalidOption=错误:选项 [{0}] 无效 -ERR_InvalidInstallerType=错误:类型 [{0}] 无效或不受支持 -ERR_BothMainJarAndModule=错误:不能同时包含 --main-jar 和 --module 选项 -ERR_NoEntryPoint=错误:创建应用程序映像需要 --main-jar 或 --module 选项 -ERR_CannotParseOptions=错误:正在处理 @filename 选项:{0} -ERR_MissingJLinkOptMacAppStore=错误:对于 --jlink-options 参数,--mac-app-store 参数需要 {0} 选项 -ERR_MacAppStoreRuntimeBinExists=错误:运行时映像 "{0}" 不应包含 "bin" 文件夹。生成与 --mac-app-store 参数一起使用的运行时映像时,使用 --strip-native-commands jlink 选项。 +ERR_MissingArgument2=缺少参数:{0} 或 {1} +ERR_InvalidAppName=应用程序名称 {0} 无效 +ERR_InvalidSLName=添加启动程序名称 {0} 无效 +ERR_InvalidOption=选项 [{0}] 无效 +ERR_InvalidInstallerType=类型 [{0}] 无效或不受支持 +ERR_NoEntryPoint=创建应用程序映像需要 --main-jar 或 --module 选项 +ERR_CannotParseOptions=正在处理 @filename 选项:{0} +ERR_MissingJLinkOptMacAppStore=对于 --jlink-options 参数,--mac-app-store 参数需要 {0} 选项 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties index 3e6f8e30d6a..baaba64b398 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_de.properties @@ -23,15 +23,9 @@ # questions. # # - -app.bundler.name=Windows-Anwendungsimage -exe.bundler.name=EXE-Installationsprogrammpackage -msi.bundler.name=MSI-Installationsprogrammpackage - param.menu-group.default=Unbekannt resource.executable-properties-template=Vorlage für das Erstellen der ausführbaren Eigenschaftendatei -resource.setup-icon=Symbol für Dialogfeld "Setup" resource.post-msi-script=Auszuführendes Skript nach dem Erstellen der MSI-Datei für das EXE-Installationsprogramm resource.wxl-file=WiX-Lokalisierungsdatei resource.main-wix-file=Haupt-WiX-Projektdatei @@ -65,12 +59,10 @@ message.potential.windows.defender.issue=Warnung: Windows Defender verhindert ev message.outputting-to-location=EXE für Installationsprogramm wird generiert in: {0}. message.output-location=Installationsprogramm (.exe) gespeichert in: {0} message.tool-version=[{0}]-Version [{1}] erkannt. -message.creating-association-with-null-extension=Verknüpfung mit Nullerweiterung wird erstellt. message.wrong-tool-version=[{0}]-Version {1} wurde erkannt. Erforderlich ist jedoch Version {2}. message.use-wix36-features=WiX {0} erkannt. Erweiterte Bereinigungsaktion wird aktiviert. message.product-code=MSI-ProductCode: {0}. message.upgrade-code=MSI-UpgradeCode: {0}. message.preparing-msi-config=MSI-Konfiguration wird vorbereitet: {0}. message.generating-msi=MSI wird generiert: {0}. -message.invalid.install.dir=Warnung: Ungültiges Installationsverzeichnis {0}. Installationsverzeichnis muss ein relativer Unterpfad unter dem Standardinstallationsverzeichnis wie "Programme" sein. Der Anwendungsname "{1}" wird als Standardwert verwendet. diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties index 07604dc9980..119c7532b1f 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_ja.properties @@ -23,15 +23,9 @@ # questions. # # - -app.bundler.name=Windowsアプリケーション・イメージ -exe.bundler.name=EXEインストーラ・パッケージ -msi.bundler.name=MSIインストーラ・パッケージ - param.menu-group.default=不明 resource.executable-properties-template=実行可能なプロパティ・ファイル作成用のテンプレート -resource.setup-icon=設定ダイアログ・アイコン resource.post-msi-script=exeインストーラのmsiファイルが作成された後に実行するスクリプト resource.wxl-file=WiXローカリゼーション・ファイル resource.main-wix-file=メインWiXプロジェクト・ファイル @@ -65,12 +59,10 @@ message.potential.windows.defender.issue=警告: Windows Defenderが原因でjpa message.outputting-to-location=インストーラのEXEを次に生成しています: {0} message.output-location=インストーラ(.exe)は次に保存されました: {0} message.tool-version=[{0}]バージョン[{1}]が検出されました。 -message.creating-association-with-null-extension=null拡張子との関連付けを作成しています。 message.wrong-tool-version=[{0}]バージョン{1}が検出されましたが、バージョン{2}が必要です。 message.use-wix36-features=WiX {0}が検出されました。拡張クリーンアップ・アクションを有効化しています。 message.product-code=MSI ProductCode: {0}。 message.upgrade-code=MSI UpgradeCode: {0}。 message.preparing-msi-config=MSI構成を準備しています: {0} message.generating-msi=MSIを生成しています: {0}。 -message.invalid.install.dir=警告: インストール・ディレクトリ{0}が無効です。インストール・ディレクトリはデフォルトのインストール場所("プログラム・ファイル"など)の下の相対サブパスである必要があります。アプリケーション名"{1}"にデフォルト設定されています。 diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties index 7eae69fba2f..66d8a9d8b96 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources_zh_CN.properties @@ -23,15 +23,9 @@ # questions. # # - -app.bundler.name=Windows 应用程序映像 -exe.bundler.name=EXE 安装程序包 -msi.bundler.name=MSI 安装程序包 - param.menu-group.default=未知 resource.executable-properties-template=用于创建可执行属性文件的模板 -resource.setup-icon=设置对话框图标 resource.post-msi-script=在为 exe 安装程序创建 msi 文件之后要运行的脚本 resource.wxl-file=WiX 本地化文件 resource.main-wix-file=主 WiX 项目文件 @@ -65,12 +59,10 @@ message.potential.windows.defender.issue=警告:Windows Defender 可能会阻 message.outputting-to-location=正在为安装程序生成 EXE, 位置: {0}。 message.output-location=安装程序 (.exe) 已保存到: {0} message.tool-version=检测到 [{0}] 版本 [{1}]。 -message.creating-association-with-null-extension=正在使用空扩展名创建关联。 message.wrong-tool-version=检测到 [{0}] 版本 {1}, 但需要版本 {2}。 message.use-wix36-features=检测到 WiX {0}。正在启用高级清除操作。 message.product-code=MSI ProductCode:{0}。 message.upgrade-code=MSI UpgradeCode:{0}。 message.preparing-msi-config=正在准备 MSI 配置: {0}。 message.generating-msi=正在生成 MSI: {0}。 -message.invalid.install.dir=警告:安装目录 {0} 无效。安装目录应当是默认安装位置(如 "Program Files")下面的相对子路径。默认为应用程序名称 "{1}"。 From 2241218ef64ed6cb51f962f3ab6db1a766f1744f Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 16 Dec 2025 21:25:41 +0000 Subject: [PATCH 125/211] 8373631: Improve classes in the "jdk.jpackage.internal.util.function" package Reviewed-by: almatvee --- .../jdk/jpackage/internal/MacFromOptions.java | 12 +- .../jdk/jpackage/internal/TempKeychain.java | 4 +- .../jdk/jpackage/internal/AppImageFile.java | 2 +- .../jpackage/internal/PackagingPipeline.java | 2 +- .../jdk/jpackage/internal/cli/Main.java | 2 +- .../internal/cli/OptionsProcessor.java | 2 +- .../jdk/jpackage/internal/util/FileUtils.java | 5 +- .../jdk/jpackage/internal/util/Result.java | 61 +- .../jdk/jpackage/internal/util/XmlUtils.java | 6 +- .../internal/util/function/ExceptionBox.java | 64 +- .../util/function/ThrowingBiConsumer.java | 12 +- .../util/function/ThrowingBiFunction.java | 12 +- .../util/function/ThrowingConsumer.java | 12 +- .../util/function/ThrowingFunction.java | 12 +- .../util/function/ThrowingRunnable.java | 12 +- .../util/function/ThrowingSupplier.java | 12 +- .../util/function/ThrowingUnaryOperator.java | 12 +- .../internal/WinSystemEnvironment.java | 2 +- .../jdk/jpackage/test/AnnotationsTest.java | 6 +- .../jdk/jpackage/test/PackageTestTest.java | 6 +- .../jdk/jpackage/test/TKitTest.java | 11 +- .../jdk/jpackage/test/AdditionalLauncher.java | 4 +- .../jdk/jpackage/test/JPackageCommand.java | 22 +- .../jpackage/test/JPackageStringBundle.java | 6 +- .../jdk/jpackage/test/LauncherVerifier.java | 2 +- .../jdk/jpackage/test/LinuxHelper.java | 2 +- .../helpers/jdk/jpackage/test/MacHelper.java | 2 +- .../helpers/jdk/jpackage/test/MacSign.java | 19 +- .../jdk/jpackage/test/MacSignVerify.java | 4 +- .../helpers/jdk/jpackage/test/Main.java | 9 +- .../helpers/jdk/jpackage/test/MethodCall.java | 4 +- .../jdk/jpackage/test/ObjectMapper.java | 8 +- .../jdk/jpackage/test/PackageTest.java | 26 +- .../helpers/jdk/jpackage/test/TKit.java | 39 +- .../jdk/jpackage/test/TestBuilder.java | 16 +- .../jdk/jpackage/test/TestInstance.java | 18 +- .../test/WinExecutableIconVerifier.java | 6 +- .../jdk/jpackage/test/WindowsHelper.java | 4 +- .../internal/PackagingPipelineTest.java | 4 +- .../cli/OptionsValidationFailTest.java | 2 +- .../jpackage/internal/util/ResultTest.java | 602 ++++++++++++++++++ .../util/function/ExceptionBoxTest.java | 246 +++++++ .../util/function/FunctionalTest.java | 189 ++++++ .../tools/jdk/jpackage/test/JUnitAdapter.java | 6 +- .../tools/jpackage/linux/AppAboutUrlTest.java | 4 +- .../jpackage/macosx/CustomInfoPListTest.java | 12 +- .../jpackage/macosx/EntitlementsTest.java | 2 +- .../tools/jpackage/share/AppContentTest.java | 3 +- test/jdk/tools/jpackage/share/AsyncTest.java | 27 +- test/jdk/tools/jpackage/share/BasicTest.java | 4 +- test/jdk/tools/jpackage/share/IconTest.java | 4 +- .../tools/jpackage/share/InOutPathTest.java | 23 +- .../tools/jpackage/share/PerUserCfgTest.java | 4 +- .../jpackage/share/RuntimePackageTest.java | 4 +- .../jdk/tools/jpackage/share/ServiceTest.java | 4 +- 55 files changed, 1339 insertions(+), 261 deletions(-) create mode 100644 test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/ResultTest.java create mode 100644 test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/ExceptionBoxTest.java create mode 100644 test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/FunctionalTest.java diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java index 074014dede0..b1094331740 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacFromOptions.java @@ -49,7 +49,7 @@ import static jdk.jpackage.internal.cli.StandardOption.PREDEFINED_RUNTIME_IMAGE; import static jdk.jpackage.internal.model.MacPackage.RUNTIME_BUNDLE_LAYOUT; import static jdk.jpackage.internal.model.StandardPackageType.MAC_DMG; import static jdk.jpackage.internal.model.StandardPackageType.MAC_PKG; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import java.nio.file.Path; import java.util.Objects; @@ -106,7 +106,7 @@ final class MacFromOptions { final boolean sign = MAC_SIGN.findIn(options).orElse(false); final boolean appStore = MAC_APP_STORE.findIn(options).orElse(false); - final var appResult = Result.create(() -> createMacApplicationInternal(options)); + final var appResult = Result.of(() -> createMacApplicationInternal(options)); final Optional pkgBuilder; if (appResult.hasValue()) { @@ -146,18 +146,18 @@ final class MacFromOptions { final var expiredAppCertException = appResult.firstError().orElseThrow(); - final var pkgSignConfigResult = Result.create(signingIdentityBuilder::create); + final var pkgSignConfigResult = Result.of(signingIdentityBuilder::create); try { rethrowIfNotExpiredCertificateException(pkgSignConfigResult); // The certificate for the package signing config is also expired! } catch (RuntimeException ex) { // Some error occurred trying to configure the signing config for the package. // Ignore it, bail out with the first error. - rethrowUnchecked(expiredAppCertException); + throw toUnchecked(expiredAppCertException); } Log.error(pkgSignConfigResult.firstError().orElseThrow().getMessage()); - rethrowUnchecked(expiredAppCertException); + throw toUnchecked(expiredAppCertException); } } @@ -303,7 +303,7 @@ final class MacFromOptions { } } - rethrowUnchecked(ex); + throw toUnchecked(ex); } private static SigningIdentityBuilder createSigningIdentityBuilder(Options options) { diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java index 97709678c67..b38faecd96f 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/TempKeychain.java @@ -35,7 +35,7 @@ import jdk.jpackage.internal.util.function.ThrowingConsumer; final class TempKeychain implements Closeable { - static void withKeychains(ThrowingConsumer> keychainConsumer, List keychains) throws Throwable { + static void withKeychains(ThrowingConsumer, ? extends Exception> keychainConsumer, List keychains) throws Exception { keychains.forEach(Objects::requireNonNull); if (keychains.isEmpty() || OSVersion.current().compareTo(new OSVersion(10, 12)) < 0) { keychainConsumer.accept(keychains); @@ -47,7 +47,7 @@ final class TempKeychain implements Closeable { } } - static void withKeychain(ThrowingConsumer keychainConsumer, Keychain keychain) throws Throwable { + static void withKeychain(ThrowingConsumer keychainConsumer, Keychain keychain) throws Exception { Objects.requireNonNull(keychainConsumer); withKeychains(keychains -> { keychainConsumer.accept(keychains.getFirst()); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java index b6b4322302e..5f473b554be 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/AppImageFile.java @@ -198,7 +198,7 @@ final class AppImageFile { } catch (XPathExpressionException ex) { // This should never happen as XPath expressions should be correct - throw ExceptionBox.rethrowUnchecked(ex); + throw ExceptionBox.toUnchecked(ex); } catch (SAXException ex) { // Malformed input XML throw new JPackageException(I18N.format("error.malformed-app-image-file", relativeAppImageFilePath, appImageDir), ex); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagingPipeline.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagingPipeline.java index a2750fee260..2ee35b658ea 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagingPipeline.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/PackagingPipeline.java @@ -508,7 +508,7 @@ final class PackagingPipeline { try { builder.create().call(); } catch (Exception ex) { - throw ExceptionBox.rethrowUnchecked(ex); + throw ExceptionBox.toUnchecked(ex); } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java index af51bc9fd98..57f627b1548 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/Main.java @@ -110,7 +110,7 @@ public final class Main { Log.fatalError(I18N.format("ERR_CannotParseOptions", ex.getMessage())); return 1; } catch (IOException ex) { - throw ExceptionBox.rethrowUnchecked(ex); + throw ExceptionBox.toUnchecked(ex); } final var bundlingEnv = ServiceLoader.load(CliBundlingEnvironment.class, diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java index 1bc5c36989f..54003b714a2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/cli/OptionsProcessor.java @@ -87,7 +87,7 @@ final class OptionsProcessor { final var untypedOptions = optionsBuilder.create(); // Create command line structure analyzer. - final var analyzerResult = Result.create(() -> new OptionsAnalyzer(untypedOptions, bundlingEnv)); + final var analyzerResult = Result.of(() -> new OptionsAnalyzer(untypedOptions, bundlingEnv)); if (analyzerResult.hasErrors()) { // Failed to derive the bundling operation from the command line. allErrors.addAll(analyzerResult.mapErrors().errors()); diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java index 49c395642f4..2f7f2682a71 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/FileUtils.java @@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Optional; import jdk.internal.util.OperatingSystem; -import jdk.jpackage.internal.util.function.ExceptionBox; import jdk.jpackage.internal.util.function.ThrowingConsumer; public final class FileUtils { @@ -170,15 +169,13 @@ public final class FileUtils { } } - private void runActionOnPath(ThrowingConsumer action, Path path) { + private void runActionOnPath(ThrowingConsumer action, Path path) { try { action.accept(path); } catch (IOException ex) { if (this.ex == null) { this.ex = ex; } - } catch (Throwable t) { - throw ExceptionBox.rethrowUnchecked(t); } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java index 8a61acafe77..46e99f134df 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/Result.java @@ -24,33 +24,28 @@ */ package jdk.jpackage.internal.util; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; - import java.util.Collection; import java.util.List; +import java.util.Objects; import java.util.Optional; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import java.util.function.UnaryOperator; import java.util.stream.StreamSupport; +import jdk.jpackage.internal.util.function.ExceptionBox; +import jdk.jpackage.internal.util.function.ThrowingSupplier; public record Result(Optional value, Collection errors) { public Result { if (value.isEmpty() == errors.isEmpty()) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("'value' and 'errors' cannot both be non-empty or both be empty"); } - - if (value.isEmpty() && errors.isEmpty()) { - throw new IllegalArgumentException("Error collection must be non-empty"); - } - } public T orElseThrow() { firstError().ifPresent(ex -> { - rethrowUnchecked(ex); + throw ExceptionBox.toUnchecked(ex); }); return value.orElseThrow(); } @@ -64,7 +59,16 @@ public record Result(Optional value, Collection error } public Result map(Function conv) { - return new Result<>(value.map(conv), errors); + if (hasValue()) { + var mapped = value.map(conv); + if (mapped.isEmpty()) { + throw new NullPointerException(); + } else { + return new Result<>(mapped, errors); + } + } else { + return mapErrors(); + } } public Result flatMap(Function> conv) { @@ -73,12 +77,12 @@ public record Result(Optional value, Collection error }); } - public Result mapErrors(UnaryOperator> errorsMapper) { - return new Result<>(value, errorsMapper.apply(errors)); - } - + @SuppressWarnings("unchecked") public Result mapErrors() { - return new Result<>(Optional.empty(), errors); + if (hasValue()) { + throw new IllegalStateException("Can not map errors from a result without errors"); + } + return (Result)this; } public Result peekErrors(Consumer> consumer) { @@ -97,12 +101,31 @@ public record Result(Optional value, Collection error return errors.stream().findFirst(); } - public static Result create(Supplier supplier) { + public static Result of(Supplier supplier) { + return of(supplier::get, RuntimeException.class); + } + + public static Result of( + ThrowingSupplier supplier, Class supplierExceptionType) { + + Objects.requireNonNull(supplier); + Objects.requireNonNull(supplierExceptionType); + + T value; try { - return ofValue(supplier.get()); + value = supplier.get(); } catch (Exception ex) { - return ofError(ex); + if (supplierExceptionType.isInstance(ex)) { + return ofError(ex); + } else if (ex instanceof RuntimeException rex) { + throw rex; + } else { + // Unreachable because the `supplier` can throw exceptions of type or supertype `E` or runtime exceptions. + throw ExceptionBox.reachedUnreachable(); + } } + + return ofValue(value); } public static Result ofValue(T value) { diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java index c8761259254..f62ffee9260 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/XmlUtils.java @@ -24,7 +24,7 @@ */ package jdk.jpackage.internal.util; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import java.io.IOException; import java.io.Writer; @@ -80,7 +80,7 @@ public final class XmlUtils { xml.flush(); xml.close(); } catch (XMLStreamException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } @@ -101,7 +101,7 @@ public final class XmlUtils { xml.flush(); xml.close(); } catch (XMLStreamException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java index 8428d5d1e7f..40503469873 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ExceptionBox.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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 @@ -30,23 +30,55 @@ public class ExceptionBox extends RuntimeException { private static final long serialVersionUID = 1L; - public static RuntimeException rethrowUnchecked(Throwable throwable) { - if (throwable instanceof RuntimeException err) { - throw err; + public static RuntimeException toUnchecked(Exception ex) { + switch (ex) { + case RuntimeException rex -> { + return rex; + } + case InvocationTargetException itex -> { + var t = itex.getCause(); + if (t instanceof Exception cause) { + return toUnchecked(cause); + } else { + throw (Error)t; + } + } + case InterruptedException _ -> { + Thread.currentThread().interrupt(); + return new ExceptionBox(ex); + } + default -> { + return new ExceptionBox(ex); + } } - - if (throwable instanceof Error err) { - throw err; - } - - if (throwable instanceof InvocationTargetException err) { - throw rethrowUnchecked(err.getCause()); - } - - throw new ExceptionBox(throwable); } - private ExceptionBox(Throwable throwable) { - super(throwable); + public static Exception unbox(Throwable t) { + switch (t) { + case ExceptionBox ex -> { + return unbox(ex.getCause()); + } + case InvocationTargetException ex -> { + return unbox(ex.getCause()); + } + case Exception ex -> { + return ex; + } + case Error err -> { + throw err; + } + default -> { + // Unreachable + throw reachedUnreachable(); + } + } + } + + public static Error reachedUnreachable() { + return new AssertionError("Reached unreachable!"); + } + + private ExceptionBox(Exception ex) { + super(ex); } } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java index 3ed0fd67d84..374eaf803d9 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,17 +27,17 @@ package jdk.jpackage.internal.util.function; import java.util.function.BiConsumer; @FunctionalInterface -public interface ThrowingBiConsumer { +public interface ThrowingBiConsumer { - void accept(T t, U u) throws Throwable; + void accept(T t, U u) throws E; public static BiConsumer toBiConsumer( - ThrowingBiConsumer v) { + ThrowingBiConsumer v) { return (t, u) -> { try { v.accept(t, u); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java index 8c2df773eb5..13b0b53c887 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingBiFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,17 +27,17 @@ package jdk.jpackage.internal.util.function; import java.util.function.BiFunction; @FunctionalInterface -public interface ThrowingBiFunction { +public interface ThrowingBiFunction { - R apply(T t, U u) throws Throwable; + R apply(T t, U u) throws E; public static BiFunction toBiFunction( - ThrowingBiFunction v) { + ThrowingBiFunction v) { return (t, u) -> { try { return v.apply(t, u); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java index ef1b0a61df7..38342a361c0 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingConsumer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,16 +27,16 @@ package jdk.jpackage.internal.util.function; import java.util.function.Consumer; @FunctionalInterface -public interface ThrowingConsumer { +public interface ThrowingConsumer { - void accept(T t) throws Throwable; + void accept(T t) throws E; - public static Consumer toConsumer(ThrowingConsumer v) { + public static Consumer toConsumer(ThrowingConsumer v) { return o -> { try { v.accept(o); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java index 2b5eae43842..5bbfb254858 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingFunction.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,16 +27,16 @@ package jdk.jpackage.internal.util.function; import java.util.function.Function; @FunctionalInterface -public interface ThrowingFunction { +public interface ThrowingFunction { - R apply(T t) throws Throwable; + R apply(T t) throws E; - public static Function toFunction(ThrowingFunction v) { + public static Function toFunction(ThrowingFunction v) { return t -> { try { return v.apply(t); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java index 7c75c4d9753..f3ce5affbbf 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingRunnable.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,16 +25,16 @@ package jdk.jpackage.internal.util.function; @FunctionalInterface -public interface ThrowingRunnable { +public interface ThrowingRunnable { - void run() throws Throwable; + void run() throws E; - public static Runnable toRunnable(ThrowingRunnable v) { + public static Runnable toRunnable(ThrowingRunnable v) { return () -> { try { v.run(); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java index c69c4729190..4f194a0f4d2 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingSupplier.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,16 +27,16 @@ package jdk.jpackage.internal.util.function; import java.util.function.Supplier; @FunctionalInterface -public interface ThrowingSupplier { +public interface ThrowingSupplier { - T get() throws Throwable; + T get() throws E; - public static Supplier toSupplier(ThrowingSupplier v) { + public static Supplier toSupplier(ThrowingSupplier v) { return () -> { try { return v.get(); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java index 7a2a0fd67cf..3d757bbec48 100644 --- a/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java +++ b/src/jdk.jpackage/share/classes/jdk/jpackage/internal/util/function/ThrowingUnaryOperator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, 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,17 +27,17 @@ package jdk.jpackage.internal.util.function; import java.util.function.UnaryOperator; @FunctionalInterface -public interface ThrowingUnaryOperator { +public interface ThrowingUnaryOperator { - T apply(T t) throws Throwable; + T apply(T t) throws E; public static UnaryOperator toUnaryOperator( - ThrowingUnaryOperator v) { + ThrowingUnaryOperator v) { return t -> { try { return v.apply(t); - } catch (Throwable ex) { - throw ExceptionBox.rethrowUnchecked(ex); + } catch (Exception ex) { + throw ExceptionBox.toUnchecked(ex); } }; } diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinSystemEnvironment.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinSystemEnvironment.java index ab0cc37b9fe..c0bea444e00 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinSystemEnvironment.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/WinSystemEnvironment.java @@ -34,6 +34,6 @@ record WinSystemEnvironment(WixToolset wixToolset) implements SystemEnvironment } static Result create() { - return Result.create(WixTool::createToolset).map(WinSystemEnvironment::new); + return Result.of(WixTool::createToolset).map(WinSystemEnvironment::new); } } diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java index f88d1f81a34..42dd8eda19b 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/AnnotationsTest.java @@ -353,12 +353,12 @@ public class AnnotationsTest extends JUnitAdapter { try { log = captureJPackageTestLog(() -> Main.main(TestBuilder.build().workDirRoot(workDir), args)); assertRecordedTestDescs(expectedTestDescs); - } catch (Throwable t) { - t.printStackTrace(System.err); + } catch (Exception ex) { + ex.printStackTrace(System.err); System.exit(1); // Redundant, but needed to suppress "The local variable log may not have been initialized" error. - throw new RuntimeException(t); + throw new RuntimeException(ex); } final var actualTestCount = Integer.parseInt(log.stream().dropWhile(line -> { diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java index 4723f4dadbd..16909d0eb40 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/PackageTestTest.java @@ -168,7 +168,7 @@ public class PackageTestTest extends JUnitAdapter { protected final int expectedTicks; } - private static class CountingConsumer extends TickCounter implements ThrowingConsumer { + private static class CountingConsumer extends TickCounter implements ThrowingConsumer { @Override public void accept(JPackageCommand cmd) { @@ -188,7 +188,7 @@ public class PackageTestTest extends JUnitAdapter { private final String label; } - private static class CountingRunnable extends TickCounter implements ThrowingRunnable { + private static class CountingRunnable extends TickCounter implements ThrowingRunnable { @Override public void run() { @@ -208,7 +208,7 @@ public class PackageTestTest extends JUnitAdapter { private final String label; } - private static class CountingBundleVerifier extends TickCounter implements ThrowingBiConsumer { + private static class CountingBundleVerifier extends TickCounter implements ThrowingBiConsumer { @Override public void accept(JPackageCommand cmd, Executor.Result result) { diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java index 590f23b002d..00172791ad8 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/TKitTest.java @@ -25,6 +25,7 @@ package jdk.jpackage.test; import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; +import java.io.IOException; import java.lang.reflect.Method; import java.nio.file.Files; import java.nio.file.Path; @@ -212,13 +213,13 @@ public class TKitTest extends JUnitAdapter { @Test @ParameterSupplier("testCreateTempPath") - public void testCreateTempFile(CreateTempTestSpec testSpec) throws Throwable { + public void testCreateTempFile(CreateTempTestSpec testSpec) throws IOException { testSpec.test(TKit::createTempFile, TKit::assertFileExists); } @Test @ParameterSupplier("testCreateTempPath") - public void testCreateTempDirectory(CreateTempTestSpec testSpec) throws Throwable { + public void testCreateTempDirectory(CreateTempTestSpec testSpec) throws IOException { testSpec.test(TKit::createTempDirectory, TKit::assertDirectoryEmpty); } @@ -232,7 +233,7 @@ public class TKitTest extends JUnitAdapter { } } - void test(ThrowingFunction createTempPath, Consumer assertTempPathExists) throws Throwable { + void test(ThrowingFunction createTempPath, Consumer assertTempPathExists) throws IOException { for (var existingFile : existingFiles) { existingFile = TKit.workDir().resolve(existingFile); @@ -333,14 +334,14 @@ public class TKitTest extends JUnitAdapter { }).toList(); } - private static void runAssertWithExpectedLogOutput(ThrowingRunnable action, + private static void runAssertWithExpectedLogOutput(ThrowingRunnable action, boolean expectFail, String... expectLogStrings) { runWithExpectedLogOutput(() -> { TKit.assertAssert(!expectFail, toRunnable(action)); }, expectLogStrings); } - private static void runWithExpectedLogOutput(ThrowingRunnable action, + private static void runWithExpectedLogOutput(ThrowingRunnable action, String... expectLogStrings) { final var output = JUnitAdapter.captureJPackageTestLog(action); if (output.size() == 1 && expectLogStrings.length == 1) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java index 95373fa0d61..8ce3f4d2948 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/AdditionalLauncher.java @@ -152,7 +152,7 @@ public final class AdditionalLauncher { } public AdditionalLauncher setPersistenceHandler( - ThrowingBiConsumer>> handler) { + ThrowingBiConsumer>, ? extends Exception> handler) { if (handler != null) { createFileHandler = ThrowingBiConsumer.toBiConsumer(handler); } else { @@ -182,7 +182,7 @@ public final class AdditionalLauncher { Optional.ofNullable(defaultArguments), Optional.ofNullable(icon), rawProperties); } - private ThrowingConsumer createVerifierAsConsumer() { + private ThrowingConsumer createVerifierAsConsumer() { return cmd -> { createVerifier().verify(cmd, verifyActions.stream().sorted(Comparator.comparing(Action::ordinal)).toArray(Action[]::new)); }; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java index 197e835ed8d..f80f1e61cd3 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageCommand.java @@ -291,7 +291,7 @@ public class JPackageCommand extends CommandArguments { public JPackageCommand setFakeRuntime() { verifyMutable(); - ThrowingConsumer createBulkFile = path -> { + ThrowingConsumer createBulkFile = path -> { Files.createDirectories(path.getParent()); try (FileOutputStream out = new FileOutputStream(path.toFile())) { byte[] bytes = new byte[4 * 1024]; @@ -328,12 +328,12 @@ public class JPackageCommand extends CommandArguments { .removeArgumentWithValue("--input"); } - JPackageCommand addPrerequisiteAction(ThrowingConsumer action) { + JPackageCommand addPrerequisiteAction(ThrowingConsumer action) { prerequisiteActions.add(action); return this; } - JPackageCommand addVerifyAction(ThrowingConsumer action) { + JPackageCommand addVerifyAction(ThrowingConsumer action) { return addVerifyAction(action, ActionRole.DEFAULT); } @@ -343,12 +343,12 @@ public class JPackageCommand extends CommandArguments { ; } - JPackageCommand addVerifyAction(ThrowingConsumer action, ActionRole actionRole) { + JPackageCommand addVerifyAction(ThrowingConsumer action, ActionRole actionRole) { verifyActions.add(action, actionRole); return this; } - Stream> getVerifyActionsWithRole(ActionRole actionRole) { + Stream> getVerifyActionsWithRole(ActionRole actionRole) { return verifyActions.actionsWithRole(actionRole); } @@ -1648,16 +1648,16 @@ public class JPackageCommand extends CommandArguments { actions.addAll(other.actions); } - void add(ThrowingConsumer action) { + void add(ThrowingConsumer action) { add(action, ActionRole.DEFAULT); } - void add(ThrowingConsumer action, ActionRole role) { + void add(ThrowingConsumer action, ActionRole role) { verifyMutable(); actions.add(new Action(action, role)); } - Stream> actionsWithRole(ActionRole role) { + Stream> actionsWithRole(ActionRole role) { Objects.requireNonNull(role); return actions.stream().filter(action -> { return Objects.equals(action.role(), role); @@ -1666,7 +1666,7 @@ public class JPackageCommand extends CommandArguments { private static final class Action implements Consumer { - Action(ThrowingConsumer impl, ActionRole role) { + Action(ThrowingConsumer impl, ActionRole role) { this.impl = Objects.requireNonNull(impl); this.role = Objects.requireNonNull(role); } @@ -1675,7 +1675,7 @@ public class JPackageCommand extends CommandArguments { return role; } - ThrowingConsumer impl() { + ThrowingConsumer impl() { return impl; } @@ -1688,7 +1688,7 @@ public class JPackageCommand extends CommandArguments { } private final ActionRole role; - private final ThrowingConsumer impl; + private final ThrowingConsumer impl; private boolean executed; } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java index cdf2855faef..9425b84472c 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/JPackageStringBundle.java @@ -26,7 +26,7 @@ package jdk.jpackage.test; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.text.MessageFormat; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; public enum JPackageStringBundle { @@ -40,7 +40,7 @@ public enum JPackageStringBundle { i18nClass_getString = i18nClass.getDeclaredMethod("getString", String.class); i18nClass_getString.setAccessible(true); } catch (ClassNotFoundException|NoSuchMethodException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } @@ -51,7 +51,7 @@ public enum JPackageStringBundle { try { return (String)i18nClass_getString.invoke(i18nClass, key); } catch (IllegalAccessException|InvocationTargetException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java index 89468ef7f86..15d96311d98 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherVerifier.java @@ -102,7 +102,7 @@ public final class LauncherVerifier { EXECUTE_LAUNCHER(LauncherVerifier::executeLauncher), ; - Action(ThrowingBiConsumer action) { + Action(ThrowingBiConsumer action) { this.action = ThrowingBiConsumer.toBiConsumer(action); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java index e795f7c9760..3b02a3f6a69 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LinuxHelper.java @@ -645,7 +645,7 @@ public final class LinuxHelper { } private static void withTestFileAssociationsFile(FileAssociations fa, - ThrowingConsumer consumer) { + ThrowingConsumer consumer) { boolean iterated[] = new boolean[] { false }; PackageTest.withFileAssociationsTestRuns(fa, (testRun, testFiles) -> { if (!iterated[0]) { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java index caeb0a206fc..678d25e4007 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacHelper.java @@ -78,7 +78,7 @@ import org.xml.sax.SAXException; public final class MacHelper { public static void withExplodedDmg(JPackageCommand cmd, - ThrowingConsumer consumer) { + ThrowingConsumer consumer) { cmd.verifyIsOfType(PackageType.MAC_DMG); // Explode DMG assuming this can require interaction, thus use `yes`. diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java index 7d2bb908edb..15249c51887 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSign.java @@ -42,6 +42,7 @@ import java.nio.file.Path; import java.nio.file.StandardCopyOption; import java.nio.file.StandardOpenOption; import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.security.cert.CertificateExpiredException; import java.security.cert.CertificateFactory; import java.security.cert.CertificateNotYetValidException; @@ -526,7 +527,7 @@ public final class MacSign { private record CertificateStats(List allResolvedCertificateRequests, List knownCertificateRequests, - Map unmappedCertificates) { + Map unmappedCertificates) { static CertificateStats get(KeychainWithCertsSpec spec) { return CACHE.computeIfAbsent(spec, CertificateStats::create); @@ -560,7 +561,7 @@ public final class MacSign { private static CertificateStats create(KeychainWithCertsSpec spec) { final var allCertificates = spec.keychain().findCertificates(); final List allResolvedCertificateRequests = new ArrayList<>(); - final Map unmappedCertificates = new HashMap<>(); + final Map unmappedCertificates = new HashMap<>(); withTempDirectory(workDir -> { for (final var cert : allCertificates) { @@ -568,13 +569,7 @@ public final class MacSign { try { resolvedCertificateRequest = new ResolvedCertificateRequest(cert); } catch (RuntimeException ex) { - final Throwable t; - if (ex instanceof ExceptionBox) { - t = ex.getCause(); - } else { - t = ex; - } - unmappedCertificates.put(cert, t); + unmappedCertificates.put(cert, ExceptionBox.unbox(ex)); continue; } @@ -635,13 +630,13 @@ public final class MacSign { SHA1(20, () -> MessageDigest.getInstance("SHA-1")), SHA256(32, () -> MessageDigest.getInstance("SHA-256")); - DigestAlgorithm(int hashLength, ThrowingSupplier createDigest) { + DigestAlgorithm(int hashLength, ThrowingSupplier createDigest) { this.hashLength = hashLength; this.createDigest = createDigest; } final int hashLength; - final ThrowingSupplier createDigest; + final ThrowingSupplier createDigest; } public record CertificateHash(byte[] value, DigestAlgorithm alg) { @@ -1223,7 +1218,7 @@ public final class MacSign { }).map(KeychainWithCertsSpec::keychain); } - private static void withTempDirectory(ThrowingConsumer callback) { + private static void withTempDirectory(ThrowingConsumer callback) { try { final var dir = Files.createTempDirectory("jdk.jpackage.test"); try { diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java index 123fba56b71..1f37829791e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MacSignVerify.java @@ -262,8 +262,8 @@ public final class MacSignVerify { signIdentities.add(new SignIdentity(name, fingerprint)); } while (lineIt.hasNext()); return signIdentities; - } catch (Throwable t) { - t.printStackTrace(); + } catch (Exception ex) { + ex.printStackTrace(); reportUnexpectedCommandOutcome(exec.getPrintableCommandLine(), result); return null; // Unreachable } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java index fa8fe166f5a..fee5b65c897 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Main.java @@ -37,15 +37,16 @@ import java.util.List; import java.util.function.Function; import java.util.function.Predicate; import java.util.stream.Stream; +import jdk.jpackage.internal.util.function.ExceptionBox; public final class Main { - public static void main(String... args) throws Throwable { + public static void main(String... args) throws Exception { main(TestBuilder.build(), args); } - public static void main(TestBuilder.Builder builder, String... args) throws Throwable { + public static void main(TestBuilder.Builder builder, String... args) throws Exception { boolean listTests = false; List tests = new ArrayList<>(); try (TestBuilder testBuilder = builder.testConsumer(tests::add).create()) { @@ -86,8 +87,8 @@ public final class Main { try { testBuilder.processCmdLineArg(arg); success = true; - } catch (Throwable throwable) { - TKit.unbox(throwable); + } catch (Exception ex) { + throw ExceptionBox.unbox(ex); } finally { if (!success) { TKit.log(String.format("Error processing parameter=[%s]", arg)); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java index 73d0a7fe495..b27531d0572 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/MethodCall.java @@ -40,7 +40,7 @@ import java.util.stream.Stream; import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.TestInstance.TestDesc; -class MethodCall implements ThrowingConsumer { +class MethodCall implements ThrowingConsumer { MethodCall(Object[] instanceCtorArgs, Method method, Object ... args) { Objects.requireNonNull(instanceCtorArgs); @@ -107,7 +107,7 @@ class MethodCall implements ThrowingConsumer { } @Override - public void accept(Object thiz) throws Throwable { + public void accept(Object thiz) throws Exception { method.invoke(thiz, methodArgs); } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java index f35e255951e..126d0e07f00 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/ObjectMapper.java @@ -24,7 +24,7 @@ package jdk.jpackage.test; import static java.util.stream.Collectors.groupingBy; import static java.util.stream.Collectors.toSet; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; import static jdk.jpackage.internal.util.function.ThrowingRunnable.toRunnable; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; @@ -283,7 +283,7 @@ public final class ObjectMapper { try { return m.invoke(obj); } catch (IllegalAccessException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } catch (InvocationTargetException ex) { return map(ex.getTargetException()); } @@ -724,7 +724,7 @@ public final class ObjectMapper { } xml.writeEndElement(); } catch (Exception ex) { - rethrowUnchecked(ex); + throw toUnchecked(ex); } } @@ -740,7 +740,7 @@ public final class ObjectMapper { } xml.writeEndElement(); } catch (Exception ex) { - rethrowUnchecked(ex); + throw toUnchecked(ex); } } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java index 5b3815510ce..2e4f11d056f 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/PackageTest.java @@ -22,7 +22,7 @@ */ package jdk.jpackage.test; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import static jdk.jpackage.internal.util.function.ThrowingBiConsumer.toBiConsumer; import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; @@ -143,7 +143,7 @@ public final class PackageTest extends RunnablePackageTest { return this; } - private PackageTest addInitializer(ThrowingConsumer v, String id) { + private PackageTest addInitializer(ThrowingConsumer v, String id) { Objects.requireNonNull(v); if (id != null) { if (namedInitializers.contains(id)) { @@ -156,11 +156,11 @@ public final class PackageTest extends RunnablePackageTest { return this; } - private PackageTest addRunOnceInitializer(ThrowingRunnable v, String id) { + private PackageTest addRunOnceInitializer(ThrowingRunnable v, String id) { Objects.requireNonNull(v); - return addInitializer(new ThrowingConsumer() { + return addInitializer(new ThrowingConsumer() { @Override - public void accept(JPackageCommand unused) throws Throwable { + public void accept(JPackageCommand unused) throws Exception { if (!executed) { executed = true; v.run(); @@ -171,21 +171,21 @@ public final class PackageTest extends RunnablePackageTest { }, id); } - public PackageTest addInitializer(ThrowingConsumer v) { + public PackageTest addInitializer(ThrowingConsumer v) { return addInitializer(v, null); } - public PackageTest addRunOnceInitializer(ThrowingRunnable v) { + public PackageTest addRunOnceInitializer(ThrowingRunnable v) { return addRunOnceInitializer(v, null); } - public PackageTest addBundleVerifier(ThrowingBiConsumer v) { + public PackageTest addBundleVerifier(ThrowingBiConsumer v) { Objects.requireNonNull(v); currentTypes.forEach(type -> handlers.get(type).addBundleVerifier(toBiConsumer(v))); return this; } - public PackageTest addBundleVerifier(ThrowingConsumer v) { + public PackageTest addBundleVerifier(ThrowingConsumer v) { Objects.requireNonNull(v); return addBundleVerifier((cmd, unused) -> toConsumer(v).accept(cmd)); } @@ -222,13 +222,13 @@ public final class PackageTest extends RunnablePackageTest { return this; } - public PackageTest addInstallVerifier(ThrowingConsumer v) { + public PackageTest addInstallVerifier(ThrowingConsumer v) { currentTypes.forEach(type -> handlers.get(type).addInstallVerifier( toConsumer(v))); return this; } - public PackageTest addUninstallVerifier(ThrowingConsumer v) { + public PackageTest addUninstallVerifier(ThrowingConsumer v) { currentTypes.forEach(type -> handlers.get(type).addUninstallVerifier( toConsumer(v))); return this; @@ -259,7 +259,7 @@ public final class PackageTest extends RunnablePackageTest { } static void withFileAssociationsTestRuns(FileAssociations fa, - ThrowingBiConsumer> consumer) { + ThrowingBiConsumer, ? extends Exception> consumer) { Objects.requireNonNull(consumer); for (var testRun : fa.getTestRuns()) { TKit.withTempDirectory("fa-test-files", tempDir -> { @@ -860,7 +860,7 @@ public final class PackageTest extends RunnablePackageTest { "Check the package has %d top installation directories", expectedRootCount)); } catch (IOException ex) { - rethrowUnchecked(ex); + throw toUnchecked(ex); } } diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java index 0afdf31ec68..90c73f97106 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -33,7 +33,6 @@ import java.io.Closeable; import java.io.IOException; import java.io.PrintStream; import java.io.UncheckedIOException; -import java.lang.reflect.InvocationTargetException; import java.nio.file.FileSystems; import java.nio.file.Files; import java.nio.file.LinkOption; @@ -110,7 +109,7 @@ public final class TKit { throw throwUnknownPlatformError(); }).get(); - static void withExtraLogStream(ThrowingRunnable action) { + static void withExtraLogStream(ThrowingRunnable action) { if (state().extraLogStream != null) { ThrowingRunnable.toRunnable(action).run(); } else { @@ -120,19 +119,19 @@ public final class TKit { } } - static void withExtraLogStream(ThrowingRunnable action, PrintStream logStream) { + static void withExtraLogStream(ThrowingRunnable action, PrintStream logStream) { withNewState(action, stateBuilder -> { stateBuilder.extraLogStream(logStream); }); } - public static void withMainLogStream(ThrowingRunnable action, PrintStream logStream) { + public static void withMainLogStream(ThrowingRunnable action, PrintStream logStream) { withNewState(action, stateBuilder -> { stateBuilder.mainLogStream(logStream); }); } - public static void withStackTraceStream(ThrowingRunnable action, PrintStream logStream) { + public static void withStackTraceStream(ThrowingRunnable action, PrintStream logStream) { withNewState(action, stateBuilder -> { stateBuilder.stackTraceStream(logStream); }); @@ -146,7 +145,7 @@ public final class TKit { STATE.set(Objects.requireNonNull(v)); } - private static void withNewState(ThrowingRunnable action, Consumer stateBuilderMutator) { + private static void withNewState(ThrowingRunnable action, Consumer stateBuilderMutator) { Objects.requireNonNull(action); Objects.requireNonNull(stateBuilderMutator); @@ -198,7 +197,7 @@ public final class TKit { }); } - static T runAdhocTest(ThrowingSupplier action) { + static T runAdhocTest(ThrowingSupplier action) { final List box = new ArrayList<>(); runAdhocTest(() -> { box.add(action.get()); @@ -206,7 +205,7 @@ public final class TKit { return box.getFirst(); } - static void runAdhocTest(ThrowingRunnable action) { + static void runAdhocTest(ThrowingRunnable action) { Objects.requireNonNull(action); final Path workDir = toSupplier(() -> Files.createTempDirectory("jdk.jpackage-test")).get(); @@ -227,28 +226,20 @@ public final class TKit { runTests(List.of(test), Set.of(RunTestMode.FAIL_FAST)); } - static Runnable ignoreExceptions(ThrowingRunnable action) { + static Runnable ignoreExceptions(ThrowingRunnable action) { return () -> { try { try { action.run(); - } catch (Throwable ex) { - unbox(ex); + } catch (Exception ex) { + throw ExceptionBox.unbox(ex); } - } catch (Throwable throwable) { - printStackTrace(throwable); + } catch (Exception | AssertionError t) { + printStackTrace(t); } }; } - static void unbox(Throwable throwable) throws Throwable { - try { - throw throwable; - } catch (ExceptionBox | InvocationTargetException ex) { - unbox(ex.getCause()); - } - } - public static Path workDir() { return currentTest().workDir(); } @@ -440,7 +431,7 @@ public final class TKit { return createTempPath(role, Files::createFile); } - private static Path createTempPath(Path templatePath, ThrowingUnaryOperator createPath) { + private static Path createTempPath(Path templatePath, ThrowingUnaryOperator createPath) { if (templatePath.isAbsolute()) { throw new IllegalArgumentException(); } @@ -458,13 +449,11 @@ public final class TKit { return createPath.apply(path); } catch (IOException ex) { throw new UncheckedIOException(ex); - } catch (Throwable t) { - throw ExceptionBox.rethrowUnchecked(t); } } public static Path withTempDirectory(String role, - ThrowingConsumer action) { + ThrowingConsumer action) { final Path tempDir = ThrowingSupplier.toSupplier( () -> createTempDirectory(role)).get(); boolean keepIt = true; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java index 4009fe2f687..5f4547c701e 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestBuilder.java @@ -128,7 +128,7 @@ final class TestBuilder implements AutoCloseable { clear(); } - void processCmdLineArg(String arg) throws Throwable { + void processCmdLineArg(String arg) throws Exception { int separatorIdx = arg.indexOf('='); final String argName; final String argValue; @@ -140,7 +140,7 @@ final class TestBuilder implements AutoCloseable { argValue = null; } try { - ThrowingConsumer argProcessor = argProcessors.get(argName); + var argProcessor = argProcessors.get(argName); if (argProcessor == null) { throw new ParseException("Unrecognized"); } @@ -205,8 +205,8 @@ final class TestBuilder implements AutoCloseable { } private void createTestInstance(MethodCall testBody) { - final List> curBeforeActions; - final List> curAfterActions; + final List> curBeforeActions; + final List> curAfterActions; Method testMethod = testBody.getMethod(); if (Stream.of(BeforeEach.class, AfterEach.class).anyMatch( @@ -326,7 +326,7 @@ final class TestBuilder implements AutoCloseable { } // Wraps Method.invoke() into ThrowingRunnable.run() - private ThrowingConsumer wrap(Method method) { + private ThrowingConsumer wrap(Method method) { return (test) -> { Class methodClass = method.getDeclaringClass(); String methodName = String.join(".", methodClass.getName(), @@ -375,13 +375,13 @@ final class TestBuilder implements AutoCloseable { } private final TestMethodSupplier testMethodSupplier; - private final Map> argProcessors; + private final Map> argProcessors; private final Consumer testConsumer; private final Path workDirRoot; private final ClassLoader testClassLoader; private List testGroup; - private List> beforeActions; - private List> afterActions; + private List> beforeActions; + private List> afterActions; private Set excludedTests; private Set includedTests; private String spaceSubstitute; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java index 4445a194ee7..3c622200249 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TestInstance.java @@ -46,7 +46,7 @@ import jdk.jpackage.internal.util.function.ThrowingFunction; import jdk.jpackage.internal.util.function.ThrowingRunnable; import jdk.jpackage.internal.util.function.ThrowingSupplier; -final class TestInstance implements ThrowingRunnable { +final class TestInstance implements ThrowingRunnable { static final class TestDesc { private TestDesc(Class clazz, String functionName, String functionArgs, String instanceArgs) { @@ -149,7 +149,7 @@ final class TestInstance implements ThrowingRunnable { private final String instanceArgs; } - TestInstance(ThrowingRunnable testBody, Path workDirRoot) { + TestInstance(ThrowingRunnable testBody, Path workDirRoot) { assertCount = 0; this.testConstructor = (unused) -> null; this.testBody = (unused) -> testBody.run(); @@ -160,8 +160,8 @@ final class TestInstance implements ThrowingRunnable { this.workDir = workDirRoot.resolve(createWorkDirPath(testDesc)); } - TestInstance(MethodCall testBody, List> beforeActions, - List> afterActions, boolean dryRun, Path workDirRoot) { + TestInstance(MethodCall testBody, List> beforeActions, + List> afterActions, boolean dryRun, Path workDirRoot) { assertCount = 0; this.testConstructor = v -> ((MethodCall)v).newInstance(); this.testBody = testBody; @@ -226,7 +226,7 @@ final class TestInstance implements ThrowingRunnable { } @Override - public void run() throws Throwable { + public void run() throws Exception { final String fullName = fullName(); TKit.log(String.format("[ RUN ] %s", fullName)); try { @@ -333,10 +333,10 @@ final class TestInstance implements ThrowingRunnable { private Status status; private RuntimeException skippedTestException; private final TestDesc testDesc; - private final ThrowingFunction, Object> testConstructor; - private final ThrowingConsumer testBody; - private final List> beforeActions; - private final List> afterActions; + private final ThrowingFunction, Object, ? extends Exception> testConstructor; + private final ThrowingConsumer testBody; + private final List> beforeActions; + private final List> afterActions; private final boolean dryRun; private final Path workDir; diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinExecutableIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinExecutableIconVerifier.java index 5110259e6f3..f4468fa9ab0 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinExecutableIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WinExecutableIconVerifier.java @@ -22,7 +22,7 @@ */ package jdk.jpackage.test; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import java.awt.image.BufferedImage; import java.io.IOException; @@ -195,7 +195,7 @@ public final class WinExecutableIconVerifier { iconSwap.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } @@ -268,7 +268,7 @@ public final class WinExecutableIconVerifier { } } } catch (IllegalAccessException | InvocationTargetException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } finally { executable.toFile().setWritable(false, true); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java index 5e97b0d2dde..72b5dbc578b 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/WindowsHelper.java @@ -22,7 +22,7 @@ */ package jdk.jpackage.test; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import java.io.IOException; @@ -634,7 +634,7 @@ public class WindowsHelper { getShortPathWrapper.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { - throw rethrowUnchecked(ex); + throw toUnchecked(ex); } } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java index 8168b876d2f..721e0802d16 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/PackagingPipelineTest.java @@ -23,7 +23,7 @@ package jdk.jpackage.internal; -import static jdk.jpackage.internal.util.function.ExceptionBox.rethrowUnchecked; +import static jdk.jpackage.internal.util.function.ExceptionBox.toUnchecked; import static jdk.jpackage.internal.util.function.ThrowingConsumer.toConsumer; import static jdk.jpackage.internal.util.function.ThrowingSupplier.toSupplier; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -412,7 +412,7 @@ public class PackagingPipelineTest { final var expectedException = new Exception("foo"); final var ex = testExceptionRethrow(expectedException, ExceptionBox.class, () -> { - rethrowUnchecked(expectedException); + throw toUnchecked(expectedException); }); assertSame(expectedException, ex.getCause()); } diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java index a46cb20815f..ee261dfe8a8 100644 --- a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/cli/OptionsValidationFailTest.java @@ -160,7 +160,7 @@ public class OptionsValidationFailTest { } @TestFactory - Stream getTestCasesFromErrorTest() throws Throwable { + Stream getTestCasesFromErrorTest() throws Exception { final var jpackageTestsUnnamedModule = JUnitAdapter.class.getModule(); final var testClassloader = new InMemoryClassLoader(Stream.of( diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/ResultTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/ResultTest.java new file mode 100644 index 00000000000..ca8f7aad102 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/ResultTest.java @@ -0,0 +1,602 @@ +/* + * Copyright (c) 2025, 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 jdk.jpackage.internal.util; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.Set; +import java.util.function.Consumer; +import java.util.function.Function; +import jdk.jpackage.internal.util.function.ExceptionBox; +import jdk.jpackage.internal.util.function.ThrowingSupplier; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +import org.junit.jupiter.params.provider.ValueSource; + +public class ResultTest { + + @Test + public void test_ctor_with_value() { + var result = new Result(Optional.of("foo"), List.of()); + + assertTrue(result.hasValue()); + assertFalse(result.hasErrors()); + assertEquals(Optional.of("foo"), result.value()); + assertEquals(List.of(), result.errors()); + assertEquals(Optional.empty(), result.firstError()); + } + + @Test + public void test_ctor_with_errors() { + var ex = new Exception("Kaput!"); + var result = new Result(Optional.empty(), List.of(ex)); + + assertFalse(result.hasValue()); + assertTrue(result.hasErrors()); + assertEquals(Optional.empty(), result.value()); + assertEquals(List.of(ex), result.errors()); + assertEquals(Optional.of(ex), result.firstError()); + } + + @Test + public void test_ctor_invalid_npe() { + assertThrowsExactly(NullPointerException.class, () -> { + new Result(Optional.of("foo"), null); + }); + + assertThrowsExactly(NullPointerException.class, () -> { + new Result(null, List.of(new Exception())); + }); + + assertThrowsExactly(NullPointerException.class, () -> { + new Result(null, null); + }); + } + + @Test + public void test_ctor_invalid_both_empty() { + var ex = assertThrowsExactly(IllegalArgumentException.class, () -> { + new Result(Optional.empty(), List.of()); + }); + assertEquals("'value' and 'errors' cannot both be non-empty or both be empty", ex.getMessage()); + } + + @Test + public void test_ctor_invalid_both_non_empty() { + var ex = assertThrowsExactly(IllegalArgumentException.class, () -> { + new Result(Optional.of("foo"), List.of(new Exception())); + }); + assertEquals("'value' and 'errors' cannot both be non-empty or both be empty", ex.getMessage()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_ofValue(boolean valid) { + if (valid) { + assertTrue(Result.ofValue("foo").hasValue()); + } else { + assertThrowsExactly(NullPointerException.class, () -> { + Result.ofValue(null); + }); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_ofError(boolean valid) { + if (valid) { + var err = new Exception("foo"); + var result = Result.ofError(err); + assertEquals(List.of(err), result.errors()); + } else { + assertThrowsExactly(NullPointerException.class, () -> { + Result.ofError(null); + }); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_ofErrors(boolean valid) { + if (valid) { + var errors = List.of(new Exception("foo"), new IllegalArgumentException("bar")); + var result = Result.ofErrors(errors); + assertSame(errors, result.errors()); + } else { + assertThrowsExactly(NullPointerException.class, () -> { + Result.ofErrors(null); + }); + + assertThrowsExactly(NullPointerException.class, () -> { + var errors = new ArrayList(); + errors.add(new Exception()); + errors.add(null); + Result.ofErrors(errors); + }); + } + } + + @Test + public void test_of() { + assertEquals("foo", Result.of(() -> { + return "foo"; + }).orElseThrow()); + } + + @Test + public void test_of_null_value() { + assertThrowsExactly(NullPointerException.class, () -> { + Result.of(() -> { + return null; + }); + }); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_of_throws(boolean declaredExceptionType) { + + Exception cause; + if (declaredExceptionType) { + cause = new IOException("foo"); + } else { + cause = new UnsupportedOperationException("bar"); + } + + ThrowingSupplier supplier = () -> { + if (declaredExceptionType) { + throw (IOException)cause; + } else { + throw (UnsupportedOperationException)cause; + } + }; + + if (declaredExceptionType) { + var result = Result.of(supplier, IOException.class); + assertSame(cause, result.firstError().orElseThrow()); + assertEquals(1, result.errors().size()); + } else { + var ex = assertThrowsExactly(cause.getClass(), () -> { + Result.of(supplier, IOException.class); + }); + assertSame(cause, ex); + } + } + + @Test + public void test_orElseThrow_hasValue() { + assertEquals("foo", Result.ofValue("foo").orElseThrow()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_orElseThrow(boolean uncheckedException) { + Exception ex; + Class expectedType; + if (uncheckedException) { + ex = new RuntimeException("Kaput!"); + expectedType = ex.getClass(); + } else { + ex = new Exception("Kaput!"); + expectedType = ExceptionBox.class; + } + + var actual = assertThrowsExactly(expectedType, Result.ofError(ex)::orElseThrow); + + if (uncheckedException) { + assertSame(ex, actual); + } else { + assertSame(ex, actual.getCause()); + } + } + + @ParameterizedTest + @MethodSource + public void test_map_and_flatMap(MapTestSpec spec) { + spec.run(); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_peekValue(boolean hasValue) { + var pickedValue = Slot.createEmpty(); + + Consumer consumer = v -> { + assertNotNull(v); + assertTrue(pickedValue.find().isEmpty()); + pickedValue.set(v); + }; + + Result result; + if (hasValue) { + result = Result.ofValue("foo"); + } else { + result = Result.ofError(new Exception("foo")); + } + result.peekValue(consumer); + + if (hasValue) { + assertEquals("foo", pickedValue.get()); + } else { + assertTrue(pickedValue.find().isEmpty()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_peekErrors(boolean hasValue) { + var pickedErrors = Slot.>createEmpty(); + + Consumer> consumer = v -> { + assertNotNull(v); + assertTrue(pickedErrors.find().isEmpty()); + pickedErrors.set(v); + }; + + Result result; + if (hasValue) { + result = Result.ofValue("foo"); + } else { + result = Result.ofErrors(List.of(new Exception("foo"), new IOException("bar"))); + } + result.peekErrors(consumer); + + if (hasValue) { + assertTrue(pickedErrors.find().isEmpty()); + } else { + assertSame(result.errors(), pickedErrors.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_mapErrors(boolean hasValue) { + Result result; + if (hasValue) { + result = Result.ofValue("foo"); + } else { + result = Result.ofErrors(List.of(new Exception("foo"), new IOException("bar"))); + } + + if (hasValue) { + var ex = assertThrowsExactly(IllegalStateException.class, result::mapErrors); + assertEquals("Can not map errors from a result without errors", ex.getMessage()); + } else { + assertSame(result, result.mapErrors()); + } + } + + @Test + public void test_allHaveValues_empty() { + assertTrue(Result.allHaveValues()); + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_allHaveValues(boolean expected) { + if (expected) { + assertTrue(Result.allHaveValues(Result.ofValue("foo"), Result.ofValue(37))); + } else { + assertFalse(Result.allHaveValues(Result.ofValue("foo"), Result.ofError(new Exception()))); + } + } + + enum MapFunctionType { + MAP, + FLAT_MAP, + ; + } + + enum MapFunctionOutcome { + RETURN_NON_NULL, + RETURN_NULL, + THROW, + FLAT_MAP_NEW_ERRORS(MapFunctionType.FLAT_MAP), + ; + + MapFunctionOutcome(MapFunctionType... supportedTypes) { + this.supportedTypes = Set.of(supportedTypes); + } + + MapFunctionOutcome() { + this(MapFunctionType.values()); + } + + private final Set supportedTypes; + } + + record MapTestSpec(boolean hasValue, MapFunctionOutcome outcome, MapFunctionType type) { + MapTestSpec { + Objects.requireNonNull(outcome); + Objects.requireNonNull(type); + } + + @Override + public String toString() { + var tokens = new ArrayList(); + tokens.add(outcome.name()); + if (type == MapFunctionType.FLAT_MAP) { + tokens.add("flatMap"); + } + if (!hasValue) { + tokens.add("no-value"); + } + return String.join(", ", tokens); + } + + void run() { + var builder = MapTest.build(); + if (hasValue) { + builder.initialValue(100); + } + + Function plainMapper; + switch (outcome) { + case RETURN_NON_NULL -> { + if (hasValue) { + builder.expectValue("200"); + } + plainMapper = v -> { + return String.valueOf(v * 2); + }; + } + case RETURN_NULL -> { + builder.expectExceptionOfType(NullPointerException.class); + plainMapper = _ -> { + return null; + }; + } + case THROW -> { + var cause = new UnsupportedOperationException("Unsupported"); + builder.expectException(cause); + plainMapper = _ -> { + throw cause; + }; + } + case FLAT_MAP_NEW_ERRORS -> { + if (hasValue) { + // Just a stub to make `builder.create()` pass. + builder.expectValue(""); + } + var mappedResult = Result.ofError(new UnsupportedOperationException("Whoopsy-daisy")); + var test = builder.create().copyWithMappedValue(mappedResult); + test.flatMap(v -> { + return mappedResult; + }); + return; + } + default -> { + throw ExceptionBox.reachedUnreachable(); + } + } + + var test = builder.create(); + + switch (type) { + case MAP -> { + test.map(plainMapper); + } + case FLAT_MAP -> { + test.flatMap(v -> { + return Optional.ofNullable(plainMapper.apply(v)).map(Result::ofValue).orElse(null); + }); + } + } + } + } + + private static List test_map_and_flatMap() { + var data = new ArrayList(); + for (var type : MapFunctionType.values()) { + for (var outcome : MapFunctionOutcome.values()) { + if (outcome.supportedTypes.contains(type)) { + for (var hasValue : List.of(true, false)) { + data.add(new MapTestSpec(hasValue, outcome, type)); + } + } + } + } + return data; + } + + private static final class Counter implements Function { + + Counter(Function impl) { + this.impl = Objects.requireNonNull(impl); + } + + @Override + public U apply(T v) { + counter++; + return impl.apply(v); + } + + int count() { + return counter; + } + + private int counter; + private final Function impl; + } + + private record MapTest( + Result initialValue, + Optional> mappedValue, + Optional expectedException, + Optional> expectedExceptionType) { + + MapTest { + Objects.requireNonNull(initialValue); + Objects.requireNonNull(mappedValue); + Objects.requireNonNull(expectedException); + Objects.requireNonNull(expectedExceptionType); + + if (expectedExceptionType.isPresent() && mappedValue.isPresent()) { + // Bad configuration: the mapping operation is expected to throw, + // but it also expects it to return a value. + throw new IllegalArgumentException(); + } + + if (expectedExceptionType.isEmpty() && mappedValue.isEmpty()) { + // Bad configuration: the mapping operation is expected to return normally (not to throw), + // but it also doesn't expect a mapped value. + throw new IllegalArgumentException(); + } + + if (initialValue.hasErrors() && mappedValue.map(Result::hasValue).orElse(false)) { + // Bad configuration: the initial value has errors but they expect a mapped value without errors. + throw new IllegalArgumentException(); + } + + expectedException.map(Object::getClass).ifPresent(expectedExpectedExceptionType -> { + var configuredExpectedExceptionType = expectedExceptionType.orElseThrow(); + if (!configuredExpectedExceptionType.equals(expectedExpectedExceptionType)) { + throw new IllegalArgumentException(String.format( + "expectedException=%s; expectedExceptionType=%s", + expectedExpectedExceptionType, configuredExpectedExceptionType)); + } + }); + } + + MapTest copyWithMappedValue(Result v) { + return new MapTest<>(initialValue, Optional.of(v), expectedException, expectedExceptionType); + } + + static Builder build() { + return new Builder<>(); + } + + void map(Function mapper) { + map(new Counter<>(mapper), initialValue::map); + } + + void flatMap(Function> mapper) { + map(new Counter<>(mapper), initialValue::flatMap); + } + + private void map(Counter countingMapper, Function, Result> mapper) { + + if (initialValue.hasErrors()) { + Result mapped = mapper.apply(countingMapper); + assertTrue(mapped.hasErrors()); + assertEquals(initialValue.errors(), mapped.errors()); + } else { + expectedExceptionType.ifPresentOrElse(theExpectedExceptionType -> { + var ex = assertThrowsExactly(theExpectedExceptionType, () -> { + initialValue.map(countingMapper); + }); + + expectedException.ifPresent(theExpectedException -> { + assertSame(theExpectedException, ex); + }); + }, () -> { + Result mapped = mapper.apply(countingMapper); + assertEquals(mappedValue.orElseThrow(), mapped); + }); + } + + if (initialValue.hasValue()) { + assertEquals(1, countingMapper.count()); + } else { + assertEquals(0, countingMapper.count()); + } + } + + static final class Builder { + + MapTest create() { + + var theInitialValue = Optional.ofNullable(initialValue).orElseGet(() -> { + return Result.ofError(new Exception("Kaput!")); + }); + + return new MapTest<>( + theInitialValue, + Optional.ofNullable(expectedValue).map(Result::ofValue).or(() -> { + if (expectedExceptionType == null) { + return Optional.of(theInitialValue.mapErrors()); + } else { + return Optional.empty(); + } + }), + Optional.ofNullable(expectedException), + Optional.ofNullable(expectedExceptionType)); + } + + Builder initialValue(Result v) { + initialValue = v; + return this; + } + + Builder initialValue(T v) { + return initialValue(Result.ofValue(v)); + } + + Builder expectException(Exception v) { + expectedException = v; + if (expectedException != null) { + expectedExceptionType = expectedException.getClass(); + expectValue(null); + } else { + expectedExceptionType = null; + } + return this; + } + + Builder expectExceptionOfType(Class v) { + expectedException = null; + expectedExceptionType = v; + if (v != null) { + expectValue(null); + } + return this; + } + + Builder expectValue(U v) { + expectedValue = v; + if (v != null) { + expectException(null); + } + return this; + } + + private Result initialValue; + private U expectedValue; + private Exception expectedException; + private Class expectedExceptionType; + } + } +} diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/ExceptionBoxTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/ExceptionBoxTest.java new file mode 100644 index 00000000000..c3ef239b02d --- /dev/null +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/ExceptionBoxTest.java @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2025, 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 jdk.jpackage.internal.util.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; + +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.util.Objects; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.UnaryOperator; +import jdk.jpackage.internal.util.Slot; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.EnumSource; + +public class ExceptionBoxTest { + + @Test + public void test_unbox_RuntimeException() { + var ex = new RuntimeException(); + assertSame(ex, ExceptionBox.unbox(ex)); + } + + @Test + public void test_unbox_Exception() { + var ex = new Exception(); + assertSame(ex, ExceptionBox.unbox(ex)); + } + + @Test + public void test_unbox_InvocationTargetException() { + var ex = new Exception(); + assertSame(ex, ExceptionBox.unbox(new InvocationTargetException(ex))); + } + + @Test + public void test_unbox_ExceptionBox() { + var ex = new Exception("foo"); + // There is no way to directly instantiate ExceptionBox, use a workaround. + var box = assertThrowsExactly(ExceptionBox.class, () -> { + throw ExceptionBox.toUnchecked(ex); + }); + assertSame(ex, ExceptionBox.unbox(box)); + } + + @Test + public void test_unbox_Error() { + var err = new Error("On Fire!"); + var thrown = assertThrowsExactly(Error.class, () -> { + ExceptionBox.unbox(err); + }); + assertSame(err, thrown); + } + + @Test + public void test_reachedUnreachable() { + var err = ExceptionBox.reachedUnreachable(); + assertEquals("Reached unreachable!", err.getMessage()); + } + + @Test + public void test_toUnchecked_RuntimeException() { + assertToUnchecked(new RuntimeException(), true); + } + + @Test + public void test_toUnchecked_Exception() { + assertToUnchecked(new Exception(), false); + } + + @Test + public void test_toUnchecked_ExceptionBox() { + // There is no way to directly instantiate ExceptionBox, use a workaround. + var box = assertThrowsExactly(ExceptionBox.class, () -> { + throw ExceptionBox.toUnchecked(new Exception("foo")); + }); + assertToUnchecked(box, true); + } + + @Test + public void test_toUnchecked_InterruptedException() throws InterruptedException { + + var workerThreadReadyToWait = Slot.createEmpty(); + + var workerThreadInterruptedExceptionCaught = Slot.createEmpty(); + + var workerThreadException = new AtomicReference(); + + var thread = Thread.ofVirtual().uncaughtExceptionHandler((Thread _, Throwable e) -> { + trace("unexpected exception: %s", e); + workerThreadException.set(e); + }).start(() -> { + try { + var lock = new Object(); + synchronized (lock) { + synchronized (workerThreadReadyToWait) { + workerThreadReadyToWait.set(true); + workerThreadReadyToWait.notify(); + } + trace("wait"); + lock.wait(); + } + } catch (InterruptedException iex) { + trace("interrupted state cleared"); + synchronized (workerThreadInterruptedExceptionCaught) { + workerThreadInterruptedExceptionCaught.set(true); + trace("notify about to interrupt itself"); + workerThreadInterruptedExceptionCaught.notify(); + } + trace("before toUnchecked()"); + var box = assertThrowsExactly(ExceptionBox.class, () -> { + throw ExceptionBox.toUnchecked(iex); + }); + assertSame(iex, box.getCause()); + } + }); + + // Wait until the worker thread gets to the point + // when interrupting it will cause InterruptedException. + synchronized (workerThreadReadyToWait) { + while (workerThreadReadyToWait.find().isEmpty()) { + workerThreadReadyToWait.wait(); + } + } + + trace("interrupt %s", thread); + thread.interrupt(); + + // Wait until the worker thread catches an InterruptedException. + synchronized (workerThreadInterruptedExceptionCaught) { + while (workerThreadInterruptedExceptionCaught.find().isEmpty()) { + trace("wait for %s to catch InterruptedException", thread); + workerThreadInterruptedExceptionCaught.wait(); + } + } + + // Block waiting when ExceptionBox.toUnchecked() + // called in the worker thread will interrupt the worker thread. + while (!thread.isInterrupted()) { + trace("wait %s is interrupted", thread); + Thread.sleep(100); + } + + trace("join interrupted %s", thread); + thread.join(); + + assertNull(workerThreadException.get()); + } + + @ParameterizedTest + @EnumSource(InvocationTargetExceptionType.class) + public void test_rethrowUnchecked_InvocationTargetException(InvocationTargetExceptionType type) + throws NoSuchMethodException, SecurityException, IllegalAccessException { + + var m = ExceptionBoxTest.class.getMethod(type.methodName); + + try { + m.invoke(null); + } catch (InvocationTargetException ex) { + var cause = assertThrows(type.expectedThrownType, () -> { + throw ExceptionBox.toUnchecked(ex); + }); + assertSame(ex.getCause(), type.expectedThrowableGetter.apply(cause)); + } + } + + public enum InvocationTargetExceptionType { + CHECKED("throwIOException", t -> { + return t.getCause(); + }, ExceptionBox.class), + UNCHECKED("throwNPE", x -> x, RuntimeException.class), + ERROR("throwError", x -> x, Error.class), + ; + + InvocationTargetExceptionType( + String methodName, + UnaryOperator expectedThrowableGetter, + Class expectedThrownType) { + this.methodName = Objects.requireNonNull(methodName); + this.expectedThrownType = Objects.requireNonNull(expectedThrownType); + this.expectedThrowableGetter = Objects.requireNonNull(expectedThrowableGetter); + } + + final String methodName; + final Class expectedThrownType; + final UnaryOperator expectedThrowableGetter; + } + + public static void throwIOException() throws IOException { + throw new IOException("foo"); + } + + public static void throwNPE() { + throw new NullPointerException("foo"); + } + + public static void throwError() { + throw new Error("Kaput!"); + } + + private static void assertToUnchecked(Exception cause, boolean asis) { + Class expectedType; + if (asis) { + expectedType = cause.getClass(); + } else { + expectedType = ExceptionBox.class; + } + var unchecked = ExceptionBox.toUnchecked(cause); + if (asis) { + assertSame(cause, unchecked); + } else { + assertSame(cause, unchecked.getCause()); + } + } + + private void trace(String format, Object... args) { + Objects.requireNonNull(format); + System.out.println(String.format("[%s]: %s", Thread.currentThread(), String.format(format, args))); + } +} diff --git a/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/FunctionalTest.java b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/FunctionalTest.java new file mode 100644 index 00000000000..67c082916a6 --- /dev/null +++ b/test/jdk/tools/jpackage/junit/share/jdk.jpackage/jdk/jpackage/internal/util/function/FunctionalTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2025, 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 jdk.jpackage.internal.util.function; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrowsExactly; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; +import java.util.function.Supplier; +import jdk.jpackage.internal.util.Slot; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +public class FunctionalTest { + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toRunnable(boolean error) { + var reply = Slot.createEmpty(); + + var runnable = ThrowingRunnable.toRunnable(() -> { + if (error) { + throw new Exception(); + } else { + reply.set(135); + } + }); + + if (error) { + assertThrowsExactly(ExceptionBox.class, runnable::run); + assertTrue(reply.find().isEmpty()); + } else { + runnable.run(); + assertEquals(135, reply.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toSupplier(boolean error) { + var supplier = ThrowingSupplier.toSupplier(() -> { + if (error) { + throw new Exception(); + } else { + return 135; + } + }); + + if (error) { + assertThrowsExactly(ExceptionBox.class, supplier::get); + } else { + assertEquals(135, supplier.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toConsumer(boolean error) { + var reply = Slot.createEmpty(); + + Runnable runnable = () -> { + ThrowingConsumer.toConsumer(v -> { + if (error) { + throw new Exception(); + } else { + reply.set(v); + } + }).accept(135); + }; + + if (error) { + assertThrowsExactly(ExceptionBox.class, runnable::run); + assertTrue(reply.find().isEmpty()); + } else { + runnable.run(); + assertEquals(135, reply.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toBiConsumer(boolean error) { + var reply = Slot.createEmpty(); + var reply2 = Slot.createEmpty(); + + Runnable runnable = () -> { + ThrowingBiConsumer.toBiConsumer((x, y) -> { + if (error) { + throw new Exception(); + } else { + reply.set(x); + reply2.set(y); + } + }).accept(456, "Hello"); + }; + + if (error) { + assertThrowsExactly(ExceptionBox.class, runnable::run); + assertTrue(reply.find().isEmpty()); + assertTrue(reply2.find().isEmpty()); + } else { + runnable.run(); + assertEquals(456, reply.get()); + assertEquals("Hello", reply2.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toFunction(boolean error) { + Supplier supplier = () -> { + return ThrowingFunction.toFunction(v -> { + if (error) { + throw new Exception(); + } else { + return String.valueOf(v); + } + }).apply(765); + }; + + if (error) { + assertThrowsExactly(ExceptionBox.class, supplier::get); + } else { + assertEquals("765", supplier.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toBiFunction(boolean error) { + Supplier< Map.Entry> supplier = () -> { + return ThrowingBiFunction.>toBiFunction((x, y) -> { + if (error) { + throw new Exception(); + } else { + return Map.entry(y, x + 23); + } + }).apply(400, "foo"); + }; + + if (error) { + assertThrowsExactly(ExceptionBox.class, supplier::get); + } else { + assertEquals(Map.entry("foo", 423), supplier.get()); + } + } + + @ParameterizedTest + @ValueSource(booleans = {true, false}) + public void test_toUnaryOperator(boolean error) { + Supplier supplier = () -> { + return ThrowingUnaryOperator.toUnaryOperator(v -> { + if (error) { + throw new Exception(); + } else { + return v - 222; + } + }).apply(777); + }; + + if (error) { + assertThrowsExactly(ExceptionBox.class, supplier::get); + } else { + assertEquals(555, supplier.get()); + } + } +} diff --git a/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitAdapter.java b/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitAdapter.java index 5a605b1642d..952b4b520d5 100644 --- a/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitAdapter.java +++ b/test/jdk/tools/jpackage/junit/tools/jdk/jpackage/test/JUnitAdapter.java @@ -49,7 +49,7 @@ public class JUnitAdapter { } } - public static Stream createJPackageTests(ClassLoader testClassLoader, String... args) throws Throwable { + public static Stream createJPackageTests(ClassLoader testClassLoader, String... args) throws Exception { final List tests = new ArrayList<>(); try (final var testBuilder = TestBuilder.build().workDirRoot(Path.of("")).testClassLoader(testClassLoader).testConsumer(tests::add).create()) { for (final var arg : args) { @@ -64,11 +64,11 @@ public class JUnitAdapter { } @TestFactory - Stream createJPackageTests() throws Throwable { + Stream createJPackageTests() throws Exception { return createJPackageTests(getClass().getClassLoader(), "--jpt-run=" + getClass().getName()); } - static List captureJPackageTestLog(ThrowingRunnable runnable) { + static List captureJPackageTestLog(ThrowingRunnable runnable) { final var buf = new ByteArrayOutputStream(); try (PrintStream ps = new PrintStream(buf, true, StandardCharsets.UTF_8)) { TKit.withExtraLogStream(runnable, ps); diff --git a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java index aef46e29725..8196ab733c9 100644 --- a/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java +++ b/test/jdk/tools/jpackage/linux/AppAboutUrlTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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 @@ -82,7 +82,7 @@ public class AppAboutUrlTest { runTest(JPackageCommand::setFakeRuntime, "", "(none)"); } - private static void runTest(ThrowingConsumer initializer, + private static void runTest(ThrowingConsumer initializer, String expectedDebHomepage, String expectedRpmUrl) { new PackageTest() .forTypes(PackageType.LINUX) diff --git a/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java b/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java index dd94330d039..50445c0e9ab 100644 --- a/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java +++ b/test/jdk/tools/jpackage/macosx/CustomInfoPListTest.java @@ -23,7 +23,6 @@ import static java.util.Collections.unmodifiableSortedSet; import static java.util.Map.entry; -import jdk.jpackage.internal.util.Slot; import static jdk.jpackage.internal.util.PListWriter.writeDict; import static jdk.jpackage.internal.util.PListWriter.writeKey; import static jdk.jpackage.internal.util.PListWriter.writePList; @@ -52,6 +51,7 @@ import java.util.stream.Stream; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import jdk.jpackage.internal.util.PListReader; +import jdk.jpackage.internal.util.Slot; import jdk.jpackage.internal.util.function.ThrowingBiConsumer; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.ParameterSupplier; @@ -84,7 +84,7 @@ public class CustomInfoPListTest { @Test @ParameterSupplier("customPLists") - public void testAppImage(TestConfig cfg) throws Throwable { + public void testAppImage(TestConfig cfg) { testApp(new ConfigurationTarget(JPackageCommand.helloAppImage()), cfg); } @@ -254,6 +254,10 @@ public class CustomInfoPListTest { .addArguments(cmd.getAllArguments()) .setPackageType(PackageType.IMAGE) .removeArgumentWithValue("--resource-dir") + // Ignore externally configured runtime if any. + // It may or may not have the "bin" directory, it also can be a bundle. + // These factors affect the runtime plist file (see JDK-8363980) which may not be the default one. + .ignoreDefaultRuntime(true) .setArgumentValue("--dest", TKit.createTempDirectory("vanilla")); vanillaCmd.execute(); @@ -320,8 +324,8 @@ public class CustomInfoPListTest { ; private CustomPListType( - ThrowingBiConsumer inputPlistWriter, - ThrowingBiConsumer outputPlistWriter, + ThrowingBiConsumer inputPlistWriter, + ThrowingBiConsumer outputPlistWriter, String outputPlistFilename) { this.inputPlistWriter = ThrowingBiConsumer.toBiConsumer(inputPlistWriter); this.outputPlistWriter = ThrowingBiConsumer.toBiConsumer(outputPlistWriter); diff --git a/test/jdk/tools/jpackage/macosx/EntitlementsTest.java b/test/jdk/tools/jpackage/macosx/EntitlementsTest.java index aa5879e0c61..6e03c858db3 100644 --- a/test/jdk/tools/jpackage/macosx/EntitlementsTest.java +++ b/test/jdk/tools/jpackage/macosx/EntitlementsTest.java @@ -99,7 +99,7 @@ public class EntitlementsTest { }), ; - EntitlementsSource(ThrowingConsumer initializer) { + EntitlementsSource(ThrowingConsumer initializer) { this.initializer = toConsumer(initializer); } diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index 97c83bba57d..b6066bb9cc4 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -37,7 +37,6 @@ import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; -import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; @@ -631,7 +630,7 @@ public class AppContentTest { private static final class FileContentFactory implements ContentFactory { - FileContentFactory(ThrowingSupplier factory, Path pathInAppContentRoot) { + FileContentFactory(ThrowingSupplier factory, Path pathInAppContentRoot) { this.factory = ThrowingSupplier.toSupplier(factory); this.pathInAppContentRoot = pathInAppContentRoot; if (pathInAppContentRoot.isAbsolute()) { diff --git a/test/jdk/tools/jpackage/share/AsyncTest.java b/test/jdk/tools/jpackage/share/AsyncTest.java index b2755d4594f..e3a3f7e3cb8 100644 --- a/test/jdk/tools/jpackage/share/AsyncTest.java +++ b/test/jdk/tools/jpackage/share/AsyncTest.java @@ -37,6 +37,7 @@ import java.util.function.Predicate; import java.util.spi.ToolProvider; import java.util.stream.IntStream; import jdk.jpackage.internal.util.function.ThrowingRunnable; +import jdk.jpackage.internal.util.Slot; import jdk.jpackage.test.Annotations.ParameterSupplier; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.HelloApp; @@ -61,7 +62,7 @@ import jdk.jpackage.test.TKit; public class AsyncTest { @Test - public void test() throws Throwable { + public void test() throws Exception { // Create test jar only once. // Besides of saving time, this avoids asynchronous invocations of java tool provider that randomly fail. @@ -94,7 +95,7 @@ public class AsyncTest { future.get(3, TimeUnit.MINUTES); } - Throwable[] fatalError = new Throwable[1]; + var fatalError = Slot.createEmpty(); for (var future : futures) { var result = future.get(); @@ -102,13 +103,11 @@ public class AsyncTest { TKit.trace(String.format("[%s] STDOUT END", result.id())); TKit.trace(String.format("[%s] STDERR BEGIN\n%s", result.id(), result.stderrBuffer())); TKit.trace(String.format("[%s] STDERR END", result.id())); - result.throwable().filter(Predicate.not(TKit::isSkippedException)).ifPresent(t -> { - fatalError[0] = t; - }); + result.exception().filter(Predicate.not(TKit::isSkippedException)).ifPresent(fatalError::set); } - if (fatalError[0] != null) { - throw fatalError[0]; + if (fatalError.find().isPresent()) { + throw fatalError.get(); } } } @@ -143,13 +142,13 @@ public class AsyncTest { } - private record Result(String stdoutBuffer, String stderrBuffer, String id, Optional throwable) { + private record Result(String stdoutBuffer, String stderrBuffer, String id, Optional exception) { Result { Objects.requireNonNull(stdoutBuffer); Objects.requireNonNull(stderrBuffer); Objects.requireNonNull(id); - Objects.requireNonNull(throwable); + Objects.requireNonNull(exception); } } @@ -157,7 +156,7 @@ public class AsyncTest { private record Workload( ByteArrayOutputStream stdoutBuffer, ByteArrayOutputStream stderrBuffer, - ThrowingRunnable runnable, + ThrowingRunnable runnable, String id) implements Callable { Workload { @@ -167,7 +166,7 @@ public class AsyncTest { Objects.requireNonNull(id); } - Workload(ThrowingRunnable runnable, String id) { + Workload(ThrowingRunnable runnable, String id) { this(new ByteArrayOutputStream(), new ByteArrayOutputStream(), runnable, id); } @@ -202,14 +201,14 @@ public class AsyncTest { } }); - Optional err = Optional.empty(); + Optional err = Optional.empty(); try (var bufOut = new PrintStream(stdoutBuffer, true, StandardCharsets.UTF_8); var bufErr = new PrintStream(stderrBuffer, true, StandardCharsets.UTF_8)) { TKit.withStackTraceStream(() -> { TKit.withMainLogStream(runnable, bufOut); }, bufErr); - } catch (Throwable t) { - err = Optional.of(t); + } catch (Exception ex) { + err = Optional.of(ex); } return new Result(stdoutBufferAsString(), stderrBufferAsString(), id, err); } diff --git a/test/jdk/tools/jpackage/share/BasicTest.java b/test/jdk/tools/jpackage/share/BasicTest.java index 958fe150711..0f5d87048dd 100644 --- a/test/jdk/tools/jpackage/share/BasicTest.java +++ b/test/jdk/tools/jpackage/share/BasicTest.java @@ -307,12 +307,12 @@ public final class BasicTest { @Test @Parameter("true") @Parameter("false") - public void testNoOutputDir(boolean appImage) throws Throwable { + public void testNoOutputDir(boolean appImage) throws IOException { var cmd = JPackageCommand.helloAppImage(); final var execDir = cmd.outputDir(); - final ThrowingConsumer initializer = cmdNoOutputDir -> { + final ThrowingConsumer initializer = cmdNoOutputDir -> { cmd.executePrerequisiteActions(); final var pkgType = cmdNoOutputDir.packageType(); diff --git a/test/jdk/tools/jpackage/share/IconTest.java b/test/jdk/tools/jpackage/share/IconTest.java index 12458eda34b..17759db7192 100644 --- a/test/jdk/tools/jpackage/share/IconTest.java +++ b/test/jdk/tools/jpackage/share/IconTest.java @@ -203,7 +203,7 @@ public class IconTest { return withDesktopFile; } - private ThrowingBiConsumer createBundleVerifier() { + private ThrowingBiConsumer createBundleVerifier() { return (cmd, result) -> { Stream.of(Launcher.Main, Launcher.Additional).filter(config::containsKey).forEach(launcher -> { createConsoleOutputVerifier(cmd, launcher).ifPresent(verifier -> { @@ -276,7 +276,7 @@ public class IconTest { return Optional.of(TKit.assertTextStream(lookupString.getValue())); } - private ThrowingConsumer createInstallVerifier() { + private ThrowingConsumer createInstallVerifier() { return cmd -> { var verifier = new LauncherIconVerifier(); diff --git a/test/jdk/tools/jpackage/share/InOutPathTest.java b/test/jdk/tools/jpackage/share/InOutPathTest.java index d36731c2960..211fb843263 100644 --- a/test/jdk/tools/jpackage/share/InOutPathTest.java +++ b/test/jdk/tools/jpackage/share/InOutPathTest.java @@ -21,6 +21,8 @@ * questions. */ +import static jdk.jpackage.test.RunnablePackageTest.Action.CREATE_AND_UNPACK; + import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; @@ -31,17 +33,16 @@ import java.util.Set; import java.util.function.Predicate; import java.util.stream.Stream; import jdk.internal.util.OperatingSystem; -import jdk.jpackage.test.AppImageFile; -import jdk.jpackage.test.ApplicationLayout; -import jdk.jpackage.test.PackageFile; +import jdk.jpackage.internal.util.function.ThrowingConsumer; import jdk.jpackage.test.Annotations.Parameters; import jdk.jpackage.test.Annotations.Test; -import jdk.jpackage.internal.util.function.ThrowingConsumer; +import jdk.jpackage.test.AppImageFile; +import jdk.jpackage.test.ApplicationLayout; import jdk.jpackage.test.JPackageCommand; import jdk.jpackage.test.JPackageCommand.StandardAssert; +import jdk.jpackage.test.PackageFile; import jdk.jpackage.test.PackageTest; import jdk.jpackage.test.PackageType; -import static jdk.jpackage.test.RunnablePackageTest.Action.CREATE_AND_UNPACK; import jdk.jpackage.test.TKit; /* @@ -145,11 +146,11 @@ public final class InOutPathTest { } @Test - public void test() throws Throwable { + public void test() throws Exception { runTest(packageTypes, configure); } - private static Envelope wrap(ThrowingConsumer v, String label) { + private static Envelope wrap(ThrowingConsumer v, String label) { return new Envelope(v, label); } @@ -158,8 +159,8 @@ public final class InOutPathTest { } private static void runTest(Set packageTypes, - ThrowingConsumer configure) throws Throwable { - ThrowingConsumer configureWrapper = cmd -> { + ThrowingConsumer configure) throws Exception { + ThrowingConsumer configureWrapper = cmd -> { // Make sure the input directory is empty in every test run. // This is needed because jpackage output directories in this test // are subdirectories of the input directory. @@ -268,7 +269,7 @@ public final class InOutPathTest { } } - private static final record Envelope(ThrowingConsumer value, String label) { + private static final record Envelope(ThrowingConsumer value, String label) { @Override public String toString() { // Will produce the same test description for the same label every @@ -291,7 +292,7 @@ public final class InOutPathTest { } private final Set packageTypes; - private final ThrowingConsumer configure; + private final ThrowingConsumer configure; // Placing jar file in the "Resources" subdir of the input directory would allow // to use the input directory with `--app-content` on OSX. diff --git a/test/jdk/tools/jpackage/share/PerUserCfgTest.java b/test/jdk/tools/jpackage/share/PerUserCfgTest.java index d2f368cd824..b28eb060b8f 100644 --- a/test/jdk/tools/jpackage/share/PerUserCfgTest.java +++ b/test/jdk/tools/jpackage/share/PerUserCfgTest.java @@ -158,8 +158,8 @@ public class PerUserCfgTest { } private static void withConfigFile(JPackageCommand cmd, Path srcCfgFile, - Path outputCfgFileDir, ThrowingConsumer action) throws - Throwable { + Path outputCfgFileDir, ThrowingConsumer action) throws + Exception { Path targetCfgFile = outputCfgFileDir.resolve(cmd.appLauncherCfgPath( null).getFileName()); TKit.assertPathExists(targetCfgFile, false); diff --git a/test/jdk/tools/jpackage/share/RuntimePackageTest.java b/test/jdk/tools/jpackage/share/RuntimePackageTest.java index 387b46acdfb..6cc668f94f9 100644 --- a/test/jdk/tools/jpackage/share/RuntimePackageTest.java +++ b/test/jdk/tools/jpackage/share/RuntimePackageTest.java @@ -30,7 +30,7 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.Objects; import java.util.function.Predicate; -import jdk.jpackage.internal.util.function.ThrowingSupplier; +import java.util.function.Supplier; import jdk.jpackage.test.Annotations.Parameter; import jdk.jpackage.test.Annotations.Test; import jdk.jpackage.test.JPackageCommand; @@ -114,7 +114,7 @@ public class RuntimePackageTest { return init(JPackageCommand::createInputRuntimeImage); } - private static PackageTest init(ThrowingSupplier createRuntime) { + private static PackageTest init(Supplier createRuntime) { Objects.requireNonNull(createRuntime); final Path[] runtimeImageDir = new Path[1]; diff --git a/test/jdk/tools/jpackage/share/ServiceTest.java b/test/jdk/tools/jpackage/share/ServiceTest.java index 94d3421a2cd..91950f0dba8 100644 --- a/test/jdk/tools/jpackage/share/ServiceTest.java +++ b/test/jdk/tools/jpackage/share/ServiceTest.java @@ -109,7 +109,7 @@ public class ServiceTest { } @Test - public void test() throws Throwable { + public void test() { var pkg = createPackageTest().addHelloAppInitializer("com.foo.ServiceTest"); LauncherAsServiceVerifier.build().setExpectedValue("A1").applyTo(pkg); createTestInitializer().applyTo(pkg); @@ -117,7 +117,7 @@ public class ServiceTest { } @Test - public void testUpdate() throws Throwable { + public void testUpdate() { var testInitializer = createTestInitializer().setUpgradeCode( "4050AD4D-D6CC-452A-9CB0-58E5FA8C410F"); From 30be94086aad42b99a15a05fe5115f552e8efb8b Mon Sep 17 00:00:00 2001 From: Jonas Norlinder Date: Tue, 16 Dec 2025 21:33:27 +0000 Subject: [PATCH 126/211] 8373625: CPUTimeCounters creates a total counter for unsupported GCs Reviewed-by: sjohanss, tschatzl --- src/hotspot/share/runtime/cpuTimeCounters.hpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/cpuTimeCounters.hpp b/src/hotspot/share/runtime/cpuTimeCounters.hpp index 9ad00492731..c2e636bdb1d 100644 --- a/src/hotspot/share/runtime/cpuTimeCounters.hpp +++ b/src/hotspot/share/runtime/cpuTimeCounters.hpp @@ -28,6 +28,7 @@ #define SHARE_RUNTIME_CPUTIMECOUNTERS_HPP +#include "gc/shared/gc_globals.hpp" #include "memory/iterator.hpp" #include "runtime/os.hpp" #include "runtime/perfData.hpp" @@ -83,7 +84,9 @@ public: assert(_instance == nullptr, "we can only allocate one CPUTimeCounters object"); if (UsePerfData && os::is_thread_cpu_time_supported()) { _instance = new CPUTimeCounters(); - create_counter(SUN_THREADS, CPUTimeGroups::CPUTimeType::gc_total); + if (UseG1GC || UseParallelGC) { + create_counter(SUN_THREADS, CPUTimeGroups::CPUTimeType::gc_total); + } } } From 87d881fee01c42f5847031a63d50873b3d438f7a Mon Sep 17 00:00:00 2001 From: Bradford Wetmore Date: Tue, 16 Dec 2025 21:43:43 +0000 Subject: [PATCH 127/211] 8368493: Disable most test JSSE debug output by default, and increase the test default maximum output log size Reviewed-by: jnimeh, hchao --- test/jdk/javax/net/ssl/DTLS/TEST.properties | 1 - .../net/ssl/HttpsURLConnection/Equals.java | 19 ++- .../net/ssl/SSLEngine/NoAuthClientAuth.java | 4 +- .../ssl/SSLSession/ResumeTLS13withSNI.java | 4 +- ...erverNameRejectedTLSSessionResumption.java | 19 ++- .../SSLEngineExplorerMatchedSNI.java | 4 +- .../ssl/Stapling/SSLEngineWithStapling.java | 6 +- test/jdk/javax/net/ssl/TEST.properties | 1 + test/jdk/javax/net/ssl/TLS/TestJSSE.java | 17 ++- test/jdk/javax/net/ssl/TLSCommon/TLSTest.java | 126 ++++++++++-------- .../javax/net/ssl/TLSCommon/TLSWithEdDSA.java | 20 ++- .../javax/net/ssl/TLSv12/ShortRSAKey512.java | 4 +- .../net/ssl/TLSv13/ClientHelloKeyShares.java | 20 ++- .../javax/net/ssl/TLSv13/HRRKeyShares.java | 20 ++- .../compatibility/ClientHelloProcessing.java | 19 ++- .../net/ssl/templates/SSLEngineTemplate.java | 16 +++ .../net/ssl/templates/SSLSocketTemplate.java | 15 +++ .../ssl/SSLEngineImpl/TestBadDNForPeerCA.java | 17 ++- .../SSLEngineImpl/TestBadDNForPeerCA12.java | 18 ++- .../NoInvalidateSocketException.java | 16 ++- .../ResumeClientTLS12withSNI.java | 18 ++- .../AnonCipherWithWantClientAuth.java | 21 ++- .../SigAlgosExtTestWithTLS12.java | 16 ++- .../SigSchemePropOrdering.java | 15 ++- .../ssl/Stapling/StatusResponseManager.java | 5 +- .../ssl/StatusResponseManagerTests.java | 17 ++- test/jdk/sun/security/ssl/TEST.properties | 1 + 27 files changed, 357 insertions(+), 102 deletions(-) create mode 100644 test/jdk/javax/net/ssl/TEST.properties create mode 100644 test/jdk/sun/security/ssl/TEST.properties diff --git a/test/jdk/javax/net/ssl/DTLS/TEST.properties b/test/jdk/javax/net/ssl/DTLS/TEST.properties index a50cba09c0f..ceb6c8c9c42 100644 --- a/test/jdk/javax/net/ssl/DTLS/TEST.properties +++ b/test/jdk/javax/net/ssl/DTLS/TEST.properties @@ -6,4 +6,3 @@ modules = \ java.security.jgss/sun.security.krb5.internal:+open \ java.security.jgss/sun.security.krb5.internal.ktab \ java.base/sun.security.util -maxOutputSize = 2500000 diff --git a/test/jdk/javax/net/ssl/HttpsURLConnection/Equals.java b/test/jdk/javax/net/ssl/HttpsURLConnection/Equals.java index d36dfb2630e..35913edd2bf 100644 --- a/test/jdk/javax/net/ssl/HttpsURLConnection/Equals.java +++ b/test/jdk/javax/net/ssl/HttpsURLConnection/Equals.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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,7 +27,7 @@ * @library /test/lib * @modules jdk.httpserver * @build jdk.test.lib.net.SimpleSSLContext - * @run main/othervm -Djavax.net.debug=ssl,handshake,record Equals + * @run main/othervm Equals */ import com.sun.net.httpserver.*; import java.net.*; @@ -38,9 +38,24 @@ import jdk.test.lib.net.SimpleSSLContext; public class Equals { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake,record + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + static SSLContext ctx; public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake,record"); + } + HttpsServer s2 = null; ExecutorService executor = null; try { diff --git a/test/jdk/javax/net/ssl/SSLEngine/NoAuthClientAuth.java b/test/jdk/javax/net/ssl/SSLEngine/NoAuthClientAuth.java index 208fb3935ae..95754a4763e 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/NoAuthClientAuth.java +++ b/test/jdk/javax/net/ssl/SSLEngine/NoAuthClientAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2025, 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 @@ -99,7 +99,7 @@ public class NoAuthClientAuth { * including specific handshake messages, and might be best examined * after gaining some familiarity with this application. */ - private static boolean debug = true; + private static boolean debug = false; private SSLContext sslc; diff --git a/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java b/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java index 3d05607bd39..d288fe70200 100644 --- a/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java +++ b/test/jdk/javax/net/ssl/SSLSession/ResumeTLS13withSNI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -54,7 +54,7 @@ public class ResumeTLS13withSNI { * including specific handshake messages, and might be best examined * after gaining some familiarity with this application. */ - private static final boolean debug = true; + private static final boolean debug = false; private static final ByteBuffer clientOut = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); diff --git a/test/jdk/javax/net/ssl/SSLSession/ServerNameRejectedTLSSessionResumption.java b/test/jdk/javax/net/ssl/SSLSession/ServerNameRejectedTLSSessionResumption.java index f80f3402c7e..de51b9c565e 100644 --- a/test/jdk/javax/net/ssl/SSLSession/ServerNameRejectedTLSSessionResumption.java +++ b/test/jdk/javax/net/ssl/SSLSession/ServerNameRejectedTLSSessionResumption.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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,11 +43,20 @@ import javax.net.ssl.StandardConstants; * between the server and the client happens correctly without any * errors * @library /javax/net/ssl/templates - * @run main/othervm -Djavax.net.debug=all - * ServerNameRejectedTLSSessionResumption + * @run main/othervm ServerNameRejectedTLSSessionResumption */ public class ServerNameRejectedTLSSessionResumption extends SSLContextTemplate { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; private static final String CLIENT_REQUESTED_SNI = "client.local"; // dummy host, no connection is attempted in this test @@ -56,6 +65,10 @@ public class ServerNameRejectedTLSSessionResumption private static final int PEER_PORT = 12345; public static void main(final String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + new ServerNameRejectedTLSSessionResumption().runTest(); } diff --git a/test/jdk/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java b/test/jdk/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java index a42134abdb1..bb288684384 100644 --- a/test/jdk/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java +++ b/test/jdk/javax/net/ssl/ServerName/SSLEngineExplorerMatchedSNI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -71,7 +71,7 @@ public class SSLEngineExplorerMatchedSNI extends SSLEngineService { /* * Turn on SSL debugging? */ - static boolean debug = true; + static boolean debug = false; /* * Define the server side of the test. diff --git a/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java b/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java index 506e7b00e6d..34398a4b6f8 100644 --- a/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java +++ b/test/jdk/javax/net/ssl/Stapling/SSLEngineWithStapling.java @@ -99,13 +99,13 @@ public class SSLEngineWithStapling { /* * Enables the JSSE system debugging system property: * - * -Djavax.net.debug=all + * -Djavax.net.debug=ssl,handshake * * This gives a lot of low-level information about operations underway, * including specific handshake messages, and might be best examined * after gaining some familiarity with this application. */ - private static final boolean debug = true; + private static final boolean debug = false; private SSLEngine clientEngine; // client Engine private ByteBuffer clientOut; // write side of clientEngine @@ -151,7 +151,7 @@ public class SSLEngineWithStapling { */ public static void main(String args[]) throws Exception { if (debug) { - System.setProperty("javax.net.debug", "ssl:handshake"); + System.setProperty("javax.net.debug", "ssl,handshake"); } // Create the PKI we will use for the test and start the OCSP servers diff --git a/test/jdk/javax/net/ssl/TEST.properties b/test/jdk/javax/net/ssl/TEST.properties new file mode 100644 index 00000000000..741c2565067 --- /dev/null +++ b/test/jdk/javax/net/ssl/TEST.properties @@ -0,0 +1 @@ +maxOutputSize=500000 diff --git a/test/jdk/javax/net/ssl/TLS/TestJSSE.java b/test/jdk/javax/net/ssl/TLS/TestJSSE.java index 29631064011..baabd7f6054 100644 --- a/test/jdk/javax/net/ssl/TLS/TestJSSE.java +++ b/test/jdk/javax/net/ssl/TLS/TestJSSE.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2025, 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,6 +27,17 @@ import java.security.Security; public class TestJSSE { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,record + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final String LOCAL_IP = InetAddress.getLoopbackAddress().getHostAddress(); public static void main(String... args) throws Exception { @@ -35,7 +46,9 @@ public class TestJSSE { Security.setProperty("jdk.tls.disabledAlgorithms", ""); // enable debug output - System.setProperty("javax.net.debug", "ssl,record"); + if (debug) { + System.setProperty("javax.net.debug", "ssl,record"); + } String srvProtocol = System.getProperty("SERVER_PROTOCOL"); String clnProtocol = System.getProperty("CLIENT_PROTOCOL"); diff --git a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java index 6aec08deedd..fc6369a2bbc 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java +++ b/test/jdk/javax/net/ssl/TLSCommon/TLSTest.java @@ -49,98 +49,112 @@ import javax.net.ssl.TrustManagerFactory; * @bug 8205111 * @enablePreview * @summary Test TLS with different types of supported keys. - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp384r1_sha384 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 ecdsa_secp384r1_sha384 * TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp521r1_sha512 + * @run main/othervm TLSTest TLSv1.3 ecdsa_secp521r1_sha512 * TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_128_GCM_SHA256 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_128_GCM_SHA256 * - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp384r1_sha384 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha1 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pkcs1_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 ec_rsa_pkcs1_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 ecdsa_sha1 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 ecdsa_secp384r1_sha384 * TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 ecdsa_secp521r1_sha512 + * @run main/othervm TLSTest TLSv1.3 ecdsa_secp521r1_sha512 * TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_rsae_sha512 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha256 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha384 TLS_AES_256_GCM_SHA384 + * @run main/othervm TLSTest TLSv1.3 rsa_pss_pss_sha512 TLS_AES_256_GCM_SHA384 * - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha256 + * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha384 + * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha384 * TLS_RSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pkcs1_sha512 + * @run main/othervm TLSTest TLSv1.2 rsa_pkcs1_sha512 * TLS_RSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ec_rsa_pkcs1_sha256 + * @run main/othervm TLSTest TLSv1.2 ec_rsa_pkcs1_sha256 * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_sha1 + * @run main/othervm TLSTest TLSv1.2 ecdsa_sha1 * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_secp384r1_sha384 + * @run main/othervm TLSTest TLSv1.2 ecdsa_secp384r1_sha384 * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 ecdsa_secp521r1_sha512 + * @run main/othervm TLSTest TLSv1.2 ecdsa_secp521r1_sha512 * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha256 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_256_CBC_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha384 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_rsae_sha512 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha256 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha256 * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha384 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha384 * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.2 rsa_pss_pss_sha512 + * @run main/othervm TLSTest TLSv1.2 rsa_pss_pss_sha512 * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 * - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha256 + * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha256 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha384 + * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha384 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pkcs1_sha512 + * @run main/othervm TLSTest TLSv1.1 rsa_pkcs1_sha512 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha256 + * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha384 + * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1.1 rsa_pss_rsae_sha512 + * @run main/othervm TLSTest TLSv1.1 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA * - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha256 TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha384 TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pkcs1_sha512 TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha256 + * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha1 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha256 TLS_RSA_WITH_AES_256_CBC_SHA + * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha384 TLS_RSA_WITH_AES_128_CBC_SHA + * @run main/othervm TLSTest TLSv1 rsa_pkcs1_sha512 TLS_RSA_WITH_AES_256_CBC_SHA + * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha256 * TLS_RSA_WITH_AES_128_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha384 + * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha384 * TLS_RSA_WITH_AES_256_CBC_SHA - * @run main/othervm -Djavax.net.debug=ssl,handshake TLSTest TLSv1 rsa_pss_rsae_sha512 + * @run main/othervm TLSTest TLSv1 rsa_pss_rsae_sha512 * TLS_RSA_WITH_AES_128_CBC_SHA */ public class TLSTest { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private volatile static boolean clientRenegoReady = false; public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake"); + } final String tlsProtocol = args[0]; final KeyType keyType = KeyType.valueOf(args[1]); diff --git a/test/jdk/javax/net/ssl/TLSCommon/TLSWithEdDSA.java b/test/jdk/javax/net/ssl/TLSCommon/TLSWithEdDSA.java index 3fabc5bd73c..f21b7b32b6a 100644 --- a/test/jdk/javax/net/ssl/TLSCommon/TLSWithEdDSA.java +++ b/test/jdk/javax/net/ssl/TLSCommon/TLSWithEdDSA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,8 +24,6 @@ /* * SunJSSE does not support dynamic system properties, no way to re-use * system properties in samevm/agentvm mode. - * For extra debugging output, add -Djavax.net.debug=ssl:handshake into the - * run directive below. */ /* @@ -74,6 +72,18 @@ import javax.net.ssl.X509KeyManager; import jdk.test.lib.security.SecurityUtils; public class TLSWithEdDSA extends SSLSocketTemplate { + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final String PASSWD = "passphrase"; private static final String DEF_TRUST_ANCHORS = "CA_DSA_1024:CA_DSA_2048:" + "CA_ECDSA_SECP256R1:CA_ECDSA_SECP384R1:CA_ECDSA_SECP521R1:" + @@ -556,6 +566,10 @@ public class TLSWithEdDSA extends SSLSocketTemplate { } public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake"); + } + SecurityUtils.removeFromDisabledTlsAlgs("TLSv1.1", "TLSv1"); certFac = CertificateFactory.getInstance("X.509"); String testFormat; diff --git a/test/jdk/javax/net/ssl/TLSv12/ShortRSAKey512.java b/test/jdk/javax/net/ssl/TLSv12/ShortRSAKey512.java index 4d4331dc973..3f8e5e4e6a5 100644 --- a/test/jdk/javax/net/ssl/TLSv12/ShortRSAKey512.java +++ b/test/jdk/javax/net/ssl/TLSv12/ShortRSAKey512.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -65,7 +65,7 @@ public class ShortRSAKey512 extends SSLContextTemplate { /* * Turn on SSL debugging? */ - static boolean debug = true; + static boolean debug = false; /* * Define the server side of the test. diff --git a/test/jdk/javax/net/ssl/TLSv13/ClientHelloKeyShares.java b/test/jdk/javax/net/ssl/TLSv13/ClientHelloKeyShares.java index 56f37a9e4f1..efb9895b33c 100644 --- a/test/jdk/javax/net/ssl/TLSv13/ClientHelloKeyShares.java +++ b/test/jdk/javax/net/ssl/TLSv13/ClientHelloKeyShares.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -22,8 +22,7 @@ */ // SunJSSE does not support dynamic system properties, no way to re-use -// system properties in samevm/agentvm mode. For further debugging output -// set the -Djavax.net.debug=ssl:handshake property on the @run lines. +// system properties in samevm/agentvm mode. /* * @test @@ -46,6 +45,17 @@ import java.util.*; public class ClientHelloKeyShares { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + // Some TLS constants we'll use for testing private static final int TLS_REC_HANDSHAKE = 22; private static final int HELLO_EXT_SUPP_GROUPS = 10; @@ -58,6 +68,10 @@ public class ClientHelloKeyShares { private static final int NG_X448 = 0x001E; public static void main(String args[]) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake"); + } + // Arguments to this test are an abitrary number of integer // values which will be the expected NamedGroup IDs in the key_share // extension. Expected named group assertions may also be affected diff --git a/test/jdk/javax/net/ssl/TLSv13/HRRKeyShares.java b/test/jdk/javax/net/ssl/TLSv13/HRRKeyShares.java index 313b2c5084b..560faf87049 100644 --- a/test/jdk/javax/net/ssl/TLSv13/HRRKeyShares.java +++ b/test/jdk/javax/net/ssl/TLSv13/HRRKeyShares.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -22,8 +22,7 @@ */ // SunJSSE does not support dynamic system properties, no way to re-use -// system properties in samevm/agentvm mode. For further debugging output -// set the -Djavax.net.debug=ssl:handshake property on the @run lines. +// system properties in samevm/agentvm mode. /* * @test @@ -48,6 +47,16 @@ import jdk.test.lib.Utils; public class HRRKeyShares { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; // Some TLS constants we'll use for testing private static final int TLS_REC_HANDSHAKE = 22; @@ -209,6 +218,11 @@ public class HRRKeyShares { } public static void main(String args[]) throws Exception { + + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake"); + } + System.out.println("Test 1: Good HRR exchange using secp384r1"); hrrKeyShareTest(NG_SECP384R1, true); System.out.println(); diff --git a/test/jdk/javax/net/ssl/compatibility/ClientHelloProcessing.java b/test/jdk/javax/net/ssl/compatibility/ClientHelloProcessing.java index c147f732ec5..4c1b621b180 100644 --- a/test/jdk/javax/net/ssl/compatibility/ClientHelloProcessing.java +++ b/test/jdk/javax/net/ssl/compatibility/ClientHelloProcessing.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -60,6 +60,17 @@ import java.util.Objects; public class ClientHelloProcessing { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl:handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final ByteBuffer SERVOUTBUF = ByteBuffer.wrap("Server Side".getBytes()); @@ -476,7 +487,11 @@ public class ClientHelloProcessing { public static void main(String[] args) throws Exception { boolean allGood = true; - System.setProperty("javax.net.debug", "ssl:handshake"); + + if (debug) { + System.setProperty("javax.net.debug", "ssl:handshake"); + } + trustMgrFac = makeTrustManagerFactory(trustFilename, passwd); keyMgrFac = makeKeyManagerFactory(keyFilename, passwd); diff --git a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java index 2c1cfaa44ef..fed82d1164f 100644 --- a/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLEngineTemplate.java @@ -54,6 +54,18 @@ import java.nio.ByteBuffer; * produced. */ public class SSLEngineTemplate extends SSLContextTemplate { + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + protected final SSLEngine clientEngine; // client Engine protected final ByteBuffer clientOut; // write side of clientEngine protected final ByteBuffer clientIn; // read side of clientEngine @@ -139,6 +151,10 @@ public class SSLEngineTemplate extends SSLContextTemplate { } public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + new SSLEngineTemplate().runTest(); } diff --git a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java index 51706cec927..9d1b1fe94c4 100644 --- a/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java +++ b/test/jdk/javax/net/ssl/templates/SSLSocketTemplate.java @@ -58,11 +58,26 @@ import java.util.concurrent.TimeUnit; */ public class SSLSocketTemplate extends SSLContextTemplate { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + /* * ================== * Run the test case. */ public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + (new SSLSocketTemplate()).run(); } diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java index 20b4c39afb1..cbdabea4a19 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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,7 +27,6 @@ * @library /test/lib * @summary SSLEngine throws IAE during parsing of X500Principal * @run main/othervm TestBadDNForPeerCA - * @run main/othervm -Djavax.net.debug=all TestBadDNForPeerCA */ import javax.net.ssl.KeyManagerFactory; @@ -45,6 +44,16 @@ import java.util.Base64; public class TestBadDNForPeerCA { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; private static final String proto = "TLSv1.3"; @@ -85,6 +94,10 @@ public class TestBadDNForPeerCA { */ public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + TestBadDNForPeerCA test = new TestBadDNForPeerCA(); try { diff --git a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java index 527ceb406c6..70405b61ab3 100644 --- a/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java +++ b/test/jdk/sun/security/ssl/SSLEngineImpl/TestBadDNForPeerCA12.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, 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,7 +27,6 @@ * @library /test/lib * @summary SSLEngine throws IAE during parsing of X500Principal * @run main/othervm TestBadDNForPeerCA12 - * @run main/othervm -Djavax.net.debug=all TestBadDNForPeerCA12 */ import javax.net.ssl.KeyManagerFactory; @@ -45,6 +44,17 @@ import java.util.Base64; public class TestBadDNForPeerCA12 { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + // Test was originally written for TLSv1.2 private static final String proto = "TLSv1.2"; @@ -108,6 +118,10 @@ public class TestBadDNForPeerCA12 { */ public static void main(String[] args) throws Exception { + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + TestBadDNForPeerCA12 test = new TestBadDNForPeerCA12(); try { diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java b/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java index 696eb58d463..977e005daf3 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/NoInvalidateSocketException.java @@ -52,6 +52,18 @@ import java.util.Objects; import java.util.concurrent.TimeUnit; public class NoInvalidateSocketException extends SSLSocketTemplate { + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,session + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final int ITERATIONS = 10; // This controls how long the main thread waits before closing the socket. @@ -73,8 +85,8 @@ public class NoInvalidateSocketException extends SSLSocketTemplate { private static volatile boolean finished = false; public static void main(String[] args) throws Exception { - if (System.getProperty("javax.net.debug") == null) { - System.setProperty("javax.net.debug", "session"); + if (debug) { + System.setProperty("javax.net.debug", "ssl,session"); } if (args != null && args.length >= 1) { diff --git a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java index c9768c1756c..b21d7aa4e31 100644 --- a/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java +++ b/test/jdk/sun/security/ssl/SSLSessionImpl/ResumeClientTLS12withSNI.java @@ -26,7 +26,7 @@ * @bug 8350830 * @summary TLS 1.2 Client session resumption having ServerNameIndication * @modules java.base/sun.security.tools.keytool - * @run main/othervm -Djavax.net.debug=all ResumeClientTLS12withSNI + * @run main/othervm ResumeClientTLS12withSNI */ import javax.net.ssl.*; @@ -41,6 +41,17 @@ import java.util.*; public class ResumeClientTLS12withSNI { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + /* * Enables logging of the SSLEngine operations. */ @@ -77,6 +88,11 @@ public class ResumeClientTLS12withSNI { * Main entry point for this test. */ public static void main(String args[]) throws Exception { + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + Files.deleteIfExists(Path.of(keyFilename)); sun.security.tools.keytool.Main.main( diff --git a/test/jdk/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java b/test/jdk/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java index 145a68a6b0e..d085c1fe890 100644 --- a/test/jdk/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java +++ b/test/jdk/sun/security/ssl/ServerHandshaker/AnonCipherWithWantClientAuth.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2025, 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 @@ -32,7 +32,7 @@ * @modules jdk.crypto.ec * @library /javax/net/ssl/templates * @summary Calling setWantClientAuth(true) disables anonymous suites - * @run main/othervm -Djavax.net.debug=all AnonCipherWithWantClientAuth + * @run main/othervm AnonCipherWithWantClientAuth */ import java.io.InputStream; @@ -41,10 +41,27 @@ import java.security.Security; import javax.net.ssl.SSLSocket; public class AnonCipherWithWantClientAuth extends SSLSocketTemplate { + + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=all + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + /* * Run the test case. */ public static void main(String[] args) throws Exception { + + if (debug) { + System.setProperty("javax.net.debug", "all"); + } + // reset the security property to make sure that the algorithms // and keys used in this test are not disabled. Security.setProperty("jdk.tls.disabledAlgorithms", ""); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java index 43bc40fabf2..351d3ad76a1 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigAlgosExtTestWithTLS12.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (C) 2021, 2024, Tencent. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -56,6 +56,16 @@ import java.nio.ByteBuffer; import java.util.*; public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl,handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; private static final boolean CLIENT_AUTH = Boolean.getBoolean("test.clientAuth"); @@ -114,7 +124,9 @@ public class SigAlgosExtTestWithTLS12 extends SSLEngineTemplate { } public static void main(String[] args) throws Exception { - System.setProperty("javax.net.debug", "ssl:handshake"); + if (debug) { + System.setProperty("javax.net.debug", "ssl,handshake"); + } try { new SigAlgosExtTestWithTLS12().run(); diff --git a/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java b/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java index b7719e6af19..4299c1cc049 100644 --- a/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java +++ b/test/jdk/sun/security/ssl/SignatureScheme/SigSchemePropOrdering.java @@ -38,6 +38,16 @@ import java.util.Arrays; import java.util.List; public class SigSchemePropOrdering extends AbstractCheckSignatureSchemes { + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl:handshake + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; private static final String SIG_SCHEME_STR = "rsa_pkcs1_sha256,rsa_pss_rsae_sha256,rsa_pss_pss_sha256," + @@ -48,7 +58,10 @@ public class SigSchemePropOrdering extends AbstractCheckSignatureSchemes { } public static void main(String[] args) throws Exception { - System.setProperty("javax.net.debug", "ssl:handshake"); + if (debug) { + System.setProperty("javax.net.debug", "ssl:handshake"); + } + System.setProperty("jdk.tls.client.SignatureSchemes", SIG_SCHEME_STR); System.setProperty("jdk.tls.server.SignatureSchemes", SIG_SCHEME_STR); new SigSchemePropOrdering().run(); diff --git a/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java b/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java index 57b16ed7862..6e78c6b4c73 100644 --- a/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java +++ b/test/jdk/sun/security/ssl/Stapling/StatusResponseManager.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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 @@ -28,7 +28,6 @@ * jdk.test.lib.security.CertificateBuilder * @bug 8046321 8339403 * @summary OCSP Stapling for TLS - * @run main/othervm -Djavax.net.debug=ssl:respmgr - * java.base/sun.security.ssl.StatusResponseManagerTests + * @run main/othervm java.base/sun.security.ssl.StatusResponseManagerTests */ diff --git a/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java b/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java index bcfc1290cf0..c7ecbe9f13c 100644 --- a/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java +++ b/test/jdk/sun/security/ssl/Stapling/java.base/sun/security/ssl/StatusResponseManagerTests.java @@ -47,7 +47,17 @@ import static sun.security.ssl.CertStatusExtension.*; */ public class StatusResponseManagerTests { - private static final boolean debug = true; + /* + * Enables the JSSE system debugging system property: + * + * -Djavax.net.debug=ssl:respmgr + * + * This gives a lot of low-level information about operations underway, + * including specific handshake messages, and might be best examined + * after gaining some familiarity with this application. + */ + private static final boolean debug = false; + private static final boolean ocspDebug = false; private static Field responseCacheField; @@ -72,6 +82,11 @@ public class StatusResponseManagerTests { static X509Certificate[] chain; public static void main(String[] args) throws Exception { + + if (debug) { + System.setProperty("javax.net.debug", "ssl:respmgr"); + } + responseCacheField = StatusResponseManager.class.getDeclaredField("responseCache"); responseCacheField.setAccessible(true); diff --git a/test/jdk/sun/security/ssl/TEST.properties b/test/jdk/sun/security/ssl/TEST.properties new file mode 100644 index 00000000000..741c2565067 --- /dev/null +++ b/test/jdk/sun/security/ssl/TEST.properties @@ -0,0 +1 @@ +maxOutputSize=500000 From 3f07710270dbe7268f21828dff20e2eb810b1e70 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 16 Dec 2025 23:17:29 +0000 Subject: [PATCH 128/211] 8373441: Remove DCmdFactory::_enabled Reviewed-by: kevinw, fparain, jsjolen --- src/hotspot/share/jfr/dcmd/jfrDcmds.cpp | 14 +-- .../share/logging/logDiagnosticCommand.cpp | 2 +- .../share/services/diagnosticCommand.cpp | 111 +++++++++--------- .../share/services/diagnosticFramework.cpp | 7 +- .../share/services/diagnosticFramework.hpp | 31 ++--- src/hotspot/share/services/management.cpp | 6 +- .../management/DiagnosticCommandMBean.java | 4 +- 7 files changed, 77 insertions(+), 98 deletions(-) diff --git a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp index d18136e1570..549d879de99 100644 --- a/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp +++ b/src/hotspot/share/jfr/dcmd/jfrDcmds.cpp @@ -47,14 +47,14 @@ bool register_jfr_dcmds() { uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean; - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); // JFR.query Uncomment when developing new queries for the JFR.view command - // DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, true)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + // DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, /*hidden=*/true)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); return true; } diff --git a/src/hotspot/share/logging/logDiagnosticCommand.cpp b/src/hotspot/share/logging/logDiagnosticCommand.cpp index adf596afc94..c9b1015ab45 100644 --- a/src/hotspot/share/logging/logDiagnosticCommand.cpp +++ b/src/hotspot/share/logging/logDiagnosticCommand.cpp @@ -46,7 +46,7 @@ LogDiagnosticCommand::LogDiagnosticCommand(outputStream* output, bool heap_alloc void LogDiagnosticCommand::registerCommand() { uint32_t full_visibility = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean; - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_visibility, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_visibility)); } void LogDiagnosticCommand::execute(DCmdSource source, TRAPS) { diff --git a/src/hotspot/share/services/diagnosticCommand.cpp b/src/hotspot/share/services/diagnosticCommand.cpp index 91b23904676..0ff7f445d24 100644 --- a/src/hotspot/share/services/diagnosticCommand.cpp +++ b/src/hotspot/share/services/diagnosticCommand.cpp @@ -98,78 +98,78 @@ void DCmd::register_dcmds(){ // Third argument specifies if the command is hidden uint32_t full_export = DCmd_Source_Internal | DCmd_Source_AttachAPI | DCmd_Source_MBean; - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #if INCLUDE_SERVICES - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(DCmd_Source_Internal | DCmd_Source_AttachAPI, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(DCmd_Source_Internal | DCmd_Source_AttachAPI)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #if INCLUDE_JVMTI // Both JVMTI and SERVICES have to be enabled to have this dcmd - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // INCLUDE_JVMTI #endif // INCLUDE_SERVICES #if INCLUDE_JVMTI - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // INCLUDE_JVMTI - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #if INCLUDE_JVMTI - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // INCLUDE_JVMTI - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #ifdef LINUX - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // LINUX #if defined(LINUX) || defined(_WIN64) || defined(__APPLE__) - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true,false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true,false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // LINUX or WINDOWS or MacOS - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); // Enhanced JMX Agent Support // These commands not currently exported via the DiagnosticCommandMBean uint32_t jmx_agent_export_flags = DCmd_Source_Internal | DCmd_Source_AttachAPI; - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags, true,false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags, true,false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags, true,false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags, true,false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(jmx_agent_export_flags)); #if INCLUDE_CDS - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); #endif // INCLUDE_CDS - DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export, true, false)); + DCmdFactory::register_DCmdFactory(new DCmdFactoryImpl(full_export)); } HelpDCmd::HelpDCmd(outputStream* output, bool heap) : DCmdWithParser(output, heap), @@ -192,8 +192,7 @@ void HelpDCmd::execute(DCmdSource source, TRAPS) { for (int i = 0; i < cmd_list->length(); i++) { DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i), strlen(cmd_list->at(i))); - output()->print_cr("%s%s", factory->name(), - factory->is_enabled() ? "" : " [disabled]"); + output()->print_cr("%s", factory->name()); output()->print_cr("\t%s", factory->description()); output()->cr(); factory = factory->next(); @@ -203,8 +202,7 @@ void HelpDCmd::execute(DCmdSource source, TRAPS) { DCmdFactory* factory = DCmdFactory::factory(source, _cmd.value(), strlen(_cmd.value())); if (factory != nullptr) { - output()->print_cr("%s%s", factory->name(), - factory->is_enabled() ? "" : " [disabled]"); + output()->print_cr("%s", factory->name()); output()->print_cr("%s", factory->description()); output()->print_cr("\nImpact: %s", factory->impact()); output()->cr(); @@ -223,8 +221,7 @@ void HelpDCmd::execute(DCmdSource source, TRAPS) { for (int i = 0; i < cmd_list->length(); i++) { DCmdFactory* factory = DCmdFactory::factory(source, cmd_list->at(i), strlen(cmd_list->at(i))); - output()->print_cr("%s%s", factory->name(), - factory->is_enabled() ? "" : " [disabled]"); + output()->print_cr("%s", factory->name()); factory = factory->_next; } output()->print_cr("\nFor more information about a specific command use 'help '."); diff --git a/src/hotspot/share/services/diagnosticFramework.cpp b/src/hotspot/share/services/diagnosticFramework.cpp index c37fe7b4e1e..71cc461f161 100644 --- a/src/hotspot/share/services/diagnosticFramework.cpp +++ b/src/hotspot/share/services/diagnosticFramework.cpp @@ -563,10 +563,6 @@ DCmd* DCmdFactory::create_local_DCmd(DCmdSource source, CmdLine &line, outputStream* out, TRAPS) { DCmdFactory* f = factory(source, line.cmd_addr(), line.cmd_len()); if (f != nullptr) { - if (!f->is_enabled()) { - THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), - f->disabled_message()); - } return f->create_resource_instance(out); } THROW_MSG_NULL(vmSymbols::java_lang_IllegalArgumentException(), @@ -594,8 +590,7 @@ GrowableArray* DCmdFactory::DCmdInfo_list(DCmdSource source ) { if (!factory->is_hidden() && (factory->export_flags() & source)) { array->append(new DCmdInfo(factory->name(), factory->description(), factory->impact(), - factory->num_arguments(), - factory->is_enabled())); + factory->num_arguments())); } factory = factory->next(); } diff --git a/src/hotspot/share/services/diagnosticFramework.hpp b/src/hotspot/share/services/diagnosticFramework.hpp index 206b5ed27b4..5f9253b492e 100644 --- a/src/hotspot/share/services/diagnosticFramework.hpp +++ b/src/hotspot/share/services/diagnosticFramework.hpp @@ -117,21 +117,18 @@ protected: const char* const _description; /* Short description */ const char* const _impact; /* Impact on the JVM */ const int _num_arguments; /* Number of supported options or arguments */ - const bool _is_enabled; /* True if the diagnostic command can be invoked, false otherwise */ public: DCmdInfo(const char* name, const char* description, const char* impact, - int num_arguments, - bool enabled) + int num_arguments) : _name(name), _description(description), _impact(impact), - _num_arguments(num_arguments), _is_enabled(enabled) {} + _num_arguments(num_arguments) {} const char* name() const { return _name; } bool name_equals(const char* cmd_name) const; const char* description() const { return _description; } const char* impact() const { return _impact; } int num_arguments() const { return _num_arguments; } - bool is_enabled() const { return _is_enabled; } }; // A DCmdArgumentInfo instance provides a description of a diagnostic command @@ -233,8 +230,6 @@ public: // static const char* name() { return "";} // static const char* description() { return "";} - static const char* disabled_message() { return "Diagnostic command currently disabled"; } - // The impact() method returns a description of the intrusiveness of the diagnostic // command on the Java Virtual Machine behavior. The rational for this method is that some // diagnostic commands can seriously disrupt the behavior of the Java Virtual Machine @@ -337,8 +332,7 @@ public: }; // Diagnostic commands are not directly instantiated but created with a factory. -// Each diagnostic command class has its own factory. The DCmdFactory class also -// manages the status of the diagnostic command (hidden, enabled). A DCmdFactory +// Each diagnostic command class has its own factory. A DCmdFactory // has to be registered to make the diagnostic command available (see // management.cpp) class DCmdFactory: public CHeapObj { @@ -350,10 +344,6 @@ private: // Pointer to the next factory in the singly-linked list of registered // diagnostic commands DCmdFactory* _next; - // When disabled, a diagnostic command cannot be executed. Any attempt to - // execute it will result in the printing of the disabled message without - // instantiating the command. - const bool _enabled; // When hidden, a diagnostic command doesn't appear in the list of commands // provided by the 'help' command. const bool _hidden; @@ -361,10 +351,9 @@ private: const int _num_arguments; public: - DCmdFactory(int num_arguments, uint32_t flags, bool enabled, bool hidden) - : _next(nullptr), _enabled(enabled), _hidden(hidden), + DCmdFactory(int num_arguments, uint32_t flags, bool hidden) + : _next(nullptr), _hidden(hidden), _export_flags(flags), _num_arguments(num_arguments) {} - bool is_enabled() const { return _enabled; } bool is_hidden() const { return _hidden; } uint32_t export_flags() const { return _export_flags; } int num_arguments() const { return _num_arguments; } @@ -373,11 +362,8 @@ public: virtual const char* name() const = 0; virtual const char* description() const = 0; virtual const char* impact() const = 0; - virtual const char* disabled_message() const = 0; // Register a DCmdFactory to make a diagnostic command available. // Once registered, a diagnostic command must not be unregistered. - // To prevent a diagnostic command from being executed, just set the - // enabled flag to false. static int register_DCmdFactory(DCmdFactory* factory); static DCmdFactory* factory(DCmdSource source, const char* cmd, size_t len); // Returns a resourceArea allocated diagnostic command for the given command line @@ -401,8 +387,8 @@ private: // where this template is used to create and register factories. template class DCmdFactoryImpl : public DCmdFactory { public: - DCmdFactoryImpl(uint32_t flags, bool enabled, bool hidden) : - DCmdFactory(get_num_arguments(), flags, enabled, hidden) { } + DCmdFactoryImpl(uint32_t flags, bool hidden = false) : + DCmdFactory(get_num_arguments(), flags, hidden) { } // Returns a resourceArea allocated instance DCmd* create_resource_instance(outputStream* output) const { return new DCmdClass(output, false); @@ -416,9 +402,6 @@ public: const char* impact() const { return DCmdClass::impact(); } - const char* disabled_message() const { - return DCmdClass::disabled_message(); - } private: #ifdef ASSERT diff --git a/src/hotspot/share/services/management.cpp b/src/hotspot/share/services/management.cpp index cc26e2e1352..290e4839c96 100644 --- a/src/hotspot/share/services/management.cpp +++ b/src/hotspot/share/services/management.cpp @@ -2032,7 +2032,11 @@ JVM_ENTRY(void, jmm_GetDiagnosticCommandInfo(JNIEnv *env, jobjectArray cmds, infoArray[i].description = info->description(); infoArray[i].impact = info->impact(); infoArray[i].num_arguments = info->num_arguments(); - infoArray[i].enabled = info->is_enabled(); + + // All registered DCmds are always enabled. We set the dcmdInfo::enabled + // field to true to be compatible with the Java API + // com.sun.management.internal.DiagnosticCommandInfo. + infoArray[i].enabled = true; } JVM_END diff --git a/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java b/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java index d5fedf93855..994757f17c3 100644 --- a/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java +++ b/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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 @@ -135,7 +135,7 @@ import javax.management.DynamicMBean; * * * dcmd.enabledboolean - * True if the diagnostic command is enabled, false otherwise + * This field is always true -- diagnostic commands cannot be disabled. * * * dcmd.argumentsDescriptor From e635330ae17fd2ce653ec75fd57fdd72d2512bba Mon Sep 17 00:00:00 2001 From: Anjian Wen Date: Wed, 17 Dec 2025 02:41:19 +0000 Subject: [PATCH 129/211] 8373069: RISC-V: implement GHASH intrinsic Reviewed-by: fjiang, fyang --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 3 + src/hotspot/cpu/riscv/globals_riscv.hpp | 3 +- src/hotspot/cpu/riscv/stubGenerator_riscv.cpp | 71 +++++++++++++++++-- src/hotspot/cpu/riscv/vm_version_riscv.cpp | 16 +++++ src/hotspot/cpu/riscv/vm_version_riscv.hpp | 2 + .../os_cpu/linux_riscv/riscv_hwprobe.cpp | 3 + 6 files changed, 90 insertions(+), 8 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index 711ae03bf27..b657c1f108d 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -2662,6 +2662,9 @@ enum Nf { INSN(vsha2ch_vv, 0b1110111, 0b010, 0b1, 0b101110); INSN(vsha2cl_vv, 0b1110111, 0b010, 0b1, 0b101111); + // Vector GHASH (Zvkg) Extension + INSN(vghsh_vv, 0b1110111, 0b010, 0b1, 0b101100); + #undef INSN #define INSN(NAME, op, funct3, Vs1, funct6) \ diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index c78bfaa8ffd..390ed2daeb9 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -123,6 +123,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseZvkn, false, EXPERIMENTAL, \ "Use Zvkn group extension, Zvkned, Zvknhb, Zvkb, Zvkt") \ product(bool, UseCtxFencei, false, EXPERIMENTAL, \ - "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") + "Use PR_RISCV_CTX_SW_FENCEI_ON to avoid explicit icache flush") \ + product(bool, UseZvkg, false, EXPERIMENTAL, "Use Zvkg instructions") #endif // CPU_RISCV_GLOBALS_RISCV_HPP diff --git a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp index 49c80dce88a..75669d0e89c 100644 --- a/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp +++ b/src/hotspot/cpu/riscv/stubGenerator_riscv.cpp @@ -2655,8 +2655,7 @@ class StubGenerator: public StubCodeGenerator { // x10 - input length // address generate_cipherBlockChaining_encryptAESCrypt() { - assert(UseAESIntrinsics, "Must be"); - assert(UseZvkn, "need AES instructions (Zvkned extension) support"); + assert(UseAESIntrinsics, "need AES instructions (Zvkned extension) support"); __ align(CodeEntryAlignment); StubId stub_id = StubId::stubgen_cipherBlockChaining_encryptAESCrypt_id; StubCodeMark mark(this, stub_id); @@ -2745,8 +2744,7 @@ class StubGenerator: public StubCodeGenerator { // x10 - input length // address generate_cipherBlockChaining_decryptAESCrypt() { - assert(UseAESIntrinsics, "Must be"); - assert(UseZvkn, "need AES instructions (Zvkned extension) support"); + assert(UseAESIntrinsics, "need AES instructions (Zvkned extension) support"); __ align(CodeEntryAlignment); StubId stub_id = StubId::stubgen_cipherBlockChaining_decryptAESCrypt_id; StubCodeMark mark(this, stub_id); @@ -2950,9 +2948,7 @@ class StubGenerator: public StubCodeGenerator { // x10 - input length // address generate_counterMode_AESCrypt() { - assert(UseAESCTRIntrinsics, "Must be"); - assert(UseZvkn, "need AES instructions (Zvkned extension) support"); - assert(UseZbb, "need basic bit manipulation (Zbb extension) support"); + assert(UseAESCTRIntrinsics, "need AES instructions (Zvkned extension) and Zbb extension support"); __ align(CodeEntryAlignment); StubId stub_id = StubId::stubgen_counterMode_AESCrypt_id; @@ -3001,6 +2997,63 @@ class StubGenerator: public StubCodeGenerator { return start; } + /** + * Arguments: + * + * Input: + * c_rarg0 - current state address + * c_rarg1 - H key address + * c_rarg2 - data address + * c_rarg3 - number of blocks + * + * Output: + * Updated state at c_rarg0 + */ + address generate_ghash_processBlocks() { + assert(UseGHASHIntrinsics, "need GHASH instructions (Zvkg extension) and Zvbb support"); + + __ align(CodeEntryAlignment); + StubId stub_id = StubId::stubgen_ghash_processBlocks_id; + StubCodeMark mark(this, stub_id); + + address start = __ pc(); + __ enter(); + + Register state = c_rarg0; + Register subkeyH = c_rarg1; + Register data = c_rarg2; + Register blocks = c_rarg3; + + VectorRegister partial_hash = v1; + VectorRegister hash_subkey = v2; + VectorRegister cipher_text = v3; + + const unsigned int BLOCK_SIZE = 16; + + __ vsetivli(x0, 2, Assembler::e64, Assembler::m1); + __ vle64_v(hash_subkey, subkeyH); + __ vrev8_v(hash_subkey, hash_subkey); + __ vle64_v(partial_hash, state); + __ vrev8_v(partial_hash, partial_hash); + + __ vsetivli(x0, 4, Assembler::e32, Assembler::m1); + Label L_ghash_loop; + __ bind(L_ghash_loop); + __ vle32_v(cipher_text, data); + __ addi(data, data, BLOCK_SIZE); + __ vghsh_vv(partial_hash, hash_subkey, cipher_text); + __ subi(blocks, blocks, 1); + __ bnez(blocks, L_ghash_loop); + + __ vsetivli(x0, 2, Assembler::e64, Assembler::m1); + __ vrev8_v(partial_hash, partial_hash); + __ vse64_v(partial_hash, state); + __ leave(); + __ ret(); + + return start; + } + // code for comparing 8 characters of strings with Latin1 and Utf16 encoding void compare_string_8_x_LU(Register tmpL, Register tmpU, Register strL, Register strU, Label& DIFF) { @@ -7227,6 +7280,10 @@ static const int64_t right_3_bits = right_n_bits(3); StubRoutines::_counterMode_AESCrypt = generate_counterMode_AESCrypt(); } + if (UseGHASHIntrinsics) { + StubRoutines::_ghash_processBlocks = generate_ghash_processBlocks(); + } + if (UsePoly1305Intrinsics) { StubRoutines::_poly1305_processBlocks = generate_poly1305_processBlocks(); } diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.cpp b/src/hotspot/cpu/riscv/vm_version_riscv.cpp index 75605f25759..22f19c4f5ea 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.cpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.cpp @@ -457,6 +457,22 @@ void VM_Version::c2_initialize() { FLAG_SET_DEFAULT(UseAESCTRIntrinsics, false); } } + + if (UseZvkg) { + if (FLAG_IS_DEFAULT(UseGHASHIntrinsics) && UseZvbb) { + FLAG_SET_DEFAULT(UseGHASHIntrinsics, true); + } + + if (UseGHASHIntrinsics && !UseZvbb) { + warning("Cannot enable UseGHASHIntrinsics on cpu without UseZvbb support"); + FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); + } + } else { + if (UseGHASHIntrinsics) { + warning("Cannot enable UseGHASHIntrinsics on cpu without UseZvkg support"); + FLAG_SET_DEFAULT(UseGHASHIntrinsics, false); + } + } } #endif // COMPILER2 diff --git a/src/hotspot/cpu/riscv/vm_version_riscv.hpp b/src/hotspot/cpu/riscv/vm_version_riscv.hpp index 168a3a576d0..03c843efc69 100644 --- a/src/hotspot/cpu/riscv/vm_version_riscv.hpp +++ b/src/hotspot/cpu/riscv/vm_version_riscv.hpp @@ -289,6 +289,8 @@ class VM_Version : public Abstract_VM_Version { decl(Zvfh , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvfh, &ext_v, &ext_Zfh, nullptr)) \ /* Shorthand for Zvkned + Zvknhb + Zvkb + Zvkt */ \ decl(Zvkn , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkn, &ext_v, nullptr)) \ + /* Zvkg crypto extension for ghash and gcm */ \ + decl(Zvkg , RV_NO_FLAG_BIT, true , UPDATE_DEFAULT_DEP(UseZvkg, &ext_v, nullptr)) \ #define DECLARE_RV_EXT_FEATURE(PRETTY, LINUX_BIT, FSTRING, FLAGF) \ struct ext_##PRETTY##RVExtFeatureValue : public RVExtFeatureValue { \ diff --git a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp index ec756c44fe6..253f460dca3 100644 --- a/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp +++ b/src/hotspot/os_cpu/linux_riscv/riscv_hwprobe.cpp @@ -256,6 +256,9 @@ void RiscvHwprobe::add_features_from_query_result() { is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKT)) { VM_Version::ext_Zvkn.enable_feature(); } + if (is_set(RISCV_HWPROBE_KEY_IMA_EXT_0, RISCV_HWPROBE_EXT_ZVKG)) { + VM_Version::ext_Zvkg.enable_feature(); + } #endif // ====== non-extensions ====== From e9b4696acc966d96d42880e840c8fe27434e4e1b Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Wed, 17 Dec 2025 07:18:26 +0000 Subject: [PATCH 130/211] 8373097: Save command should create missing parent directories Reviewed-by: jlahoda --- .../jdk/internal/jshell/tool/JShellTool.java | 14 +++++++++++++- test/langtools/jdk/jshell/ToolBasicTest.java | 5 ++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java index 795321253fd..9a030f7e46b 100644 --- a/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java +++ b/src/jdk.jshell/share/classes/jdk/internal/jshell/tool/JShellTool.java @@ -3362,7 +3362,19 @@ public class JShellTool implements MessageHandler { // error occurred, already reported return false; } - try (BufferedWriter writer = Files.newBufferedWriter(toPathResolvingUserHome(filename), + // Create missing parent directories before writing to target file + Path target; + try { + target = toPathResolvingUserHome(filename); + Path parent = target.getParent(); + if (parent != null) { + Files.createDirectories(parent); + } + } catch (Exception e) { + errormsg("jshell.err.file.exception", "/save", filename, e); + return false; + } + try (BufferedWriter writer = Files.newBufferedWriter(target, Charset.defaultCharset(), CREATE, TRUNCATE_EXISTING, WRITE)) { if (at.hasOption("-history")) { diff --git a/test/langtools/jdk/jshell/ToolBasicTest.java b/test/langtools/jdk/jshell/ToolBasicTest.java index 5015d1f64b1..7fba0a9cd44 100644 --- a/test/langtools/jdk/jshell/ToolBasicTest.java +++ b/test/langtools/jdk/jshell/ToolBasicTest.java @@ -585,6 +585,7 @@ public class ToolBasicTest extends ReplToolTesting { Compiler compiler = new Compiler(); Path path = compiler.getPath("testSave.repl"); { + Path pathWithDirectories = compiler.getPath("what/ever/testSave.repl"); List list = Arrays.asList( "int a;", "class A { public String toString() { return \"A\"; } }" @@ -593,9 +594,11 @@ public class ToolBasicTest extends ReplToolTesting { (a) -> assertVariable(a, "int", "a"), (a) -> assertCommand(a, "()", null, null, null, "", ""), (a) -> assertClass(a, "class A { public String toString() { return \"A\"; } }", "class", "A"), - (a) -> assertCommand(a, "/save " + path.toString(), "") + (a) -> assertCommand(a, "/save " + path.toString(), ""), + (a) -> assertCommand(a, "/save " + pathWithDirectories.toString(), "") ); assertEquals(list, Files.readAllLines(path)); + assertEquals(list, Files.readAllLines(pathWithDirectories)); } { List output = new ArrayList<>(); From 94c51ce314eea7a4f188fa0db1bae0e3f3dbd230 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 17 Dec 2025 07:22:37 +0000 Subject: [PATCH 131/211] 8372635: Lambdas do not copy over SYNTHETIC flag for local variables Reviewed-by: vromero, liach --- .../sun/tools/javac/comp/LambdaToMethod.java | 5 +- .../javac/patterns/SyntheticVariables.java | 138 ++++++++++++++++++ 2 files changed, 141 insertions(+), 2 deletions(-) create mode 100644 test/langtools/tools/javac/patterns/SyntheticVariables.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java index b13c9e0fe2b..22cb796870b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/LambdaToMethod.java @@ -1152,7 +1152,7 @@ public class LambdaToMethod extends TreeTranslator { propagateAnnos = false; break; case LOCAL_VAR: - ret = new VarSymbol(sym.flags() & FINAL, sym.name, sym.type, translatedSym); + ret = new VarSymbol(sym.flags(), sym.name, sym.type, translatedSym); ret.pos = sym.pos; // If sym.data == ElementKind.EXCEPTION_PARAMETER, // set ret.data = ElementKind.EXCEPTION_PARAMETER too. @@ -1164,7 +1164,8 @@ public class LambdaToMethod extends TreeTranslator { } break; case PARAM: - ret = new VarSymbol((sym.flags() & FINAL) | PARAMETER, sym.name, types.erasure(sym.type), translatedSym); + Assert.check((sym.flags() & PARAMETER) != 0); + ret = new VarSymbol(sym.flags(), sym.name, types.erasure(sym.type), translatedSym); ret.pos = sym.pos; break; default: diff --git a/test/langtools/tools/javac/patterns/SyntheticVariables.java b/test/langtools/tools/javac/patterns/SyntheticVariables.java new file mode 100644 index 00000000000..26ece40d656 --- /dev/null +++ b/test/langtools/tools/javac/patterns/SyntheticVariables.java @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8372635 + * @enablePreview + * @summary Verify temporary variables created for pattern matching are + * marked as synthetic. + * @compile -g SyntheticVariables.java + * @run main SyntheticVariables + */ + +import java.io.IOException; +import java.io.InputStream; +import java.lang.classfile.Attributes; +import java.lang.classfile.ClassFile; +import java.lang.classfile.ClassModel; +import java.lang.classfile.MethodModel; +import java.lang.classfile.attribute.CodeAttribute; +import java.lang.classfile.attribute.LocalVariableTableAttribute; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; + +public class SyntheticVariables { + + public static void main(String[] args) throws IOException { + try (InputStream in = Test.class.getClassLoader().getResource(Test.class.getName().replace('.', '/') + ".class").openStream()) { + ClassModel model = ClassFile.of().parse(in.readAllBytes()); + Map name2Method = model.methods().stream().collect(Collectors.toMap(m -> m.methodName().stringValue(), m -> m)); + assertEquals(Set.of("str", "b", "b2", "this", "l", "o"), localVars(name2Method.get("testInMethod"))); + assertEquals(Set.of("str", "b", "b2", "l", "o"), localVars(name2Method.get("lambda$testInLambda$0"))); + } + } + + private static Set localVars(MethodModel method) { + CodeAttribute code = method.findAttribute(Attributes.code()).orElseThrow(); + LocalVariableTableAttribute lvt = code.findAttribute(Attributes.localVariableTable()).orElseThrow(); + return lvt.localVariables() + .stream() + .map(info -> info.name().stringValue()) + .collect(Collectors.toSet()); + } + + private static void assertEquals(Set expected, Set actual) { + if (!Objects.equals(expected, actual)) { + throw new AssertionError("Unexpected value, expected: " + expected + + ", got: " + actual); + } + } + + public record Test(Object o) { + private void testInMethod() { + Object o = create(); + + //synthetic variable for the instanceof's expression + boolean b = o.toString() instanceof String str && str.isEmpty(); + + System.err.println(b); + + //synthetic variable for the switch's selector and index: + switch (create()) { + //synthetic variable for the nested component values, + //and for the synthetic catch over the getters + case Test(Test(String str)) when str.isEmpty() -> System.err.println(1); + case Test(Test(String str)) -> System.err.println(2); + default -> System.err.println(2); + } + + List l = List.of(0); + + //synthetic variable for case where the static and dynamic types + //don't match for primitive patterns: + boolean b2 = l.get(0) instanceof int; + + System.err.println(b2); + } + + private void testInLambda() { + Object o = create(); + Runnable r = () -> { + + //synthetic variable for the instanceof's expression + boolean b = o.toString() instanceof String str && str.isEmpty(); + + System.err.println(b); + + //synthetic variable for the switch's selector and index: + switch (create()) { + //synthetic variable for the nested component values, + //and for the synthetic catch over the getters + case Test(Test(String str)) when str.isEmpty() -> System.err.println(1); + case Test(Test(String str)) -> System.err.println(2); + default -> System.err.println(2); + } + + List l = List.of(0); + + //synthetic variable for case where the static and dynamic types + //don't match for primitive patterns: + boolean b2 = l.get(0) instanceof int; + + System.err.println(b2); + }; + } + private static String val = "v"; + public static Test create() { + try { + return new Test(new Test(val)); + } finally { + val += val; + } + } + } +} From 386ad61458a3901622b92ca56982d728c11b846a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Wed, 17 Dec 2025 07:49:58 +0000 Subject: [PATCH 132/211] 8373409: java/net/httpclient/http3/H3ErrorHandlingTest.java failed due to deadlock Reviewed-by: dfuchs --- .../internal/net/http/quic/QuicEndpoint.java | 66 +++++++++---------- .../httpclient/http3/H3ErrorHandlingTest.java | 1 + 2 files changed, 31 insertions(+), 36 deletions(-) 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 b1de5ef4bfd..8bdba21594c 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 @@ -1581,34 +1581,30 @@ public abstract sealed class QuicEndpoint implements AutoCloseable peerIssuedResetTokens.replaceAll((tok, c) -> c == from ? to : c); } - public void draining(final QuicPacketReceiver connection) { + public void draining(final QuicConnectionImpl connection) { // remap the connection to a DrainingConnection if (closed) return; + + final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO + connection.localConnectionIdManager().close(); + DrainingConnection draining = new DrainingConnection(connection.connectionIds(), idleTimeout); + // we can ignore stateless reset in the draining state. + remapPeerIssuedResetToken(connection, draining); + connection.connectionIds().forEach((id) -> - connections.compute(id, this::remapDraining)); + connections.compute(id, (i, r) -> remapDraining(i, r, draining))); + draining.startTimer(); assert !connections.containsValue(connection) : connection; } - private DrainingConnection remapDraining(QuicConnectionId id, QuicPacketReceiver conn) { + private DrainingConnection remapDraining(QuicConnectionId id, QuicPacketReceiver conn, DrainingConnection draining) { if (closed) return null; var debugOn = debug.on() && !Thread.currentThread().isVirtual(); - if (conn instanceof ClosingConnection closing) { + if (conn instanceof QuicConnectionImpl || conn instanceof ClosingConnection) { if (debugOn) debug.log("remapping %s to DrainingConnection", id); - final var draining = closing.toDraining(); - remapPeerIssuedResetToken(closing, draining); - draining.startTimer(); - return draining; - } else if (conn instanceof DrainingConnection draining) { - return draining; - } else if (conn instanceof QuicConnectionImpl impl) { - final long idleTimeout = impl.peerPtoMs() * 3; // 3 PTO - impl.localConnectionIdManager().close(); - if (debugOn) debug.log("remapping %s to DrainingConnection", id); - var draining = new DrainingConnection(conn.connectionIds(), idleTimeout); - // we can ignore stateless reset in the draining state. - remapPeerIssuedResetToken(impl, draining); - draining.startTimer(); return draining; + } else if (conn instanceof DrainingConnection d) { + return d; } else if (conn == null) { // connection absent (was probably removed), don't remap to draining if (debugOn) { @@ -1623,30 +1619,32 @@ public abstract sealed class QuicEndpoint implements AutoCloseable protected void closing(QuicConnectionImpl connection, ByteBuffer datagram) { if (closed) return; - ByteBuffer closing = ByteBuffer.allocate(datagram.limit()); - closing.put(datagram.slice()); - closing.flip(); + ByteBuffer closingDatagram = ByteBuffer.allocate(datagram.limit()); + closingDatagram.put(datagram.slice()); + closingDatagram.flip(); + + final long idleTimeout = connection.peerPtoMs() * 3; // 3 PTO + connection.localConnectionIdManager().close(); + var closingConnection = new ClosingConnection(connection.connectionIds(), idleTimeout, datagram); + remapPeerIssuedResetToken(connection, closingConnection); + connection.connectionIds().forEach((id) -> - connections.compute(id, (i, r) -> remapClosing(i, r, closing))); + connections.compute(id, (i, r) -> remapClosing(i, r, closingConnection))); + closingConnection.startTimer(); assert !connections.containsValue(connection) : connection; } - private ClosedConnection remapClosing(QuicConnectionId id, QuicPacketReceiver conn, ByteBuffer datagram) { + private ClosedConnection remapClosing(QuicConnectionId id, QuicPacketReceiver conn, ClosingConnection closingConnection) { if (closed) return null; var debugOn = debug.on() && !Thread.currentThread().isVirtual(); - if (conn instanceof ClosingConnection closing) { + if (conn instanceof QuicConnectionImpl) { + if (debugOn) debug.log("remapping %s to ClosingConnection", id); + return closingConnection; + } else if (conn instanceof ClosingConnection closing) { // we already have a closing datagram, drop the new one return closing; } else if (conn instanceof DrainingConnection draining) { return draining; - } else if (conn instanceof QuicConnectionImpl impl) { - final long idleTimeout = impl.peerPtoMs() * 3; // 3 PTO - impl.localConnectionIdManager().close(); - if (debugOn) debug.log("remapping %s to ClosingConnection", id); - var closing = new ClosingConnection(conn.connectionIds(), idleTimeout, datagram); - remapPeerIssuedResetToken(impl, closing); - closing.startTimer(); - return closing; } else if (conn == null) { // connection absent (was probably removed), don't remap to closing if (debugOn) { @@ -1896,10 +1894,6 @@ public abstract sealed class QuicEndpoint implements AutoCloseable debug.log("ClosingConnection(%s): dropping %s packet", localConnectionIds, headersType); } } - - private DrainingConnection toDraining() { - return new DrainingConnection(localConnectionIds, maxIdleTimeMs); - } } /** diff --git a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java index 4315fd36de5..bb5aeacbb0c 100644 --- a/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java +++ b/test/jdk/java/net/httpclient/http3/H3ErrorHandlingTest.java @@ -71,6 +71,7 @@ import static org.testng.Assert.*; /* * @test + * @bug 8373409 * @key intermittent * @comment testResetControlStream may fail if the client doesn't read the stream type * before the stream is reset, From 9e2008bf5e9a63b640eefc6cc7ec5c4f344c4266 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 17 Dec 2025 08:44:46 +0000 Subject: [PATCH 133/211] 8373676: Test javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java fails on a machine without IPV6 Reviewed-by: jpai, dfuchs --- .../net/ssl/HttpsURLConnection/SubjectAltNameIP.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java b/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java index 2def2f69d6e..cbd2089e7bd 100644 --- a/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java +++ b/test/jdk/javax/net/ssl/HttpsURLConnection/SubjectAltNameIP.java @@ -30,7 +30,7 @@ * @modules java.base/sun.net.util * @comment Insert -Djavax.net.debug=all into the following lines to enable SSL debugging * @run main/othervm SubjectAltNameIP 127.0.0.1 - * @run main/othervm SubjectAltNameIP [::1] + * @run main/othervm SubjectAltNameIP ::1 */ import javax.net.ssl.HandshakeCompletedListener; @@ -166,14 +166,19 @@ public class SubjectAltNameIP { } public static void main(String[] args) throws Exception { + boolean isIpv6Addr = IPAddressUtil.isIPv6LiteralAddress(args[0]); - if (IPAddressUtil.isIPv6LiteralAddress(args[0]) && !IPSupport.hasIPv6()) { + if (isIpv6Addr && !IPSupport.hasIPv6()) { throw new SkippedException("Skipping test - IPv6 is not supported"); } /* * Start the tests. */ - new SubjectAltNameIP(args[0]); + if (isIpv6Addr) { // use the URL notion wrapper + new SubjectAltNameIP("[" + args[0] + "]"); + } else { + new SubjectAltNameIP(args[0]); + } } Thread serverThread = null; From 4924b29fa519996b806ac0f4a7c898085f44bc4c Mon Sep 17 00:00:00 2001 From: Michael McMahon Date: Wed, 17 Dec 2025 08:54:56 +0000 Subject: [PATCH 134/211] 8370655: Check EINTR handling InetAddress implementation and NET_ThrowNew Reviewed-by: alanb --- src/java.base/share/native/libnet/net_util.c | 1 - .../unix/native/libnet/Inet4AddressImpl.c | 34 ++++++++++++------- .../unix/native/libnet/Inet6AddressImpl.c | 32 +++++++++++------ .../unix/native/libnet/net_util_md.c | 15 ++++---- .../unix/native/libnet/net_util_md.h | 13 +++++++ 5 files changed, 62 insertions(+), 33 deletions(-) diff --git a/src/java.base/share/native/libnet/net_util.c b/src/java.base/share/native/libnet/net_util.c index 5b356d04b3c..7b148f03cfd 100644 --- a/src/java.base/share/native/libnet/net_util.c +++ b/src/java.base/share/native/libnet/net_util.c @@ -86,7 +86,6 @@ DEF_JNI_OnLoad(JavaVM *vm, void *reserved) /* check if SO_REUSEPORT is supported on this platform */ REUSEPORT_available = reuseport_supported(IPv6_available); - return JNI_VERSION_1_2; } diff --git a/src/java.base/unix/native/libnet/Inet4AddressImpl.c b/src/java.base/unix/native/libnet/Inet4AddressImpl.c index fff524e03ae..f537226c330 100644 --- a/src/java.base/unix/native/libnet/Inet4AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet4AddressImpl.c @@ -108,7 +108,8 @@ Java_java_net_Inet4AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hints.ai_flags = AI_CANONNAME; hints.ai_family = AF_INET; - error = getaddrinfo(hostname, NULL, &hints, &res); + NET_RESTARTABLE(error, getaddrinfo(hostname, NULL, &hints, &res), + error == EAI_SYSTEM && errno == EINTR); if (error) { #if defined(MACOSX) @@ -229,17 +230,21 @@ Java_java_net_Inet4AddressImpl_getHostByAddr(JNIEnv *env, jobject this, sa.sin_addr.s_addr = htonl(addr); sa.sin_family = AF_INET; - if (getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), - host, sizeof(host), NULL, 0, NI_NAMEREQD)) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); - } else { + int r; + + NET_RESTARTABLE(r, getnameinfo((struct sockaddr *)&sa, sizeof(struct sockaddr_in), + host, sizeof(host), NULL, 0, NI_NAMEREQD), + r == EAI_SYSTEM && errno == EINTR); + + if (r == 0) { ret = (*env)->NewStringUTF(env, host); - if (ret == NULL) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + if (ret != NULL) { + return ret; } } - return ret; + JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + return NULL; } /** @@ -283,7 +288,8 @@ tcp_ping4(JNIEnv *env, SOCKETADDRESS *sa, SOCKETADDRESS *netif, jint timeout, SET_NONBLOCKING(fd); sa->sa4.sin_port = htons(7); // echo port - connect_rv = connect(fd, &sa->sa, sizeof(struct sockaddr_in)); + NET_RESTARTABLE(connect_rv, connect(fd, &sa->sa, sizeof(struct sockaddr_in)), + connect_rv == -1 && errno == EINTR); // connection established or refused immediately, either way it means // we were able to reach the host! @@ -397,8 +403,11 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, icmp->icmp_cksum = 0; // manually calculate checksum icmp->icmp_cksum = in_cksum((u_short *)icmp, plen); + // send it - n = sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in)); + NET_RESTARTABLE(n, sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in)), + n == -1 && errno == EINTR) + if (n < 0 && errno != EINPROGRESS) { #if defined(__linux__) /* @@ -422,8 +431,9 @@ ping4(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); if (tmout2 >= 0) { len = sizeof(sa_recv); - n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, - (struct sockaddr *)&sa_recv, &len); + NET_RESTARTABLE(n, recvfrom(fd, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *)&sa_recv, &len), + n == -1 && errno == EINTR); // check if we received enough data if (n < (jint)sizeof(struct ip)) { continue; diff --git a/src/java.base/unix/native/libnet/Inet6AddressImpl.c b/src/java.base/unix/native/libnet/Inet6AddressImpl.c index 83354356936..8dce4f9cc6b 100644 --- a/src/java.base/unix/native/libnet/Inet6AddressImpl.c +++ b/src/java.base/unix/native/libnet/Inet6AddressImpl.c @@ -227,7 +227,8 @@ Java_java_net_Inet6AddressImpl_lookupAllHostAddr(JNIEnv *env, jobject this, hints.ai_flags = AI_CANONNAME; hints.ai_family = lookupCharacteristicsToAddressFamily(characteristics); - error = getaddrinfo(hostname, NULL, &hints, &res); + NET_RESTARTABLE(error, getaddrinfo(hostname, NULL, &hints, &res), + error == EAI_SYSTEM && errno == EINTR); if (error) { #if defined(MACOSX) @@ -430,16 +431,20 @@ Java_java_net_Inet6AddressImpl_getHostByAddr(JNIEnv *env, jobject this, len = sizeof(struct sockaddr_in6); } - if (getnameinfo(&sa.sa, len, host, sizeof(host), NULL, 0, NI_NAMEREQD)) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); - } else { + int r; + + NET_RESTARTABLE(r, getnameinfo(&sa.sa, len, host, sizeof(host), NULL, 0, NI_NAMEREQD), + r == EAI_SYSTEM && errno == EINTR); + + if (r == 0) { ret = (*env)->NewStringUTF(env, host); - if (ret == NULL) { - JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + if (ret != NULL) { + return ret; } } - return ret; + JNU_ThrowByName(env, "java/net/UnknownHostException", NULL); + return NULL; } /** @@ -483,7 +488,8 @@ tcp_ping6(JNIEnv *env, SOCKETADDRESS *sa, SOCKETADDRESS *netif, jint timeout, SET_NONBLOCKING(fd); sa->sa6.sin6_port = htons(7); // echo port - connect_rv = connect(fd, &sa->sa, sizeof(struct sockaddr_in6)); + NET_RESTARTABLE(connect_rv, connect(fd, &sa->sa, sizeof(struct sockaddr_in6)), + connect_rv == -1 && errno == EINTR); // connection established or refused immediately, either way it means // we were able to reach the host! @@ -604,7 +610,10 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, memcpy(sendbuf + sizeof(struct icmp6_hdr), &tv, sizeof(tv)); icmp6->icmp6_cksum = 0; // send it - n = sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in6)); + + NET_RESTARTABLE(n, sendto(fd, sendbuf, plen, 0, &sa->sa, sizeof(struct sockaddr_in6)), + n == -1 && errno == EINTR); + if (n < 0 && errno != EINPROGRESS) { #if defined(__linux__) /* @@ -628,8 +637,9 @@ ping6(JNIEnv *env, jint fd, SOCKETADDRESS *sa, SOCKETADDRESS *netif, tmout2 = NET_Wait(env, fd, NET_WAIT_READ, tmout2); if (tmout2 >= 0) { len = sizeof(sa_recv); - n = recvfrom(fd, recvbuf, sizeof(recvbuf), 0, - (struct sockaddr *)&sa_recv, &len); + NET_RESTARTABLE(n, recvfrom(fd, recvbuf, sizeof(recvbuf), 0, + (struct sockaddr *)&sa_recv, &len), + n == -1 && errno == EINTR); // check if we received enough data if (n < (jint)sizeof(struct icmp6_hdr)) { continue; diff --git a/src/java.base/unix/native/libnet/net_util_md.c b/src/java.base/unix/native/libnet/net_util_md.c index 9bb6a026961..b0915615d96 100644 --- a/src/java.base/unix/native/libnet/net_util_md.c +++ b/src/java.base/unix/native/libnet/net_util_md.c @@ -76,9 +76,6 @@ NET_ThrowNew(JNIEnv *env, int errorNumber, char *msg) { jio_snprintf(fullMsg, sizeof(fullMsg), "socket closed: %s", msg); JNU_ThrowByName(env, JNU_JAVANETPKG "SocketException", fullMsg); break; - case EINTR: - JNU_ThrowByName(env, JNU_JAVAIOPKG "InterruptedIOException", msg); - break; default: errno = errorNumber; JNU_ThrowByNameWithLastError(env, JNU_JAVANETPKG "SocketException", msg); @@ -627,11 +624,11 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) pfd.fd = fd; pfd.events = 0; if (flags & NET_WAIT_READ) - pfd.events |= POLLIN; + pfd.events |= POLLIN; if (flags & NET_WAIT_WRITE) - pfd.events |= POLLOUT; + pfd.events |= POLLOUT; if (flags & NET_WAIT_CONNECT) - pfd.events |= POLLOUT; + pfd.events |= POLLOUT; errno = 0; read_rv = poll(&pfd, 1, nanoTimeout / NET_NSEC_PER_MSEC); @@ -639,13 +636,13 @@ NET_Wait(JNIEnv *env, jint fd, jint flags, jint timeout) newNanoTime = JVM_NanoTime(env, 0); nanoTimeout -= (newNanoTime - prevNanoTime); if (nanoTimeout < NET_NSEC_PER_MSEC) { - return read_rv > 0 ? 0 : -1; + return read_rv > 0 ? 0 : -1; } prevNanoTime = newNanoTime; if (read_rv > 0) { - break; + break; } - } /* while */ + } /* while */ return (nanoTimeout / NET_NSEC_PER_MSEC); } diff --git a/src/java.base/unix/native/libnet/net_util_md.h b/src/java.base/unix/native/libnet/net_util_md.h index 902cf96732f..d6cb3250bbe 100644 --- a/src/java.base/unix/native/libnet/net_util_md.h +++ b/src/java.base/unix/native/libnet/net_util_md.h @@ -80,4 +80,17 @@ void NET_ThrowUnknownHostExceptionWithGaiError(JNIEnv *env, void NET_ThrowByNameWithLastError(JNIEnv *env, const char *name, const char *defaultDetail); +/** + * Invokes CALL in a loop, setting RET to return value. + * Invokes PREDICATE for condition to restart CALL (in loop) + * Return RET otherwise + */ +#define NET_RESTARTABLE(RET,CALL,PREDICATE) \ + while (1) { \ + RET = CALL; \ + if (!(PREDICATE)) { \ + break; \ + } \ + } + #endif /* NET_UTILS_MD_H */ From af18fbd42d2a437dd35f33e557a8906ca0c3bd07 Mon Sep 17 00:00:00 2001 From: Arno Zeller Date: Wed, 17 Dec 2025 09:08:29 +0000 Subject: [PATCH 135/211] 8371559: Intermittent timeouts in test javax/net/ssl/Stapling/HttpsUrlConnClient.java Reviewed-by: mbaesken, myankelevich --- .../net/ssl/Stapling/HttpsUrlConnClient.java | 86 +++++++++++-------- 1 file changed, 48 insertions(+), 38 deletions(-) diff --git a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java index b9829621d68..c34311f1689 100644 --- a/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java +++ b/test/jdk/javax/net/ssl/Stapling/HttpsUrlConnClient.java @@ -33,7 +33,11 @@ * @run main/othervm HttpsUrlConnClient RSASSA-PSS RSASSA-PSS */ -import java.io.*; +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; import java.math.BigInteger; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -41,7 +45,9 @@ import java.net.Socket; import java.net.URL; import java.net.HttpURLConnection; import java.net.InetAddress; + import javax.net.ssl.*; + import java.security.KeyStore; import java.security.PublicKey; import java.security.Security; @@ -55,7 +61,16 @@ import java.security.cert.X509Certificate; import java.security.cert.PKIXRevocationChecker; import java.security.spec.PKCS8EncodedKeySpec; import java.text.SimpleDateFormat; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Base64; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.TimeZone; +import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; import jdk.test.lib.security.SimpleOCSPServer; @@ -92,10 +107,6 @@ public class HttpsUrlConnClient { static String INT_ALIAS = "intermediate"; static String SSL_ALIAS = "ssl"; - /* - * Is the server ready to serve? - */ - volatile static boolean serverReady = false; volatile int serverPort = 0; volatile Exception serverException = null; @@ -164,7 +175,7 @@ public class HttpsUrlConnClient { ClientParameters cliParams = new ClientParameters(); cliParams.protocols = allowedProts; ServerParameters servParams = new ServerParameters(); - serverReady = false; + CountDownLatch serverReady = new CountDownLatch(1); System.out.println("====================================="); System.out.println("Stapling enabled, PKIXParameters with"); @@ -192,7 +203,7 @@ public class HttpsUrlConnClient { Security.setProperty("ocsp.enable", "false"); HttpsUrlConnClient sslTest = new HttpsUrlConnClient(cliParams, - servParams); + servParams, serverReady); TestResult tr = sslTest.getResult(); if (!checkClientValidationFailure(tr.clientExc, BasicReason.REVOKED)) { if (tr.clientExc != null) { @@ -219,10 +230,11 @@ public class HttpsUrlConnClient { /* * Define the server side of the test. * - * If the server prematurely exits, serverReady will be set to true + * If the server prematurely exits, serverReady will be counted down * to avoid infinite hangs. */ - void doServerSide(ServerParameters servParams) throws Exception { + void doServerSide(ServerParameters servParams, CountDownLatch serverReady) + throws Exception { // Selectively enable or disable the feature System.setProperty("jdk.tls.server.enableStatusRequestExtension", @@ -274,7 +286,7 @@ public class HttpsUrlConnClient { /* * Signal Client, we're ready for his connect. */ - serverReady = true; + serverReady.countDown(); try (SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept(); BufferedReader in = new BufferedReader( @@ -306,18 +318,13 @@ public class HttpsUrlConnClient { /* * Define the client side of the test. * - * If the server prematurely exits, serverReady will be set to true + * If the server prematurely exits, serverReady will be counted down * to avoid infinite hangs. */ - void doClientSide(ClientParameters cliParams) throws Exception { + void doClientSide(ClientParameters cliParams, CountDownLatch serverReady) + throws Exception { - // Wait 5 seconds for server ready - for (int i = 0; (i < 100 && !serverReady); i++) { - Thread.sleep(50); - } - if (!serverReady) { - throw new RuntimeException("Server not ready yet"); - } + serverReady.await(); // Selectively enable or disable the feature System.setProperty("jdk.tls.client.enableStatusRequestExtension", @@ -373,16 +380,16 @@ public class HttpsUrlConnClient { * * Fork off the other side, then do your work. */ - HttpsUrlConnClient(ClientParameters cliParams, - ServerParameters servParams) throws Exception { + HttpsUrlConnClient(ClientParameters cliParams, ServerParameters servParams, + CountDownLatch serverReady) throws Exception { Exception startException = null; try { if (separateServerThread) { - startServer(servParams, true); - startClient(cliParams, false); + startServer(servParams, true, serverReady); + startClient(cliParams, false, serverReady); } else { - startClient(cliParams, true); - startServer(servParams, false); + startClient(cliParams, true, serverReady); + startServer(servParams, false, serverReady); } } catch (Exception e) { startException = e; @@ -453,51 +460,53 @@ public class HttpsUrlConnClient { return tr; } - final void startServer(ServerParameters servParams, boolean newThread) - throws Exception { + final void startServer(ServerParameters servParams, boolean newThread, + CountDownLatch serverReady) throws IOException { if (newThread) { serverThread = new Thread() { @Override public void run() { try { - doServerSide(servParams); + doServerSide(servParams, serverReady); } catch (Exception e) { /* * Our server thread just died. * * Release the client, if not active already... */ - System.err.println("Server died..."); - serverReady = true; + System.err.println("Server died: " + e); serverException = e; + } finally { + serverReady.countDown(); } } }; serverThread.start(); } else { try { - doServerSide(servParams); + doServerSide(servParams, serverReady); } catch (Exception e) { + System.err.println("Server died: " + e); serverException = e; } finally { - serverReady = true; + serverReady.countDown(); } } } - final void startClient(ClientParameters cliParams, boolean newThread) - throws Exception { + final void startClient(ClientParameters cliParams, boolean newThread, + CountDownLatch serverReady) throws Exception { if (newThread) { clientThread = new Thread() { @Override public void run() { try { - doClientSide(cliParams); + doClientSide(cliParams, serverReady); } catch (Exception e) { /* * Our client thread just died. */ - System.err.println("Client died..."); + System.err.println("Client died: " + e); clientException = e; } } @@ -505,9 +514,10 @@ public class HttpsUrlConnClient { clientThread.start(); } else { try { - doClientSide(cliParams); + doClientSide(cliParams, serverReady); } catch (Exception e) { clientException = e; + System.err.println("Client died: " + e); } } } From fc76403b01c4e801f2a58810deeec2a6ebfa8458 Mon Sep 17 00:00:00 2001 From: Raffaello Giulietti Date: Wed, 17 Dec 2025 09:20:48 +0000 Subject: [PATCH 136/211] 8373798: Refactor java/math tests to use JUnit Reviewed-by: darcy --- .../jdk/java/math/BigDecimal/Constructor.java | 56 +++++--- .../math/BigInteger/LargeValueExceptions.java | 134 ++++++++++-------- 2 files changed, 111 insertions(+), 79 deletions(-) diff --git a/test/jdk/java/math/BigDecimal/Constructor.java b/test/jdk/java/math/BigDecimal/Constructor.java index b7371074225..975d96772a6 100644 --- a/test/jdk/java/math/BigDecimal/Constructor.java +++ b/test/jdk/java/math/BigDecimal/Constructor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2025, 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 @@ -26,45 +26,57 @@ * @bug 4259453 8200698 * @summary Test constructors of BigDecimal * @library .. - * @run testng Constructor + * @run junit Constructor */ +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + import java.math.BigDecimal; -import org.testng.annotations.Test; public class Constructor { - @Test(expectedExceptions=NumberFormatException.class) + @Test public void stringConstructor() { - BigDecimal bd = new BigDecimal("1.2e"); + Assertions.assertThrows(NumberFormatException.class, () -> { + BigDecimal bd = new BigDecimal("1.2e"); + }); } - @Test(expectedExceptions=NumberFormatException.class) + @Test public void charArrayConstructorNegativeOffset() { - BigDecimal bd = new BigDecimal(new char[5], -1, 4, null); + Assertions.assertThrows(NumberFormatException.class, () -> { + BigDecimal bd = new BigDecimal(new char[5], -1, 4, null); + }); } - @Test(expectedExceptions=NumberFormatException.class) + @Test public void charArrayConstructorNegativeLength() { - BigDecimal bd = new BigDecimal(new char[5], 0, -1, null); + Assertions.assertThrows(NumberFormatException.class, () -> { + BigDecimal bd = new BigDecimal(new char[5], 0, -1, null); + }); } - @Test(expectedExceptions=NumberFormatException.class) + @Test public void charArrayConstructorIntegerOverflow() { - try { - BigDecimal bd = new BigDecimal(new char[5], Integer.MAX_VALUE - 5, - 6, null); - } catch (NumberFormatException nfe) { - if (nfe.getCause() instanceof IndexOutOfBoundsException) { - throw new RuntimeException - ("NumberFormatException should not have a cause"); - } else { - throw nfe; + Assertions.assertThrows(NumberFormatException.class, () -> { + try { + BigDecimal bd = new BigDecimal(new char[5], Integer.MAX_VALUE - 5, + 6, null); + } catch (NumberFormatException nfe) { + if (nfe.getCause() instanceof IndexOutOfBoundsException) { + throw new RuntimeException + ("NumberFormatException should not have a cause"); + } else { + throw nfe; + } } - } + }); } - @Test(expectedExceptions=NumberFormatException.class) + @Test public void charArrayConstructorIndexOutOfBounds() { - BigDecimal bd = new BigDecimal(new char[5], 1, 5, null); + Assertions.assertThrows(NumberFormatException.class, () -> { + BigDecimal bd = new BigDecimal(new char[5], 1, 5, null); + }); } } diff --git a/test/jdk/java/math/BigInteger/LargeValueExceptions.java b/test/jdk/java/math/BigInteger/LargeValueExceptions.java index 4c85281a5c0..9670691e51c 100644 --- a/test/jdk/java/math/BigInteger/LargeValueExceptions.java +++ b/test/jdk/java/math/BigInteger/LargeValueExceptions.java @@ -26,13 +26,16 @@ * @bug 8200698 * @summary Tests that exceptions are thrown for ops which would overflow * @requires (sun.arch.data.model == "64" & os.maxMemory >= 4g) - * @run testng/othervm/timeout=480 -Xmx4g LargeValueExceptions + * @run junit/othervm/timeout=480 -Xmx4g LargeValueExceptions */ + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + import java.math.BigInteger; + import static java.math.BigInteger.ONE; -import org.testng.ITestResult; -import org.testng.annotations.AfterMethod; -import org.testng.annotations.Test; // // The intent of this test is to probe the boundaries between overflow and @@ -64,47 +67,48 @@ public class LargeValueExceptions { // Half BigInteger.MAX_MAG_LENGTH private static final int MAX_INTS_HALF = MAX_INTS / 2; - // Print the run time of each sub-test in milliseconds - @AfterMethod - public void getRunTime(ITestResult tr) { - long time = tr.getEndMillis() - tr.getStartMillis(); - System.out.printf("Run time: %d ms%n", time); - } - // --- squaring --- // Largest no overflow determined by examining data lengths alone. - @Test(enabled=false) + @Test + @Disabled public void squareNoOverflow() { BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1).subtract(ONE); BigInteger y = x.multiply(x); } // Smallest no overflow determined by extra calculations. - @Test(enabled=false) + @Test + @Disabled public void squareIndefiniteOverflowSuccess() { BigInteger x = ONE.shiftLeft(16*MAX_INTS - 1); BigInteger y = x.multiply(x); } // Largest overflow detected by extra calculations. - @Test(expectedExceptions=ArithmeticException.class,enabled=false) + @Test + @Disabled public void squareIndefiniteOverflowFailure() { - BigInteger x = ONE.shiftLeft(16*MAX_INTS).subtract(ONE); - BigInteger y = x.multiply(x); + Assertions.assertThrows(ArithmeticException.class, () -> { + BigInteger x = ONE.shiftLeft(16*MAX_INTS).subtract(ONE); + BigInteger y = x.multiply(x); + }); } // Smallest overflow detected by examining data lengths alone. - @Test(expectedExceptions=ArithmeticException.class) + @Test public void squareDefiniteOverflow() { - BigInteger x = ONE.shiftLeft(16*MAX_INTS); - BigInteger y = x.multiply(x); + Assertions.assertThrows(ArithmeticException.class, () -> { + BigInteger x = ONE.shiftLeft(16*MAX_INTS); + BigInteger y = x.multiply(x); + }); } // --- multiplication --- // Largest no overflow determined by examining data lengths alone. - @Test(enabled=false) + @Test + @Disabled public void multiplyNoOverflow() { final int halfMaxBits = MAX_INTS_HALF << 5; @@ -114,7 +118,8 @@ public class LargeValueExceptions { } // Smallest no overflow determined by extra calculations. - @Test(enabled=false) + @Test + @Disabled public void multiplyIndefiniteOverflowSuccess() { BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2) - 1); long m = MAX_BITS - x.bitLength(); @@ -130,68 +135,83 @@ public class LargeValueExceptions { } // Largest overflow detected by extra calculations. - @Test(expectedExceptions=ArithmeticException.class,enabled=false) + @Test + @Disabled public void multiplyIndefiniteOverflowFailure() { - BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); - long m = MAX_BITS - x.bitLength(); + Assertions.assertThrows(ArithmeticException.class, () -> { + BigInteger x = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); + long m = MAX_BITS - x.bitLength(); - BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); - long n = MAX_BITS - y.bitLength(); + BigInteger y = ONE.shiftLeft((int)(MAX_BITS/2)).subtract(ONE); + long n = MAX_BITS - y.bitLength(); - if (m + n != MAX_BITS) { - throw new RuntimeException("Unexpected leading zero sum"); - } + if (m + n != MAX_BITS) { + throw new RuntimeException("Unexpected leading zero sum"); + } - BigInteger z = x.multiply(y); + BigInteger z = x.multiply(y); + }); } // Smallest overflow detected by examining data lengths alone. - @Test(expectedExceptions=ArithmeticException.class) + @Test public void multiplyDefiniteOverflow() { - // multiply by 4 as MAX_INTS_HALF refers to ints - byte[] xmag = new byte[4*MAX_INTS_HALF]; - xmag[0] = (byte)0xff; - BigInteger x = new BigInteger(1, xmag); + Assertions.assertThrows(ArithmeticException.class, () -> { + // multiply by 4 as MAX_INTS_HALF refers to ints + byte[] xmag = new byte[4*MAX_INTS_HALF]; + xmag[0] = (byte)0xff; + BigInteger x = new BigInteger(1, xmag); - byte[] ymag = new byte[4*MAX_INTS_HALF + 1]; - ymag[0] = (byte)0xff; - BigInteger y = new BigInteger(1, ymag); + byte[] ymag = new byte[4*MAX_INTS_HALF + 1]; + ymag[0] = (byte)0xff; + BigInteger y = new BigInteger(1, ymag); - BigInteger z = x.multiply(y); + BigInteger z = x.multiply(y); + }); } // --- exponentiation --- - @Test(expectedExceptions=ArithmeticException.class) + @Test public void powOverflow() { - BigInteger.TEN.pow(Integer.MAX_VALUE); + Assertions.assertThrows(ArithmeticException.class, () -> { + BigInteger.TEN.pow(Integer.MAX_VALUE); + }); } - @Test(expectedExceptions=ArithmeticException.class) + @Test public void powOverflow1() { - int shift = 20; - int exponent = 1 << shift; - BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)); - BigInteger y = x.pow(exponent); + Assertions.assertThrows(ArithmeticException.class, () -> { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)); + BigInteger y = x.pow(exponent); + }); } - @Test(expectedExceptions=ArithmeticException.class) + @Test public void powOverflow2() { - int shift = 20; - int exponent = 1 << shift; - BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).add(ONE); - BigInteger y = x.pow(exponent); + Assertions.assertThrows(ArithmeticException.class, () -> { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).add(ONE); + BigInteger y = x.pow(exponent); + }); } - @Test(expectedExceptions=ArithmeticException.class,enabled=false) + @Test + @Disabled public void powOverflow3() { - int shift = 20; - int exponent = 1 << shift; - BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).subtract(ONE); - BigInteger y = x.pow(exponent); + Assertions.assertThrows(ArithmeticException.class, () -> { + int shift = 20; + int exponent = 1 << shift; + BigInteger x = ONE.shiftLeft((int)(MAX_BITS / exponent)).subtract(ONE); + BigInteger y = x.pow(exponent); + }); } - @Test(enabled=false) + @Test + @Disabled public void powOverflow4() { int shift = 20; int exponent = 1 << shift; From 9a23f8aa337e1292179625ce9bb8abe22c9e22e2 Mon Sep 17 00:00:00 2001 From: Aggelos Biboudis Date: Wed, 17 Dec 2025 10:31:23 +0000 Subject: [PATCH 137/211] 8373552: ExactConversionsSupport: bad JLS links in javadoc Reviewed-by: liach, iris --- .../java/lang/runtime/ExactConversionsSupport.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/lang/runtime/ExactConversionsSupport.java b/src/java.base/share/classes/java/lang/runtime/ExactConversionsSupport.java index 6e17a4b85a0..b86891749da 100644 --- a/src/java.base/share/classes/java/lang/runtime/ExactConversionsSupport.java +++ b/src/java.base/share/classes/java/lang/runtime/ExactConversionsSupport.java @@ -64,9 +64,12 @@ package java.lang.runtime; * floating-point type is considered exact. * * - * @jls 5.7.1 Exact Testing Conversions - * @jls 5.7.2 Unconditionally Exact Testing Conversions - * @jls 15.20.2 The instanceof Operator + * @see + * JLS 5.7.1 Exact Testing Conversions + * @see + * JLS 5.7.2 Unconditionally Exact Testing Conversions + * @see + * JLS 15.20.2 The instanceof Operator * * @implNote Some exactness checks describe a test which can be redirected * safely through one of the existing methods. Those are omitted too (i.e., From e4636d69e7e41477619a163e97fd3af2e5942dde Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Wed, 17 Dec 2025 11:17:39 +0000 Subject: [PATCH 138/211] 8373420: C2: Add true/false_proj*() methods for IfNode as a replacement for proj_out*(true/false) Reviewed-by: dfenacci, roland, epeter --- src/hotspot/share/opto/castnode.cpp | 7 +++---- src/hotspot/share/opto/castnode.hpp | 2 +- src/hotspot/share/opto/cfgnode.hpp | 22 ++++++++++++++++++++-- src/hotspot/share/opto/ifnode.cpp | 16 +++++++++------- src/hotspot/share/opto/loopTransform.cpp | 18 ++++++++---------- src/hotspot/share/opto/loopUnswitch.cpp | 2 +- src/hotspot/share/opto/loopnode.cpp | 17 ++++++++--------- src/hotspot/share/opto/loopnode.hpp | 2 +- src/hotspot/share/opto/loopopts.cpp | 16 ++++++++-------- src/hotspot/share/opto/macro.cpp | 4 ++-- src/hotspot/share/opto/stringopts.cpp | 2 +- 11 files changed, 62 insertions(+), 46 deletions(-) diff --git a/src/hotspot/share/opto/castnode.cpp b/src/hotspot/share/opto/castnode.cpp index 9c764f22e38..998b6a79903 100644 --- a/src/hotspot/share/opto/castnode.cpp +++ b/src/hotspot/share/opto/castnode.cpp @@ -313,8 +313,7 @@ void CastIINode::remove_range_check_cast(Compile* C) { } } - -bool CastLLNode::is_inner_loop_backedge(ProjNode* proj) { +bool CastLLNode::is_inner_loop_backedge(IfProjNode* proj) { if (proj != nullptr) { Node* ctrl_use = proj->unique_ctrl_out_or_null(); if (ctrl_use != nullptr && ctrl_use->Opcode() == Op_Loop && @@ -333,8 +332,8 @@ bool CastLLNode::cmp_used_at_inner_loop_exit_test(CmpNode* cmp) { for (DUIterator_Fast jmax, j = bol->fast_outs(jmax); j < jmax; j++) { Node* iff = bol->fast_out(j); if (iff->Opcode() == Op_If) { - ProjNode* true_proj = iff->as_If()->proj_out_or_null(true); - ProjNode* false_proj = iff->as_If()->proj_out_or_null(false); + IfTrueNode* true_proj = iff->as_If()->true_proj_or_null(); + IfFalseNode* false_proj = iff->as_If()->false_proj_or_null(); if (is_inner_loop_backedge(true_proj) || is_inner_loop_backedge(false_proj)) { return true; } diff --git a/src/hotspot/share/opto/castnode.hpp b/src/hotspot/share/opto/castnode.hpp index 2ff13e44780..f22df546f41 100644 --- a/src/hotspot/share/opto/castnode.hpp +++ b/src/hotspot/share/opto/castnode.hpp @@ -239,7 +239,7 @@ public: init_class_id(Class_CastLL); } - static bool is_inner_loop_backedge(ProjNode* proj); + static bool is_inner_loop_backedge(IfProjNode* proj); static bool cmp_used_at_inner_loop_exit_test(CmpNode* cmp); bool used_at_inner_loop_exit_test() const; diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index ef799f4c39a..5f7f4790443 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -354,7 +354,7 @@ class IfNode : public MultiBranchNode { static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc); protected: - ProjNode* range_check_trap_proj(int& flip, Node*& l, Node*& r); + IfProjNode* range_check_trap_proj(int& flip, Node*& l, Node*& r) const; Node* Ideal_common(PhaseGVN *phase, bool can_reshape); Node* search_identical(int dist, PhaseIterGVN* igvn); @@ -433,6 +433,24 @@ public: static IfNode* make_with_same_profile(IfNode* if_node_profile, Node* ctrl, Node* bol); + IfTrueNode* true_proj() const { + return proj_out(true)->as_IfTrue(); + } + + IfTrueNode* true_proj_or_null() const { + ProjNode* true_proj = proj_out_or_null(true); + return true_proj == nullptr ? nullptr : true_proj->as_IfTrue(); + } + + IfFalseNode* false_proj() const { + return proj_out(false)->as_IfFalse(); + } + + IfFalseNode* false_proj_or_null() const { + ProjNode* false_proj = proj_out_or_null(false); + return false_proj == nullptr ? nullptr : false_proj->as_IfFalse(); + } + virtual int Opcode() const; virtual bool pinned() const { return true; } virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } @@ -523,7 +541,7 @@ class ParsePredicateNode : public IfNode { // Return the uncommon trap If projection of this Parse Predicate. ParsePredicateUncommonProj* uncommon_proj() const { - return proj_out(0)->as_IfFalse(); + return false_proj(); } Node* uncommon_trap() const; diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 83e975b95a2..763888b65b2 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -487,7 +487,7 @@ IfNode* IfNode::make_with_same_profile(IfNode* if_node_profile, Node* ctrl, Node // if this IfNode follows a range check pattern return the projection // for the failed path -ProjNode* IfNode::range_check_trap_proj(int& flip_test, Node*& l, Node*& r) { +IfProjNode* IfNode::range_check_trap_proj(int& flip_test, Node*& l, Node*& r) const { if (outcnt() != 2) { return nullptr; } @@ -515,8 +515,10 @@ ProjNode* IfNode::range_check_trap_proj(int& flip_test, Node*& l, Node*& r) { // Flip 1: If (Bool[<] CmpU(l, LoadRange)) ... // Flip 2: If (Bool[<=] CmpU(LoadRange, l)) ... - ProjNode* iftrap = proj_out_or_null(flip_test == 2 ? true : false); - return iftrap; + if (flip_test == 2) { + return true_proj_or_null(); + } + return false_proj_or_null(); } @@ -528,7 +530,7 @@ int RangeCheckNode::is_range_check(Node* &range, Node* &index, jint &offset) { int flip_test = 0; Node* l = nullptr; Node* r = nullptr; - ProjNode* iftrap = range_check_trap_proj(flip_test, l, r); + IfProjNode* iftrap = range_check_trap_proj(flip_test, l, r); if (iftrap == nullptr) { return 0; @@ -1875,8 +1877,8 @@ static IfNode* idealize_test(PhaseGVN* phase, IfNode* iff) { assert(iff->in(0) != nullptr, "If must be live"); if (iff->outcnt() != 2) return nullptr; // Malformed projections. - Node* old_if_f = iff->proj_out(false); - Node* old_if_t = iff->proj_out(true); + IfFalseNode* old_if_f = iff->false_proj(); + IfTrueNode* old_if_t = iff->true_proj(); // CountedLoopEnds want the back-control test to be TRUE, regardless of // whether they are testing a 'gt' or 'lt' condition. The 'gt' condition @@ -2192,7 +2194,7 @@ void ParsePredicateNode::mark_useless(PhaseIterGVN& igvn) { } Node* ParsePredicateNode::uncommon_trap() const { - ParsePredicateUncommonProj* uncommon_proj = proj_out(0)->as_IfFalse(); + ParsePredicateUncommonProj* uncommon_proj = false_proj(); Node* uct_region_or_call = uncommon_proj->unique_ctrl_out(); assert(uct_region_or_call->is_Region() || uct_region_or_call->is_Call(), "must be a region or call uct"); return uct_region_or_call; diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index 41bce0fe9b5..fdb3ab89b82 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -87,7 +87,7 @@ void IdealLoopTree::record_for_igvn() { Node* outer_safepoint = l->outer_safepoint(); assert(outer_safepoint != nullptr, "missing piece of strip mined loop"); _phase->_igvn._worklist.push(outer_safepoint); - Node* cle_out = _head->as_CountedLoop()->loopexit()->proj_out(false); + IfFalseNode* cle_out = _head->as_CountedLoop()->loopexit()->false_proj(); assert(cle_out != nullptr, "missing piece of strip mined loop"); _phase->_igvn._worklist.push(cle_out); } @@ -1464,9 +1464,8 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n pre_end->_prob = PROB_FAIR; // Find the pre-loop normal exit. - Node* pre_exit = pre_end->proj_out(false); - assert(pre_exit->Opcode() == Op_IfFalse, ""); - IfFalseNode *new_pre_exit = new IfFalseNode(pre_end); + IfFalseNode* pre_exit = pre_end->false_proj(); + IfFalseNode* new_pre_exit = new IfFalseNode(pre_end); _igvn.register_new_node_with_optimizer(new_pre_exit); set_idom(new_pre_exit, pre_end, dd_main_head); set_loop(new_pre_exit, outer_loop->_parent); @@ -1707,8 +1706,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new, //------------------------------ // Step A: Create a new post-Loop. - Node* main_exit = outer_main_end->proj_out(false); - assert(main_exit->Opcode() == Op_IfFalse, ""); + IfFalseNode* main_exit = outer_main_end->false_proj(); int dd_main_exit = dom_depth(main_exit); // Step A1: Clone the loop body of main. The clone becomes the post-loop. @@ -1721,7 +1719,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new, post_head->set_post_loop(main_head); // clone_loop() above changes the exit projection - main_exit = outer_main_end->proj_out(false); + main_exit = outer_main_end->false_proj(); // Reduce the post-loop trip count. CountedLoopEndNode* post_end = old_new[main_end->_idx]->as_CountedLoopEnd(); @@ -1786,7 +1784,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new, // right after the execution of the inner CountedLoop. // We have to make sure that such stores in the post loop have the right memory inputs from the main loop // The moved store node is always attached right after the inner loop exit, and just before the safepoint - const Node* if_false = main_end->proj_out(false); + const IfFalseNode* if_false = main_end->false_proj(); for (DUIterator j = if_false->outs(); if_false->has_out(j); j++) { Node* store = if_false->out(j); if (store->is_Store()) { @@ -3944,7 +3942,7 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { return false; } - Node* exit = head->loopexit()->proj_out_or_null(0); + IfFalseNode* exit = head->loopexit()->false_proj_or_null(); if (exit == nullptr) { return false; } @@ -3988,7 +3986,7 @@ bool PhaseIdealLoop::intrinsify_fill(IdealLoopTree* lpt) { // If the store is on the backedge, it is not executed in the last // iteration, and we must subtract 1 from the len. - Node* backedge = head->loopexit()->proj_out(1); + IfTrueNode* backedge = head->loopexit()->true_proj(); if (store->in(0) == backedge) { len = new SubINode(len, _igvn.intcon(1)); _igvn.register_new_node_with_optimizer(len); diff --git a/src/hotspot/share/opto/loopUnswitch.cpp b/src/hotspot/share/opto/loopUnswitch.cpp index 287f8354dc1..cc83bdda561 100644 --- a/src/hotspot/share/opto/loopUnswitch.cpp +++ b/src/hotspot/share/opto/loopUnswitch.cpp @@ -488,7 +488,7 @@ IfTrueNode* PhaseIdealLoop::create_new_if_for_multiversion(IfTrueNode* multivers IfNode* multiversion_if = multiversioning_fast_proj->in(0)->as_If(); Node* entry = multiversion_if->in(0); OpaqueMultiversioningNode* opaque = multiversion_if->in(1)->as_OpaqueMultiversioning(); - IfFalseNode* multiversion_slow_proj = multiversion_if->proj_out(0)->as_IfFalse(); + IfFalseNode* multiversion_slow_proj = multiversion_if->false_proj(); Node* slow_path = multiversion_slow_proj->unique_ctrl_out(); // The slow_loop may still be delayed, and waiting for runtime-checks to be added to the diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 42d3ee105f8..dacc1a1a734 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -79,11 +79,10 @@ bool LoopNode::is_valid_counted_loop(BasicType bt) const { BaseCountedLoopNode* l = as_BaseCountedLoop(); BaseCountedLoopEndNode* le = l->loopexit_or_null(); if (le != nullptr && - le->proj_out_or_null(1 /* true */) == l->in(LoopNode::LoopBackControl)) { + le->true_proj_or_null() == l->in(LoopNode::LoopBackControl)) { Node* phi = l->phi(); - Node* exit = le->proj_out_or_null(0 /* false */); - if (exit != nullptr && exit->Opcode() == Op_IfFalse && - phi != nullptr && phi->is_Phi() && + IfFalseNode* exit = le->false_proj_or_null(); + if (exit != nullptr && phi != nullptr && phi->is_Phi() && phi->in(LoopNode::LoopBackControl) == l->incr() && le->loopnode() == l && le->stride_is_con()) { return true; @@ -942,7 +941,7 @@ bool PhaseIdealLoop::create_loop_nest(IdealLoopTree* loop, Node_List &old_new) { safepoint = find_safepoint(back_control, x, loop); } - Node* exit_branch = exit_test->proj_out(false); + IfFalseNode* exit_branch = exit_test->false_proj(); Node* entry_control = head->in(LoopNode::EntryControl); // Clone the control flow of the loop to build an outer loop @@ -3087,7 +3086,7 @@ IfFalseNode* OuterStripMinedLoopNode::outer_loop_exit() const { if (le == nullptr) { return nullptr; } - Node* c = le->proj_out_or_null(false); + IfFalseNode* c = le->false_proj_or_null(); if (c == nullptr) { return nullptr; } @@ -3407,7 +3406,7 @@ void OuterStripMinedLoopNode::adjust_strip_mined_loop(PhaseIterGVN* igvn) { return; } - Node* cle_tail = inner_cle->proj_out(true); + IfTrueNode* cle_tail = inner_cle->true_proj(); ResourceMark rm; Node_List old_new; if (cle_tail->outcnt() > 1) { @@ -3549,7 +3548,7 @@ void OuterStripMinedLoopNode::transform_to_counted_loop(PhaseIterGVN* igvn, Phas iloop->replace_node_and_forward_ctrl(outer_le, new_end); } // the backedge of the inner loop must be rewired to the new loop end - Node* backedge = cle->proj_out(true); + IfTrueNode* backedge = cle->true_proj(); igvn->replace_input_of(backedge, 0, new_end); if (iloop != nullptr) { iloop->set_idom(backedge, new_end, iloop->dom_depth(new_end) + 1); @@ -3630,7 +3629,7 @@ const Type* OuterStripMinedLoopEndNode::Value(PhaseGVN* phase) const { bool OuterStripMinedLoopEndNode::is_expanded(PhaseGVN *phase) const { // The outer strip mined loop head only has Phi uses after expansion if (phase->is_IterGVN()) { - Node* backedge = proj_out_or_null(true); + IfTrueNode* backedge = true_proj_or_null(); if (backedge != nullptr) { Node* head = backedge->unique_ctrl_out_or_null(); if (head != nullptr && head->is_OuterStripMinedLoop()) { diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index 3b97d76773f..ffc283ac941 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -607,7 +607,7 @@ public: virtual SafePointNode* outer_safepoint() const; CountedLoopNode* inner_counted_loop() const { return unique_ctrl_out()->as_CountedLoop(); } CountedLoopEndNode* inner_counted_loop_end() const { return inner_counted_loop()->loopexit(); } - IfFalseNode* inner_loop_exit() const { return inner_counted_loop_end()->proj_out(false)->as_IfFalse(); } + IfFalseNode* inner_loop_exit() const { return inner_counted_loop_end()->false_proj(); } void adjust_strip_mined_loop(PhaseIterGVN* igvn); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index b1422d5db20..8f85b7f270e 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1321,8 +1321,8 @@ bool PhaseIdealLoop::identical_backtoback_ifs(Node *n) { return false; } IfNode* dom_if = dom->as_If(); - Node* proj_true = dom_if->proj_out(1); - Node* proj_false = dom_if->proj_out(0); + IfTrueNode* proj_true = dom_if->true_proj(); + IfFalseNode* proj_false = dom_if->false_proj(); for (uint i = 1; i < region->req(); i++) { if (is_dominator(proj_true, region->in(i))) { @@ -1585,8 +1585,8 @@ bool PhaseIdealLoop::try_merge_identical_ifs(Node* n) { dom_if->in(1)->in(1)->as_SubTypeCheck()->method() != nullptr), "only for subtype checks with profile data attached"); _igvn.replace_input_of(n, 1, dom_if->in(1)); } - ProjNode* dom_proj_true = dom_if->proj_out(1); - ProjNode* dom_proj_false = dom_if->proj_out(0); + IfTrueNode* dom_proj_true = dom_if->true_proj(); + IfFalseNode* dom_proj_false = dom_if->false_proj(); // Now split the IF RegionNode* new_false_region; @@ -1630,10 +1630,10 @@ bool PhaseIdealLoop::try_merge_identical_ifs(Node* n) { // unrelated control dependency. for (uint i = 1; i < new_false_region->req(); i++) { if (is_dominator(dom_proj_true, new_false_region->in(i))) { - dominated_by(dom_proj_true->as_IfProj(), new_false_region->in(i)->in(0)->as_If()); + dominated_by(dom_proj_true, new_false_region->in(i)->in(0)->as_If()); } else { assert(is_dominator(dom_proj_false, new_false_region->in(i)), "bad if"); - dominated_by(dom_proj_false->as_IfProj(), new_false_region->in(i)->in(0)->as_If()); + dominated_by(dom_proj_false, new_false_region->in(i)->in(0)->as_If()); } } return true; @@ -2394,7 +2394,7 @@ void PhaseIdealLoop::clone_outer_loop(LoopNode* head, CloneLoopMode mode, IdealL CountedLoopEndNode* cle = cl->loopexit(); CountedLoopNode* new_cl = old_new[cl->_idx]->as_CountedLoop(); CountedLoopEndNode* new_cle = new_cl->as_CountedLoop()->loopexit_or_null(); - Node* cle_out = cle->proj_out(false); + IfFalseNode* cle_out = cle->false_proj(); Node* new_sfpt = nullptr; Node* new_cle_out = cle_out->clone(); @@ -2691,7 +2691,7 @@ void PhaseIdealLoop::fix_ctrl_uses(const Node_List& body, const IdealLoopTree* l if (use->in(0) == cle) { IfFalseNode* cle_out = use->as_IfFalse(); IfNode* le = cl->outer_loop_end(); - use = le->proj_out(false); + use = le->false_proj(); use_loop = get_loop(use); if (mode == CloneIncludesStripMined) { nnn = old_new[le->_idx]; diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index bc07f937f1e..80818a4ddc7 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2379,8 +2379,8 @@ void PhaseMacroExpand::expand_subtypecheck_node(SubTypeCheckNode *check) { continue; } - Node* iftrue = iff->as_If()->proj_out(1); - Node* iffalse = iff->as_If()->proj_out(0); + IfTrueNode* iftrue = iff->as_If()->true_proj(); + IfFalseNode* iffalse = iff->as_If()->false_proj(); Node* ctrl = iff->in(0); Node* subklass = nullptr; diff --git a/src/hotspot/share/opto/stringopts.cpp b/src/hotspot/share/opto/stringopts.cpp index 6b98c4ca2b0..e499ba932e1 100644 --- a/src/hotspot/share/opto/stringopts.cpp +++ b/src/hotspot/share/opto/stringopts.cpp @@ -255,7 +255,7 @@ void StringConcat::eliminate_unneeded_control() { Compile* C = _stringopts->C; C->gvn_replace_by(n, n->in(0)->in(0)); // get rid of the other projection - C->gvn_replace_by(n->in(0)->as_If()->proj_out(false), C->top()); + C->gvn_replace_by(n->in(0)->as_If()->false_proj(), C->top()); } else if (n->is_Region()) { Node* iff = n->in(1)->in(0); assert(n->req() == 3 && n->in(2)->in(0) == iff, "not a diamond"); From 5e7ae281326ca306339aaba101d4206dffdb9ca0 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 17 Dec 2025 12:13:58 +0000 Subject: [PATCH 139/211] 8373677: Clear text HttpServer connection could fail fast if receiving SSL ClientHello Reviewed-by: jpai, djelinski --- .../classes/sun/net/httpserver/Request.java | 37 +++- .../sun/net/httpserver/ServerImpl.java | 12 +- .../net/httpserver/ClearTextServerSSL.java | 159 ++++++++++++++++++ 3 files changed, 206 insertions(+), 2 deletions(-) create mode 100644 test/jdk/com/sun/net/httpserver/ClearTextServerSSL.java diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java index 4a4afc8d7ce..75eeb29f015 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/Request.java @@ -25,6 +25,7 @@ package sun.net.httpserver; +import java.net.ProtocolException; import java.nio.*; import java.io.*; import java.nio.channels.*; @@ -39,15 +40,18 @@ class Request { static final int BUF_LEN = 2048; static final byte CR = 13; static final byte LF = 10; + static final byte FIRST_CHAR = 32; private String startLine; private SocketChannel chan; private InputStream is; private OutputStream os; private final int maxReqHeaderSize; + private final boolean firstClearRequest; - Request(InputStream rawInputStream, OutputStream rawout) throws IOException { + Request(InputStream rawInputStream, OutputStream rawout, boolean firstClearRequest) throws IOException { this.maxReqHeaderSize = ServerConfig.getMaxReqHeaderSize(); + this.firstClearRequest = firstClearRequest; is = rawInputStream; os = rawout; do { @@ -78,6 +82,25 @@ class Request { boolean gotCR = false, gotLF = false; pos = 0; lineBuf = new StringBuffer(); long lsize = 32; + + // For the first request that comes on a clear connection + // we will check that the first non CR/LF char on the + // request line is eligible. This should be the first char + // of a method name, so it should be at least greater or equal + // to 32 (FIRST_CHAR) which is the space character. + // The main goal here is to fail fast if we receive 0x16 (22) which + // happens to be the first byte of a TLS handshake record. + // This is typically what would be received if a TLS client opened + // a TLS connection on a non-TLS server. + // If we receive 0x16 we should close the connection immediately as + // it indicates we're receiving a ClientHello on a clear + // connection, and we will never receive the expected CRLF that + // terminates the first request line. + // Though we could check only for 0x16, any characters < 32 + // (excluding CRLF) is not expected at this position in a + // request line, so we can still fail here early if any of + // those are detected. + int offset = 0; while (!gotLF) { int c = is.read(); if (c == -1) { @@ -89,6 +112,12 @@ class Request { } else { gotCR = false; consume(CR); + if (firstClearRequest && offset == 0) { + if (c < FIRST_CHAR) { + throw new ProtocolException("Unexpected start of request line"); + } + offset++; + } consume(c); lsize = lsize + 2; } @@ -96,6 +125,12 @@ class Request { if (c == CR) { gotCR = true; } else { + if (firstClearRequest && offset == 0) { + if (c < FIRST_CHAR) { + throw new ProtocolException("Unexpected start of request line"); + } + offset++; + } consume(c); lsize = lsize + 1; } diff --git a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java index 1eb918b4e66..e8c8d336e03 100644 --- a/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java +++ b/src/jdk.httpserver/share/classes/sun/net/httpserver/ServerImpl.java @@ -45,6 +45,7 @@ import java.lang.System.Logger; import java.lang.System.Logger.Level; import java.net.BindException; import java.net.InetSocketAddress; +import java.net.ProtocolException; import java.net.ServerSocket; import java.net.URI; import java.net.URISyntaxException; @@ -733,7 +734,16 @@ class ServerImpl { connection.raw = rawin; connection.rawout = rawout; } - Request req = new Request(rawin, rawout); + + Request req; + try { + req = new Request(rawin, rawout, newconnection && !https); + } catch (ProtocolException pe) { + logger.log(Level.DEBUG, "closing due to: " + pe); + reject(Code.HTTP_BAD_REQUEST, "", pe.getMessage()); + return; + } + requestLine = req.requestLine(); if (requestLine == null) { /* connection closed */ diff --git a/test/jdk/com/sun/net/httpserver/ClearTextServerSSL.java b/test/jdk/com/sun/net/httpserver/ClearTextServerSSL.java new file mode 100644 index 00000000000..75e4f3fcf45 --- /dev/null +++ b/test/jdk/com/sun/net/httpserver/ClearTextServerSSL.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2025, 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 + * @bug 8373677 + * @summary Tests for verifying that a non-SSL server can detect + * when a client attempts to use SSL. + * @library /test/lib + * @run junit/othervm ${test.main.class} + */ + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.SimpleSSLContext; +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.net.URI; +import java.net.URISyntaxException; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.logging.ConsoleHandler; +import java.util.logging.Level; +import java.util.logging.Logger; + +import javax.net.ssl.SSLException; + +import static com.sun.net.httpserver.HttpExchange.RSPBODY_EMPTY; +import static java.net.http.HttpClient.Builder.NO_PROXY; +import static org.junit.jupiter.api.Assertions.*; + +public class ClearTextServerSSL { + + static final InetAddress LOOPBACK_ADDR = InetAddress.getLoopbackAddress(); + static final boolean ENABLE_LOGGING = true; + static final Logger logger = Logger.getLogger("com.sun.net.httpserver"); + + static final String CTXT_PATH = "/ClearTextServerSSL"; + + @BeforeAll + public static void setup() { + if (ENABLE_LOGGING) { + ConsoleHandler ch = new ConsoleHandler(); + logger.setLevel(Level.ALL); + ch.setLevel(Level.ALL); + logger.addHandler(ch); + } + } + + @Test + public void test() throws Exception { + var sslContext = new SimpleSSLContext().get(); + var handler = new TestHandler(); + var server = HttpServer.create(new InetSocketAddress(LOOPBACK_ADDR, 0), 0); + server.createContext(path(""), handler); + server.start(); + try (var client = HttpClient.newBuilder() + .sslContext(sslContext) + .proxy(NO_PROXY) + .build()) { + var request = HttpRequest.newBuilder() + .uri(uri("http", server, path("/clear"))) + .build(); + var response = client.send(request, HttpResponse.BodyHandlers.ofString()); + assertEquals(200, response.statusCode()); + var sslRequest = HttpRequest.newBuilder() + .uri(uri("https", server, path("/ssl"))) + .build(); + Assertions.assertThrows(SSLException.class, () -> { + client.send(sslRequest, HttpResponse.BodyHandlers.ofString()); + }); + try (var socket = new Socket()) { + socket.connect(server.getAddress()); + byte[] badRequest = { + 22, 'B', 'A', 'D', ' ', + '/', ' ' , + 'H', 'T', 'T', 'P', '/', '1', '.', '1' }; + socket.getOutputStream().write(badRequest); + socket.getOutputStream().flush(); + var reader = new InputStreamReader(socket.getInputStream()); + var line = reader.readAllLines(); + Assertions.assertEquals("HTTP/1.1 400 Bad Request", line.get(0)); + System.out.println("Got expected response:"); + line.stream().map(l -> "\t" + l).forEach(System.out::println); + } + + } finally { + server.stop(0); + } + } + + // --- infra --- + + static String path(String path) { + assert CTXT_PATH.startsWith("/"); + assert !CTXT_PATH.endsWith("/"); + if (path.startsWith("/")) { + return CTXT_PATH + path; + } else { + return CTXT_PATH + "/" + path; + } + } + + static URI uri(String scheme, HttpServer server, String path) throws URISyntaxException { + return URIBuilder.newBuilder() + .scheme(scheme) + .loopback() + .port(server.getAddress().getPort()) + .path(path) + .build(); + } + + /** + * A test handler that reads any request bytes and sends + * an empty 200 response + */ + static class TestHandler implements HttpHandler { + @java.lang.Override + public void handle(HttpExchange exchange) throws IOException { + try (var reqBody = exchange.getRequestBody()) { + reqBody.readAllBytes(); + exchange.sendResponseHeaders(200, RSPBODY_EMPTY); + } catch (Throwable t) { + t.printStackTrace(); + exchange.sendResponseHeaders(500, RSPBODY_EMPTY); + } + } + } +} From 39306d7ab901a1d27d9bfd80f04d917b4d17d07f Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 17 Dec 2025 13:19:49 +0000 Subject: [PATCH 140/211] 8373800: Remove ScopedValueBindingsResolver Reviewed-by: alanb, liach --- src/hotspot/share/classfile/vmClassMacros.hpp | 3 +++ src/hotspot/share/prims/jvm.cpp | 13 +------------ 2 files changed, 4 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/classfile/vmClassMacros.hpp b/src/hotspot/share/classfile/vmClassMacros.hpp index 04f0aaaaa44..71d6b9f22b2 100644 --- a/src/hotspot/share/classfile/vmClassMacros.hpp +++ b/src/hotspot/share/classfile/vmClassMacros.hpp @@ -190,6 +190,9 @@ /* GC support */ \ do_klass(FillerObject_klass, jdk_internal_vm_FillerObject ) \ \ + /* Scoped Values */ \ + do_klass(ScopedValue_Carrier_klass, java_lang_ScopedValue_Carrier ) \ + \ /*end*/ #endif // SHARE_CLASSFILE_VMCLASSMACROS_HPP diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 48d89235c98..ef5aca96a57 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1211,22 +1211,11 @@ JVM_ENTRY(jboolean, JVM_IsHiddenClass(JNIEnv *env, jclass cls)) JVM_END -class ScopedValueBindingsResolver { -public: - InstanceKlass* Carrier_klass; - ScopedValueBindingsResolver(JavaThread* THREAD) { - Klass *k = SystemDictionary::resolve_or_fail(vmSymbols::java_lang_ScopedValue_Carrier(), true, THREAD); - Carrier_klass = InstanceKlass::cast(k); - } -}; - JVM_ENTRY(jobject, JVM_FindScopedValueBindings(JNIEnv *env, jclass cls)) ResourceMark rm(THREAD); GrowableArray* local_array = new GrowableArray(12); JvmtiVMObjectAllocEventCollector oam; - static ScopedValueBindingsResolver resolver(THREAD); - // Iterate through Java frames vframeStream vfst(thread); for(; !vfst.at_end(); vfst.next()) { @@ -1239,7 +1228,7 @@ JVM_ENTRY(jobject, JVM_FindScopedValueBindings(JNIEnv *env, jclass cls)) InstanceKlass* holder = method->method_holder(); if (name == vmSymbols::runWith_method_name()) { if (holder == vmClasses::Thread_klass() - || holder == resolver.Carrier_klass) { + || holder == vmClasses::ScopedValue_Carrier_klass()) { loc = 1; } } From 9862f8f0d351448803f8930333d5a7286e6c3565 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Wed, 17 Dec 2025 13:38:37 +0000 Subject: [PATCH 141/211] 8373513: C2: Move ProjNode::other_if_proj() to IfProjNode Reviewed-by: epeter, roland --- src/hotspot/share/opto/cfgnode.cpp | 4 +- src/hotspot/share/opto/cfgnode.hpp | 21 +++++---- src/hotspot/share/opto/ifnode.cpp | 57 +++++++++++++------------ src/hotspot/share/opto/library_call.cpp | 2 +- src/hotspot/share/opto/memnode.cpp | 2 +- src/hotspot/share/opto/multnode.cpp | 7 +-- src/hotspot/share/opto/multnode.hpp | 3 -- src/hotspot/share/opto/predicates.cpp | 4 +- 8 files changed, 49 insertions(+), 51 deletions(-) diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 776a2d4c90b..ad5adfca8e5 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -933,8 +933,8 @@ bool RegionNode::optimize_trichotomy(PhaseIterGVN* igvn) { } // At this point we know that region->in(idx1) and region->(idx2) map to the same // value and control flow. Now search for ifs that feed into these region inputs. - ProjNode* proj1 = region->in(idx1)->isa_Proj(); - ProjNode* proj2 = region->in(idx2)->isa_Proj(); + IfProjNode* proj1 = region->in(idx1)->isa_IfProj(); + IfProjNode* proj2 = region->in(idx2)->isa_IfProj(); if (proj1 == nullptr || proj1->outcnt() != 1 || proj2 == nullptr || proj2->outcnt() != 1) { return false; // No projection inputs with region as unique user found diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 5f7f4790443..fd40123078a 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -342,15 +342,15 @@ class IfNode : public MultiBranchNode { // Helper methods for fold_compares bool cmpi_folds(PhaseIterGVN* igvn, bool fold_ne = false); bool is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn); - bool has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fail); - bool has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn); - Node* merge_uncommon_traps(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn); + bool has_shared_region(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail) const; + bool has_only_uncommon_traps(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail, PhaseIterGVN* igvn) const; + Node* merge_uncommon_traps(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn); static void improve_address_types(Node* l, Node* r, ProjNode* fail, PhaseIterGVN* igvn); - bool is_cmp_with_loadrange(ProjNode* proj); - bool is_null_check(ProjNode* proj, PhaseIterGVN* igvn); - bool is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn); - void reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn); - bool fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn); + bool is_cmp_with_loadrange(IfProjNode* proj) const; + bool is_null_check(IfProjNode* proj, PhaseIterGVN* igvn) const; + bool is_side_effect_free_test(IfProjNode* proj, PhaseIterGVN* igvn) const; + static void reroute_side_effect_free_unc(IfProjNode* proj, IfProjNode* dom_proj, PhaseIterGVN* igvn); + bool fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn); static bool is_dominator_unc(CallStaticJavaNode* dom_unc, CallStaticJavaNode* unc); protected: @@ -559,6 +559,11 @@ public: IfProjNode(IfNode *ifnode, uint idx) : CProjNode(ifnode,idx) {} virtual Node* Identity(PhaseGVN* phase); + // Return the other IfProj node. + IfProjNode* other_if_proj() const { + return in(0)->as_If()->proj_out(1 - _con)->as_IfProj(); + } + void pin_array_access_nodes(PhaseIterGVN* igvn); protected: diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 763888b65b2..cd8017f9fb3 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -771,7 +771,7 @@ bool IfNode::cmpi_folds(PhaseIterGVN* igvn, bool fold_ne) { // Is a dominating control suitable for folding with this if? bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) { return ctrl != nullptr && - ctrl->is_Proj() && + ctrl->is_IfProj() && ctrl->outcnt() == 1 && // No side-effects ctrl->in(0) != nullptr && ctrl->in(0)->Opcode() == Op_If && @@ -784,8 +784,8 @@ bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) { } // Do this If and the dominating If share a region? -bool IfNode::has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fail) { - ProjNode* otherproj = proj->other_if_proj(); +bool IfNode::has_shared_region(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail) const { + IfProjNode* otherproj = proj->other_if_proj(); Node* otherproj_ctrl_use = otherproj->unique_ctrl_out_or_null(); RegionNode* region = (otherproj_ctrl_use != nullptr && otherproj_ctrl_use->is_Region()) ? otherproj_ctrl_use->as_Region() : nullptr; success = nullptr; @@ -793,13 +793,14 @@ bool IfNode::has_shared_region(ProjNode* proj, ProjNode*& success, ProjNode*& fa if (otherproj->outcnt() == 1 && region != nullptr && !region->has_phi()) { for (int i = 0; i < 2; i++) { - ProjNode* proj = proj_out(i); - if (success == nullptr && proj->outcnt() == 1 && proj->unique_out() == region) { - success = proj; + IfProjNode* next_proj = proj_out(i)->as_IfProj(); + if (success == nullptr && next_proj->outcnt() == 1 && next_proj->unique_out() == region) { + success = next_proj; } else if (fail == nullptr) { - fail = proj; + fail = next_proj; } else { - success = fail = nullptr; + success = nullptr; + fail = nullptr; } } } @@ -850,8 +851,8 @@ ProjNode* IfNode::uncommon_trap_proj(CallStaticJavaNode*& call, Deoptimization:: } // Do this If and the dominating If both branch out to an uncommon trap -bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNode*& fail, PhaseIterGVN* igvn) { - ProjNode* otherproj = proj->other_if_proj(); +bool IfNode::has_only_uncommon_traps(IfProjNode* proj, IfProjNode*& success, IfProjNode*& fail, PhaseIterGVN* igvn) const { + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(); if (otherproj->outcnt() == 1 && dom_unc != nullptr) { @@ -888,8 +889,8 @@ bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNod !igvn->C->too_many_traps(dom_method, dom_bci, Deoptimization::Reason_range_check) && // Return true if c2 manages to reconcile with UnstableIf optimization. See the comments for it. igvn->C->remove_unstable_if_trap(dom_unc, true/*yield*/)) { - success = unc_proj; - fail = unc_proj->other_if_proj(); + success = unc_proj->as_IfProj(); + fail = unc_proj->as_IfProj()->other_if_proj(); return true; } } @@ -898,7 +899,7 @@ bool IfNode::has_only_uncommon_traps(ProjNode* proj, ProjNode*& success, ProjNod } // Check that the 2 CmpI can be folded into as single CmpU and proceed with the folding -bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn) { +bool IfNode::fold_compares_helper(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn) { Node* this_cmp = in(1)->in(1); BoolNode* this_bool = in(1)->as_Bool(); IfNode* dom_iff = proj->in(0)->as_If(); @@ -906,7 +907,7 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f Node* lo = dom_iff->in(1)->in(1)->in(2); Node* hi = this_cmp->in(2); Node* n = this_cmp->in(1); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); const TypeInt* lo_type = IfNode::filtered_int_type(igvn, n, otherproj); const TypeInt* hi_type = IfNode::filtered_int_type(igvn, n, success); @@ -1108,11 +1109,11 @@ bool IfNode::fold_compares_helper(ProjNode* proj, ProjNode* success, ProjNode* f // Merge the branches that trap for this If and the dominating If into // a single region that branches to the uncommon trap for the // dominating If -Node* IfNode::merge_uncommon_traps(ProjNode* proj, ProjNode* success, ProjNode* fail, PhaseIterGVN* igvn) { +Node* IfNode::merge_uncommon_traps(IfProjNode* proj, IfProjNode* success, IfProjNode* fail, PhaseIterGVN* igvn) { Node* res = this; assert(success->in(0) == this, "bad projection"); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* unc = success->is_uncommon_trap_proj(); CallStaticJavaNode* dom_unc = otherproj->is_uncommon_trap_proj(); @@ -1239,7 +1240,7 @@ void IfNode::improve_address_types(Node* l, Node* r, ProjNode* fail, PhaseIterGV #endif } -bool IfNode::is_cmp_with_loadrange(ProjNode* proj) { +bool IfNode::is_cmp_with_loadrange(IfProjNode* proj) const { if (in(1) != nullptr && in(1)->in(1) != nullptr && in(1)->in(1)->in(2) != nullptr) { @@ -1258,7 +1259,7 @@ bool IfNode::is_cmp_with_loadrange(ProjNode* proj) { return false; } -bool IfNode::is_null_check(ProjNode* proj, PhaseIterGVN* igvn) { +bool IfNode::is_null_check(IfProjNode* proj, PhaseIterGVN* igvn) const { Node* other = in(1)->in(1)->in(2); if (other->in(MemNode::Address) != nullptr && proj->in(0)->in(1) != nullptr && @@ -1275,7 +1276,7 @@ bool IfNode::is_null_check(ProjNode* proj, PhaseIterGVN* igvn) { // Check that the If that is in between the 2 integer comparisons has // no side effect -bool IfNode::is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn) { +bool IfNode::is_side_effect_free_test(IfProjNode* proj, PhaseIterGVN* igvn) const { if (proj == nullptr) { return false; } @@ -1315,9 +1316,9 @@ bool IfNode::is_side_effect_free_test(ProjNode* proj, PhaseIterGVN* igvn) { // won't be guarded by the first CmpI anymore. It can trap in cases // where the first CmpI would have prevented it from executing: on a // trap, we need to restart execution at the state of the first CmpI -void IfNode::reroute_side_effect_free_unc(ProjNode* proj, ProjNode* dom_proj, PhaseIterGVN* igvn) { +void IfNode::reroute_side_effect_free_unc(IfProjNode* proj, IfProjNode* dom_proj, PhaseIterGVN* igvn) { CallStaticJavaNode* dom_unc = dom_proj->is_uncommon_trap_if_pattern(); - ProjNode* otherproj = proj->other_if_proj(); + IfProjNode* otherproj = proj->other_if_proj(); CallStaticJavaNode* unc = proj->is_uncommon_trap_if_pattern(); Node* call_proj = dom_unc->unique_ctrl_out(); Node* halt = call_proj->unique_ctrl_out(); @@ -1348,9 +1349,9 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) { if (is_ctrl_folds(ctrl, igvn)) { // A integer comparison immediately dominated by another integer // comparison - ProjNode* success = nullptr; - ProjNode* fail = nullptr; - ProjNode* dom_cmp = ctrl->as_Proj(); + IfProjNode* success = nullptr; + IfProjNode* fail = nullptr; + IfProjNode* dom_cmp = ctrl->as_IfProj(); if (has_shared_region(dom_cmp, success, fail) && // Next call modifies graph so must be last fold_compares_helper(dom_cmp, success, fail, igvn)) { @@ -1364,11 +1365,11 @@ Node* IfNode::fold_compares(PhaseIterGVN* igvn) { return nullptr; } else if (ctrl->in(0) != nullptr && ctrl->in(0)->in(0) != nullptr) { - ProjNode* success = nullptr; - ProjNode* fail = nullptr; + IfProjNode* success = nullptr; + IfProjNode* fail = nullptr; Node* dom = ctrl->in(0)->in(0); - ProjNode* dom_cmp = dom->isa_Proj(); - ProjNode* other_cmp = ctrl->isa_Proj(); + IfProjNode* dom_cmp = dom->isa_IfProj(); + IfProjNode* other_cmp = ctrl->isa_IfProj(); // Check if it's an integer comparison dominated by another // integer comparison with another test in between diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 2263fa720ce..a057f66a989 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -6171,7 +6171,7 @@ LibraryCallKit::tightly_coupled_allocation(Node* ptr) { CallStaticJavaNode* LibraryCallKit::get_uncommon_trap_from_success_proj(Node* node) { if (node->is_IfProj()) { - Node* other_proj = node->as_IfProj()->other_if_proj(); + IfProjNode* other_proj = node->as_IfProj()->other_if_proj(); for (DUIterator_Fast jmax, j = other_proj->fast_outs(jmax); j < jmax; j++) { Node* obs = other_proj->fast_out(j); if (obs->in(0) == other_proj && obs->is_CallStaticJava() && diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 19ff90df5ed..5b76f5b42cf 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -3103,7 +3103,7 @@ MergePrimitiveStores::CFGStatus MergePrimitiveStores::cfg_status_for_pair(const ctrl_use->in(0)->outcnt() != 2) { return CFGStatus::Failure; // Not RangeCheck. } - ProjNode* other_proj = ctrl_use->as_IfProj()->other_if_proj(); + IfProjNode* other_proj = ctrl_use->as_IfProj()->other_if_proj(); Node* trap = other_proj->is_uncommon_trap_proj(Deoptimization::Reason_range_check); if (trap != merge_mem->unique_out() || ctrl_use->in(0)->in(0) != ctrl_def) { diff --git a/src/hotspot/share/opto/multnode.cpp b/src/hotspot/share/opto/multnode.cpp index 9409a2f6af3..05867a35268 100644 --- a/src/hotspot/share/opto/multnode.cpp +++ b/src/hotspot/share/opto/multnode.cpp @@ -260,12 +260,7 @@ CallStaticJavaNode* ProjNode::is_uncommon_trap_if_pattern(Deoptimization::DeoptR // Not a projection of an If or variation of a dead If node. return nullptr; } - return other_if_proj()->is_uncommon_trap_proj(reason); -} - -ProjNode* ProjNode::other_if_proj() const { - assert(_con == 0 || _con == 1, "not an if?"); - return in(0)->as_If()->proj_out(1-_con); + return as_IfProj()->other_if_proj()->is_uncommon_trap_proj(reason); } NarrowMemProjNode::NarrowMemProjNode(InitializeNode* src, const TypePtr* adr_type) diff --git a/src/hotspot/share/opto/multnode.hpp b/src/hotspot/share/opto/multnode.hpp index be1351cc5b1..692b69118c9 100644 --- a/src/hotspot/share/opto/multnode.hpp +++ b/src/hotspot/share/opto/multnode.hpp @@ -200,9 +200,6 @@ public: // other_proj->[region->..]call_uct" // null otherwise CallStaticJavaNode* is_uncommon_trap_if_pattern(Deoptimization::DeoptReason reason = Deoptimization::Reason_none) const; - - // Return other proj node when this is a If proj node - ProjNode* other_if_proj() const; }; // A ProjNode variant that captures an adr_type(). Used as a projection of InitializeNode to have the right adr_type() diff --git a/src/hotspot/share/opto/predicates.cpp b/src/hotspot/share/opto/predicates.cpp index 2489ff563a9..89bc4374ca6 100644 --- a/src/hotspot/share/opto/predicates.cpp +++ b/src/hotspot/share/opto/predicates.cpp @@ -65,7 +65,7 @@ bool AssertionPredicate::has_assertion_predicate_opaque(const Node* predicate_pr // Check if the other projection (UCT projection) of `success_proj` has a Halt node as output. bool AssertionPredicate::has_halt(const IfTrueNode* success_proj) { - ProjNode* other_proj = success_proj->other_if_proj(); + IfProjNode* other_proj = success_proj->other_if_proj(); return other_proj->outcnt() == 1 && other_proj->unique_out()->Opcode() == Op_Halt; } @@ -396,7 +396,7 @@ bool InitializedAssertionPredicate::is_predicate(const Node* maybe_success_proj) #ifdef ASSERT bool InitializedAssertionPredicate::has_halt(const IfTrueNode* success_proj) { - ProjNode* other_proj = success_proj->other_if_proj(); + IfProjNode* other_proj = success_proj->other_if_proj(); if (other_proj->outcnt() != 1) { return false; } From 4e05748f0899cabb235c71ecdf4256d4ad137a0d Mon Sep 17 00:00:00 2001 From: Justin Lu Date: Wed, 17 Dec 2025 18:17:24 +0000 Subject: [PATCH 142/211] 8373716: Refactor further java/util tests from TestNG to JUnit Reviewed-by: naoto --- .../Calendar/CalendarDisplayNamesTest.java | 12 +++--- .../util/Calendar/JapaneseLenientEraTest.java | 21 +++++----- .../SupplementalJapaneseEraTestRun.java | 16 ++++---- .../util/Properties/CompatibilityTest.java | 19 +++++----- .../java/util/Properties/EncodingTest.java | 18 +++++---- .../java/util/Properties/InitialCapacity.java | 14 ++++--- .../Properties/PropertiesEntrySetTest.java | 38 +++++++++---------- .../util/Properties/PropertiesStoreTest.java | 38 ++++++++++--------- .../modules/basic/BasicTest.java | 18 +++++---- .../modules/cache/CacheTest.java | 15 ++++---- .../CaseInsensitiveNameClash.java | 14 ++++--- .../modules/visibility/VisibilityTest.java | 36 +++++++++--------- .../java/util/TimeZone/NegativeDSTTest.java | 23 +++++------ .../util/TimeZone/ZoneIdRoundTripTest.java | 21 +++++----- 14 files changed, 162 insertions(+), 141 deletions(-) diff --git a/test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java b/test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java index 7c40714fc02..171bea55fcf 100644 --- a/test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java +++ b/test/jdk/java/util/Calendar/CalendarDisplayNamesTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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,21 +21,21 @@ * questions. */ -import org.testng.Assert; -import org.testng.annotations.Test; import java.util.Calendar; import java.util.Locale; import java.util.Map; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /** * @test * @bug 8262108 8174269 * @summary Verify the results returned by Calendar.getDisplayNames() API * @comment Locale providers: CLDR,SPI - * @run testng/othervm -Djava.locale.providers=CLDR,SPI CalendarDisplayNamesTest + * @run junit/othervm -Djava.locale.providers=CLDR,SPI CalendarDisplayNamesTest * @comment Locale providers: default - * @run testng CalendarDisplayNamesTest + * @run junit CalendarDisplayNamesTest */ public class CalendarDisplayNamesTest { @@ -55,7 +55,7 @@ public class CalendarDisplayNamesTest { continue; } for (final Integer fieldValue : names.values()) { - Assert.assertTrue(fieldValue == Calendar.AM || fieldValue == Calendar.PM, + Assertions.assertTrue(fieldValue == Calendar.AM || fieldValue == Calendar.PM, "Invalid field value " + fieldValue + " for calendar field AM_PM, in locale " + locale + " with style " + style); } diff --git a/test/jdk/java/util/Calendar/JapaneseLenientEraTest.java b/test/jdk/java/util/Calendar/JapaneseLenientEraTest.java index 6a909a23a18..ca726afc29b 100644 --- a/test/jdk/java/util/Calendar/JapaneseLenientEraTest.java +++ b/test/jdk/java/util/Calendar/JapaneseLenientEraTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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,7 +25,7 @@ * @test * @bug 8206120 * @summary Test whether lenient era is accepted in JapaneseImperialCalendar - * @run testng/othervm JapaneseLenientEraTest + * @run junit/othervm JapaneseLenientEraTest */ import java.text.DateFormat; @@ -34,15 +34,15 @@ import java.util.Calendar; import java.util.Date; import java.util.Locale; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class JapaneseLenientEraTest { - @DataProvider(name="lenientEra") - Object[][] names() { + Object[][] lenientEra() { return new Object[][] { // lenient era/year, strict era/year { "Meiji 123", "Heisei 2" }, @@ -51,7 +51,8 @@ public class JapaneseLenientEraTest { }; } - @Test(dataProvider="lenientEra") + @ParameterizedTest + @MethodSource("lenientEra") public void testLenientEra(String lenient, String strict) throws Exception { Calendar c = new Calendar.Builder() .setCalendarType("japanese") @@ -61,6 +62,6 @@ public class JapaneseLenientEraTest { Date lenDate = df.parse(lenient + "-01-01"); df.setLenient(false); Date strDate = df.parse(strict + "-01-01"); - assertEquals(lenDate, strDate); + assertEquals(strDate, lenDate); } } diff --git a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java index 8eac4a97ef7..878955fdcc4 100644 --- a/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java +++ b/test/jdk/java/util/Calendar/SupplementalJapaneseEraTestRun.java @@ -27,7 +27,7 @@ * @summary Test for jdk.calendar.japanese.supplemental.era support * @library /test/lib * @build SupplementalJapaneseEraTest - * @run testng/othervm SupplementalJapaneseEraTestRun + * @run junit/othervm SupplementalJapaneseEraTestRun */ import java.util.Calendar; @@ -45,11 +45,12 @@ import static java.util.Calendar.YEAR; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.Utils; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class SupplementalJapaneseEraTestRun { - @DataProvider(name = "validprop") Object[][] validPropertyData() { return new Object[][] { //Tests with valid property values @@ -58,7 +59,6 @@ public class SupplementalJapaneseEraTestRun { }; } - @DataProvider(name = "invalidprop") Object[][] invalidPropertyData() { return new Object[][] { //Tests with invalid property values @@ -76,7 +76,8 @@ public class SupplementalJapaneseEraTestRun { }; } - @Test(dataProvider = "validprop") + @ParameterizedTest + @MethodSource("validPropertyData") public void ValidPropertyValuesTest(String prop) throws Throwable { //get the start time of the fictional next era @@ -84,7 +85,8 @@ public class SupplementalJapaneseEraTestRun { testRun(prop + startTime, List.of("-t")); } - @Test(dataProvider = "invalidprop") + @ParameterizedTest + @MethodSource("invalidPropertyData") public void InvalidPropertyValuesTest(String prop) throws Throwable { //get the start time of the fictional next era diff --git a/test/jdk/java/util/Properties/CompatibilityTest.java b/test/jdk/java/util/Properties/CompatibilityTest.java index 29c7be6fbcd..839680806c1 100644 --- a/test/jdk/java/util/Properties/CompatibilityTest.java +++ b/test/jdk/java/util/Properties/CompatibilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,19 +24,19 @@ import java.io.ByteArrayOutputStream; import java.io.IOException; import java.util.Properties; -import org.testng.Assert; - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test * @bug 8252354 - * @run testng CompatibilityTest + * @run junit CompatibilityTest * @summary Verify compatibility. */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class CompatibilityTest { - @DataProvider(name = "entries") public Object[][] getEntries() throws IOException { return new Object[][]{ {8, 238923}, @@ -53,9 +53,10 @@ public class CompatibilityTest { * @param value the value * @throws IOException */ - @Test(dataProvider = "entries") + @ParameterizedTest + @MethodSource("getEntries") void testThrows(Object key, Object value) throws IOException { - Assert.assertThrows(ClassCastException.class, () -> storeToXML(key, value)); + Assertions.assertThrows(ClassCastException.class, () -> storeToXML(key, value)); } void storeToXML(Object key, Object value) throws IOException { diff --git a/test/jdk/java/util/Properties/EncodingTest.java b/test/jdk/java/util/Properties/EncodingTest.java index d97730a37c7..069d16155f0 100644 --- a/test/jdk/java/util/Properties/EncodingTest.java +++ b/test/jdk/java/util/Properties/EncodingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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,19 +27,20 @@ import java.io.IOException; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.Properties; -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * @test * @bug 8183743 * @summary Test to verify the new overload method with Charset functions the * same as the existing method that takes a charset name. - * @run testng EncodingTest + * @run junit EncodingTest */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class EncodingTest { - @DataProvider(name = "parameters") public Object[][] getParameters() throws IOException { return new Object[][]{ {StandardCharsets.UTF_8.name(), null}, @@ -51,7 +52,8 @@ public class EncodingTest { * encoding name or a charset can be read with Properties#loadFromXML that * returns the same Properties object. */ - @Test(dataProvider = "parameters") + @ParameterizedTest + @MethodSource("getParameters") void testLoadAndStore(String encoding, Charset charset) throws IOException { Properties props = new Properties(); props.put("k0", "\u6C34"); @@ -74,6 +76,6 @@ public class EncodingTest { } } - Assert.assertEquals(props, p); + Assertions.assertEquals(p, props); } } diff --git a/test/jdk/java/util/Properties/InitialCapacity.java b/test/jdk/java/util/Properties/InitialCapacity.java index 81e5421bbef..d684c37adf4 100644 --- a/test/jdk/java/util/Properties/InitialCapacity.java +++ b/test/jdk/java/util/Properties/InitialCapacity.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -22,18 +22,22 @@ */ import java.util.Properties; -import org.testng.annotations.Test; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; /* * @test * @bug 8189319 * @summary Test that Properties(int initialCapacity) throws exceptions (or doesn't) as expected - * @run testng InitialCapacity + * @run junit InitialCapacity */ public class InitialCapacity { - @Test(expectedExceptions = IllegalArgumentException.class) - public void negativeInitCap() { Properties p = new Properties(-1); } + @Test + public void negativeInitCap() { Assertions.assertThrows(IllegalArgumentException.class, () -> { + Properties p = new Properties(-1); + }); +} @Test public void positiveInitCap() { Properties p = new Properties(10); } diff --git a/test/jdk/java/util/Properties/PropertiesEntrySetTest.java b/test/jdk/java/util/Properties/PropertiesEntrySetTest.java index d7d58be44dd..f3262f734e3 100644 --- a/test/jdk/java/util/Properties/PropertiesEntrySetTest.java +++ b/test/jdk/java/util/Properties/PropertiesEntrySetTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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 @@ -26,17 +26,17 @@ * @bug 8245694 * @summary tests the entrySet() method of Properties class * @author Yu Li - * @run testng PropertiesEntrySetTest + * @run junit PropertiesEntrySetTest */ -import org.testng.annotations.Test; import java.util.Properties; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertThrows; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; public class PropertiesEntrySetTest { @@ -99,13 +99,13 @@ public class PropertiesEntrySetTest { public void testToString() { Properties a = new Properties(); var aEntrySet = a.entrySet(); - assertEquals(aEntrySet.toString(), "[]"); + assertEquals("[]", aEntrySet.toString()); a.setProperty("p1", "1"); - assertEquals(aEntrySet.toString(), "[p1=1]"); + assertEquals("[p1=1]", aEntrySet.toString()); a.setProperty("p2", "2"); - assertEquals(aEntrySet.size(), 2); + assertEquals(2, aEntrySet.size()); assertTrue(aEntrySet.toString().trim().startsWith("[")); assertTrue(aEntrySet.toString().contains("p1=1")); assertTrue(aEntrySet.toString().contains("p2=2")); @@ -115,18 +115,18 @@ public class PropertiesEntrySetTest { b.setProperty("p2", "2"); b.setProperty("p1", "1"); var bEntrySet = b.entrySet(); - assertEquals(bEntrySet.size(), 2); + assertEquals(2, bEntrySet.size()); assertTrue(bEntrySet.toString().trim().startsWith("[")); assertTrue(bEntrySet.toString().contains("p1=1")); assertTrue(bEntrySet.toString().contains("p2=2")); assertTrue(bEntrySet.toString().trim().endsWith("]")); b.setProperty("p0", "0"); - assertEquals(bEntrySet.size(), 3); + assertEquals(3, bEntrySet.size()); assertTrue(bEntrySet.toString().contains("p0=0")); b.remove("p1"); - assertEquals(bEntrySet.size(), 2); + assertEquals(2, bEntrySet.size()); assertFalse(bEntrySet.toString().contains("p1=1")); assertTrue(bEntrySet.toString().trim().startsWith("[")); assertTrue(bEntrySet.toString().contains("p0=0")); @@ -134,7 +134,7 @@ public class PropertiesEntrySetTest { assertTrue(bEntrySet.toString().trim().endsWith("]")); b.remove("p0", "0"); - assertEquals(bEntrySet.size(), 1); + assertEquals(1, bEntrySet.size()); assertFalse(bEntrySet.toString().contains("p0=0")); assertTrue(bEntrySet.toString().trim().startsWith("[")); assertTrue(bEntrySet.toString().contains("p2=2")); @@ -151,13 +151,13 @@ public class PropertiesEntrySetTest { a.setProperty("p1", "1"); a.setProperty("p2", "2"); var aEntrySet = a.entrySet(); - assertEquals(aEntrySet.size(), 2); + assertEquals(2, aEntrySet.size()); var i = aEntrySet.iterator(); var e1 = i.next(); i.remove(); assertFalse(aEntrySet.contains(e1)); - assertEquals(aEntrySet.size(), 1); + assertEquals(1, aEntrySet.size()); var e2 = i.next(); aEntrySet.remove(e2); @@ -172,14 +172,14 @@ public class PropertiesEntrySetTest { var bEntrySet = b.entrySet(); assertFalse(bEntrySet.containsAll(aEntrySet)); - assertEquals(bEntrySet.size(), 2); + assertEquals(2, bEntrySet.size()); assertTrue(bEntrySet.removeAll(aEntrySet)); - assertEquals(bEntrySet.size(), 1); + assertEquals(1, bEntrySet.size()); assertTrue(bEntrySet.retainAll(aEntrySet)); assertTrue(bEntrySet.isEmpty()); - assertEquals(aEntrySet.size(), 2); + assertEquals(2, aEntrySet.size()); aEntrySet.clear(); assertTrue(aEntrySet.isEmpty()); diff --git a/test/jdk/java/util/Properties/PropertiesStoreTest.java b/test/jdk/java/util/Properties/PropertiesStoreTest.java index b5a5b5a45aa..88c24698a14 100644 --- a/test/jdk/java/util/Properties/PropertiesStoreTest.java +++ b/test/jdk/java/util/Properties/PropertiesStoreTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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,6 @@ * questions. */ -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import java.io.BufferedReader; import java.io.IOException; @@ -45,13 +42,18 @@ import java.util.Properties; import java.util.Set; import java.util.TreeSet; import java.util.stream.Collectors; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /* * @test * @summary tests the order in which the Properties.store() method writes out the properties * @bug 8231640 8282023 - * @run testng/othervm PropertiesStoreTest + * @run junit/othervm PropertiesStoreTest */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class PropertiesStoreTest { private static final String DATE_FORMAT_PATTERN = "EEE MMM dd HH:mm:ss zzz uuuu"; @@ -60,7 +62,6 @@ public class PropertiesStoreTest { private static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT_PATTERN, Locale.US); private static final Locale PREV_LOCALE = Locale.getDefault(); - @DataProvider(name = "propsProvider") private Object[][] createProps() { final Properties simple = new Properties(); simple.setProperty("1", "one"); @@ -101,7 +102,6 @@ public class PropertiesStoreTest { /** * Returns a {@link Locale} to use for testing */ - @DataProvider(name = "localeProvider") private Object[][] provideLocales() { // pick a non-english locale for testing Set locales = Arrays.stream(Locale.getAvailableLocales()) @@ -122,7 +122,8 @@ public class PropertiesStoreTest { * Tests that the {@link Properties#store(Writer, String)} API writes out the properties * in the expected order */ - @Test(dataProvider = "propsProvider") + @ParameterizedTest + @MethodSource("createProps") public void testStoreWriterKeyOrder(final Properties props, final String[] expectedOrder) throws Exception { // Properties.store(...) to a temp file final Path tmpFile = Files.createTempFile("8231640", "props"); @@ -136,7 +137,8 @@ public class PropertiesStoreTest { * Tests that the {@link Properties#store(OutputStream, String)} API writes out the properties * in the expected order */ - @Test(dataProvider = "propsProvider") + @ParameterizedTest + @MethodSource("createProps") public void testStoreOutputStreamKeyOrder(final Properties props, final String[] expectedOrder) throws Exception { // Properties.store(...) to a temp file final Path tmpFile = Files.createTempFile("8231640", "props"); @@ -161,7 +163,7 @@ public class PropertiesStoreTest { try (final InputStream is = Files.newInputStream(storedProps)) { loaded.load(is); } - Assert.assertEquals(loaded, props, "Unexpected properties loaded from stored state"); + Assertions.assertEquals(props, loaded, "Unexpected properties loaded from stored state"); // now read lines from the stored file and keep track of the order in which the keys were // found in that file. Compare that order with the expected store order of the keys. @@ -169,10 +171,10 @@ public class PropertiesStoreTest { try (final BufferedReader reader = Files.newBufferedReader(storedProps)) { actualOrder = readInOrder(reader); } - Assert.assertEquals(actualOrder.size(), expectedOrder.length, + Assertions.assertEquals(expectedOrder.length, actualOrder.size(), "Unexpected number of keys read from stored properties"); if (!Arrays.equals(actualOrder.toArray(new String[0]), expectedOrder)) { - Assert.fail("Unexpected order of stored property keys. Expected order: " + Arrays.toString(expectedOrder) + Assertions.fail("Unexpected order of stored property keys. Expected order: " + Arrays.toString(expectedOrder) + ", found order: " + actualOrder); } } @@ -180,7 +182,8 @@ public class PropertiesStoreTest { /** * Tests that {@link Properties#store(Writer, String)} writes out a proper date comment */ - @Test(dataProvider = "localeProvider") + @ParameterizedTest + @MethodSource("provideLocales") public void testStoreWriterDateComment(final Locale testLocale) throws Exception { // switch the default locale to the one being tested Locale.setDefault(testLocale); @@ -202,7 +205,8 @@ public class PropertiesStoreTest { /** * Tests that {@link Properties#store(OutputStream, String)} writes out a proper date comment */ - @Test(dataProvider = "localeProvider") + @ParameterizedTest + @MethodSource("provideLocales") public void testStoreOutputStreamDateComment(final Locale testLocale) throws Exception { // switch the default locale to the one being tested Locale.setDefault(testLocale); @@ -232,19 +236,19 @@ public class PropertiesStoreTest { while ((line = reader.readLine()) != null) { if (line.startsWith("#")) { if (comment != null) { - Assert.fail("More than one comment line found in the stored properties file " + file); + Assertions.fail("More than one comment line found in the stored properties file " + file); } comment = line.substring(1); } } } if (comment == null) { - Assert.fail("No comment line found in the stored properties file " + file); + Assertions.fail("No comment line found in the stored properties file " + file); } try { FORMATTER.parse(comment); } catch (DateTimeParseException pe) { - Assert.fail("Unexpected date comment: " + comment, pe); + Assertions.fail("Unexpected date comment: " + comment, pe); } } diff --git a/test/jdk/java/util/ResourceBundle/modules/basic/BasicTest.java b/test/jdk/java/util/ResourceBundle/modules/basic/BasicTest.java index 69f0db83258..c17c4622ecb 100644 --- a/test/jdk/java/util/ResourceBundle/modules/basic/BasicTest.java +++ b/test/jdk/java/util/ResourceBundle/modules/basic/BasicTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,7 @@ * jdk.test.lib.compiler.CompilerUtils * jdk.test.lib.process.ProcessTools * ModuleTestUtil - * @run testng BasicTest + * @run junit BasicTest */ import java.nio.file.Path; @@ -54,13 +54,15 @@ import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.Utils; import jdk.test.lib.compiler.CompilerUtils; import jdk.test.lib.process.ProcessTools; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; import static jdk.test.lib.Asserts.assertEquals; -import static org.testng.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class BasicTest { private static final String SRC_DIR_APPBASIC = "srcAppbasic"; private static final String SRC_DIR_APPBASIC2 = "srcAppbasic2"; @@ -92,7 +94,6 @@ public class BasicTest { private static final String MAIN = "test/jdk.test.Main"; - @DataProvider(name = "basicTestData") Object[][] basicTestData() { return new Object[][] { // Named module "test" contains resource bundles for root and en, @@ -122,7 +123,8 @@ public class BasicTest { }; } - @Test(dataProvider = "basicTestData") + @ParameterizedTest + @MethodSource("basicTestData") public void runBasicTest(String src, String mod, List moduleList, List localeList, String resFormat) throws Throwable { Path srcPath = Paths.get(Utils.TEST_SRC, src); diff --git a/test/jdk/java/util/ResourceBundle/modules/cache/CacheTest.java b/test/jdk/java/util/ResourceBundle/modules/cache/CacheTest.java index 5655eb5de2d..df72af38855 100644 --- a/test/jdk/java/util/ResourceBundle/modules/cache/CacheTest.java +++ b/test/jdk/java/util/ResourceBundle/modules/cache/CacheTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2025, 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,7 +27,7 @@ * @library /test/lib * @modules jdk.compiler * @build CacheTest jdk.test.lib.compiler.CompilerUtils - * @run testng CacheTest + * @run junit CacheTest */ import java.nio.file.Files; @@ -37,11 +37,12 @@ import java.nio.file.Paths; import static jdk.test.lib.process.ProcessTools.*; import jdk.test.lib.compiler.CompilerUtils; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class CacheTest { private static final String TEST_SRC = System.getProperty("test.src"); @@ -55,7 +56,7 @@ public class CacheTest { private static final String MAIN = "test/jdk.test.Main"; private static final String MAIN_CLASS = "jdk.test.Main"; - @BeforeTest + @BeforeAll public void compileTestModules() throws Exception { for (String mn : new String[] {MAIN_BUNDLES_MODULE, TEST_MODULE}) { diff --git a/test/jdk/java/util/ResourceBundle/modules/casesensitive/CaseInsensitiveNameClash.java b/test/jdk/java/util/ResourceBundle/modules/casesensitive/CaseInsensitiveNameClash.java index 914ebf6bbf0..45f52b512c8 100644 --- a/test/jdk/java/util/ResourceBundle/modules/casesensitive/CaseInsensitiveNameClash.java +++ b/test/jdk/java/util/ResourceBundle/modules/casesensitive/CaseInsensitiveNameClash.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, 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 @@ -28,7 +28,7 @@ * @modules jdk.compiler * @build jdk.test.lib.compiler.CompilerUtils * jdk.test.lib.process.ProcessTools CaseInsensitiveNameClash - * @run testng CaseInsensitiveNameClash + * @run junit CaseInsensitiveNameClash */ import java.nio.file.Files; @@ -37,10 +37,12 @@ import java.nio.file.Paths; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.compiler.CompilerUtils; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.Test; -import static org.testng.Assert.*; +import static org.junit.jupiter.api.Assertions.*; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class CaseInsensitiveNameClash { private static final String TEST_SRC = System.getProperty("test.src"); @@ -54,7 +56,7 @@ public class CaseInsensitiveNameClash { /** * Compiles the module used by the test */ - @BeforeTest + @BeforeAll public void compileAll() throws Exception { Path msrc = SRC_DIR.resolve(MODULE); assertTrue(CompilerUtils.compile(msrc, MODS_DIR, diff --git a/test/jdk/java/util/ResourceBundle/modules/visibility/VisibilityTest.java b/test/jdk/java/util/ResourceBundle/modules/visibility/VisibilityTest.java index e0fdb9a93ab..ee9da88d705 100644 --- a/test/jdk/java/util/ResourceBundle/modules/visibility/VisibilityTest.java +++ b/test/jdk/java/util/ResourceBundle/modules/visibility/VisibilityTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2025, 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,7 +34,7 @@ * jdk.test.lib.compiler.CompilerUtils * jdk.test.lib.process.ProcessTools * ModuleTestUtil - * @run testng VisibilityTest + * @run junit VisibilityTest */ import java.nio.file.Path; @@ -46,13 +46,13 @@ import jdk.test.lib.JDKToolLauncher; import jdk.test.lib.Utils; import jdk.test.lib.process.ProcessTools; -import org.testng.annotations.BeforeTest; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; -import static org.testng.Assert.assertEquals; - -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class VisibilityTest { private static final Path SRC_DIR = Paths.get(Utils.TEST_SRC, "src"); private static final Path MODS_DIR = Paths.get(Utils.TEST_CLASSES, "mods"); @@ -63,7 +63,7 @@ public class VisibilityTest { private static final List MODULE_LIST = List.of("embargo", "exported.named.bundles", "named.bundles", "test"); - @BeforeTest + @BeforeAll public void prepareTestEnv() throws Throwable { MODULE_LIST.forEach(mn -> ModuleTestUtil.prepareModule(SRC_DIR, MODS_DIR, mn, ".properties")); @@ -93,7 +93,6 @@ public class VisibilityTest { * "exported.named.bundle" are exported to unnamed modules. */ - @DataProvider(name = "RunWithTestResData") Object[][] RunWithTestResData() { return new Object[][] { // Tests using jdk.test.TestWithNoModuleArg and jdk.embargo.TestWithNoModuleArg. @@ -188,7 +187,6 @@ public class VisibilityTest { }; } - @DataProvider(name = "RunWithExportedResData") Object[][] RunWithExportedResData() { return new Object[][] { // Tests using jdk.test.TestWithNoModuleArg and jdk.embargo.TestWithNoModuleArg @@ -285,7 +283,6 @@ public class VisibilityTest { }; } - @DataProvider(name = "RunWithPkgResData") Object[][] RunWithPkgResData() { return new Object[][] { // jdk.pkg.resources.* are in an unnamed module. @@ -300,10 +297,11 @@ public class VisibilityTest { /** * Test cases with jdk.test.resources.* */ - @Test(dataProvider = "RunWithTestResData") + @ParameterizedTest + @MethodSource("RunWithTestResData") public void RunWithTestRes(List argsList) throws Throwable { int exitCode = runCmd(argsList); - assertEquals(exitCode, 0, "Execution of the tests with " + assertEquals(0, exitCode, "Execution of the tests with " + "jdk.test.resources.* failed. " + "Unexpected exit code: " + exitCode); } @@ -311,10 +309,11 @@ public class VisibilityTest { /** * Test cases with jdk.test.resources.exported.* */ - @Test(dataProvider = "RunWithExportedResData") + @ParameterizedTest + @MethodSource("RunWithExportedResData") public void RunWithExportedRes(List argsList) throws Throwable { int exitCode = runCmd(argsList); - assertEquals(exitCode, 0, "Execution of the tests with " + assertEquals(0, exitCode, "Execution of the tests with " + "jdk.test.resources.exported.* failed. " + "Unexpected exit code: " + exitCode); } @@ -322,10 +321,11 @@ public class VisibilityTest { /** * Test cases with jdk.pkg.resources.* */ - @Test(dataProvider = "RunWithPkgResData") + @ParameterizedTest + @MethodSource("RunWithPkgResData") public void RunWithPkgRes(List argsList) throws Throwable { int exitCode = runCmd(argsList); - assertEquals(exitCode, 0, "Execution of the tests with " + assertEquals(0, exitCode, "Execution of the tests with " + "jdk.pkg.resources.* failed. " + "Unexpected exit code: " + exitCode); } diff --git a/test/jdk/java/util/TimeZone/NegativeDSTTest.java b/test/jdk/java/util/TimeZone/NegativeDSTTest.java index eb46b8d4b29..ab9438f2388 100644 --- a/test/jdk/java/util/TimeZone/NegativeDSTTest.java +++ b/test/jdk/java/util/TimeZone/NegativeDSTTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, 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,7 +21,7 @@ * questions. */ -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import java.time.Instant; import java.time.LocalDate; @@ -31,18 +31,19 @@ import java.time.ZoneId; import java.util.Date; import java.util.TimeZone; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * @test * @bug 8212970 8324065 * @summary Test whether the savings are positive in time zones that have * negative savings in the source TZ files. - * @run testng NegativeDSTTest + * @run junit NegativeDSTTest */ -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class NegativeDSTTest { private static final TimeZone DUBLIN = TimeZone.getTimeZone("Europe/Dublin"); @@ -51,7 +52,6 @@ public class NegativeDSTTest { private static final TimeZone CASABLANCA = TimeZone.getTimeZone("Africa/Casablanca"); private static final int ONE_HOUR = 3600_000; - @DataProvider private Object[][] negativeDST () { return new Object[][] { // TimeZone, localDate, offset, isDaylightSavings @@ -88,10 +88,11 @@ public class NegativeDSTTest { }; } - @Test(dataProvider="negativeDST") + @ParameterizedTest + @MethodSource("negativeDST") public void test_NegativeDST(TimeZone tz, LocalDate ld, int offset, boolean isDST) { Date d = Date.from(Instant.from(ZonedDateTime.of(ld, LocalTime.MIN, tz.toZoneId()))); - assertEquals(tz.getOffset(d.getTime()), offset); - assertEquals(tz.inDaylightTime(d), isDST); + assertEquals(offset, tz.getOffset(d.getTime())); + assertEquals(isDST, tz.inDaylightTime(d)); } } diff --git a/test/jdk/java/util/TimeZone/ZoneIdRoundTripTest.java b/test/jdk/java/util/TimeZone/ZoneIdRoundTripTest.java index 0f1eeb88328..16e24f7cb27 100644 --- a/test/jdk/java/util/TimeZone/ZoneIdRoundTripTest.java +++ b/test/jdk/java/util/TimeZone/ZoneIdRoundTripTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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,20 +25,20 @@ import java.time.ZoneId; import java.time.ZoneOffset; import java.util.TimeZone; -import org.testng.annotations.Test; -import org.testng.annotations.DataProvider; -import static org.testng.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import org.junit.jupiter.api.TestInstance; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.MethodSource; /** * @test * @bug 8285844 * @summary Checks round-trips between TimeZone and ZoneId are consistent - * @run testng ZoneIdRoundTripTest + * @run junit ZoneIdRoundTripTest */ -@Test +@TestInstance(TestInstance.Lifecycle.PER_CLASS) public class ZoneIdRoundTripTest { - @DataProvider private Object[][] testZoneIds() { return new Object[][] { {ZoneId.of("Z"), 0}, @@ -60,11 +60,12 @@ public class ZoneIdRoundTripTest { }; } - @Test(dataProvider="testZoneIds") + @ParameterizedTest + @MethodSource("testZoneIds") public void test_ZoneIdRoundTrip(ZoneId zid, int offset) { var tz = TimeZone.getTimeZone(zid); - assertEquals(tz.getRawOffset(), offset); - assertEquals(tz.toZoneId().normalized(), zid.normalized()); + assertEquals(offset, tz.getRawOffset()); + assertEquals(zid.normalized(), tz.toZoneId().normalized()); } } From f3a48560b5e3a280f6f76031eb3d475ff9ee49f4 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 17 Dec 2025 18:44:49 +0000 Subject: [PATCH 143/211] 8373807: test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java getURI() uses "localhost" Reviewed-by: jpai --- .../net/httpclient/websocket/DummyWebSocketServer.java | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java index 9034cf9f28a..abc1748e3f2 100644 --- a/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java +++ b/test/jdk/java/net/httpclient/websocket/DummyWebSocketServer.java @@ -351,7 +351,14 @@ public class DummyWebSocketServer implements Closeable { if (!started.get()) { throw new IllegalStateException("Not yet started"); } - return URI.create("ws://localhost:" + address.getPort()); + String ip = address.getAddress().isAnyLocalAddress() + ? InetAddress.getLoopbackAddress().getHostAddress() + : address.getAddress().getHostAddress(); + if (ip.indexOf(':') >= 0) { + ip = String.format("[%s]", ip); + } + + return URI.create("ws://" + ip + ":" + address.getPort()); } private boolean readRequest(SocketChannel channel, StringBuilder request) From e75726ee03ca4664827ca5d680c02bcf2a96f4ea Mon Sep 17 00:00:00 2001 From: Chen Liang Date: Wed, 17 Dec 2025 20:52:14 +0000 Subject: [PATCH 144/211] 8373832: Test java/lang/invoke/TestVHInvokerCaching.java tests nothing Reviewed-by: jvernee, shade --- test/jdk/java/lang/invoke/TestVHInvokerCaching.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java index ccd97f82e9b..0a1ae5914ca 100644 --- a/test/jdk/java/lang/invoke/TestVHInvokerCaching.java +++ b/test/jdk/java/lang/invoke/TestVHInvokerCaching.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, 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,7 +37,7 @@ import java.util.ArrayList; import java.util.List; import static java.lang.invoke.MethodHandles.lookup; -import static org.testng.Assert.assertSame; +import static org.testng.Assert.*; public class TestVHInvokerCaching { @@ -74,7 +74,7 @@ public class TestVHInvokerCaching { MethodHandles.Lookup lookup = lookup(); - for (Field field : Holder.class.getFields()) { + for (Field field : Holder.class.getDeclaredFields()) { String fieldName = field.getName(); Class fieldType = field.getType(); @@ -82,6 +82,8 @@ public class TestVHInvokerCaching { testHandles.add(lookup.findVarHandle(Holder.class, fieldName, fieldType)); } + assertFalse(testHandles.isEmpty()); + return testHandles.stream().map(vh -> new Object[]{ vh }).toArray(Object[][]::new); } } From b3fab41460eabf253879d140b55b6b12036c7c10 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Wed, 17 Dec 2025 22:14:39 +0000 Subject: [PATCH 145/211] 8373654: Tests in sources/ should only run once Reviewed-by: shade, lmesnik --- test/hotspot/jtreg/sources/TestIncludesAreSorted.java | 2 ++ test/hotspot/jtreg/sources/TestNoNULL.java | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java index e0e77992ace..f8694da6c5a 100644 --- a/test/hotspot/jtreg/sources/TestIncludesAreSorted.java +++ b/test/hotspot/jtreg/sources/TestIncludesAreSorted.java @@ -24,6 +24,8 @@ /* * @test * @bug 8343802 + * @comment Only need to run this once, in tier1. + * @requires vm.flagless & vm.debug * @summary Tests that HotSpot C++ files have sorted includes * @build SortIncludes * @run main TestIncludesAreSorted diff --git a/test/hotspot/jtreg/sources/TestNoNULL.java b/test/hotspot/jtreg/sources/TestNoNULL.java index 9c993572aea..b914ea6c799 100644 --- a/test/hotspot/jtreg/sources/TestNoNULL.java +++ b/test/hotspot/jtreg/sources/TestNoNULL.java @@ -24,6 +24,8 @@ /* * @test * @bug 8343802 + * @comment Only need to run this once, in tier1. + * @requires vm.flagless & vm.debug * @summary Test prevent NULL backsliding in hotspot code and tests * @run main TestNoNULL */ From 232b41b2227bc9d03d88d316aa28d0cbe87086f7 Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Wed, 17 Dec 2025 22:16:38 +0000 Subject: [PATCH 146/211] 8373392: Replace CDS object subgraphs with @AOTSafeClassInitializer Reviewed-by: liach, heidinga --- src/hotspot/share/cds/aotArtifactFinder.cpp | 6 +- src/hotspot/share/cds/aotClassInitializer.cpp | 6 +- src/hotspot/share/cds/aotMetaspace.cpp | 2 +- src/hotspot/share/cds/cdsConfig.cpp | 10 +- src/hotspot/share/cds/cdsConfig.hpp | 1 - src/hotspot/share/cds/cdsEnumKlass.cpp | 4 +- src/hotspot/share/cds/cdsEnumKlass.hpp | 2 +- src/hotspot/share/cds/cdsHeapVerifier.cpp | 2 +- src/hotspot/share/cds/finalImageRecipes.cpp | 2 + src/hotspot/share/cds/heapShared.cpp | 48 ++-- .../share/classes/java/lang/Byte.java | 2 + .../share/classes/java/lang/Character.java | 2 + .../share/classes/java/lang/Integer.java | 75 +++-- .../share/classes/java/lang/Long.java | 2 + .../share/classes/java/lang/Module.java | 2 + .../share/classes/java/lang/ModuleLayer.java | 2 + .../share/classes/java/lang/Short.java | 2 + .../java/lang/module/Configuration.java | 2 + .../java/util/ImmutableCollections.java | 15 +- .../classes/java/util/jar/Attributes.java | 4 + .../internal/loader/ArchivedClassLoaders.java | 2 + .../jdk/internal/math/FDBigInteger.java | 3 + .../internal/module/ArchivedBootLayer.java | 4 +- .../internal/module/ArchivedModuleGraph.java | 5 +- .../classes/sun/util/locale/BaseLocale.java | 14 +- test/hotspot/jtreg/TEST.groups | 1 + .../cds/SharedSymbolTableBucketSize.java | 44 ++- .../cds/appcds/aotCache/AOTLoggingTag.java | 11 - .../appcds/aotCache/HeapObjectIdentity.java | 261 ++++++++++++++++++ .../cacheObject/ArchiveHeapTestClass.java | 156 +---------- 30 files changed, 456 insertions(+), 236 deletions(-) create mode 100644 test/hotspot/jtreg/runtime/cds/appcds/aotCache/HeapObjectIdentity.java diff --git a/src/hotspot/share/cds/aotArtifactFinder.cpp b/src/hotspot/share/cds/aotArtifactFinder.cpp index 5f346e832a8..f85f1e46520 100644 --- a/src/hotspot/share/cds/aotArtifactFinder.cpp +++ b/src/hotspot/share/cds/aotArtifactFinder.cpp @@ -145,7 +145,7 @@ void AOTArtifactFinder::find_artifacts() { #if INCLUDE_CDS_JAVA_HEAP // Keep scanning until we discover no more class that need to be AOT-initialized. - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { while (_pending_aot_inited_classes->length() > 0) { InstanceKlass* ik = _pending_aot_inited_classes->pop(); HeapShared::copy_and_rescan_aot_inited_mirror(ik); @@ -188,7 +188,7 @@ void AOTArtifactFinder::end_scanning_for_oops() { } void AOTArtifactFinder::add_aot_inited_class(InstanceKlass* ik) { - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { if (RegeneratedClasses::is_regenerated_object(ik)) { precond(RegeneratedClasses::get_original_object(ik)->is_initialized()); } else { @@ -258,7 +258,7 @@ void AOTArtifactFinder::add_cached_instance_class(InstanceKlass* ik) { return; } scan_oops_in_instance_class(ik); - if (ik->is_hidden() && CDSConfig::is_initing_classes_at_dump_time()) { + if (ik->is_hidden() && CDSConfig::is_dumping_aot_linked_classes()) { bool succeed = AOTClassLinker::try_add_candidate(ik); guarantee(succeed, "All cached hidden classes must be aot-linkable"); add_aot_inited_class(ik); diff --git a/src/hotspot/share/cds/aotClassInitializer.cpp b/src/hotspot/share/cds/aotClassInitializer.cpp index 00db747622f..06fc3af6f30 100644 --- a/src/hotspot/share/cds/aotClassInitializer.cpp +++ b/src/hotspot/share/cds/aotClassInitializer.cpp @@ -40,7 +40,7 @@ DEBUG_ONLY(InstanceKlass* _aot_init_class = nullptr;) bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { assert(!ArchiveBuilder::is_active() || !ArchiveBuilder::current()->is_in_buffer_space(ik), "must be source klass"); - if (!CDSConfig::is_initing_classes_at_dump_time()) { + if (!CDSConfig::is_dumping_aot_linked_classes()) { return false; } @@ -64,7 +64,7 @@ bool AOTClassInitializer::can_archive_initialized_mirror(InstanceKlass* ik) { // Automatic selection for aot-inited classes // ========================================== // - // When CDSConfig::is_initing_classes_at_dump_time is enabled, + // When CDSConfig::is_dumping_aot_linked_classes is enabled, // AOTArtifactFinder::find_artifacts() finds the classes of all // heap objects that are reachable from HeapShared::_run_time_special_subgraph, // and mark these classes as aot-inited. This preserves the initialized @@ -310,7 +310,7 @@ void AOTClassInitializer::init_test_class(TRAPS) { // // -XX:AOTInitTestClass is NOT a general mechanism for including user-defined objects into // the AOT cache. Therefore, this option is NOT available in product JVM. - if (AOTInitTestClass != nullptr && CDSConfig::is_initing_classes_at_dump_time()) { + if (AOTInitTestClass != nullptr && CDSConfig::is_dumping_aot_linked_classes()) { log_info(aot)("Debug build only: force initialization of AOTInitTestClass %s", AOTInitTestClass); TempNewSymbol class_name = SymbolTable::new_symbol(AOTInitTestClass); Handle app_loader(THREAD, SystemDictionary::java_system_loader()); diff --git a/src/hotspot/share/cds/aotMetaspace.cpp b/src/hotspot/share/cds/aotMetaspace.cpp index 098d3baed58..3824a2be3e2 100644 --- a/src/hotspot/share/cds/aotMetaspace.cpp +++ b/src/hotspot/share/cds/aotMetaspace.cpp @@ -1141,7 +1141,7 @@ void AOTMetaspace::dump_static_archive_impl(StaticArchiveBuilder& builder, TRAPS AOTReferenceObjSupport::initialize(CHECK); AOTReferenceObjSupport::stabilize_cached_reference_objects(CHECK); - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { // java.lang.Class::reflectionFactory cannot be archived yet. We set this field // to null, and it will be initialized again at runtime. log_debug(aot)("Resetting Class::reflectionFactory"); diff --git a/src/hotspot/share/cds/cdsConfig.cpp b/src/hotspot/share/cds/cdsConfig.cpp index 86533e212d8..5f6b568dd6e 100644 --- a/src/hotspot/share/cds/cdsConfig.cpp +++ b/src/hotspot/share/cds/cdsConfig.cpp @@ -1026,23 +1026,19 @@ void CDSConfig::set_has_aot_linked_classes(bool has_aot_linked_classes) { _has_aot_linked_classes |= has_aot_linked_classes; } -bool CDSConfig::is_initing_classes_at_dump_time() { - return is_dumping_heap() && is_dumping_aot_linked_classes(); -} - bool CDSConfig::is_dumping_invokedynamic() { // Requires is_dumping_aot_linked_classes(). Otherwise the classes of some archived heap // objects used by the archive indy callsites may be replaced at runtime. return AOTInvokeDynamicLinking && is_dumping_aot_linked_classes() && is_dumping_heap(); } -// When we are dumping aot-linked classes and we are able to write archived heap objects, we automatically -// enable the archiving of MethodHandles. This will in turn enable the archiving of MethodTypes and hidden +// When we are dumping aot-linked classes, we automatically enable the archiving of MethodHandles. +// This will in turn enable the archiving of MethodTypes and hidden // classes that are used in the implementation of MethodHandles. // Archived MethodHandles are required for higher-level optimizations such as AOT resolution of invokedynamic // and dynamic proxies. bool CDSConfig::is_dumping_method_handles() { - return is_initing_classes_at_dump_time(); + return is_dumping_aot_linked_classes(); } #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/cdsConfig.hpp b/src/hotspot/share/cds/cdsConfig.hpp index d199e97eefd..202904e8231 100644 --- a/src/hotspot/share/cds/cdsConfig.hpp +++ b/src/hotspot/share/cds/cdsConfig.hpp @@ -187,7 +187,6 @@ public: static void disable_heap_dumping() { CDS_ONLY(_disable_heap_dumping = true); } static bool is_dumping_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); static bool is_loading_heap() NOT_CDS_JAVA_HEAP_RETURN_(false); - static bool is_initing_classes_at_dump_time() NOT_CDS_JAVA_HEAP_RETURN_(false); static bool is_dumping_invokedynamic() NOT_CDS_JAVA_HEAP_RETURN_(false); static bool is_dumping_method_handles() NOT_CDS_JAVA_HEAP_RETURN_(false); diff --git a/src/hotspot/share/cds/cdsEnumKlass.cpp b/src/hotspot/share/cds/cdsEnumKlass.cpp index 1bf6ba4eba8..177d1d6e3ad 100644 --- a/src/hotspot/share/cds/cdsEnumKlass.cpp +++ b/src/hotspot/share/cds/cdsEnumKlass.cpp @@ -40,7 +40,7 @@ bool CDSEnumKlass::is_enum_obj(oop orig_obj) { } // !!! This is legacy support for enum classes before JEP 483. This file is not used when -// !!! CDSConfig::is_initing_classes_at_dump_time()==true. +// !!! CDSConfig::is_dumping_aot_linked_classes()==true. // // Java Enum classes have synthetic methods that look like this // enum MyEnum {FOO, BAR} @@ -63,7 +63,7 @@ bool CDSEnumKlass::is_enum_obj(oop orig_obj) { void CDSEnumKlass::handle_enum_obj(int level, KlassSubGraphInfo* subgraph_info, oop orig_obj) { - assert(!CDSConfig::is_initing_classes_at_dump_time(), "only for legacy support of enums"); + assert(!CDSConfig::is_dumping_aot_linked_classes(), "only for legacy support of enums"); assert(level > 1, "must never be called at the first (outermost) level"); assert(is_enum_obj(orig_obj), "must be"); diff --git a/src/hotspot/share/cds/cdsEnumKlass.hpp b/src/hotspot/share/cds/cdsEnumKlass.hpp index e6019ff705e..a4829368430 100644 --- a/src/hotspot/share/cds/cdsEnumKlass.hpp +++ b/src/hotspot/share/cds/cdsEnumKlass.hpp @@ -35,7 +35,7 @@ class JavaFieldStream; class KlassSubGraphInfo; // This is legacy support for enum classes before JEP 483. This code is not needed when -// CDSConfig::is_initing_classes_at_dump_time()==true. +// CDSConfig::is_dumping_aot_linked_classes()==true. class CDSEnumKlass: AllStatic { public: static bool is_enum_obj(oop orig_obj); diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index 65063b4b005..3ed0dce1f66 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -156,7 +156,7 @@ CDSHeapVerifier::CDSHeapVerifier() : _archived_objs(0), _problems(0) # undef ADD_EXCL - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { add_shared_secret_accessors(); } ClassLoaderDataGraph::classes_do(this); diff --git a/src/hotspot/share/cds/finalImageRecipes.cpp b/src/hotspot/share/cds/finalImageRecipes.cpp index bf8a760904c..8ba4514dfed 100644 --- a/src/hotspot/share/cds/finalImageRecipes.cpp +++ b/src/hotspot/share/cds/finalImageRecipes.cpp @@ -206,6 +206,8 @@ void FinalImageRecipes::load_all_classes(TRAPS) { if (ik->has_aot_safe_initializer() && (flags & WAS_INITED) != 0) { assert(ik->class_loader() == nullptr, "supported only for boot classes for now"); + ResourceMark rm(THREAD); + log_info(aot, init)("Initializing %s", ik->external_name()); ik->initialize(CHECK); } } diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index f2382289c7d..fdc335f3799 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -209,8 +209,14 @@ static bool is_subgraph_root_class_of(ArchivableStaticFieldInfo fields[], Instan } bool HeapShared::is_subgraph_root_class(InstanceKlass* ik) { - return is_subgraph_root_class_of(archive_subgraph_entry_fields, ik) || - is_subgraph_root_class_of(fmg_archive_subgraph_entry_fields, ik); + assert(CDSConfig::is_dumping_heap(), "dump-time only"); + if (!CDSConfig::is_dumping_aot_linked_classes()) { + // Legacy CDS archive support (to be deprecated) + return is_subgraph_root_class_of(archive_subgraph_entry_fields, ik) || + is_subgraph_root_class_of(fmg_archive_subgraph_entry_fields, ik); + } else { + return false; + } } oop HeapShared::CachedOopInfo::orig_referrer() const { @@ -934,12 +940,16 @@ void HeapShared::scan_java_class(Klass* orig_k) { void HeapShared::archive_subgraphs() { assert(CDSConfig::is_dumping_heap(), "must be"); - archive_object_subgraphs(archive_subgraph_entry_fields, - false /* is_full_module_graph */); + if (!CDSConfig::is_dumping_aot_linked_classes()) { + archive_object_subgraphs(archive_subgraph_entry_fields, + false /* is_full_module_graph */); + if (CDSConfig::is_dumping_full_module_graph()) { + archive_object_subgraphs(fmg_archive_subgraph_entry_fields, + true /* is_full_module_graph */); + } + } if (CDSConfig::is_dumping_full_module_graph()) { - archive_object_subgraphs(fmg_archive_subgraph_entry_fields, - true /* is_full_module_graph */); Modules::verify_archived_modules(); } } @@ -1295,8 +1305,10 @@ void HeapShared::resolve_classes(JavaThread* current) { if (!is_archived_heap_in_use()) { return; // nothing to do } - resolve_classes_for_subgraphs(current, archive_subgraph_entry_fields); - resolve_classes_for_subgraphs(current, fmg_archive_subgraph_entry_fields); + if (!CDSConfig::is_using_aot_linked_classes()) { + resolve_classes_for_subgraphs(current, archive_subgraph_entry_fields); + resolve_classes_for_subgraphs(current, fmg_archive_subgraph_entry_fields); + } } void HeapShared::resolve_classes_for_subgraphs(JavaThread* current, ArchivableStaticFieldInfo fields[]) { @@ -1734,13 +1746,13 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap } } - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { if (java_lang_Class::is_instance(orig_obj)) { orig_obj = scratch_java_mirror(orig_obj); assert(orig_obj != nullptr, "must be archived"); } } else if (java_lang_Class::is_instance(orig_obj) && subgraph_info != _dump_time_special_subgraph) { - // Without CDSConfig::is_initing_classes_at_dump_time(), we only allow archived objects to + // Without CDSConfig::is_dumping_aot_linked_classes(), we only allow archived objects to // point to the mirrors of (1) j.l.Object, (2) primitive classes, and (3) box classes. These are initialized // very early by HeapShared::init_box_classes(). if (orig_obj == vmClasses::Object_klass()->java_mirror() @@ -1808,9 +1820,9 @@ bool HeapShared::walk_one_object(PendingOopStack* stack, int level, KlassSubGrap orig_obj->oop_iterate(&pusher); } - if (CDSConfig::is_initing_classes_at_dump_time()) { - // The classes of all archived enum instances have been marked as aot-init, - // so there's nothing else to be done in the production run. + if (CDSConfig::is_dumping_aot_linked_classes()) { + // The enum klasses are archived with aot-initialized mirror. + // See AOTClassInitializer::can_archive_initialized_mirror(). } else { // This is legacy support for enum classes before JEP 483 -- we cannot rerun // the enum's in the production run, so special handling is needed. @@ -1949,7 +1961,7 @@ void HeapShared::verify_reachable_objects_from(oop obj) { #endif void HeapShared::check_special_subgraph_classes() { - if (CDSConfig::is_initing_classes_at_dump_time()) { + if (CDSConfig::is_dumping_aot_linked_classes()) { // We can have aot-initialized classes (such as Enums) that can reference objects // of arbitrary types. Currently, we trust the JEP 483 implementation to only // aot-initialize classes that are "safe". @@ -2136,9 +2148,11 @@ void HeapShared::init_subgraph_entry_fields(ArchivableStaticFieldInfo fields[], void HeapShared::init_subgraph_entry_fields(TRAPS) { assert(CDSConfig::is_dumping_heap(), "must be"); _dump_time_subgraph_info_table = new (mtClass)DumpTimeKlassSubGraphInfoTable(); - init_subgraph_entry_fields(archive_subgraph_entry_fields, CHECK); - if (CDSConfig::is_dumping_full_module_graph()) { - init_subgraph_entry_fields(fmg_archive_subgraph_entry_fields, CHECK); + if (!CDSConfig::is_dumping_aot_linked_classes()) { + init_subgraph_entry_fields(archive_subgraph_entry_fields, CHECK); + if (CDSConfig::is_dumping_full_module_graph()) { + init_subgraph_entry_fields(fmg_archive_subgraph_entry_fields, CHECK); + } } } diff --git a/src/java.base/share/classes/java/lang/Byte.java b/src/java.base/share/classes/java/lang/Byte.java index d9913e354a4..0f3f7f40d05 100644 --- a/src/java.base/share/classes/java/lang/Byte.java +++ b/src/java.base/share/classes/java/lang/Byte.java @@ -26,6 +26,7 @@ package java.lang; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -103,6 +104,7 @@ public final class Byte extends Number implements Comparable, Constable { return Optional.of(DynamicConstantDesc.ofNamed(BSM_EXPLICIT_CAST, DEFAULT_NAME, CD_byte, intValue())); } + @AOTSafeClassInitializer private static final class ByteCache { private ByteCache() {} diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index b71849eaee7..ffda729a45a 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -26,6 +26,7 @@ package java.lang; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -9379,6 +9380,7 @@ class Character implements java.io.Serializable, Comparable, Constabl this.value = value; } + @AOTSafeClassInitializer private static final class CharacterCache { private CharacterCache(){} diff --git a/src/java.base/share/classes/java/lang/Integer.java b/src/java.base/share/classes/java/lang/Integer.java index 2742ec40abf..a9da1c32490 100644 --- a/src/java.base/share/classes/java/lang/Integer.java +++ b/src/java.base/share/classes/java/lang/Integer.java @@ -28,6 +28,8 @@ package java.lang; import jdk.internal.misc.CDS; import jdk.internal.misc.VM; import jdk.internal.util.DecimalDigits; +import jdk.internal.vm.annotation.AOTRuntimeSetup; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -891,15 +893,20 @@ public final class Integer extends Number * with new Integer object(s) after initialization. */ + @AOTSafeClassInitializer private static final class IntegerCache { static final int low = -128; - static final int high; + @Stable static int high; - @Stable - static final Integer[] cache; + @Stable static Integer[] cache; static Integer[] archivedCache; static { + runtimeSetup(); + } + + @AOTRuntimeSetup + private static void runtimeSetup() { // high value may be configured by property int h = 127; String integerCacheHighPropValue = @@ -915,34 +922,50 @@ public final class Integer extends Number } high = h; - // Load IntegerCache.archivedCache from archive, if possible - CDS.initializeFromArchive(IntegerCache.class); - int size = (high - low) + 1; - - // Use the archived cache if it exists and is large enough - if (archivedCache == null || size > archivedCache.length) { - Integer[] c = new Integer[size]; - int j = low; - // If archive has Integer cache, we must use all instances from it. - // Otherwise, the identity checks between archived Integers and - // runtime-cached Integers would fail. - int archivedSize = (archivedCache == null) ? 0 : archivedCache.length; - for (int i = 0; i < archivedSize; i++) { - c[i] = archivedCache[i]; - assert j == archivedCache[i]; - j++; - } - // Fill the rest of the cache. - for (int i = archivedSize; i < size; i++) { - c[i] = new Integer(j++); - } - archivedCache = c; + Integer[] precomputed = null; + if (cache != null) { + // IntegerCache has been AOT-initialized. + precomputed = cache; + } else { + // Legacy CDS archive support (to be deprecated): + // Load IntegerCache.archivedCache from archive, if possible + CDS.initializeFromArchive(IntegerCache.class); + precomputed = archivedCache; } - cache = archivedCache; + + cache = loadOrInitializeCache(precomputed); + archivedCache = cache; // Legacy CDS archive support (to be deprecated) // range [-128, 127] must be interned (JLS7 5.1.7) assert IntegerCache.high >= 127; } + private static Integer[] loadOrInitializeCache(Integer[] precomputed) { + int size = (high - low) + 1; + + // Use the precomputed cache if it exists and is large enough + if (precomputed != null && size <= precomputed.length) { + return precomputed; + } + + Integer[] c = new Integer[size]; + int j = low; + // If we loading a precomputed cache (from AOT cache or CDS archive), + // we must use all instances from it. + // Otherwise, the Integers from the AOT cache (or CDS archive) will not + // have the same object identity as items in IntegerCache.cache[]. + int precomputedSize = (precomputed == null) ? 0 : precomputed.length; + for (int i = 0; i < precomputedSize; i++) { + c[i] = precomputed[i]; + assert j == precomputed[i]; + j++; + } + // Fill the rest of the cache. + for (int i = precomputedSize; i < size; i++) { + c[i] = new Integer(j++); + } + return c; + } + private IntegerCache() {} } diff --git a/src/java.base/share/classes/java/lang/Long.java b/src/java.base/share/classes/java/lang/Long.java index 3077e7c0a38..c5cd9650f2d 100644 --- a/src/java.base/share/classes/java/lang/Long.java +++ b/src/java.base/share/classes/java/lang/Long.java @@ -35,6 +35,7 @@ import java.util.Optional; import jdk.internal.misc.CDS; import jdk.internal.util.DecimalDigits; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -911,6 +912,7 @@ public final class Long extends Number return Long.valueOf(parseLong(s, 10)); } + @AOTSafeClassInitializer private static final class LongCache { private LongCache() {} diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index cd2b8095ee4..bd04345554b 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -69,6 +69,7 @@ import jdk.internal.module.ServicesCatalog; import jdk.internal.module.Resources; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; /** @@ -391,6 +392,7 @@ public final class Module implements AnnotatedElement { private static final Module EVERYONE_MODULE; private static final Set EVERYONE_SET; + @AOTSafeClassInitializer private static class ArchivedData { private static ArchivedData archivedData; private final Module allUnnamedModule; diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index 9d922f787a6..a073de6b14a 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -53,6 +53,7 @@ import jdk.internal.module.ServicesCatalog; import jdk.internal.misc.CDS; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; /** @@ -145,6 +146,7 @@ import jdk.internal.vm.annotation.Stable; * @see Module#getLayer() */ +@AOTSafeClassInitializer public final class ModuleLayer { // the empty layer (may be initialized from the CDS archive) diff --git a/src/java.base/share/classes/java/lang/Short.java b/src/java.base/share/classes/java/lang/Short.java index 4c64427b6df..920500a7fa3 100644 --- a/src/java.base/share/classes/java/lang/Short.java +++ b/src/java.base/share/classes/java/lang/Short.java @@ -26,6 +26,7 @@ package java.lang; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; @@ -230,6 +231,7 @@ public final class Short extends Number implements Comparable, Constable return Optional.of(DynamicConstantDesc.ofNamed(BSM_EXPLICIT_CAST, DEFAULT_NAME, CD_short, intValue())); } + @AOTSafeClassInitializer private static final class ShortCache { private ShortCache() {} diff --git a/src/java.base/share/classes/java/lang/module/Configuration.java b/src/java.base/share/classes/java/lang/module/Configuration.java index a76a32cfb28..40eeddc3f0b 100644 --- a/src/java.base/share/classes/java/lang/module/Configuration.java +++ b/src/java.base/share/classes/java/lang/module/Configuration.java @@ -44,6 +44,7 @@ import java.util.stream.Stream; import jdk.internal.misc.CDS; import jdk.internal.module.ModuleReferenceImpl; import jdk.internal.module.ModuleTarget; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; /** @@ -155,6 +156,7 @@ import jdk.internal.vm.annotation.Stable; * @since 9 * @see java.lang.ModuleLayer */ +@AOTSafeClassInitializer public final class Configuration { // @see Configuration#empty() diff --git a/src/java.base/share/classes/java/util/ImmutableCollections.java b/src/java.base/share/classes/java/util/ImmutableCollections.java index abc48ff5ed9..e7fe22490da 100644 --- a/src/java.base/share/classes/java/util/ImmutableCollections.java +++ b/src/java.base/share/classes/java/util/ImmutableCollections.java @@ -42,6 +42,9 @@ import java.util.function.UnaryOperator; import jdk.internal.access.JavaUtilCollectionAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTRuntimeSetup; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; +import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; /** @@ -52,6 +55,7 @@ import jdk.internal.vm.annotation.Stable; * classes use a serial proxy and thus have no need to declare serialVersionUID. */ @SuppressWarnings("serial") +@AOTSafeClassInitializer class ImmutableCollections { /** * A "salt" value used for randomizing iteration order. This is initialized once @@ -59,14 +63,20 @@ class ImmutableCollections { * it needs to vary sufficiently from one run to the next so that iteration order * will vary between JVM runs. */ - private static final long SALT32L; + @Stable private static long SALT32L; /** * For set and map iteration, we will iterate in "reverse" stochastically, * decided at bootstrap time. */ - private static final boolean REVERSE; + @Stable private static boolean REVERSE; + static { + runtimeSetup(); + } + + @AOTRuntimeSetup + private static void runtimeSetup() { // to generate a reasonably random and well-mixed SALT, use an arbitrary // value (a slice of pi), multiply with a random seed, then pick // the mid 32-bits from the product. By picking a SALT value in the @@ -102,6 +112,7 @@ class ImmutableCollections { static final MapN EMPTY_MAP; static { + // Legacy CDS archive support (to be deprecated) CDS.initializeFromArchive(ImmutableCollections.class); if (archivedObjects == null) { EMPTY = new Object(); diff --git a/src/java.base/share/classes/java/util/jar/Attributes.java b/src/java.base/share/classes/java/util/jar/Attributes.java index 9322bb9acac..20ff81676c9 100644 --- a/src/java.base/share/classes/java/util/jar/Attributes.java +++ b/src/java.base/share/classes/java/util/jar/Attributes.java @@ -36,6 +36,7 @@ import java.util.Objects; import java.util.Set; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; import sun.nio.cs.UTF_8; @@ -60,6 +61,7 @@ import sun.util.logging.PlatformLogger; * @see Manifest * @since 1.2 */ +@AOTSafeClassInitializer public class Attributes implements Map, Cloneable { /** * The attribute name-value mappings. @@ -450,6 +452,7 @@ public class Attributes implements Map, Cloneable { * * @spec jar/jar.html JAR File Specification */ + @AOTSafeClassInitializer public static class Name { private final String name; private final int hashCode; @@ -669,6 +672,7 @@ public class Attributes implements Map, Cloneable { static { + // Legacy CDS archive support (to be deprecated) CDS.initializeFromArchive(Attributes.Name.class); if (KNOWN_NAMES == null) { diff --git a/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java index be3425590fc..439772a8789 100644 --- a/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java +++ b/src/java.base/share/classes/jdk/internal/loader/ArchivedClassLoaders.java @@ -27,11 +27,13 @@ package jdk.internal.loader; import java.util.Map; import jdk.internal.misc.CDS; import jdk.internal.module.ServicesCatalog; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; /** * Used to archive the built-in class loaders, their services catalogs, and the * package-to-module map used by the built-in class loaders. */ +@AOTSafeClassInitializer class ArchivedClassLoaders { private static ArchivedClassLoaders archivedClassLoaders; diff --git a/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java index 1ef9dee3a8a..5413226c112 100644 --- a/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java +++ b/src/java.base/share/classes/jdk/internal/math/FDBigInteger.java @@ -26,6 +26,7 @@ package jdk.internal.math; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; import java.util.Arrays; @@ -33,6 +34,7 @@ import java.util.Arrays; /** * A simple big integer class specifically for floating point base conversion. */ +@AOTSafeClassInitializer final class FDBigInteger { @Stable @@ -53,6 +55,7 @@ final class FDBigInteger { // Initialize FDBigInteger cache of powers of 5. static { + // Legacy CDS archive support (to be deprecated) CDS.initializeFromArchive(FDBigInteger.class); Object[] caches = archivedCaches; if (caches == null) { diff --git a/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java b/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java index 5c806f81dcd..425238dd521 100644 --- a/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java +++ b/src/java.base/share/classes/jdk/internal/module/ArchivedBootLayer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2025, 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,10 +25,12 @@ package jdk.internal.module; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; /** * Used by ModuleBootstrap for archiving the boot layer. */ +@AOTSafeClassInitializer class ArchivedBootLayer { private static ArchivedBootLayer archivedBootLayer; diff --git a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java index 4f9223d0171..deb280c878d 100644 --- a/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java +++ b/src/java.base/share/classes/jdk/internal/module/ArchivedModuleGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2025, 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 @@ -30,11 +30,13 @@ import java.util.function.Function; import java.lang.module.Configuration; import java.lang.module.ModuleFinder; import jdk.internal.misc.CDS; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; /** * Used by ModuleBootstrap for archiving the configuration for the boot layer, * and the system module finder. */ +@AOTSafeClassInitializer class ArchivedModuleGraph { private static ArchivedModuleGraph archivedModuleGraph; @@ -126,6 +128,7 @@ class ArchivedModuleGraph { } static { + // Legacy CDS archive support (to be deprecated) CDS.initializeFromArchive(ArchivedModuleGraph.class); } } diff --git a/src/java.base/share/classes/sun/util/locale/BaseLocale.java b/src/java.base/share/classes/sun/util/locale/BaseLocale.java index 58ec6d76aa5..31078720ddc 100644 --- a/src/java.base/share/classes/sun/util/locale/BaseLocale.java +++ b/src/java.base/share/classes/sun/util/locale/BaseLocale.java @@ -34,11 +34,14 @@ package sun.util.locale; import jdk.internal.misc.CDS; import jdk.internal.util.ReferencedKeySet; +import jdk.internal.vm.annotation.AOTRuntimeSetup; +import jdk.internal.vm.annotation.AOTSafeClassInitializer; import jdk.internal.vm.annotation.Stable; import java.util.StringJoiner; import java.util.function.Supplier; +@AOTSafeClassInitializer public final class BaseLocale { public static @Stable BaseLocale[] constantBaseLocales; @@ -63,6 +66,7 @@ public final class BaseLocale { CANADA_FRENCH = 18, NUM_CONSTANTS = 19; static { + // Legacy CDS archive support (to be deprecated) CDS.initializeFromArchive(BaseLocale.class); BaseLocale[] baseLocales = constantBaseLocales; if (baseLocales == null) { @@ -91,13 +95,21 @@ public final class BaseLocale { } // Interned BaseLocale cache - private static final LazyConstant> CACHE = + @Stable private static LazyConstant> CACHE; + static { + runtimeSetup(); + } + + @AOTRuntimeSetup + private static void runtimeSetup() { + CACHE = LazyConstant.of(new Supplier<>() { @Override public ReferencedKeySet get() { return ReferencedKeySet.create(true, ReferencedKeySet.concurrentHashMapSupplier()); } }); + } public static final String SEP = "_"; diff --git a/test/hotspot/jtreg/TEST.groups b/test/hotspot/jtreg/TEST.groups index d4f1470aea5..2288e8f8876 100644 --- a/test/hotspot/jtreg/TEST.groups +++ b/test/hotspot/jtreg/TEST.groups @@ -522,6 +522,7 @@ hotspot_aot_classlinking = \ -runtime/cds/appcds/aotFlags \ -runtime/cds/appcds/aotProfile \ -runtime/cds/appcds/BadBSM.java \ + -runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java \ -runtime/cds/appcds/cacheObject/ArchivedIntegerCacheTest.java \ -runtime/cds/appcds/cacheObject/ArchivedModuleCompareTest.java \ -runtime/cds/appcds/CDSandJFR.java \ diff --git a/test/hotspot/jtreg/runtime/cds/SharedSymbolTableBucketSize.java b/test/hotspot/jtreg/runtime/cds/SharedSymbolTableBucketSize.java index 2db4ab2df23..070384a2703 100644 --- a/test/hotspot/jtreg/runtime/cds/SharedSymbolTableBucketSize.java +++ b/test/hotspot/jtreg/runtime/cds/SharedSymbolTableBucketSize.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2025, 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 @@ -31,6 +31,8 @@ * java.management */ +import java.util.regex.Matcher; +import java.util.regex.Pattern; import jdk.test.lib.cds.CDSTestUtils; import jdk.test.lib.process.OutputAnalyzer; @@ -43,8 +45,44 @@ public class SharedSymbolTableBucketSize { + Integer.valueOf(bucket_size)); CDSTestUtils.checkMappingFailure(output); - String regex = "Average bucket size : ([0-9]+\\.[0-9]+).*"; - String s = output.firstMatch(regex, 1); + /* [1] There may be other table stats that precede the symbol tabble. + Skip all thse until we find this: + + [0.677s][info][aot,hashtables] Shared symbol table stats -------- base: 0x0000000800000000 + [0.677s][info][aot,hashtables] Number of entries : 46244 + [0.677s][info][aot,hashtables] Total bytes used : 393792 + [0.677s][info][aot,hashtables] Average bytes per entry : 8.516 + [0.677s][info][aot,hashtables] Average bucket size : 7.734 + [0.677s][info][aot,hashtables] Variance of bucket size : 7.513 + [0.677s][info][aot,hashtables] Std. dev. of bucket size: 2.741 + [0.677s][info][aot,hashtables] Maximum bucket size : 20 + [0.677s][info][aot,hashtables] Empty buckets : 2 + [0.677s][info][aot,hashtables] Value_Only buckets : 24 + [0.677s][info][aot,hashtables] Other buckets : 5953 + .... + */ + Pattern pattern0 = Pattern.compile("Shared symbol table stats.*", Pattern.DOTALL); + Matcher matcher0 = pattern0.matcher(output.getStdout()); + String stat = null; + if (matcher0.find()) { + stat = matcher0.group(0); + } + if (stat == null) { + throw new Exception("FAILED: pattern \"" + pattern0 + "\" not found"); + } + + /* (2) The first "Average bucket size" line in the remaining output is for the + shared symbol table */ + Pattern pattern = Pattern.compile("Average bucket size *: *([0-9]+\\.[0-9]+).*", Pattern.MULTILINE); + Matcher matcher = pattern.matcher(stat); + String s = null; + if (matcher.find()) { + s = matcher.group(1); + } + if (s == null) { + throw new Exception("FAILED: pattern \"" + pattern + "\" not found"); + } + Float f = Float.parseFloat(s); int size = Math.round(f); if (size != bucket_size) { diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java index 896df7ca496..4cc6ef81c45 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/AOTLoggingTag.java @@ -83,17 +83,6 @@ public class AOTLoggingTag { out.shouldContain("[aot] Opened AOT cache hello.aot"); out.shouldHaveExitValue(0); - //---------------------------------------------------------------------- - printTestCase("All old -Xlog:cds+heap logs have been changed to -Xlog:aot+heap should alias to -Xlog:cds+heap"); - pb = ProcessTools.createLimitedTestJavaProcessBuilder( - "-XX:AOTCache=" + aotCacheFile, - "-Xlog:aot+heap", - "-cp", appJar, helloClass); - out = CDSTestUtils.executeAndLog(pb, "prod"); - out.shouldNotContain("No tag set matches selection: aot+heap"); - out.shouldContain("[aot,heap] resolve subgraph java.lang.Integer$IntegerCache"); - out.shouldHaveExitValue(0); - //---------------------------------------------------------------------- printTestCase("Production Run: errors should be printed with [aot] decoration"); pb = ProcessTools.createLimitedTestJavaProcessBuilder( diff --git a/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HeapObjectIdentity.java b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HeapObjectIdentity.java new file mode 100644 index 00000000000..cdd0921627a --- /dev/null +++ b/test/hotspot/jtreg/runtime/cds/appcds/aotCache/HeapObjectIdentity.java @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2025, 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 AOT cache should preserve heap object identity when required by JLS. For example, Enums and Integers. + * @requires vm.cds + * @requires vm.cds.supports.aot.class.linking + * @requires vm.debug + * @library /test/lib + * @build HeapObjectIdentity + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar dummy.jar + * Dummy + * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar + * HeapObjectIdentityApp + * MyAOTInitedClass + * MyAOTInitedClass$MyEnum + * MyAOTInitedClass$Wrapper + * @run driver HeapObjectIdentity AOT --two-step-training + */ + +import jdk.test.lib.cds.CDSAppTester; +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.helpers.ClassFileInstaller; + +public class HeapObjectIdentity { + static final String appJar = ClassFileInstaller.getJarPath("dummy.jar"); + static final String bootJar = ClassFileInstaller.getJarPath("boot.jar"); + static final String mainClass = "HeapObjectIdentityApp"; // Loaded from boot.jar + + public static void main(String[] args) throws Exception { + Tester t = new Tester(); + t.run(args); + + // Integer$IntegerCache should preserve the object identity of cached Integer objects, + // even when the cache size is different between assembly and production. + t.productionRun(new String[] { + "-XX:AutoBoxCacheMax=2048" + }); + } + + static class Tester extends CDSAppTester { + public Tester() { + super(mainClass); + } + + @Override + public String classpath(RunMode runMode) { + return appJar; + } + + @Override + public String[] vmArgs(RunMode runMode) { + String bootcp = "-Xbootclasspath/a:" + bootJar; + if (runMode == RunMode.ASSEMBLY) { + return new String[] { + "-Xlog:aot+class=debug", + "-XX:AOTInitTestClass=MyAOTInitedClass", + bootcp + }; + } else { + return new String[] {bootcp}; + } + } + + @Override + public String[] appCommandLine(RunMode runMode) { + return new String[] { + mainClass, + runMode.toString(), + }; + } + + @Override + public void checkExecution(OutputAnalyzer out, RunMode runMode) throws Exception { + if (runMode == RunMode.ASSEMBLY) { + out.shouldContain("MyAOTInitedClass aot-linked inited"); + } + } + } +} + +class HeapObjectIdentityApp { + public static void main(String... args) { + MyAOTInitedClass.test(); + } +} + +// This class is loaded by the boot loader, as -XX:AOTInitTestClass is not too friendly +// with classes by other loaders. +class MyAOTInitedClass { + static Object[] archivedObjects; + static { + if (archivedObjects == null) { + archivedObjects = new Object[14]; + archivedObjects[0] = Wrapper.BOOLEAN; + archivedObjects[1] = Wrapper.INT.zero(); + archivedObjects[2] = Wrapper.DOUBLE.zero(); + archivedObjects[3] = MyEnum.DUMMY1; + + archivedObjects[4] = Boolean.class; + archivedObjects[5] = Byte.class; + archivedObjects[6] = Character.class; + archivedObjects[7] = Short.class; + archivedObjects[8] = Integer.class; + archivedObjects[9] = Long.class; + archivedObjects[10] = Float.class; + archivedObjects[11] = Double.class; + archivedObjects[12] = Void.class; + + archivedObjects[13] = Integer.valueOf(1); + } else { + System.out.println("Initialized from CDS"); + } + } + + public static void test() { + if (archivedObjects[0] != Wrapper.BOOLEAN) { + throw new RuntimeException("Huh 0"); + } + + if (archivedObjects[1] != Wrapper.INT.zero()) { + throw new RuntimeException("Huh 1"); + } + + if (archivedObjects[2] != Wrapper.DOUBLE.zero()) { + throw new RuntimeException("Huh 2"); + } + + if (archivedObjects[3] != MyEnum.DUMMY1) { + throw new RuntimeException("Huh 3"); + } + + if (MyEnum.BOOLEAN != true) { + throw new RuntimeException("Huh 10.1"); + } + if (MyEnum.BYTE != -128) { + throw new RuntimeException("Huh 10.2"); + } + if (MyEnum.CHAR != 'c') { + throw new RuntimeException("Huh 10.3"); + } + if (MyEnum.SHORT != -12345) { + throw new RuntimeException("Huh 10.4"); + } + if (MyEnum.INT != -123456) { + throw new RuntimeException("Huh 10.5"); + } + if (MyEnum.LONG != 0x1234567890L) { + throw new RuntimeException("Huh 10.6"); + } + if (MyEnum.LONG2 != -0x1234567890L) { + throw new RuntimeException("Huh 10.7"); + } + if (MyEnum.FLOAT != 567891.0f) { + throw new RuntimeException("Huh 10.8"); + } + if (MyEnum.DOUBLE != 12345678905678.890) { + throw new RuntimeException("Huh 10.9"); + } + + checkClass(4, Boolean.class); + checkClass(5, Byte.class); + checkClass(6, Character.class); + checkClass(7, Short.class); + checkClass(8, Integer.class); + checkClass(9, Long.class); + checkClass(10, Float.class); + checkClass(11, Double.class); + checkClass(12, Void.class); + + if (archivedObjects[13] != Integer.valueOf(1)) { + throw new RuntimeException("Integer cache identity test failed"); + } + + System.out.println("Success!"); + } + + static void checkClass(int index, Class c) { + if (archivedObjects[index] != c) { + throw new RuntimeException("archivedObjects[" + index + "] should be " + c); + } + } + + // Simplified version of sun.invoke.util.Wrapper + public enum Wrapper { + // wrapperType simple primitiveType simple char emptyArray + BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0]), + INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0]), + DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0]) + ; + + public static final int COUNT = 10; + private static final Object DOUBLE_ZERO = (Double)(double)0; + + private final Class wrapperType; + private final Class primitiveType; + private final char basicTypeChar; + private final String basicTypeString; + private final Object emptyArray; + + Wrapper(Class wtype, + String wtypeName, + Class ptype, + String ptypeName, + char tchar, + Object emptyArray) { + this.wrapperType = wtype; + this.primitiveType = ptype; + this.basicTypeChar = tchar; + this.basicTypeString = String.valueOf(this.basicTypeChar); + this.emptyArray = emptyArray; + } + + public Object zero() { + return switch (this) { + case BOOLEAN -> Boolean.FALSE; + case INT -> (Integer)0; + case DOUBLE -> DOUBLE_ZERO; + default -> null; + }; + } + } + + enum MyEnum { + DUMMY1, + DUMMY2; + + static final boolean BOOLEAN = true; + static final byte BYTE = -128; + static final short SHORT = -12345; + static final char CHAR = 'c'; + static final int INT = -123456; + static final long LONG = 0x1234567890L; + static final long LONG2 = -0x1234567890L; + static final float FLOAT = 567891.0f; + static final double DOUBLE = 12345678905678.890; + } +} + +class Dummy {} diff --git a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java index fed56937f2f..3b1ccff1bfa 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/cacheObject/ArchiveHeapTestClass.java @@ -36,7 +36,7 @@ * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar boot.jar * CDSTestClassA CDSTestClassA$XX CDSTestClassA$YY * CDSTestClassB CDSTestClassC CDSTestClassD - * CDSTestClassE CDSTestClassF CDSTestClassG CDSTestClassG$MyEnum CDSTestClassG$Wrapper + * CDSTestClassE CDSTestClassF * pkg.ClassInPackage * @run driver jdk.test.lib.helpers.ClassFileInstaller -jar app.jar Hello * @run driver ArchiveHeapTestClass @@ -58,7 +58,6 @@ public class ArchiveHeapTestClass { static final String CDSTestClassD_name = CDSTestClassD.class.getName(); static final String CDSTestClassE_name = CDSTestClassE.class.getName(); static final String CDSTestClassF_name = CDSTestClassF.class.getName(); - static final String CDSTestClassG_name = CDSTestClassG.class.getName(); static final String ClassInPackage_name = pkg.ClassInPackage.class.getName().replace('.', '/'); static final String ARCHIVE_TEST_FIELD_NAME = "archivedObjects"; @@ -162,15 +161,6 @@ public class ArchiveHeapTestClass { output = dumpBootAndHello(CDSTestClassF_name); mustFail(output, "Class java.util.logging.Level not allowed in archive heap"); } - - testCase("Complex enums"); - output = dumpBootAndHello(CDSTestClassG_name, "-XX:+AOTClassLinking", "-Xlog:cds+class=debug"); - mustSucceed(output); - - TestCommon.run("-Xbootclasspath/a:" + bootJar, "-cp", appJar, "-Xlog:aot+heap,cds+init", - CDSTestClassG_name) - .assertNormalExit("init subgraph " + CDSTestClassG_name, - "Initialized from CDS"); } } @@ -287,147 +277,3 @@ class CDSTestClassF { archivedObjects[0] = java.util.logging.Level.OFF; } } - -class CDSTestClassG { - static Object[] archivedObjects; - static { - if (archivedObjects == null) { - archivedObjects = new Object[13]; - archivedObjects[0] = Wrapper.BOOLEAN; - archivedObjects[1] = Wrapper.INT.zero(); - archivedObjects[2] = Wrapper.DOUBLE.zero(); - archivedObjects[3] = MyEnum.DUMMY1; - - archivedObjects[4] = Boolean.class; - archivedObjects[5] = Byte.class; - archivedObjects[6] = Character.class; - archivedObjects[7] = Short.class; - archivedObjects[8] = Integer.class; - archivedObjects[9] = Long.class; - archivedObjects[10] = Float.class; - archivedObjects[11] = Double.class; - archivedObjects[12] = Void.class; - } else { - System.out.println("Initialized from CDS"); - } - } - - public static void main(String args[]) { - if (archivedObjects[0] != Wrapper.BOOLEAN) { - throw new RuntimeException("Huh 0"); - } - - if (archivedObjects[1] != Wrapper.INT.zero()) { - throw new RuntimeException("Huh 1"); - } - - if (archivedObjects[2] != Wrapper.DOUBLE.zero()) { - throw new RuntimeException("Huh 2"); - } - - if (archivedObjects[3] != MyEnum.DUMMY1) { - throw new RuntimeException("Huh 3"); - } - - if (MyEnum.BOOLEAN != true) { - throw new RuntimeException("Huh 10.1"); - } - if (MyEnum.BYTE != -128) { - throw new RuntimeException("Huh 10.2"); - } - if (MyEnum.CHAR != 'c') { - throw new RuntimeException("Huh 10.3"); - } - if (MyEnum.SHORT != -12345) { - throw new RuntimeException("Huh 10.4"); - } - if (MyEnum.INT != -123456) { - throw new RuntimeException("Huh 10.5"); - } - if (MyEnum.LONG != 0x1234567890L) { - throw new RuntimeException("Huh 10.6"); - } - if (MyEnum.LONG2 != -0x1234567890L) { - throw new RuntimeException("Huh 10.7"); - } - if (MyEnum.FLOAT != 567891.0f) { - throw new RuntimeException("Huh 10.8"); - } - if (MyEnum.DOUBLE != 12345678905678.890) { - throw new RuntimeException("Huh 10.9"); - } - - checkClass(4, Boolean.class); - checkClass(5, Byte.class); - checkClass(6, Character.class); - checkClass(7, Short.class); - checkClass(8, Integer.class); - checkClass(9, Long.class); - checkClass(10, Float.class); - checkClass(11, Double.class); - checkClass(12, Void.class); - - System.out.println("Success!"); - } - - static void checkClass(int index, Class c) { - if (archivedObjects[index] != c) { - throw new RuntimeException("archivedObjects[" + index + "] should be " + c); - } - } - - // Simplified version of sun.invoke.util.Wrapper - public enum Wrapper { - // wrapperType simple primitiveType simple char emptyArray - BOOLEAN( Boolean.class, "Boolean", boolean.class, "boolean", 'Z', new boolean[0]), - INT ( Integer.class, "Integer", int.class, "int", 'I', new int[0]), - DOUBLE ( Double.class, "Double", double.class, "double", 'D', new double[0]) - ; - - public static final int COUNT = 10; - private static final Object DOUBLE_ZERO = (Double)(double)0; - - private final Class wrapperType; - private final Class primitiveType; - private final char basicTypeChar; - private final String basicTypeString; - private final Object emptyArray; - - Wrapper(Class wtype, - String wtypeName, - Class ptype, - String ptypeName, - char tchar, - Object emptyArray) { - this.wrapperType = wtype; - this.primitiveType = ptype; - this.basicTypeChar = tchar; - this.basicTypeString = String.valueOf(this.basicTypeChar); - this.emptyArray = emptyArray; - } - - public Object zero() { - return switch (this) { - case BOOLEAN -> Boolean.FALSE; - case INT -> (Integer)0; - case DOUBLE -> DOUBLE_ZERO; - default -> null; - }; - } - } - - enum MyEnum { - DUMMY1, - DUMMY2; - - static final boolean BOOLEAN = true; - static final byte BYTE = -128; - static final short SHORT = -12345; - static final char CHAR = 'c'; - static final int INT = -123456; - static final long LONG = 0x1234567890L; - static final long LONG2 = -0x1234567890L; - static final float FLOAT = 567891.0f; - static final double DOUBLE = 12345678905678.890; - } -} From 17d633a8ee7538625501a90469cb6a68b9ba4820 Mon Sep 17 00:00:00 2001 From: Kelvin Nilsen Date: Wed, 17 Dec 2025 22:21:24 +0000 Subject: [PATCH 147/211] 8373720: GenShen: Count live-at-old mark using Snapshot at Beginning Reviewed-by: ysr --- .../heuristics/shenandoahOldHeuristics.cpp | 9 +++++++-- .../shenandoahGenerationalEvacuationTask.cpp | 3 ++- .../share/gc/shenandoah/shenandoahHeapRegion.hpp | 16 ++++++++++++++++ .../shenandoah/shenandoahHeapRegion.inline.hpp | 1 + 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp index 1f257560bcb..8bf068df0a8 100644 --- a/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp +++ b/src/hotspot/share/gc/shenandoah/heuristics/shenandoahOldHeuristics.cpp @@ -335,7 +335,13 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { size_t garbage = region->garbage(); size_t live_bytes = region->get_live_data_bytes(); - live_data += live_bytes; + if (!region->was_promoted_in_place()) { + // As currently implemented, region->get_live_data_bytes() represents bytes concurrently marked. + // Expansion of the region by promotion during concurrent marking is above TAMS, and is not included + // as live-data at [start of] old marking. + live_data += live_bytes; + } + // else, regions that were promoted in place had 0 old live data at mark start if (region->is_regular() || region->is_regular_pinned()) { // Only place regular or pinned regions with live data into the candidate set. @@ -374,7 +380,6 @@ void ShenandoahOldHeuristics::prepare_for_old_collections() { } } - // TODO: subtract from live_data bytes promoted during concurrent GC. _old_generation->set_live_bytes_at_last_mark(live_data); // Unlike young, we are more interested in efficiently packing OLD-gen than in reclaiming garbage first. We sort by live-data. diff --git a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp index de45877994c..c9b956f9c2f 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahGenerationalEvacuationTask.cpp @@ -223,7 +223,6 @@ void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion // We do not need to scan above TAMS because restored top equals tams assert(obj_addr == tams, "Expect loop to terminate when obj_addr equals tams"); - { ShenandoahHeapLocker locker(_heap->lock()); @@ -251,6 +250,7 @@ void ShenandoahGenerationalEvacuationTask::promote_in_place(ShenandoahHeapRegion // Transfer this region from young to old, increasing promoted_reserve if available space exceeds plab_min_size() _heap->free_set()->add_promoted_in_place_region_to_old_collector(region); region->set_affiliation(OLD_GENERATION); + region->set_promoted_in_place(); } } @@ -289,6 +289,7 @@ void ShenandoahGenerationalEvacuationTask::promote_humongous(ShenandoahHeapRegio r->index(), p2i(r->bottom()), p2i(r->top())); // We mark the entire humongous object's range as dirty after loop terminates, so no need to dirty the range here r->set_affiliation(OLD_GENERATION); + r->set_promoted_in_place(); } ShenandoahFreeSet* freeset = _heap->free_set(); diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp index 2ed5614c698..cf0dc5476d0 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.hpp @@ -262,6 +262,7 @@ private: HeapWord* volatile _update_watermark; uint _age; + bool _promoted_in_place; CENSUS_NOISE(uint _youth;) // tracks epochs of retrograde ageing (rejuvenation) ShenandoahSharedFlag _recycling; // Used to indicate that the region is being recycled; see try_recycle*(). @@ -354,6 +355,15 @@ public: inline void save_top_before_promote(); inline HeapWord* get_top_before_promote() const { return _top_before_promoted; } + + inline void set_promoted_in_place() { + _promoted_in_place = true; + } + + // Returns true iff this region was promoted in place subsequent to the most recent start of concurrent old marking. + inline bool was_promoted_in_place() { + return _promoted_in_place; + } inline void restore_top_before_promote(); inline size_t garbage_before_padded_for_promote() const; @@ -379,7 +389,13 @@ public: inline void increase_live_data_gc_words(size_t s); inline bool has_live() const; + + // Represents the number of live bytes identified by most recent marking effort. Does not include the bytes + // above TAMS. inline size_t get_live_data_bytes() const; + + // Represents the number of live words identified by most recent marking effort. Does not include the words + // above TAMS. inline size_t get_live_data_words() const; inline size_t garbage() const; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp index 69673eb7a60..b9304ee9daa 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahHeapRegion.inline.hpp @@ -152,6 +152,7 @@ inline void ShenandoahHeapRegion::internal_increase_live_data(size_t s) { inline void ShenandoahHeapRegion::clear_live_data() { AtomicAccess::store(&_live_data, (size_t)0); + _promoted_in_place = false; } inline size_t ShenandoahHeapRegion::get_live_data_words() const { From c16ce929c7bc127fe18d3faa037d81c2760a44a2 Mon Sep 17 00:00:00 2001 From: Dan Smith Date: Wed, 17 Dec 2025 22:38:50 +0000 Subject: [PATCH 148/211] 8370970: DocCheck failure in jdkDoctypeBadcharsCheck.java and jdkCheckHtml.java Reviewed-by: liach --- test/docs/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/docs/ProblemList.txt b/test/docs/ProblemList.txt index 4df8bbcc53c..83693eacbd1 100644 --- a/test/docs/ProblemList.txt +++ b/test/docs/ProblemList.txt @@ -41,5 +41,3 @@ ############################################################################# jdk/javadoc/doccheck/checks/jdkCheckLinks.java 8370249 generic-all -jdk/javadoc/doccheck/checks/jdkCheckHtml.java 8370970 generic-all -jdk/javadoc/doccheck/checks/jdkDoctypeBadcharsCheck.java 8370970 generic-all From ea5834415db6410c73271c496811ff6b5dcc87ef Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Thu, 18 Dec 2025 01:46:45 +0000 Subject: [PATCH 149/211] 8373887: jpackage tests may potentially deadlock Reviewed-by: almatvee --- .../jdk/jpackage/test/ExecutorTest.java | 8 +++- .../helpers/jdk/jpackage/test/Executor.java | 38 +++++++++++++++++-- 2 files changed, 42 insertions(+), 4 deletions(-) diff --git a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java index c5d8aed845c..2b075e0f13c 100644 --- a/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java +++ b/test/jdk/tools/jpackage/helpers-test/jdk/jpackage/test/ExecutorTest.java @@ -210,7 +210,13 @@ public class ExecutorTest extends JUnitAdapter { assertEquals(0, result[0].getExitCode()); - assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); + // If we dump the subprocesses's output, and the command produced both STDOUT and STDERR, + // then the captured STDOUT may contain interleaved command's STDOUT and STDERR, + // not in sequential order (STDOUT followed by STDERR). + // In this case don't check the contents of the captured command's STDOUT. + if (toolProvider || outputCapture.outLines().isEmpty() || (command.stdout().isEmpty() || command.stderr().isEmpty())) { + assertEquals(expectedCapturedSystemOut(commandWithDiscardedStreams), outputCapture.outLines()); + } assertEquals(expectedCapturedSystemErr(commandWithDiscardedStreams), outputCapture.errLines()); assertEquals(expectedResultStdout(commandWithDiscardedStreams), result[0].stdout().getOutput()); diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java index 91625603a2b..ef118e525c5 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/Executor.java @@ -32,6 +32,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.PrintStream; import java.io.StringReader; +import java.io.UncheckedIOException; import java.io.Writer; import java.nio.file.Path; import java.util.ArrayList; @@ -42,12 +43,15 @@ import java.util.Map; import java.util.Objects; import java.util.Optional; import java.util.Set; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CompletionException; import java.util.function.Supplier; import java.util.regex.Pattern; import java.util.spi.ToolProvider; import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.jpackage.internal.util.function.ThrowingSupplier; +import jdk.jpackage.internal.util.function.ExceptionBox; public final class Executor extends CommandArguments { @@ -465,9 +469,37 @@ public final class Executor extends CommandArguments { trace("Execute " + sb.toString() + "..."); Process process = builder.start(); - final var output = combine( - processProcessStream(outputStreamsControl.stdout(), process.getInputStream()), - processProcessStream(outputStreamsControl.stderr(), process.getErrorStream())); + var stdoutGobbler = CompletableFuture.>>supplyAsync(() -> { + try { + return processProcessStream(outputStreamsControl.stdout(), process.getInputStream()); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + var stderrGobbler = CompletableFuture.>>supplyAsync(() -> { + try { + return processProcessStream(outputStreamsControl.stderr(), process.getErrorStream()); + } catch (IOException ex) { + throw new UncheckedIOException(ex); + } + }); + + final CommandOutput output; + + try { + output = combine(stdoutGobbler.join(), stderrGobbler.join()); + } catch (CompletionException ex) { + var cause = ex.getCause(); + switch (cause) { + case UncheckedIOException uioex -> { + throw uioex.getCause(); + } + default -> { + throw ExceptionBox.toUnchecked(ExceptionBox.unbox(cause)); + } + } + } final int exitCode = process.waitFor(); trace("Done. Exit code: " + exitCode); From 0146077a51635500de771e9cf2c9788ae931b7a0 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Thu, 18 Dec 2025 04:27:18 +0000 Subject: [PATCH 150/211] 8373723: Deadlock with JvmtiTagMap::flush_object_free_events() Reviewed-by: dholmes, coleenp --- src/hotspot/share/prims/jvmtiTagMap.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/prims/jvmtiTagMap.cpp b/src/hotspot/share/prims/jvmtiTagMap.cpp index 90a3461f321..04cb70863cd 100644 --- a/src/hotspot/share/prims/jvmtiTagMap.cpp +++ b/src/hotspot/share/prims/jvmtiTagMap.cpp @@ -1204,8 +1204,10 @@ void JvmtiTagMap::flush_object_free_events() { assert_not_at_safepoint(); if (env()->is_enabled(JVMTI_EVENT_OBJECT_FREE)) { { + // The other thread can block for safepoints during event callbacks, so ensure we + // are safepoint-safe while waiting. + ThreadBlockInVM tbivm(JavaThread::current()); MonitorLocker ml(lock(), Mutex::_no_safepoint_check_flag); - // If another thread is posting events, let it finish while (_posting_events) { ml.wait(); } From b4462625413e7c2c12778eaad1f2f21d81f59c52 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 18 Dec 2025 07:04:40 +0000 Subject: [PATCH 151/211] 8373682: Test compiler/loopopts/superword/TestReinterpretAndCast.java fails on x86_64 with AVX but without f16c Reviewed-by: kvn, jsikstro, chagedorn --- .../compiler/loopopts/superword/TestReinterpretAndCast.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestReinterpretAndCast.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestReinterpretAndCast.java index ab2801179f2..9c5140d2aaa 100644 --- a/test/hotspot/jtreg/compiler/loopopts/superword/TestReinterpretAndCast.java +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestReinterpretAndCast.java @@ -162,7 +162,7 @@ public class TestReinterpretAndCast { IRNode.STORE_VECTOR, "> 0", IRNode.VECTOR_REINTERPRET, "> 0"}, // We have at least I2F applyIfPlatform = {"64-bit", "true"}, - applyIfCPUFeature = {"avx", "true"}) + applyIfCPUFeatureAnd = {"avx", "true", "f16c", "true"}) @IR(counts = {IRNode.LOAD_VECTOR_I, IRNode.VECTOR_SIZE + "min(max_int, max_float, max_short)", "> 0", IRNode.VECTOR_CAST_F2HF, IRNode.VECTOR_SIZE + "min(max_int, max_float, max_short)", "> 0", IRNode.STORE_VECTOR, "> 0", @@ -208,7 +208,7 @@ public class TestReinterpretAndCast { IRNode.STORE_VECTOR, "> 0", IRNode.VECTOR_REINTERPRET, "> 0"}, // We have at least F2I applyIfPlatform = {"64-bit", "true"}, - applyIfCPUFeature = {"avx", "true"}) + applyIfCPUFeatureAnd = {"avx", "true", "f16c", "true"}) @IR(counts = {IRNode.LOAD_VECTOR_S, IRNode.VECTOR_SIZE + "min(max_float, max_short, max_long)", "> 0", IRNode.VECTOR_CAST_HF2F, IRNode.VECTOR_SIZE + "min(max_float, max_short, max_long)", "> 0", IRNode.VECTOR_CAST_I2L, IRNode.VECTOR_SIZE + "min(max_float, max_short, max_long)", "> 0", From 00050f84d44f3ec23e9c6da52bffd68770010749 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 18 Dec 2025 07:05:05 +0000 Subject: [PATCH 152/211] 8373502: C2 SuperWord: speculative check uses VPointer variable was pinned after speculative check, leading to bad graph Reviewed-by: thartmann, roland --- src/hotspot/share/opto/vectorization.cpp | 25 +++++++ src/hotspot/share/opto/vectorization.hpp | 16 +++++ ...ingCheckVPointerVariablesNotAvailable.java | 71 +++++++++++++++++++ 3 files changed, 112 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java diff --git a/src/hotspot/share/opto/vectorization.cpp b/src/hotspot/share/opto/vectorization.cpp index 15b2df663b6..230ff280f03 100644 --- a/src/hotspot/share/opto/vectorization.cpp +++ b/src/hotspot/share/opto/vectorization.cpp @@ -1060,6 +1060,29 @@ bool VPointer::can_make_speculative_aliasing_check_with(const VPointer& other) c return false; } + // The speculative check also needs to create the pointer expressions for both + // VPointers. We must check that we can do that, i.e. that all variables of the + // VPointers are available at the speculative check (and not just pre-loop invariant). + if (!this->can_make_pointer_expression_at_speculative_check()) { +#ifdef ASSERT + if (_vloop.is_trace_speculative_aliasing_analysis()) { + tty->print_cr("VPointer::can_make_speculative_aliasing_check_with: not all variables of VPointer are avaialbe at speculative check!"); + this->print_on(tty); + } +#endif + return false; + } + + if (!other.can_make_pointer_expression_at_speculative_check()) { +#ifdef ASSERT + if (_vloop.is_trace_speculative_aliasing_analysis()) { + tty->print_cr("VPointer::can_make_speculative_aliasing_check_with: not all variables of VPointer are avaialbe at speculative check!"); + other.print_on(tty); + } +#endif + return false; + } + return true; } @@ -1147,6 +1170,8 @@ BoolNode* VPointer::make_speculative_aliasing_check_with(const VPointer& other, Node* main_init = new ConvL2INode(main_initL); phase->register_new_node_with_ctrl_of(main_init, pre_init); + assert(vp1.can_make_pointer_expression_at_speculative_check(), "variables must be available early enough to avoid cycles"); + assert(vp2.can_make_pointer_expression_at_speculative_check(), "variables must be available early enough to avoid cycles"); Node* p1_init = vp1.make_pointer_expression(main_init, ctrl); Node* p2_init = vp2.make_pointer_expression(main_init, ctrl); Node* size1 = igvn.longcon(vp1.size()); diff --git a/src/hotspot/share/opto/vectorization.hpp b/src/hotspot/share/opto/vectorization.hpp index aacd406f798..9308712f78a 100644 --- a/src/hotspot/share/opto/vectorization.hpp +++ b/src/hotspot/share/opto/vectorization.hpp @@ -1188,6 +1188,22 @@ private: return true; } + // We already know that all non-iv summands are pre loop invariant. + // See init_are_non_iv_summands_pre_loop_invariant + // That is good enough for alignment computations in the pre-loop limit. But it is not + // sufficient if we want to use the variables of the VPointer at the speculative check, + // which is further up before the pre-loop. + bool can_make_pointer_expression_at_speculative_check() const { + bool success = true; + mem_pointer().for_each_non_empty_summand([&] (const MemPointerSummand& s) { + Node* variable = s.variable(); + if (variable != _vloop.iv() && !_vloop.is_available_for_speculative_check(variable)) { + success = false; + } + }); + return success; + } + // In the pointer analysis, and especially the AlignVector analysis, we assume that // stride and scale are not too large. For example, we multiply "iv_scale * iv_stride", // and assume that this does not overflow the int range. We also take "abs(iv_scale)" diff --git a/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java new file mode 100644 index 00000000000..47540da5648 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/superword/TestAliasingCheckVPointerVariablesNotAvailable.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2025, 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=with-flags + * @bug 8373502 + * @summary Test where a VPointer variable was pinned at the pre-loop, but not available at the + * Auto_Vectorization_Check, and so it should not be used for the auto vectorization + * aliasing check, to avoid a bad (circular) graph. + * @run main/othervm + * -XX:CompileCommand=compileonly,*TestAliasingCheckVPointerVariablesNotAvailable::test + * -XX:-TieredCompilation + * -Xcomp + * ${test.main.class} + */ + +/* + * @test id=vanilla + * @bug 8373502 + * @run main ${test.main.class} + */ + +package compiler.loopopts.superword; + +public class TestAliasingCheckVPointerVariablesNotAvailable { + static int iFld; + + public static void main(String[] strArr) { + test(); + } + + static void test() { + int iArr[] = new int[400]; + boolean flag = false; + for (int i = 6; i < 50000; i++) { // Trigger OSR + try { + int x = 234 / iFld; + iFld = iArr[3]; + } catch (ArithmeticException a_e) { + } + for (int j = i; j < 2; j++) { + if (flag) { + iArr[j] = 117; + } else { + iArr[1] = 34; + } + iArr[1] += i; + } + } + } +} From e67805067a8f537862200e808e20464f12d21c9c Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Thu, 18 Dec 2025 07:31:06 +0000 Subject: [PATCH 153/211] 8367341: C2: apply KnownBits and unsigned bounds to And / Or operations Reviewed-by: hgreule, epeter --- src/hotspot/share/opto/addnode.cpp | 91 +--- src/hotspot/share/opto/mulnode.cpp | 78 +--- src/hotspot/share/opto/rangeinference.cpp | 8 +- src/hotspot/share/opto/rangeinference.hpp | 231 +++++++++- src/hotspot/share/opto/type.hpp | 2 + src/hotspot/share/opto/utilities/xor.hpp | 47 -- src/hotspot/share/utilities/intn_t.hpp | 1 + .../gtest/opto/test_rangeinference.cpp | 425 +++++++++++++++++- test/hotspot/gtest/opto/test_xor_node.cpp | 102 ----- 9 files changed, 651 insertions(+), 334 deletions(-) delete mode 100644 src/hotspot/share/opto/utilities/xor.hpp delete mode 100644 test/hotspot/gtest/opto/test_xor_node.cpp diff --git a/src/hotspot/share/opto/addnode.cpp b/src/hotspot/share/opto/addnode.cpp index 6075317d86e..accb3d32b67 100644 --- a/src/hotspot/share/opto/addnode.cpp +++ b/src/hotspot/share/opto/addnode.cpp @@ -31,8 +31,8 @@ #include "opto/movenode.hpp" #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" +#include "opto/rangeinference.hpp" #include "opto/subnode.hpp" -#include "opto/utilities/xor.hpp" #include "runtime/stubRoutines.hpp" // Portions of code courtesy of Clifford Click @@ -1011,35 +1011,8 @@ Node* OrINode::Ideal(PhaseGVN* phase, bool can_reshape) { // the logical operations the ring's ADD is really a logical OR function. // This also type-checks the inputs for sanity. Guaranteed never to // be passed a TOP or BOTTOM type, these are filtered out by pre-check. -const Type *OrINode::add_ring( const Type *t0, const Type *t1 ) const { - const TypeInt *r0 = t0->is_int(); // Handy access - const TypeInt *r1 = t1->is_int(); - - // If both args are bool, can figure out better types - if ( r0 == TypeInt::BOOL ) { - if ( r1 == TypeInt::ONE) { - return TypeInt::ONE; - } else if ( r1 == TypeInt::BOOL ) { - return TypeInt::BOOL; - } - } else if ( r0 == TypeInt::ONE ) { - if ( r1 == TypeInt::BOOL ) { - return TypeInt::ONE; - } - } - - // If either input is all ones, the output is all ones. - // x | ~0 == ~0 <==> x | -1 == -1 - if (r0 == TypeInt::MINUS_1 || r1 == TypeInt::MINUS_1) { - return TypeInt::MINUS_1; - } - - // If either input is not a constant, just return all integers. - if( !r0->is_con() || !r1->is_con() ) - return TypeInt::INT; // Any integer, but still no symbols. - - // Otherwise just OR them bits. - return TypeInt::make( r0->get_con() | r1->get_con() ); +const Type* OrINode::add_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_or(t1->is_int(), t2->is_int()); } //============================================================================= @@ -1087,22 +1060,8 @@ Node* OrLNode::Ideal(PhaseGVN* phase, bool can_reshape) { } //------------------------------add_ring--------------------------------------- -const Type *OrLNode::add_ring( const Type *t0, const Type *t1 ) const { - const TypeLong *r0 = t0->is_long(); // Handy access - const TypeLong *r1 = t1->is_long(); - - // If either input is all ones, the output is all ones. - // x | ~0 == ~0 <==> x | -1 == -1 - if (r0 == TypeLong::MINUS_1 || r1 == TypeLong::MINUS_1) { - return TypeLong::MINUS_1; - } - - // If either input is not a constant, just return all integers. - if( !r0->is_con() || !r1->is_con() ) - return TypeLong::LONG; // Any integer, but still no symbols. - - // Otherwise just OR them bits. - return TypeLong::make( r0->get_con() | r1->get_con() ); +const Type* OrLNode::add_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_or(t1->is_long(), t2->is_long()); } //---------------------------Helper ------------------------------------------- @@ -1189,46 +1148,14 @@ const Type* XorINode::Value(PhaseGVN* phase) const { // the logical operations the ring's ADD is really a logical OR function. // This also type-checks the inputs for sanity. Guaranteed never to // be passed a TOP or BOTTOM type, these are filtered out by pre-check. -const Type *XorINode::add_ring( const Type *t0, const Type *t1 ) const { - const TypeInt *r0 = t0->is_int(); // Handy access - const TypeInt *r1 = t1->is_int(); - - if (r0->is_con() && r1->is_con()) { - // compute constant result - return TypeInt::make(r0->get_con() ^ r1->get_con()); - } - - // At least one of the arguments is not constant - - if (r0->_lo >= 0 && r1->_lo >= 0) { - // Combine [r0->_lo, r0->_hi] ^ [r0->_lo, r1->_hi] -> [0, upper_bound] - jint upper_bound = xor_upper_bound_for_ranges(r0->_hi, r1->_hi); - return TypeInt::make(0, upper_bound, MAX2(r0->_widen, r1->_widen)); - } - - return TypeInt::INT; +const Type* XorINode::add_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_xor(t1->is_int(), t2->is_int()); } //============================================================================= //------------------------------add_ring--------------------------------------- -const Type *XorLNode::add_ring( const Type *t0, const Type *t1 ) const { - const TypeLong *r0 = t0->is_long(); // Handy access - const TypeLong *r1 = t1->is_long(); - - if (r0->is_con() && r1->is_con()) { - // compute constant result - return TypeLong::make(r0->get_con() ^ r1->get_con()); - } - - // At least one of the arguments is not constant - - if (r0->_lo >= 0 && r1->_lo >= 0) { - // Combine [r0->_lo, r0->_hi] ^ [r0->_lo, r1->_hi] -> [0, upper_bound] - julong upper_bound = xor_upper_bound_for_ranges(r0->_hi, r1->_hi); - return TypeLong::make(0, upper_bound, MAX2(r0->_widen, r1->_widen)); - } - - return TypeLong::LONG; +const Type* XorLNode::add_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_xor(t1->is_long(), t2->is_long()); } Node* XorLNode::Ideal(PhaseGVN* phase, bool can_reshape) { diff --git a/src/hotspot/share/opto/mulnode.cpp b/src/hotspot/share/opto/mulnode.cpp index 280781f686b..aa8d6cfce2e 100644 --- a/src/hotspot/share/opto/mulnode.cpp +++ b/src/hotspot/share/opto/mulnode.cpp @@ -29,6 +29,7 @@ #include "opto/memnode.hpp" #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" +#include "opto/rangeinference.hpp" #include "opto/subnode.hpp" #include "utilities/powerOfTwo.hpp" @@ -620,80 +621,14 @@ const Type* MulHiValue(const Type *t1, const Type *t2, const Type *bot) { return TypeLong::LONG; } -template -static const IntegerType* and_value(const IntegerType* r0, const IntegerType* r1) { - typedef typename IntegerType::NativeType NativeType; - static_assert(std::is_signed::value, "Native type of IntegerType must be signed!"); - - int widen = MAX2(r0->_widen, r1->_widen); - - // If both types are constants, we can calculate a constant result. - if (r0->is_con() && r1->is_con()) { - return IntegerType::make(r0->get_con() & r1->get_con()); - } - - // If both ranges are positive, the result will range from 0 up to the hi value of the smaller range. The minimum - // of the two constrains the upper bound because any higher value in the other range will see all zeroes, so it will be masked out. - if (r0->_lo >= 0 && r1->_lo >= 0) { - return IntegerType::make(0, MIN2(r0->_hi, r1->_hi), widen); - } - - // If only one range is positive, the result will range from 0 up to that range's maximum value. - // For the operation 'x & C' where C is a positive constant, the result will be in the range [0..C]. With that observation, - // we can say that for any integer c such that 0 <= c <= C will also be in the range [0..C]. Therefore, 'x & [c..C]' - // where c >= 0 will be in the range [0..C]. - if (r0->_lo >= 0) { - return IntegerType::make(0, r0->_hi, widen); - } - - if (r1->_lo >= 0) { - return IntegerType::make(0, r1->_hi, widen); - } - - // At this point, all positive ranges will have already been handled, so the only remaining cases will be negative ranges - // and constants. - - assert(r0->_lo < 0 && r1->_lo < 0, "positive ranges should already be handled!"); - - // As two's complement means that both numbers will start with leading 1s, the lower bound of both ranges will contain - // the common leading 1s of both minimum values. In order to count them with count_leading_zeros, the bits are inverted. - NativeType sel_val = ~MIN2(r0->_lo, r1->_lo); - - NativeType min; - if (sel_val == 0) { - // Since count_leading_zeros is undefined at 0, we short-circuit the condition where both ranges have a minimum of -1. - min = -1; - } else { - // To get the number of bits to shift, we count the leading 0-bits and then subtract one, as the sign bit is already set. - int shift_bits = count_leading_zeros(sel_val) - 1; - min = std::numeric_limits::min() >> shift_bits; - } - - NativeType max; - if (r0->_hi < 0 && r1->_hi < 0) { - // If both ranges are negative, then the same optimization as both positive ranges will apply, and the smaller hi - // value will mask off any bits set by higher values. - max = MIN2(r0->_hi, r1->_hi); - } else { - // In the case of ranges that cross zero, negative values can cause the higher order bits to be set, so the maximum - // positive value can be as high as the larger hi value. - max = MAX2(r0->_hi, r1->_hi); - } - - return IntegerType::make(min, max, widen); -} - //============================================================================= //------------------------------mul_ring--------------------------------------- // Supplied function returns the product of the inputs IN THE CURRENT RING. // For the logical operations the ring's MUL is really a logical AND function. // This also type-checks the inputs for sanity. Guaranteed never to // be passed a TOP or BOTTOM type, these are filtered out by pre-check. -const Type *AndINode::mul_ring( const Type *t0, const Type *t1 ) const { - const TypeInt* r0 = t0->is_int(); - const TypeInt* r1 = t1->is_int(); - - return and_value(r0, r1); +const Type* AndINode::mul_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_and(t1->is_int(), t2->is_int()); } static bool AndIL_is_zero_element_under_mask(const PhaseGVN* phase, const Node* expr, const Node* mask, BasicType bt); @@ -822,11 +757,8 @@ Node *AndINode::Ideal(PhaseGVN *phase, bool can_reshape) { // For the logical operations the ring's MUL is really a logical AND function. // This also type-checks the inputs for sanity. Guaranteed never to // be passed a TOP or BOTTOM type, these are filtered out by pre-check. -const Type *AndLNode::mul_ring( const Type *t0, const Type *t1 ) const { - const TypeLong* r0 = t0->is_long(); - const TypeLong* r1 = t1->is_long(); - - return and_value(r0, r1); +const Type* AndLNode::mul_ring(const Type* t1, const Type* t2) const { + return RangeInference::infer_and(t1->is_long(), t2->is_long()); } const Type* AndLNode::Value(PhaseGVN* phase) const { diff --git a/src/hotspot/share/opto/rangeinference.cpp b/src/hotspot/share/opto/rangeinference.cpp index 40b9da4bde5..cb26e68ef58 100644 --- a/src/hotspot/share/opto/rangeinference.cpp +++ b/src/hotspot/share/opto/rangeinference.cpp @@ -25,7 +25,6 @@ #include "opto/rangeinference.hpp" #include "opto/type.hpp" #include "utilities/intn_t.hpp" -#include "utilities/tuple.hpp" // If the cardinality of a TypeInt is below this threshold, use min widen, see // TypeIntPrototype::normalize_widen @@ -688,6 +687,8 @@ template class TypeIntPrototype, uintn_t<1>>; template class TypeIntPrototype, uintn_t<2>>; template class TypeIntPrototype, uintn_t<3>>; template class TypeIntPrototype, uintn_t<4>>; +template class TypeIntPrototype, uintn_t<5>>; +template class TypeIntPrototype, uintn_t<6>>; // Compute the meet of 2 types. When dual is true, the subset relation in CT is // reversed. This means that the result of 2 CTs would be the intersection of @@ -709,10 +710,7 @@ const Type* TypeIntHelper::int_type_xmeet(const CT* i1, const Type* t2) { if (!i1->_is_dual) { // meet (a.k.a union) - return CT::make_or_top(TypeIntPrototype{{MIN2(i1->_lo, i2->_lo), MAX2(i1->_hi, i2->_hi)}, - {MIN2(i1->_ulo, i2->_ulo), MAX2(i1->_uhi, i2->_uhi)}, - {i1->_bits._zeros & i2->_bits._zeros, i1->_bits._ones & i2->_bits._ones}}, - MAX2(i1->_widen, i2->_widen), false); + return int_type_union(i1, i2); } else { // join (a.k.a intersection) return CT::make_or_top(TypeIntPrototype{{MAX2(i1->_lo, i2->_lo), MIN2(i1->_hi, i2->_hi)}, diff --git a/src/hotspot/share/opto/rangeinference.hpp b/src/hotspot/share/opto/rangeinference.hpp index 73b8b43bd6e..ebfd98ca4a6 100644 --- a/src/hotspot/share/opto/rangeinference.hpp +++ b/src/hotspot/share/opto/rangeinference.hpp @@ -25,6 +25,7 @@ #ifndef SHARE_OPTO_RANGEINFERENCE_HPP #define SHARE_OPTO_RANGEINFERENCE_HPP +#include "cppstdlib/limits.hpp" #include "cppstdlib/type_traits.hpp" #include "utilities/globalDefinitions.hpp" @@ -92,19 +93,6 @@ public: RangeInt _urange; KnownBits _bits; -private: - friend class TypeInt; - friend class TypeLong; - - template - friend void test_canonicalize_constraints_exhaustive(); - - template - friend void test_canonicalize_constraints_simple(); - - template - friend void test_canonicalize_constraints_random(); - // A canonicalized version of a TypeIntPrototype, if the prototype represents // an empty type, _present is false, otherwise, _data is canonical class CanonicalizedTypeIntPrototype { @@ -158,21 +146,33 @@ public: template static const Type* int_type_xmeet(const CT* i1, const Type* t2); - template - static bool int_type_is_equal(const CT* t1, const CT* t2) { + template + static CTP int_type_union(CTP t1, CTP t2) { + using CT = std::conditional_t, std::remove_pointer_t, CTP>; + using S = std::remove_const_t; + using U = std::remove_const_t; + return CT::make(TypeIntPrototype{{MIN2(t1->_lo, t2->_lo), MAX2(t1->_hi, t2->_hi)}, + {MIN2(t1->_ulo, t2->_ulo), MAX2(t1->_uhi, t2->_uhi)}, + {t1->_bits._zeros & t2->_bits._zeros, t1->_bits._ones & t2->_bits._ones}}, + MAX2(t1->_widen, t2->_widen)); + } + + template + static bool int_type_is_equal(const CTP t1, const CTP t2) { return t1->_lo == t2->_lo && t1->_hi == t2->_hi && t1->_ulo == t2->_ulo && t1->_uhi == t2->_uhi && t1->_bits._zeros == t2->_bits._zeros && t1->_bits._ones == t2->_bits._ones; } - template - static bool int_type_is_subset(const CT* super, const CT* sub) { + template + static bool int_type_is_subset(const CTP super, const CTP sub) { + using U = decltype(super->_ulo); return super->_lo <= sub->_lo && super->_hi >= sub->_hi && super->_ulo <= sub->_ulo && super->_uhi >= sub->_uhi && // All bits that are known in super must also be known to be the same // value in sub, &~ (and not) is the same as a set subtraction on bit // sets - (super->_bits._zeros &~ sub->_bits._zeros) == 0 && (super->_bits._ones &~ sub->_bits._ones) == 0; + (super->_bits._zeros &~ sub->_bits._zeros) == U(0) && (super->_bits._ones &~ sub->_bits._ones) == U(0); } template @@ -195,4 +195,199 @@ public: #endif // PRODUCT }; +// A TypeIntMirror is structurally similar to a TypeInt or a TypeLong but it decouples the range +// inference from the Type infrastructure of the compiler. It also allows more flexibility with the +// bit width of the integer type. As a result, it is more efficient to use for intermediate steps +// of inference, as well as more flexible to perform testing on different integer types. +template +class TypeIntMirror { +public: + S _lo; + S _hi; + U _ulo; + U _uhi; + KnownBits _bits; + int _widen = 0; // dummy field to mimic the same field in TypeInt, useful in testing + + static TypeIntMirror make(const TypeIntPrototype& t, int widen) { + auto canonicalized_t = t.canonicalize_constraints(); + assert(!canonicalized_t.empty(), "must not be empty"); + return TypeIntMirror{canonicalized_t._data._srange._lo, canonicalized_t._data._srange._hi, + canonicalized_t._data._urange._lo, canonicalized_t._data._urange._hi, + canonicalized_t._data._bits}; + } + + // These allow TypeIntMirror to mimick the behaviors of TypeInt* and TypeLong*, so they can be + // passed into RangeInference methods. These are only used in testing, so they are implemented in + // the test file. + const TypeIntMirror* operator->() const; + TypeIntMirror meet(const TypeIntMirror& o) const; + bool contains(U u) const; + bool contains(const TypeIntMirror& o) const; + bool operator==(const TypeIntMirror& o) const; + + template + TypeIntMirror cast() const; +}; + +// This class contains methods for inferring the Type of the result of several arithmetic +// operations from those of the corresponding inputs. For example, given a, b such that the Type of +// a is [0, 1] and the Type of b is [-1, 3], then the Type of the sum a + b is [-1, 4]. +// The methods in this class receive one or more template parameters which are often TypeInt* or +// TypeLong*, or they can be TypeIntMirror which behave similar to TypeInt* and TypeLong* during +// testing. This allows us to verify the correctness of the implementation without coupling with +// the hotspot compiler allocation infrastructure. +class RangeInference { +private: + // If CTP is a pointer, get the underlying type. For the test helper classes, using the struct + // directly allows straightfoward equality comparison. + template + using CT = std::remove_const_t, std::remove_pointer_t, CTP>>; + + // The type of CT::_lo, should be jint for TypeInt* and jlong for TypeLong* + template + using S = std::remove_const_t::_lo)>; + + // The type of CT::_ulo, should be juint for TypeInt* and julong for TypeLong* + template + using U = std::remove_const_t::_ulo)>; + + // A TypeInt consists of 1 or 2 simple intervals, each of which will lie either in the interval + // [0, max_signed] or [min_signed, -1]. It is more optimal to analyze each simple interval + // separately when doing inference. For example, consider a, b whose Types are both [-2, 2]. By + // analyzing the interval [-2, -1] and [0, 2] separately, we can easily see that the result of + // a & b must also be in the interval [-2, 2]. This is much harder if we want to work with the + // whole value range at the same time. + // This class offers a convenient way to traverse all the simple interval of a TypeInt. + template + class SimpleIntervalIterable { + private: + TypeIntMirror, U> _first_interval; + TypeIntMirror, U> _second_interval; + int _interval_num; + + public: + SimpleIntervalIterable(CTP t) { + if (U(t->_lo) <= U(t->_hi)) { + _interval_num = 1; + _first_interval = TypeIntMirror, U>{t->_lo, t->_hi, t->_ulo, t->_uhi, t->_bits}; + } else { + _interval_num = 2; + _first_interval = TypeIntMirror, U>::make(TypeIntPrototype, U>{{t->_lo, S(t->_uhi)}, {U(t->_lo), t->_uhi}, t->_bits}, 0); + _second_interval = TypeIntMirror, U>::make(TypeIntPrototype, U>{{S(t->_ulo), t->_hi}, {t->_ulo, U(t->_hi)}, t->_bits}, 0); + } + } + + class Iterator { + private: + const SimpleIntervalIterable& _iterable; + int _current_interval; + + Iterator(const SimpleIntervalIterable& iterable) : _iterable(iterable), _current_interval(0) {} + + friend class SimpleIntervalIterable; + public: + const TypeIntMirror, U>& operator*() const { + assert(_current_interval < _iterable._interval_num, "out of bounds, %d - %d", _current_interval, _iterable._interval_num); + if (_current_interval == 0) { + return _iterable._first_interval; + } else { + return _iterable._second_interval; + } + } + + Iterator& operator++() { + assert(_current_interval < _iterable._interval_num, "out of bounds, %d - %d", _current_interval, _iterable._interval_num); + _current_interval++; + return *this; + } + + bool operator!=(const Iterator& o) const { + assert(&_iterable == &o._iterable, "not on the same iterable"); + return _current_interval != o._current_interval; + } + }; + + Iterator begin() const { + return Iterator(*this); + } + + Iterator end() const { + Iterator res(*this); + res._current_interval = _interval_num; + return res; + } + }; + + // Infer a result given the input types of a binary operation + template + static CTP infer_binary(CTP t1, CTP t2, Inference infer) { + CTP res; + bool is_init = false; + + SimpleIntervalIterable t1_simple_intervals(t1); + SimpleIntervalIterable t2_simple_intervals(t2); + + for (auto& st1 : t1_simple_intervals) { + for (auto& st2 : t2_simple_intervals) { + CTP current = infer(st1, st2); + + if (is_init) { + res = res->meet(current)->template cast>(); + } else { + is_init = true; + res = current; + } + } + } + + assert(is_init, "must be initialized"); + return res; + } + +public: + template + static CTP infer_and(CTP t1, CTP t2) { + return infer_binary(t1, t2, [&](const TypeIntMirror, U>& st1, const TypeIntMirror, U>& st2) { + S lo = std::numeric_limits>::min(); + S hi = std::numeric_limits>::max(); + U ulo = std::numeric_limits>::min(); + // The unsigned value of the result of 'and' is always not greater than both of its inputs + // since there is no position at which the bit is 1 in the result and 0 in either input + U uhi = MIN2(st1._uhi, st2._uhi); + U zeros = st1._bits._zeros | st2._bits._zeros; + U ones = st1._bits._ones & st2._bits._ones; + return CT::make(TypeIntPrototype, U>{{lo, hi}, {ulo, uhi}, {zeros, ones}}, MAX2(t1->_widen, t2->_widen)); + }); + } + + template + static CTP infer_or(CTP t1, CTP t2) { + return infer_binary(t1, t2, [&](const TypeIntMirror, U>& st1, const TypeIntMirror, U>& st2) { + S lo = std::numeric_limits>::min(); + S hi = std::numeric_limits>::max(); + // The unsigned value of the result of 'or' is always not less than both of its inputs since + // there is no position at which the bit is 0 in the result and 1 in either input + U ulo = MAX2(st1._ulo, st2._ulo); + U uhi = std::numeric_limits>::max(); + U zeros = st1._bits._zeros & st2._bits._zeros; + U ones = st1._bits._ones | st2._bits._ones; + return CT::make(TypeIntPrototype, U>{{lo, hi}, {ulo, uhi}, {zeros, ones}}, MAX2(t1->_widen, t2->_widen)); + }); + } + + template + static CTP infer_xor(CTP t1, CTP t2) { + return infer_binary(t1, t2, [&](const TypeIntMirror, U>& st1, const TypeIntMirror, U>& st2) { + S lo = std::numeric_limits>::min(); + S hi = std::numeric_limits>::max(); + U ulo = std::numeric_limits>::min(); + U uhi = std::numeric_limits>::max(); + U zeros = (st1._bits._zeros & st2._bits._zeros) | (st1._bits._ones & st2._bits._ones); + U ones = (st1._bits._zeros & st2._bits._ones) | (st1._bits._ones & st2._bits._zeros); + return CT::make(TypeIntPrototype, U>{{lo, hi}, {ulo, uhi}, {zeros, ones}}, MAX2(t1->_widen, t2->_widen)); + }); + } +}; + #endif // SHARE_OPTO_RANGEINFERENCE_HPP diff --git a/src/hotspot/share/opto/type.hpp b/src/hotspot/share/opto/type.hpp index 4666cfbcf2d..73e2ba0045a 100644 --- a/src/hotspot/share/opto/type.hpp +++ b/src/hotspot/share/opto/type.hpp @@ -798,6 +798,7 @@ public: // must always specify w static const TypeInt* make(jint lo, jint hi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); + static const TypeInt* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_int(); } // Check for single integer bool is_con() const { return _lo == _hi; } @@ -879,6 +880,7 @@ public: // must always specify w static const TypeLong* make(jlong lo, jlong hi, int widen); static const Type* make_or_top(const TypeIntPrototype& t, int widen); + static const TypeLong* make(const TypeIntPrototype& t, int widen) { return make_or_top(t, widen)->is_long(); } // Check for single integer bool is_con() const { return _lo == _hi; } diff --git a/src/hotspot/share/opto/utilities/xor.hpp b/src/hotspot/share/opto/utilities/xor.hpp deleted file mode 100644 index 20edaf0d017..00000000000 --- a/src/hotspot/share/opto/utilities/xor.hpp +++ /dev/null @@ -1,47 +0,0 @@ -#ifndef SHARE_OPTO_UTILITIES_XOR_HPP -#define SHARE_OPTO_UTILITIES_XOR_HPP - -#include "utilities/powerOfTwo.hpp" -// Code separated into its own header to allow access from GTEST - -// Given 2 non-negative values in the ranges [0, hi_0] and [0, hi_1], respectively. The bitwise -// xor of these values should also be non-negative. This method calculates an upper bound. - -// S and U type parameters correspond to the signed and unsigned -// variants of an integer to operate on. -template -static S xor_upper_bound_for_ranges(const S hi_0, const S hi_1) { - static_assert(S(-1) < S(0), "S must be signed"); - static_assert(U(-1) > U(0), "U must be unsigned"); - - assert(hi_0 >= 0, "must be non-negative"); - assert(hi_1 >= 0, "must be non-negative"); - - // x ^ y cannot have any bit set that is higher than both the highest bits set in x and y - // x cannot have any bit set that is higher than the highest bit set in hi_0 - // y cannot have any bit set that is higher than the highest bit set in hi_1 - - // We want to find a value that has all 1 bits everywhere up to and including - // the highest bits set in hi_0 as well as hi_1. For this, we can take the next - // power of 2 strictly greater than both hi values and subtract 1 from it. - - // Example 1: - // hi_0 = 5 (0b0101) hi_1=1 (0b0001) - // (5|1)+1 = 0b0110 - // round_up_pow2 = 0b1000 - // -1 = 0b0111 = max - - // Example 2 - this demonstrates need for the +1: - // hi_0 = 4 (0b0100) hi_1=4 (0b0100) - // (4|4)+1 = 0b0101 - // round_up_pow2 = 0b1000 - // -1 = 0b0111 = max - // Without the +1, round_up_pow2 would be 0b0100, resulting in 0b0011 as max - - // Note: cast to unsigned happens before +1 to avoid signed overflow, and - // round_up is safe because high bit is unset (0 <= lo <= hi) - - return round_up_power_of_2(U(hi_0 | hi_1) + 1) - 1; -} - -#endif // SHARE_OPTO_UTILITIES_XOR_HPP diff --git a/src/hotspot/share/utilities/intn_t.hpp b/src/hotspot/share/utilities/intn_t.hpp index 6f43f5c2556..594e62a1694 100644 --- a/src/hotspot/share/utilities/intn_t.hpp +++ b/src/hotspot/share/utilities/intn_t.hpp @@ -79,6 +79,7 @@ public: static_assert(min < max, ""); constexpr bool operator==(intn_t o) const { return (_v & _mask) == (o._v & _mask); } + constexpr bool operator!=(intn_t o) const { return !(*this == o); } constexpr bool operator<(intn_t o) const { return int(*this) < int(o); } constexpr bool operator>(intn_t o) const { return int(*this) > int(o); } constexpr bool operator<=(intn_t o) const { return int(*this) <= int(o); } diff --git a/test/hotspot/gtest/opto/test_rangeinference.cpp b/test/hotspot/gtest/opto/test_rangeinference.cpp index 1a62941a486..61a9ff7fb70 100644 --- a/test/hotspot/gtest/opto/test_rangeinference.cpp +++ b/test/hotspot/gtest/opto/test_rangeinference.cpp @@ -25,15 +25,16 @@ #include "opto/rangeinference.hpp" #include "opto/type.hpp" #include "runtime/os.hpp" -#include "utilities/intn_t.hpp" #include "unittest.hpp" +#include "utilities/intn_t.hpp" +#include "utilities/rbTree.hpp" +#include +#include +#include template -static U uniform_random(); - -template <> -juint uniform_random() { - return os::random(); +static U uniform_random() { + return U(juint(os::random())); } template <> @@ -201,7 +202,7 @@ static void test_canonicalize_constraints_random() { } } -TEST_VM(opto, canonicalize_constraints) { +TEST(opto, canonicalize_constraints) { test_canonicalize_constraints_trivial(); test_canonicalize_constraints_exhaustive, uintn_t<1>>(); test_canonicalize_constraints_exhaustive, uintn_t<2>>(); @@ -212,3 +213,413 @@ TEST_VM(opto, canonicalize_constraints) { test_canonicalize_constraints_random(); test_canonicalize_constraints_random(); } + +// Implementations of TypeIntMirror methods for testing purposes +template +const TypeIntMirror* TypeIntMirror::operator->() const { + return this; +} + +template +TypeIntMirror TypeIntMirror::meet(const TypeIntMirror& o) const { + return TypeIntHelper::int_type_union(*this, o); +} + +template +bool TypeIntMirror::contains(U u) const { + S s = S(u); + return s >= _lo && s <= _hi && u >= _ulo && u <= _uhi && _bits.is_satisfied_by(u); +} + +template +bool TypeIntMirror::contains(const TypeIntMirror& o) const { + return TypeIntHelper::int_type_is_subset(*this, o); +} + +template +bool TypeIntMirror::operator==(const TypeIntMirror& o) const { + return TypeIntHelper::int_type_is_equal(*this, o); +} + +template +template +TypeIntMirror TypeIntMirror::cast() const { + static_assert(std::is_same_v); + return *this; +} + +// The number of TypeIntMirror instances for integral types with a few bits. These values are +// calculated once and written down for usage in constexpr contexts. +template +static constexpr size_t all_instances_size() { + using U = decltype(CTP::_ulo); + constexpr juint max_unsigned = juint(std::numeric_limits::max()); + if constexpr (max_unsigned == 1U) { + // 1 bit + return 3; + } else if constexpr (max_unsigned == 3U) { + // 2 bits + return 15; + } else if constexpr (max_unsigned == 7U) { + // 3 bits + return 134; + } else { + // 4 bits + static_assert(max_unsigned == 15U); + // For more than 4 bits, the number of instances is too large and it is not realistic to + // compute all of them. + return 1732; + } +} + +template +static std::array()> compute_all_instances() { + using S = decltype(CTP::_lo); + using U = decltype(CTP::_ulo); + + class CTPComparator { + public: + static RBTreeOrdering cmp(const CTP& x, const RBNode* node) { + // Quick helper for the tediousness below + auto f = [](auto x, auto y) { + assert(x != y, "we only handle lt and gt cases"); + return x < y ? RBTreeOrdering::LT : RBTreeOrdering::GT; + }; + + const CTP& y = node->key(); + if (x._lo != y._lo) { + return f(x._lo, y._lo); + } else if (x._hi != y._hi) { + return f(x._hi, y._hi); + } else if (x._ulo != y._ulo) { + return f(x._ulo, y._ulo); + } else if (x._uhi != y._uhi) { + return f(x._uhi, y._uhi); + } else if (x._bits._zeros != y._bits._zeros) { + return f(x._bits._zeros, y._bits._zeros); + } else if (x._bits._ones != y._bits._ones) { + return f(x._bits._ones, y._bits._ones); + } else { + return RBTreeOrdering::EQ; + } + } + }; + + RBTreeCHeap collector; + for (jint lo = jint(std::numeric_limits::min()); lo <= jint(std::numeric_limits::max()); lo++) { + for (jint hi = lo; hi <= jint(std::numeric_limits::max()); hi++) { + for (juint ulo = 0; ulo <= juint(std::numeric_limits::max()); ulo++) { + for (juint uhi = ulo; uhi <= juint(std::numeric_limits::max()); uhi++) { + for (juint zeros = 0; zeros <= juint(std::numeric_limits::max()); zeros++) { + for (juint ones = 0; ones <= juint(std::numeric_limits::max()); ones++) { + TypeIntPrototype t{{S(lo), S(hi)}, {U(ulo), U(uhi)}, {U(zeros), U(ones)}}; + auto canonicalized_t = t.canonicalize_constraints(); + if (canonicalized_t.empty()) { + continue; + } + + TypeIntPrototype ct = canonicalized_t._data; + collector.upsert(CTP{ct._srange._lo, ct._srange._hi, ct._urange._lo, ct._urange._hi, ct._bits}, 0); + } + } + } + } + } + } + + assert(collector.size() == all_instances_size(), "unexpected size of all_instance, expected %d, actual %d", jint(all_instances_size()), jint(collector.size())); + std::array()> res; + size_t idx = 0; + collector.visit_in_order([&](RBNode* node) { + res[idx] = node->key(); + idx++; + return true; + }); + return res; +} + +template +static const std::array()>& all_instances() { + static std::array()> res = compute_all_instances(); + static_assert(std::is_trivially_destructible_v); + return res; +} + +// Check the correctness, that is, if v1 is an element of input1, v2 is an element of input2, then +// op(v1, v2) must be an element of infer(input1, input2). This version does the check exhaustively +// on all elements of input1 and input2. +template +static void test_binary_instance_correctness_exhaustive(Operation op, Inference infer, const InputType& input1, const InputType& input2) { + using S = std::remove_const_t_lo)>; + using U = std::remove_const_t_ulo)>; + InputType result = infer(input1, input2); + + for (juint v1 = juint(std::numeric_limits::min()); v1 <= juint(std::numeric_limits::max()); v1++) { + if (!input1.contains(U(v1))) { + continue; + } + + for (juint v2 = juint(std::numeric_limits::min()); v2 <= juint(std::numeric_limits::max()); v2++) { + if (!input2.contains(U(v2))) { + continue; + } + + U r = op(U(v1), U(v2)); + ASSERT_TRUE(result.contains(r)); + } + } +} + +// Check the correctness, that is, if v1 is an element of input1, v2 is an element of input2, then +// op(v1, v2) must be an element of infer(input1, input2). This version does the check randomly on +// a number of elements in input1 and input2. +template +static void test_binary_instance_correctness_samples(Operation op, Inference infer, const InputType& input1, const InputType& input2) { + using U = std::remove_const_t_ulo)>; + auto result = infer(input1, input2); + + constexpr size_t sample_count = 6; + U input1_samples[sample_count] {U(input1._lo), U(input1._hi), input1._ulo, input1._uhi, input1._ulo, input1._ulo}; + U input2_samples[sample_count] {U(input2._lo), U(input2._hi), input2._ulo, input2._uhi, input2._ulo, input2._ulo}; + + auto random_sample = [](U* samples, const InputType& input) { + constexpr size_t max_tries = 100; + constexpr size_t start_random_idx = 4; + for (size_t tries = 0, idx = start_random_idx; tries < max_tries && idx < sample_count; tries++) { + U n = uniform_random(); + if (input.contains(n)) { + samples[idx] = n; + idx++; + } + } + }; + random_sample(input1_samples, input1); + random_sample(input2_samples, input2); + + for (size_t i = 0; i < sample_count; i++) { + for (size_t j = 0; j < sample_count; j++) { + U r = op(input1_samples[i], input2_samples[j]); + ASSERT_TRUE(result.contains(r)); + } + } +} + +// Check the monotonicity, that is, if input1 is a subset of super1, input2 is a subset of super2, +// then infer(input1, input2) must be a subset of infer(super1, super2). This version does the +// check exhaustively on all supersets of input1 and input2. +template +static void test_binary_instance_monotonicity_exhaustive(Inference infer, const InputType& input1, const InputType& input2) { + InputType result = infer(input1, input2); + + for (const InputType& super1 : all_instances()) { + if (!super1.contains(input1) || super1 == input1) { + continue; + } + + for (const InputType& super2 : all_instances()) { + if (!super2.contains(input2) || super2 == input2) { + continue; + } + + ASSERT_TRUE(infer(input1, super2).contains(result)); + ASSERT_TRUE(infer(super1, input2).contains(result)); + ASSERT_TRUE(infer(super1, super2).contains(result)); + } + } +} + +// Check the monotonicity, that is, if input1 is a subset of super1, input2 is a subset of super2, +// then infer(input1, input2) must be a subset of infer(super1, super2). This version does the +// check randomly on a number of supersets of input1 and input2. +template +static void test_binary_instance_monotonicity_samples(Inference infer, const InputType& input1, const InputType& input2) { + using S = std::remove_const_t_lo)>; + using U = std::remove_const_t_ulo)>; + auto result = infer(input1, input2); + + // The set that is a superset of all other sets + InputType universe = InputType{std::numeric_limits::min(), std::numeric_limits::max(), U(0), U(-1), {U(0), U(0)}}; + ASSERT_TRUE(infer(universe, input2).contains(result)); + ASSERT_TRUE(infer(input1, universe).contains(result)); + ASSERT_TRUE(infer(universe, universe).contains(result)); + + auto random_superset = [](const InputType& input) { + S lo = MIN2(input->_lo, S(uniform_random())); + S hi = MAX2(input->_hi, S(uniform_random())); + U ulo = MIN2(input->_ulo, uniform_random()); + U uhi = MAX2(input->_uhi, uniform_random()); + U zeros = input->_bits._zeros & uniform_random(); + U ones = input->_bits._ones & uniform_random(); + InputType super = InputType::make(TypeIntPrototype{{lo, hi}, {ulo, uhi}, {zeros, ones}}, 0); + assert(super.contains(input), "impossible"); + return super; + }; + + InputType super1 = random_superset(input1); + InputType super2 = random_superset(input2); + ASSERT_TRUE(infer(super1, input2).contains(result)); + ASSERT_TRUE(infer(input1, super2).contains(result)); + ASSERT_TRUE(infer(super1, super2).contains(result)); +} + +// Verify the correctness and monotonicity of an inference function by exhautively analyzing all +// instances of InputType +template +static void test_binary_exhaustive(Operation op, Inference infer) { + for (const InputType& input1 : all_instances()) { + for (const InputType& input2 : all_instances()) { + test_binary_instance_correctness_exhaustive(op, infer, input1, input2); + if (all_instances().size() < 100) { + // This effectively covers the cases up to uintn_t<2> + test_binary_instance_monotonicity_exhaustive(infer, input1, input2); + } else { + // This effectively covers the cases of uintn_t<3> + test_binary_instance_monotonicity_samples(infer, input1, input2); + } + } + } +} + +// Verify the correctness and monotonicity of an inference function by randomly sampling instances +// of InputType +template +static void test_binary_random(Operation op, Inference infer) { + using S = std::remove_const_t; + using U = std::remove_const_t; + + constexpr size_t sample_count = 100; + InputType samples[sample_count]; + + // Fill with {0} + for (size_t i = 0; i < sample_count; i++) { + samples[i] = InputType::make(TypeIntPrototype{{S(0), S(0)}, {U(0), U(0)}, {U(0), U(0)}}, 0); + } + + // {1} + samples[1] = InputType::make(TypeIntPrototype{{S(1), S(1)}, {U(1), U(1)}, {U(0), U(0)}}, 0); + // {-1} + samples[2] = InputType::make(TypeIntPrototype{{S(-1), S(-1)}, {U(-1), U(-1)}, {U(0), U(0)}}, 0); + // {0, 1} + samples[3] = InputType::make(TypeIntPrototype{{S(0), S(1)}, {U(0), U(1)}, {U(0), U(0)}}, 0); + // {-1, 0, 1} + samples[4] = InputType::make(TypeIntPrototype{{S(-1), S(1)}, {U(0), U(-1)}, {U(0), U(0)}}, 0); + // {-1, 1} + samples[5] = InputType::make(TypeIntPrototype{{S(-1), S(1)}, {U(1), U(-1)}, {U(0), U(0)}}, 0); + // {0, 1, 2} + samples[6] = InputType::make(TypeIntPrototype{{S(0), S(2)}, {U(0), U(2)}, {U(0), U(0)}}, 0); + // {0, 2} + samples[7] = InputType::make(TypeIntPrototype{{S(0), S(2)}, {U(0), U(2)}, {U(1), U(0)}}, 0); + // [min_signed, max_signed] + samples[8] = InputType::make(TypeIntPrototype{{std::numeric_limits::min(), std::numeric_limits::max()}, {U(0), U(-1)}, {U(0), U(0)}}, 0); + // [0, max_signed] + samples[9] = InputType::make(TypeIntPrototype{{S(0), std::numeric_limits::max()}, {U(0), U(-1)}, {U(0), U(0)}}, 0); + // [min_signed, 0) + samples[10] = InputType::make(TypeIntPrototype{{std::numeric_limits::min(), S(-1)}, {U(0), U(-1)}, {U(0), U(0)}}, 0); + + constexpr size_t max_tries = 1000; + constexpr size_t start_random_idx = 11; + for (size_t tries = 0, idx = start_random_idx; tries < max_tries && idx < sample_count; tries++) { + // Try to have lo < hi + S signed_bound1 = S(uniform_random()); + S signed_bound2 = S(uniform_random()); + S lo = MIN2(signed_bound1, signed_bound2); + S hi = MAX2(signed_bound1, signed_bound2); + + // Try to have ulo < uhi + U unsigned_bound1 = uniform_random(); + U unsigned_bound2 = uniform_random(); + U ulo = MIN2(unsigned_bound1, unsigned_bound2); + U uhi = MAX2(unsigned_bound1, unsigned_bound2); + + // Try to have (zeros & ones) == 0 + U zeros = uniform_random(); + U ones = uniform_random(); + U common = zeros & ones; + zeros = zeros ^ common; + ones = ones ^ common; + + TypeIntPrototype t{{lo, hi}, {ulo, uhi}, {zeros, ones}}; + auto canonicalized_t = t.canonicalize_constraints(); + if (canonicalized_t.empty()) { + continue; + } + + samples[idx] = TypeIntMirror{canonicalized_t._data._srange._lo, canonicalized_t._data._srange._hi, + canonicalized_t._data._urange._lo, canonicalized_t._data._urange._hi, + canonicalized_t._data._bits}; + idx++; + } + + for (size_t i = 0; i < sample_count; i++) { + for (size_t j = 0; j < sample_count; j++) { + test_binary_instance_correctness_samples(op, infer, samples[i], samples[j]); + test_binary_instance_monotonicity_samples(infer, samples[i], samples[j]); + } + } +} + +template