From 257aa15f15bb835310132e6fb23e0362cafeb16a Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Thu, 1 Dec 2022 23:41:58 +0000 Subject: [PATCH 001/494] 8297444: Refactor the javacserver build tool Reviewed-by: erikj, cstein --- make/common/JavaCompilation.gmk | 24 +- make/langtools/tools/javacserver/Main.java | 29 +- make/langtools/tools/javacserver/Util.java | 148 --------- .../tools/javacserver/client/Client.java | 191 ++++++++++++ .../client/ClientConfiguration.java | 131 ++++++++ .../tools/javacserver/client/ClientMain.java | 80 ----- .../javacserver/client/SjavacClient.java | 280 ----------------- .../tools/javacserver/comp/SjavacImpl.java | 78 ----- .../javacserver/options/ArgumentIterator.java | 89 ------ .../javacserver/options/CommandLine.java | 294 ------------------ .../tools/javacserver/options/Option.java | 100 ------ .../tools/javacserver/options/Options.java | 121 ------- .../CompilerThreadPool.java} | 55 ++-- ...{IdleResetSjavac.java => IdleMonitor.java} | 62 +--- .../javacserver/server/PortFileMonitor.java | 77 +++-- .../javacserver/server/RequestHandler.java | 128 -------- .../tools/javacserver/server/Server.java | 281 +++++++++++++++++ .../tools/javacserver/server/ServerMain.java | 92 ------ .../javacserver/server/SjavacServer.java | 248 --------------- .../{server => shared}/PortFile.java | 29 +- .../PortFileInaccessibleException.java | 2 +- .../tools/javacserver/shared/Protocol.java | 144 +++++++++ .../Terminable.java => shared/Result.java} | 21 +- .../{ => util}/AutoFlushWriter.java | 3 +- .../{server/log => util}/LazyInitFileLog.java | 5 +- .../tools/javacserver/{ => util}/Log.java | 42 +-- .../log => util}/LoggingOutputStream.java | 5 +- .../RunnableTimerTask.java} | 38 +-- .../{server/Sjavac.java => util/Util.java} | 26 +- 29 files changed, 905 insertions(+), 1918 deletions(-) delete mode 100644 make/langtools/tools/javacserver/Util.java create mode 100644 make/langtools/tools/javacserver/client/Client.java create mode 100644 make/langtools/tools/javacserver/client/ClientConfiguration.java delete mode 100644 make/langtools/tools/javacserver/client/ClientMain.java delete mode 100644 make/langtools/tools/javacserver/client/SjavacClient.java delete mode 100644 make/langtools/tools/javacserver/comp/SjavacImpl.java delete mode 100644 make/langtools/tools/javacserver/options/ArgumentIterator.java delete mode 100644 make/langtools/tools/javacserver/options/CommandLine.java delete mode 100644 make/langtools/tools/javacserver/options/Option.java delete mode 100644 make/langtools/tools/javacserver/options/Options.java rename make/langtools/tools/javacserver/{comp/PooledSjavac.java => server/CompilerThreadPool.java} (60%) rename make/langtools/tools/javacserver/server/{IdleResetSjavac.java => IdleMonitor.java} (59%) delete mode 100644 make/langtools/tools/javacserver/server/RequestHandler.java create mode 100644 make/langtools/tools/javacserver/server/Server.java delete mode 100644 make/langtools/tools/javacserver/server/ServerMain.java delete mode 100644 make/langtools/tools/javacserver/server/SjavacServer.java rename make/langtools/tools/javacserver/{server => shared}/PortFile.java (94%) rename make/langtools/tools/javacserver/{client => shared}/PortFileInaccessibleException.java (98%) create mode 100644 make/langtools/tools/javacserver/shared/Protocol.java rename make/langtools/tools/javacserver/{server/Terminable.java => shared/Result.java} (74%) rename make/langtools/tools/javacserver/{ => util}/AutoFlushWriter.java (98%) rename make/langtools/tools/javacserver/{server/log => util}/LazyInitFileLog.java (97%) rename make/langtools/tools/javacserver/{ => util}/Log.java (78%) rename make/langtools/tools/javacserver/{server/log => util}/LoggingOutputStream.java (97%) rename make/langtools/tools/javacserver/{Result.java => util/RunnableTimerTask.java} (59%) rename make/langtools/tools/javacserver/{server/Sjavac.java => util/Util.java} (72%) diff --git a/make/common/JavaCompilation.gmk b/make/common/JavaCompilation.gmk index 802b0f130f9..ff7c90e5785 100644 --- a/make/common/JavaCompilation.gmk +++ b/make/common/JavaCompilation.gmk @@ -219,31 +219,35 @@ define SetupJavaCompilationBody # Use java server if it is enabled, and the user does not want a specialized # class path. ifeq ($$(ENABLE_JAVAC_SERVER)+$$($1_CLASSPATH), true+) - $1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_javacserver_classes javacserver.Main - # Create a configuration file with the needed information for the javac # server to function properly. - $1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-server.conf + $1_JAVAC_SERVER_CONFIG := $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$$($1_SAFE_NAME)-javacserver.conf + + # Arguments needed to launch the javacserver client, as well as for the + # client to launch the server. + $1_JAVAC_SERVER_ARGS := $$(INTERIM_LANGTOOLS_ARGS) \ + -cp $(BUILDTOOLS_OUTPUTDIR)/langtools_javacserver_classes # The portfile contains the tcp/ip on which the server listens # and the cookie necessary to talk to the server. $1_JAVAC_PORT_FILE := $$(call FixPath, $$(JAVAC_SERVER_DIR)/server.port) - # The servercmd specifies how to launch the server. This will be executed - # by the client, if needed. - $1_JAVAC_SERVER_CMD := $$(call FixPath, $$(JAVA) $$($1_JAVA_FLAGS) $$($1_JAVAC)) + # The javacmd tells the client how to run java to launch the server. + $1_JAVAC_SERVER_JAVA_CMD := $$(call FixPath, $$(JAVA) $$($1_JAVA_FLAGS) \ + $$($1_JAVAC_SERVER_ARGS)) - $1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_CMD) + $1_CONFIG_VARDEPS := $$($1_JAVAC_PORT_FILE) $$($1_JAVAC_SERVER_JAVA_CMD) $1_CONFIG_VARDEPS_FILE := $$(call DependOnVariable, $1_CONFIG_VARDEPS, \ $$($1_BIN)$$($1_MODULE_SUBDIR)/_the.$1.config_vardeps) + # Write these values to a config file $$($1_JAVAC_SERVER_CONFIG): $$($1_CONFIG_VARDEPS_FILE) $(ECHO) portfile=$$($1_JAVAC_PORT_FILE) > $$@ - $(ECHO) servercmd=$$($1_JAVAC_SERVER_CMD) >> $$@ + $(ECHO) javacmd=$$($1_JAVAC_SERVER_JAVA_CMD) >> $$@ # Always use small java to launch client - $1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC) \ - --server:conf=$$($1_JAVAC_SERVER_CONFIG) + $1_JAVAC_CMD := $$(JAVA_SMALL) $$($1_JAVA_FLAGS) $$($1_JAVAC_SERVER_ARGS) \ + javacserver.Main --conf=$$($1_JAVAC_SERVER_CONFIG) else # No javac server $1_JAVAC := $$(INTERIM_LANGTOOLS_ARGS) -m jdk.compiler.interim/com.sun.tools.javac.Main diff --git a/make/langtools/tools/javacserver/Main.java b/make/langtools/tools/javacserver/Main.java index 2eecfb2b4a8..b2582518948 100644 --- a/make/langtools/tools/javacserver/Main.java +++ b/make/langtools/tools/javacserver/Main.java @@ -25,34 +25,13 @@ package javacserver; -import java.util.Arrays; - -import javacserver.client.ClientMain; -import javacserver.server.ServerMain; - -import static javacserver.options.Option.STARTSERVER; +import javacserver.client.Client; /** - * The application entry point of the smart javac wrapper tool. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * The application entry point of the javacserver build tool. */ public class Main { - - public static void main(String... args) { - System.exit(go(args)); - } - - public static int go(String[] args) { - - // Server or client mode? - boolean serverMode = Arrays.asList(args) - .stream() - .anyMatch(arg -> arg.startsWith(STARTSERVER.arg)); - - return serverMode ? ServerMain.run(args) : ClientMain.run(args); + public static void main(String... args) { + Client.main(args); } } diff --git a/make/langtools/tools/javacserver/Util.java b/make/langtools/tools/javacserver/Util.java deleted file mode 100644 index 96558d503c8..00000000000 --- a/make/langtools/tools/javacserver/Util.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2012, 2022, 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. - */ - -package javacserver; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; -import java.util.stream.Stream; - -/** - * Utilities. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Util { - - - - public static String extractStringOption(String opName, String s) { - return extractStringOption(opName, s, null); - } - - private static String extractStringOptionWithDelimiter(String opName, String s, String deflt, char delimiter) { - int p = s.indexOf(opName+"="); - if (p == -1) return deflt; - p+=opName.length()+1; - int pe = s.indexOf(delimiter, p); - if (pe == -1) pe = s.length(); - return s.substring(p, pe); - } - - public static String extractStringOption(String opName, String s, String deflt) { - return extractStringOptionWithDelimiter(opName, s, deflt, ','); - } - - public static String extractStringOptionLine(String opName, String s, String deflt) { - return extractStringOptionWithDelimiter(opName, s, deflt, '\n').strip(); - } - - public static int extractIntOption(String opName, String s, int deflt) { - int p = s.indexOf(opName+"="); - if (p == -1) return deflt; - p+=opName.length()+1; - int pe = s.indexOf(',', p); - if (pe == -1) pe = s.length(); - int v = 0; - try { - v = Integer.parseInt(s.substring(p, pe)); - } catch (Exception e) {} - return v; - } - - - /** - * Convenience method to create a set with strings. - */ - public static Set set(String... ss) { - Set set = new HashSet<>(); - set.addAll(Arrays.asList(ss)); - return set; - } - - /** - * Normalize windows drive letter paths to upper case to enable string - * comparison. - * - * @param file File name to normalize - * @return The normalized string if file has a drive letter at the beginning, - * otherwise the original string. - */ - public static String normalizeDriveLetter(String file) { - if (file.length() > 2 && file.charAt(1) == ':') { - return Character.toUpperCase(file.charAt(0)) + file.substring(1); - } else if (file.length() > 3 && file.charAt(0) == '*' - && file.charAt(2) == ':') { - // Handle a wildcard * at the beginning of the string. - return file.substring(0, 1) + Character.toUpperCase(file.charAt(1)) - + file.substring(2); - } - return file; - } - - - public static Set union(Set s1, - Set s2) { - Set union = new HashSet<>(); - union.addAll(s1); - union.addAll(s2); - return union; - } - - public static Set subtract(Set orig, - Set toSubtract) { - Set difference = new HashSet<>(orig); - difference.removeAll(toSubtract); - return difference; - } - - public static String getStackTrace(Throwable t) { - StringWriter sw = new StringWriter(); - t.printStackTrace(new PrintWriter(sw)); - return sw.toString(); - } - - public static Set intersection(Collection c1, - Collection c2) { - Set intersection = new HashSet(c1); - intersection.retainAll(c2); - return intersection; - } - - - public static Stream getLines(String str) { - return str.isEmpty() - ? Stream.empty() - : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); - } -} diff --git a/make/langtools/tools/javacserver/client/Client.java b/make/langtools/tools/javacserver/client/Client.java new file mode 100644 index 00000000000..b3b4a8543a0 --- /dev/null +++ b/make/langtools/tools/javacserver/client/Client.java @@ -0,0 +1,191 @@ +/* + * Copyright (c) 2014, 2022, 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. + */ + +package javacserver.client; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Reader; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import javacserver.server.Server; +import javacserver.shared.PortFileInaccessibleException; +import javacserver.shared.Protocol; +import javacserver.shared.Result; +import javacserver.util.AutoFlushWriter; +import javacserver.util.Log; + +/** + * The javacserver client. This is called from the makefiles, and is responsible for passing the command + * line on to a server instance running javac, starting a new server if needed. + */ +public class Client { + private static final Log.Level LOG_LEVEL = Log.Level.INFO; + + // Wait 2 seconds for response, before giving up on javac server. + private static final int CONNECTION_TIMEOUT = 2000; + private static final int MAX_CONNECT_ATTEMPTS = 3; + private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; + + private final ClientConfiguration conf; + + public Client(ClientConfiguration conf) { + this.conf = conf; + } + + public static void main(String... args) { + Log.setLogForCurrentThread(new Log( + new AutoFlushWriter(new OutputStreamWriter(System.out)), + new AutoFlushWriter(new OutputStreamWriter(System.err)))); + Log.setLogLevel(LOG_LEVEL); + + ClientConfiguration conf = ClientConfiguration.fromCommandLineArguments(args); + if (conf == null) { + System.exit(Result.CMDERR.exitCode); + } + + Client client = new Client(conf); + int exitCode = client.dispatchToServer(); + + System.exit(exitCode); + } + + private int dispatchToServer() { + try { + // Check if server seems to be already running + if (!conf.portFile().hasValidValues()) { + // Fork a new server and wait for it to start + startNewServer(); + } + + try (Socket socket = tryConnect()) { + BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); + + Protocol.sendCommand(out, conf.javacArgs()); + int exitCode = Protocol.readResponse(in); + + return exitCode; + } + } catch (PortFileInaccessibleException e) { + Log.error("Port file inaccessible."); + return Result.ERROR.exitCode; + } catch (IOException ioe) { + Log.error("IOException caught during compilation: " + ioe.getMessage()); + Log.debug(ioe); + return Result.ERROR.exitCode; + } catch (InterruptedException ie) { + Thread.currentThread().interrupt(); // Restore interrupt + Log.error("Compilation interrupted."); + Log.debug(ie); + return Result.ERROR.exitCode; + } + } + + /* + * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server. + */ + private Socket tryConnect() throws IOException, InterruptedException { + int attempt = 0; + + while (true) { + Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS); + try { + Socket socket = new Socket(); + InetAddress localhost = InetAddress.getByName(null); + InetSocketAddress address = new InetSocketAddress(localhost, conf.portFile().getPort()); + socket.connect(address, CONNECTION_TIMEOUT); + Log.debug("Connected"); + return socket; + } catch (IOException ex) { + Log.error("Connection attempt failed: " + ex.getMessage()); + if (attempt >= MAX_CONNECT_ATTEMPTS) { + Log.error("Giving up"); + throw new IOException("Could not connect to server", ex); + } + } + Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); + } + } + + /* + * Fork a server process and wait for server to come around + */ + private void startNewServer() throws IOException, InterruptedException { + List cmd = new ArrayList<>(); + // conf.javaCommand() is how to start java in the way we want to run + // the server + cmd.addAll(Arrays.asList(conf.javaCommand().split(" "))); + // javacserver.server.Server is the server main class + cmd.add(Server.class.getName()); + // and it expects a port file path + cmd.add(conf.portFile().getFilename()); + + Process serverProcess; + Log.debug("Starting server. Command: " + String.join(" ", cmd)); + try { + // If the cmd for some reason can't be executed (file is not found, + // or is not executable for instance) this will throw an + // IOException + serverProcess = new ProcessBuilder(cmd).redirectErrorStream(true).start(); + } catch (IOException ex) { + // Message is typically something like: + // Cannot run program "xyz": error=2, No such file or directory + Log.error("Failed to create server process: " + ex.getMessage()); + Log.debug(ex); + throw new IOException(ex); + } + + // serverProcess != null at this point. + try { + // Throws an IOException if no valid values materialize + conf.portFile().waitForValidValues(); + } catch (IOException ex) { + // Process was started, but server failed to initialize. This could + // for instance be due to the JVM not finding the server class, + // or the server running in to some exception early on. + Log.error("javacserver server process failed to initialize: " + ex.getMessage()); + Log.error("Process output:"); + Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); + try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { + br.lines().forEach(Log::error); + } + Log.error(""); + try { + Log.error("Process exit code: " + serverProcess.exitValue()); + } catch (IllegalThreadStateException e) { + // Server is presumably still running. + } + throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); + } + } +} diff --git a/make/langtools/tools/javacserver/client/ClientConfiguration.java b/make/langtools/tools/javacserver/client/ClientConfiguration.java new file mode 100644 index 00000000000..1c901d615f3 --- /dev/null +++ b/make/langtools/tools/javacserver/client/ClientConfiguration.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2014, 2022, 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. + */ + +package javacserver.client; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; +import javacserver.shared.PortFile; +import javacserver.util.Log; + +/** + * Description of the arguments needed to start a javacserver client, as extracted from + * the command line and configuration file. + */ +public record ClientConfiguration(PortFile portFile, String javaCommand, String[] javacArgs) { + static ClientConfiguration fromCommandLineArguments(String... args) { + String confFileName = getConfFileName(args); + if (confFileName == null) { + return null; + } + + String confFileContent = getConfFileContent(confFileName); + if (confFileContent == null) { + return null; + } + + String portFileName = getPortFileName(confFileContent); + if (portFileName == null) { + return null; + } + String javaCommand = getJavaCommandString(confFileContent); + if (javaCommand == null) { + return null; + } + + PortFile portFile = new PortFile(portFileName); + String[] javacArgs = Arrays.copyOfRange(args, 1, args.length); + + ClientConfiguration conf = new ClientConfiguration(portFile, javaCommand, javacArgs); + return conf; + } + + private static String getConfFileName(String[] args) { + if (args.length < 1) { + Log.error("Error: javacserver client: missing --conf= argument"); + return null; + } + String[] conf = args[0].split("=", 2); + if (conf.length != 2 || !conf[0].equalsIgnoreCase("--conf")) { + Log.error("Error: javacserver client: first argument must be --conf="); + return null; + } + String confFileName = conf[1]; + if (!Files.exists(Path.of(confFileName))) { + Log.error("Error: javacserver client: specified conf file does not exist"); + return null; + } + return confFileName; + } + + private static String getConfFileContent(String confFile) { + try { + List confFileLines = Files.readAllLines(Path.of(confFile)); + String confFileContent = String.join("\n", confFileLines); + return confFileContent; + } catch (IOException e) { + Log.error("Cannot read configuration file " + confFile); + Log.debug(e); + return null; + } + } + + private static String getJavaCommandString(String confFileContent) { + String serverCommandString = getConfValue("javacmd", confFileContent); + if (serverCommandString.isEmpty()) { + Log.error("Configuration file missing value for 'javacmd'"); + return null; + } else { + return serverCommandString; + } + } + + private static String getPortFileName(String confFileContent) { + String portfileName = getConfValue("portfile", confFileContent); + if (portfileName.isEmpty()) { + Log.error("Configuration file missing value for 'portfile'"); + return null; + } else { + return portfileName; + } + } + + private static String getConfValue(String optionName, String content) { + String result; + int p = content.indexOf(optionName + "="); + if (p == -1) { + result = ""; + } else { + p += optionName.length() + 1; + int pe = content.indexOf('\n', p); + if (pe == -1) pe = content.length(); + result = content.substring(p, pe); + } + return result.strip(); + } +} \ No newline at end of file diff --git a/make/langtools/tools/javacserver/client/ClientMain.java b/make/langtools/tools/javacserver/client/ClientMain.java deleted file mode 100644 index c26ead5e633..00000000000 --- a/make/langtools/tools/javacserver/client/ClientMain.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.client; - -import java.io.OutputStreamWriter; -import java.io.Writer; - -import javacserver.AutoFlushWriter; -import javacserver.Log; -import javacserver.Result; -import javacserver.comp.SjavacImpl; -import javacserver.options.Options; -import javacserver.server.Sjavac; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ClientMain { - - public static int run(String[] args) { - return run(args, - new AutoFlushWriter(new OutputStreamWriter(System.out)), - new AutoFlushWriter(new OutputStreamWriter(System.err))); - } - - public static int run(String[] args, Writer out, Writer err) { - - Log.setLogForCurrentThread(new Log(out, err)); - - Options options; - try { - options = Options.parseArgs(args); - } catch (IllegalArgumentException e) { - Log.error(e.getMessage()); - return Result.CMDERR.exitCode; - } - - Log.setLogLevel(options.getLogLevel()); - - // Prepare sjavac object - boolean useServer = options.getServerConf() != null; - Sjavac sjavac = useServer ? new SjavacClient(options) : new SjavacImpl(); - - // Perform compilation - Result result = sjavac.compile(args); - - // If sjavac is running in the foreground we should shut it down at this point - if (!useServer) { - sjavac.shutdown(); - } - - return result.exitCode; - } -} diff --git a/make/langtools/tools/javacserver/client/SjavacClient.java b/make/langtools/tools/javacserver/client/SjavacClient.java deleted file mode 100644 index 3d12eb31782..00000000000 --- a/make/langtools/tools/javacserver/client/SjavacClient.java +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.client; - -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.OutputStreamWriter; -import java.io.PrintWriter; -import java.io.Reader; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.Socket; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.options.Options; -import javacserver.server.PortFile; -import javacserver.server.Sjavac; -import javacserver.server.SjavacServer; - -/** - * Sjavac implementation that delegates requests to a SjavacServer. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacClient implements Sjavac { - - private PortFile portFile; - - // The servercmd option specifies how the server part of sjavac is spawned. - // It should point to a javacserver.Main that supports --startserver - private String serverCommand; - - // Accept 120 seconds of inactivity before quitting. - private static final int KEEPALIVE = 120; - private static final int POOLSIZE = Runtime.getRuntime().availableProcessors(); - // Wait 2 seconds for response, before giving up on javac server. - private static final int CONNECTION_TIMEOUT = 2000; - private static final int MAX_CONNECT_ATTEMPTS = 3; - private static final int WAIT_BETWEEN_CONNECT_ATTEMPTS = 2000; - - public SjavacClient(Options options) { - String serverConf = options.getServerConf(); - String configFile = Util.extractStringOption("conf", serverConf, ""); - - try { - List configFileLines = Files.readAllLines(Path.of(configFile)); - String configFileContent = String.join("\n", configFileLines); - - String portfileName = Util.extractStringOptionLine("portfile", configFileContent, ""); - if (portfileName.isEmpty()) { - Log.error("Configuration file missing value for 'portfile'"); - portFile = null; - } else { - portFile = SjavacServer.getPortFile(portfileName); - } - - String serverCommandString = Util.extractStringOptionLine("servercmd", configFileContent, ""); - if (serverCommandString.isEmpty()) { - Log.error("Configuration file missing value for 'servercmd'"); - serverCommand = null; - } else { - serverCommand = serverCommandString; - } - } catch (IOException e) { - Log.error("Cannot read configuration file " + configFile); - Log.debug(e); - portFile = null; - serverCommand = null; - } - } - - @Override - public Result compile(String[] args) { - if (portFile == null || serverCommand == null) { - Log.error("Incorrect configuration, portfile and/or servercmd missing"); - return Result.ERROR; - } - - Result result = null; - try (Socket socket = tryConnect()) { - PrintWriter out = new PrintWriter(new OutputStreamWriter(socket.getOutputStream())); - BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - - // Send args array to server - out.println(args.length); - for (String arg : args) - out.println(arg); - out.flush(); - - // Read server response line by line - String line; - while (null != (line = in.readLine())) { - if (!line.contains(":")) { - throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); - } - String[] typeAndContent = line.split(":", 2); - String type = typeAndContent[0]; - String content = typeAndContent[1]; - - try { - if (Log.isDebugging()) { - // Distinguish server generated output if debugging. - content = "[sjavac-server] " + content; - } - Log.log(Log.Level.valueOf(type), content); - continue; - } catch (IllegalArgumentException e) { - // Parsing of 'type' as log level failed. - } - - if (type.equals(SjavacServer.LINE_TYPE_RC)) { - result = Result.valueOf(content); - } - } - } catch (PortFileInaccessibleException e) { - Log.error("Port file inaccessible."); - result = Result.ERROR; - } catch (IOException ioe) { - Log.error("IOException caught during compilation: " + ioe.getMessage()); - Log.debug(ioe); - result = Result.ERROR; - } catch (InterruptedException ie) { - Thread.currentThread().interrupt(); // Restore interrupt - Log.error("Compilation interrupted."); - Log.debug(ie); - result = Result.ERROR; - } - - if (result == null) { - // No LINE_TYPE_RC was found. - result = Result.ERROR; - } - - return result; - } - - /* - * Makes MAX_CONNECT_ATTEMPTS attempts to connect to server. - */ - private Socket tryConnect() throws IOException, InterruptedException { - makeSureServerIsRunning(); - int attempt = 0; - while (true) { - Log.debug("Trying to connect. Attempt " + (++attempt) + " of " + MAX_CONNECT_ATTEMPTS); - try { - return makeConnectionAttempt(); - } catch (IOException ex) { - Log.error("Connection attempt failed: " + ex.getMessage()); - if (attempt >= MAX_CONNECT_ATTEMPTS) { - Log.error("Giving up"); - throw new IOException("Could not connect to server", ex); - } - } - Thread.sleep(WAIT_BETWEEN_CONNECT_ATTEMPTS); - } - } - - private Socket makeConnectionAttempt() throws IOException { - Socket socket = new Socket(); - InetAddress localhost = InetAddress.getByName(null); - InetSocketAddress address = new InetSocketAddress(localhost, portFile.getPort()); - socket.connect(address, CONNECTION_TIMEOUT); - Log.debug("Connected"); - return socket; - } - - /* - * Will return immediately if a server already seems to be running, - * otherwise fork a new server and block until it seems to be running. - */ - private void makeSureServerIsRunning() - throws IOException, InterruptedException { - - if (portFile.exists()) { - portFile.lock(); - portFile.getValues(); - portFile.unlock(); - - if (portFile.containsPortInfo()) { - // Server seems to already be running - return; - } - } - - // Fork a new server and wait for it to start - startNewServer(); - } - - @Override - public void shutdown() { - // Nothing to clean up - } - - /* - * Fork a server process process and wait for server to come around - */ - public void startNewServer() - throws IOException, InterruptedException { - List cmd = new ArrayList<>(); - cmd.addAll(Arrays.asList(serverCommand.split(" "))); - cmd.add("--startserver:" - + "portfile=" + portFile.getFilename() - + ",poolsize=" + POOLSIZE - + ",keepalive="+ KEEPALIVE); - - Process serverProcess; - Log.debug("Starting server. Command: " + String.join(" ", cmd)); - try { - // If the cmd for some reason can't be executed (file is not found, - // or is not executable for instance) this will throw an - // IOException and p == null. - serverProcess = new ProcessBuilder(cmd) - .redirectErrorStream(true) - .start(); - } catch (IOException ex) { - // Message is typically something like: - // Cannot run program "xyz": error=2, No such file or directory - Log.error("Failed to create server process: " + ex.getMessage()); - Log.debug(ex); - throw new IOException(ex); - } - - // serverProcess != null at this point. - try { - // Throws an IOException if no valid values materialize - portFile.waitForValidValues(); - } catch (IOException ex) { - // Process was started, but server failed to initialize. This could - // for instance be due to the JVM not finding the server class, - // or the server running in to some exception early on. - Log.error("Sjavac server failed to initialize: " + ex.getMessage()); - Log.error("Process output:"); - Reader serverStdoutStderr = new InputStreamReader(serverProcess.getInputStream()); - try (BufferedReader br = new BufferedReader(serverStdoutStderr)) { - br.lines().forEach(Log::error); - } - Log.error(""); - try { - Log.error("Process exit code: " + serverProcess.exitValue()); - } catch (IllegalThreadStateException e) { - // Server is presumably still running. - } - throw new IOException("Server failed to initialize: " + ex.getMessage(), ex); - } - } -} diff --git a/make/langtools/tools/javacserver/comp/SjavacImpl.java b/make/langtools/tools/javacserver/comp/SjavacImpl.java deleted file mode 100644 index eb7ba30f73d..00000000000 --- a/make/langtools/tools/javacserver/comp/SjavacImpl.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.comp; - -import java.io.PrintWriter; -import java.io.StringWriter; -import java.util.stream.Stream; - -import com.sun.tools.javac.Main; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.options.Option; -import javacserver.server.Sjavac; - -/** - * The sjavac implementation that interacts with javac and performs the actual - * compilation. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacImpl implements Sjavac { - - @Override - @SuppressWarnings("deprecated") - public Result compile(String[] args) { - // Direct logging to our byte array stream. - StringWriter strWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter(strWriter); - - // Prepare arguments - String[] passThroughArgs = Stream.of(args) - .filter(arg -> !arg.startsWith(Option.SERVER.arg)) - .toArray(String[]::new); - // Compile - int exitcode = Main.compile(passThroughArgs, printWriter); - Result result = Result.of(exitcode); - - // Process compiler output (which is always errors) - printWriter.flush(); - Util.getLines(strWriter.toString()).forEach(Log::error); - - return result; - - } - - @Override - public void shutdown() { - // Nothing to clean up - } -} diff --git a/make/langtools/tools/javacserver/options/ArgumentIterator.java b/make/langtools/tools/javacserver/options/ArgumentIterator.java deleted file mode 100644 index 54c6105227a..00000000000 --- a/make/langtools/tools/javacserver/options/ArgumentIterator.java +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.options; - -import java.util.Iterator; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ArgumentIterator implements Iterator { - - /** The underlying argument iterator */ - private Iterator iter; - - /** Extra state used to implement peek and current */ - private String current; - private String buffered; - - public ArgumentIterator(Iterable iter) { - this.iter = iter.iterator(); - } - - @Override - public boolean hasNext() { - return buffered != null || iter.hasNext(); - } - - @Override - public String next() { - fillBuffer(); - current = buffered; - buffered = null; - return current; - } - - /** - * @return the last element returned by next() (or {@code null} if next has - * never been invoked on this iterator). - */ - public String current() { - return current; - } - - /** Can't remove current element, since we may have buffered it. */ - @Override - public void remove() { - throw new UnsupportedOperationException(); - } - - /** - * @return Returns the next element without advancing the iterator - */ - public String peek() { - fillBuffer(); - return buffered; - } - - private void fillBuffer() { - if (buffered == null && iter.hasNext()) - buffered = iter.next(); - } - -} diff --git a/make/langtools/tools/javacserver/options/CommandLine.java b/make/langtools/tools/javacserver/options/CommandLine.java deleted file mode 100644 index 017d32a0d7c..00000000000 --- a/make/langtools/tools/javacserver/options/CommandLine.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Copyright (c) 1999, 2022, 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. - */ - -package javacserver.options; - -import java.io.IOException; -import java.io.Reader; -import java.nio.charset.Charset; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.List; - -/** - * Various utility methods for processing Java tool command line arguments. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class CommandLine { - /** - * Process Win32-style command files for the specified command line - * arguments and return the resulting arguments. A command file argument - * is of the form '@file' where 'file' is the name of the file whose - * contents are to be parsed for additional arguments. The contents of - * the command file are parsed using StreamTokenizer and the original - * '@file' argument replaced with the resulting tokens. Recursive command - * files are not supported. The '@' character itself can be quoted with - * the sequence '@@'. - * @param args the arguments that may contain @files - * @return the arguments, with @files expanded - * @throws IOException if there is a problem reading any of the @files - */ - public static List parse(List args) throws IOException { - List newArgs = new ArrayList<>(); - appendParsedCommandArgs(newArgs, args); - return newArgs; - } - - private static void appendParsedCommandArgs(List newArgs, List args) throws IOException { - for (String arg : args) { - if (arg.length() > 1 && arg.charAt(0) == '@') { - arg = arg.substring(1); - if (arg.charAt(0) == '@') { - newArgs.add(arg); - } else { - loadCmdFile(arg, newArgs); - } - } else { - newArgs.add(arg); - } - } - } - - /** - * Process the given environment variable and appends any Win32-style - * command files for the specified command line arguments and return - * the resulting arguments. A command file argument - * is of the form '@file' where 'file' is the name of the file whose - * contents are to be parsed for additional arguments. The contents of - * the command file are parsed using StreamTokenizer and the original - * '@file' argument replaced with the resulting tokens. Recursive command - * files are not supported. The '@' character itself can be quoted with - * the sequence '@@'. - * @param envVariable the env variable to process - * @param args the arguments that may contain @files - * @return the arguments, with environment variable's content and expansion of @files - * @throws IOException if there is a problem reading any of the @files - * @throws UnmatchedQuote - */ - public static List parse(String envVariable, List args) - throws IOException, UnmatchedQuote { - - List inArgs = new ArrayList<>(); - appendParsedEnvVariables(inArgs, envVariable); - inArgs.addAll(args); - List newArgs = new ArrayList<>(); - appendParsedCommandArgs(newArgs, inArgs); - return newArgs; - } - - private static void loadCmdFile(String name, List args) throws IOException { - try (Reader r = Files.newBufferedReader(Paths.get(name), Charset.defaultCharset())) { - Tokenizer t = new Tokenizer(r); - String s; - while ((s = t.nextToken()) != null) { - args.add(s); - } - } - } - - public static class Tokenizer { - private final Reader in; - private int ch; - - public Tokenizer(Reader in) throws IOException { - this.in = in; - ch = in.read(); - } - - public String nextToken() throws IOException { - skipWhite(); - if (ch == -1) { - return null; - } - - StringBuilder sb = new StringBuilder(); - char quoteChar = 0; - - while (ch != -1) { - switch (ch) { - case ' ': - case '\t': - case '\f': - if (quoteChar == 0) { - return sb.toString(); - } - sb.append((char) ch); - break; - - case '\n': - case '\r': - return sb.toString(); - - case '\'': - case '"': - if (quoteChar == 0) { - quoteChar = (char) ch; - } else if (quoteChar == ch) { - quoteChar = 0; - } else { - sb.append((char) ch); - } - break; - - case '\\': - if (quoteChar != 0) { - ch = in.read(); - switch (ch) { - case '\n': - case '\r': - while (ch == ' ' || ch == '\n' || ch == '\r' || ch == '\t' || ch == '\f') { - ch = in.read(); - } - continue; - - case 'n': - ch = '\n'; - break; - case 'r': - ch = '\r'; - break; - case 't': - ch = '\t'; - break; - case 'f': - ch = '\f'; - break; - } - } - sb.append((char) ch); - break; - - default: - sb.append((char) ch); - } - - ch = in.read(); - } - - return sb.toString(); - } - - void skipWhite() throws IOException { - while (ch != -1) { - switch (ch) { - case ' ': - case '\t': - case '\n': - case '\r': - case '\f': - break; - - case '#': - ch = in.read(); - while (ch != '\n' && ch != '\r' && ch != -1) { - ch = in.read(); - } - break; - - default: - return; - } - - ch = in.read(); - } - } - } - - @SuppressWarnings("fallthrough") - private static void appendParsedEnvVariables(List newArgs, String envVariable) - throws UnmatchedQuote { - - if (envVariable == null) { - return; - } - String in = System.getenv(envVariable); - if (in == null || in.trim().isEmpty()) { - return; - } - - final char NUL = (char)0; - final int len = in.length(); - - int pos = 0; - StringBuilder sb = new StringBuilder(); - char quote = NUL; - char ch; - - loop: - while (pos < len) { - ch = in.charAt(pos); - switch (ch) { - case '\"': case '\'': - if (quote == NUL) { - quote = ch; - } else if (quote == ch) { - quote = NUL; - } else { - sb.append(ch); - } - pos++; - break; - case '\f': case '\n': case '\r': case '\t': case ' ': - if (quote == NUL) { - newArgs.add(sb.toString()); - sb.setLength(0); - while (ch == '\f' || ch == '\n' || ch == '\r' || ch == '\t' || ch == ' ') { - pos++; - if (pos >= len) { - break loop; - } - ch = in.charAt(pos); - } - break; - } - // fall through - default: - sb.append(ch); - pos++; - } - } - if (sb.length() != 0) { - newArgs.add(sb.toString()); - } - if (quote != NUL) { - throw new UnmatchedQuote(envVariable); - } - } - - public static class UnmatchedQuote extends Exception { - private static final long serialVersionUID = 0; - - public final String variableName; - - UnmatchedQuote(String variable) { - this.variableName = variable; - } - } -} diff --git a/make/langtools/tools/javacserver/options/Option.java b/make/langtools/tools/javacserver/options/Option.java deleted file mode 100644 index 2856c65627b..00000000000 --- a/make/langtools/tools/javacserver/options/Option.java +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.options; - -/** - * Sjavac options can be classified as: - * - * (1) relevant only for sjavac, such as --server - * (2) relevant for sjavac and javac, such as -d, or - * (3) relevant only for javac, such as -g. - * - * This enum represents all options from (1) and (2). Note that instances of - * this enum only entail static information about the option. For storage of - * option values, refer to Options. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public enum Option { - SERVER("--server:", "Specify server configuration file of running server") { - @Override - protected void processMatching(ArgumentIterator iter, Options.ArgDecoderOptionHelper helper) { - helper.serverConf(iter.current().substring(arg.length())); - } - }, - STARTSERVER("--startserver:", "Start server and use the given configuration file") { - @Override - protected void processMatching(ArgumentIterator iter, Options.ArgDecoderOptionHelper helper) { - helper.startServerConf(iter.current().substring(arg.length())); - } - }; - - - public final String arg; - - final String description; - - private Option(String arg, String description) { - this.arg = arg; - this.description = description; - } - - // Future cleanup: Change the "=" syntax to ":" syntax to be consistent and - // to follow the javac-option style. - - public boolean hasOption() { - return arg.endsWith(":") || arg.endsWith("="); - } - - - /** - * Process current argument of argIter. - * - * It's final, since the option customization is typically done in - * processMatching. - * - * @param argIter Iterator to read current and succeeding arguments from. - * @param helper The helper to report back to. - * @return true iff the argument was processed by this option. - */ - public final boolean processCurrent(ArgumentIterator argIter, - Options.ArgDecoderOptionHelper helper) { - String fullArg = argIter.current(); // "-tr" or "-log=level" - if (hasOption() ? fullArg.startsWith(arg) : fullArg.equals(arg)) { - processMatching(argIter, helper); - return true; - } - // Did not match - return false; - } - - /** Called by process if the current argument matches this option. */ - protected abstract void processMatching(ArgumentIterator argIter, - Options.ArgDecoderOptionHelper helper); -} diff --git a/make/langtools/tools/javacserver/options/Options.java b/make/langtools/tools/javacserver/options/Options.java deleted file mode 100644 index 507e7134fdd..00000000000 --- a/make/langtools/tools/javacserver/options/Options.java +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.options; - -import java.util.List; - -/** - * Instances of this class represent values for sjavac command line options. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class Options { - private String logLevel = "info"; - - private boolean startServer = false; - - // Server configuration string - private String serverConf; - - /** Get the log level. */ - public String getLogLevel() { - return logLevel; - } - - /** Return true iff a new server should be started */ - public boolean startServerFlag() { - return startServer; - } - - /** Return the server configuration string. */ - public String getServerConf() { - return serverConf; - } - - /** - * Parses the given argument array and returns a corresponding Options - * instance. - */ - public static Options parseArgs(String... args) { - Options options = new Options(); - options.new ArgDecoderOptionHelper().traverse(args); - return options; - } - - // OptionHelper that records the traversed options in this Options instance. - public class ArgDecoderOptionHelper { - public void reportError(String msg) { - throw new IllegalArgumentException(msg); - } - - public void serverConf(String conf) { - if (serverConf != null) - reportError("Can not specify more than one server configuration."); - else - serverConf = conf; - } - - public void startServerConf(String conf) { - if (serverConf != null) - reportError("Can not specify more than one server configuration."); - else { - startServer = true; - serverConf = conf; - } - } - - /** - * Traverses an array of arguments and performs the appropriate callbacks. - * - * @param args the arguments to traverse. - */ - void traverse(String[] args) { - Iterable allArgs; - try { - allArgs = CommandLine.parse(List.of(args)); // Detect @file and load it as a command line. - } catch (java.io.IOException e) { - throw new IllegalArgumentException("Problem reading @"+e.getMessage()); - } - ArgumentIterator argIter = new ArgumentIterator(allArgs); - - nextArg: - while (argIter.hasNext()) { - - String arg = argIter.next(); - - if (arg.startsWith("-")) { - for (Option opt : Option.values()) { - if (opt.processCurrent(argIter, this)) - continue nextArg; - } - } - } - } - } -} diff --git a/make/langtools/tools/javacserver/comp/PooledSjavac.java b/make/langtools/tools/javacserver/server/CompilerThreadPool.java similarity index 60% rename from make/langtools/tools/javacserver/comp/PooledSjavac.java rename to make/langtools/tools/javacserver/server/CompilerThreadPool.java index 3647f17cc10..3f3dea52c84 100644 --- a/make/langtools/tools/javacserver/comp/PooledSjavac.java +++ b/make/langtools/tools/javacserver/server/CompilerThreadPool.java @@ -23,54 +23,38 @@ * questions. */ -package javacserver.comp; +package javacserver.server; -import java.util.Objects; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; - -import javacserver.Log; -import javacserver.Result; -import javacserver.server.Sjavac; +import javacserver.util.Log; /** - * An sjavac implementation that limits the number of concurrent calls by - * wrapping invocations in Callables and delegating them to a FixedThreadPool. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Use a fixed thread pool to limit the amount of concurrent javac compilation + * that can happen. */ -public class PooledSjavac implements Sjavac { +public class CompilerThreadPool { + private static final int POOLSIZE = Runtime.getRuntime().availableProcessors(); - final Sjavac delegate; - final ExecutorService pool; + private final ExecutorService pool; - public PooledSjavac(Sjavac delegate, int poolsize) { - Objects.requireNonNull(delegate); - this.delegate = delegate; - pool = Executors.newFixedThreadPool(poolsize); + public CompilerThreadPool() { + this.pool = Executors.newFixedThreadPool(POOLSIZE); } - @Override - public Result compile(String[] args) { + public int dispatchCompilation(String[] args) { Log log = Log.get(); try { - return pool.submit(() -> { - Log.setLogForCurrentThread(log); - return delegate.compile(args); - }).get(); + return pool.submit(() -> Server.runCompiler(log, args)).get(); } catch (Exception e) { e.printStackTrace(); throw new RuntimeException("Error during compile", e); } } - @Override public void shutdown() { - Log.debug("Shutting down PooledSjavac"); + Log.debug("Shutting down javacserver thread pool"); pool.shutdown(); // Disable new tasks from being submitted try { // Wait a while for existing tasks to terminate @@ -78,16 +62,17 @@ public void shutdown() { pool.shutdownNow(); // Cancel currently executing tasks // Wait a while for tasks to respond to being cancelled if (!pool.awaitTermination(60, TimeUnit.SECONDS)) - Log.error("ThreadPool did not terminate"); + Log.error("Thread pool did not terminate"); } } catch (InterruptedException ie) { - // (Re-)Cancel if current thread also interrupted - pool.shutdownNow(); - // Preserve interrupt status - Thread.currentThread().interrupt(); + // (Re-)Cancel if current thread also interrupted + pool.shutdownNow(); + // Preserve interrupt status + Thread.currentThread().interrupt(); } - - delegate.shutdown(); } + public int poolSize() { + return POOLSIZE; + } } diff --git a/make/langtools/tools/javacserver/server/IdleResetSjavac.java b/make/langtools/tools/javacserver/server/IdleMonitor.java similarity index 59% rename from make/langtools/tools/javacserver/server/IdleResetSjavac.java rename to make/langtools/tools/javacserver/server/IdleMonitor.java index be4be86c622..939a97beebb 100644 --- a/make/langtools/tools/javacserver/server/IdleResetSjavac.java +++ b/make/langtools/tools/javacserver/server/IdleMonitor.java @@ -27,53 +27,30 @@ import java.util.Timer; import java.util.TimerTask; - -import javacserver.Log; -import javacserver.Result; +import java.util.function.Consumer; +import javacserver.util.RunnableTimerTask; /** - * An sjavac implementation that keeps track of idleness and shuts down the - * given Terminable upon idleness timeout. - * - * An idleness timeout kicks in {@code idleTimeout} milliseconds after the last - * request is completed. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Monitors the javacserver daemon, shutting it down if it recieves no new requests + * after a certain amount of time. */ -public class IdleResetSjavac implements Sjavac { +public class IdleMonitor { + // Accept 120 seconds of inactivity before quitting. + private static final int KEEPALIVE = 120; - private final Sjavac delegate; - private final Terminable toShutdown; + private final Consumer onShutdown; private final Timer idlenessTimer = new Timer(); - private final long idleTimeout; private int outstandingCalls = 0; // Class invariant: idlenessTimerTask != null <-> idlenessTimerTask is scheduled private TimerTask idlenessTimerTask; - public IdleResetSjavac(Sjavac delegate, - Terminable toShutdown, - long idleTimeout) { - this.delegate = delegate; - this.toShutdown = toShutdown; - this.idleTimeout = idleTimeout; + public IdleMonitor(Consumer onShutdown) { + this.onShutdown = onShutdown; scheduleTimeout(); } - @Override - public Result compile(String[] args) { - startCall(); - try { - return delegate.compile(args); - } finally { - endCall(); - } - } - - private synchronized void startCall() { + public synchronized void startCall() { // Was there no outstanding calls before this call? if (++outstandingCalls == 1) { // Then the timer task must have been scheduled @@ -85,7 +62,7 @@ private synchronized void startCall() { } } - private synchronized void endCall() { + public synchronized void endCall() { if (--outstandingCalls == 0) { // No more outstanding calls. Schedule timeout. scheduleTimeout(); @@ -95,19 +72,14 @@ private synchronized void endCall() { private void scheduleTimeout() { if (idlenessTimerTask != null) throw new IllegalStateException("Idle timeout already scheduled"); - idlenessTimerTask = new TimerTask() { - public void run() { - Log.setLogForCurrentThread(ServerMain.getErrorLog()); - toShutdown.shutdown("Server has been idle for " + (idleTimeout / 1000) + " seconds."); - } - }; - idlenessTimer.schedule(idlenessTimerTask, idleTimeout); + idlenessTimerTask = new RunnableTimerTask(() -> { + Server.restoreServerErrorLog(); + onShutdown.accept("Server has been idle for " + KEEPALIVE + " seconds."); + }); + idlenessTimer.schedule(idlenessTimerTask, KEEPALIVE * 1000); } - @Override public void shutdown() { idlenessTimer.cancel(); - delegate.shutdown(); } - } diff --git a/make/langtools/tools/javacserver/server/PortFileMonitor.java b/make/langtools/tools/javacserver/server/PortFileMonitor.java index 1b8828c694b..41a357b6db5 100644 --- a/make/langtools/tools/javacserver/server/PortFileMonitor.java +++ b/make/langtools/tools/javacserver/server/PortFileMonitor.java @@ -27,68 +27,61 @@ import java.io.IOException; import java.util.Timer; -import java.util.TimerTask; - -import javacserver.Log; +import java.util.function.Consumer; +import javacserver.shared.PortFile; +import javacserver.util.Log; +import javacserver.util.RunnableTimerTask; /** - * Monitors the presence of a port file and shuts down the given SjavacServer + * Monitors the presence of a port file and shuts down the server * whenever the port file is deleted or invalidated. * * TODO: JDK-8046882 - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. */ public class PortFileMonitor { - // Check if the portfile is gone, every 5 seconds. private static final int CHECK_PORTFILE_INTERVAL = 5000; private final Timer timer = new Timer(); private final PortFile portFile; - private final SjavacServer server; + private final Consumer onShutdown; public PortFileMonitor(PortFile portFile, - SjavacServer server) { + Consumer onShutdown) { this.portFile = portFile; - this.server = server; + this.onShutdown = onShutdown; } public void start() { Log log = Log.get(); - TimerTask shutdownCheck = new TimerTask() { - public void run() { - Log.setLogForCurrentThread(log); - Log.debug("Checking port file status..."); - try { - if (!portFile.exists()) { - // Time to quit because the portfile was deleted by another - // process, probably by the makefile that is done building. - server.shutdown("Quitting because portfile was deleted!"); - } else if (portFile.markedForStop()) { - // Time to quit because another process touched the file - // server.port.stop to signal that the server should stop. - // This is necessary on some operating systems that lock - // the port file hard! - server.shutdown("Quitting because a portfile.stop file was found!"); - } else if (!portFile.stillMyValues()) { - // Time to quit because another build has started. - server.shutdown("Quitting because portfile is now owned by another javac server!"); - } - } catch (IOException e) { - Log.error("IOException caught in PortFileMonitor."); - Log.debug(e); - } catch (InterruptedException e) { - Thread.currentThread().interrupt(); - Log.error(e); - } - } - }; + timer.schedule(new RunnableTimerTask(() -> checkPortFile(log)), 0, CHECK_PORTFILE_INTERVAL); + } - timer.schedule(shutdownCheck, 0, CHECK_PORTFILE_INTERVAL); + private void checkPortFile(Log log) { + Log.setLogForCurrentThread(log); + Log.debug("Checking port file status..."); + try { + if (!portFile.exists()) { + // Time to quit because the portfile was deleted by another + // process, probably by the makefile that is done building. + onShutdown.accept("Quitting because portfile was deleted!"); + } else if (portFile.markedForStop()) { + // Time to quit because another process touched the file + // server.port.stop to signal that the server should stop. + // This is necessary on some operating systems that lock + // the port file hard! + onShutdown.accept("Quitting because a portfile.stop file was found!"); + } else if (!portFile.stillMyValues()) { + // Time to quit because another build has started. + onShutdown.accept("Quitting because portfile is now owned by another javac server!"); + } + } catch (IOException e) { + Log.error("IOException caught in PortFileMonitor."); + Log.debug(e); + } catch (InterruptedException e) { + Thread.currentThread().interrupt(); + Log.error(e); + } } public void shutdown() { diff --git a/make/langtools/tools/javacserver/server/RequestHandler.java b/make/langtools/tools/javacserver/server/RequestHandler.java deleted file mode 100644 index b2d04e4606b..00000000000 --- a/make/langtools/tools/javacserver/server/RequestHandler.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.server; - -import java.io.BufferedReader; -import java.io.InputStreamReader; -import java.io.PrintWriter; -import java.net.Socket; -import java.nio.file.Path; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; - -import static javacserver.server.SjavacServer.LINE_TYPE_RC; - - -/** - * A RequestHandler handles requests performed over a socket. Specifically it - * - Reads the command string specifying which method is to be invoked - * - Reads the appropriate arguments - * - Delegates the actual invocation to the given sjavac implementation - * - Writes the result back to the socket output stream - * - * None of the work performed by this class is really bound by the CPU. It - * should be completely fine to have a large number of RequestHandlers active. - * To limit the number of concurrent compilations, use PooledSjavac. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class RequestHandler extends Thread { - - private final Socket socket; - private final Sjavac sjavac; - - public RequestHandler(Socket socket, Sjavac sjavac) { - this.socket = socket; - this.sjavac = sjavac; - } - - @Override - public void run() { - - try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); - PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { - - // Set up logging for this thread. Stream back logging messages to - // client on the format format "level:msg". - Log.setLogForCurrentThread(new Log(out, out) { - @Override - protected boolean isLevelLogged(Level l) { - // Make sure it is up to the client to decide whether or - // not this message should be displayed. - return true; - } - - @Override - protected void printLogMsg(Level msgLevel, String msg) { - // Follow sjavac server/client protocol: Send one line - // at a time and prefix with message with "level:". - Util.getLines(msg) - .map(line -> msgLevel + ":" + line) - .forEach(line -> super.printLogMsg(msgLevel, line)); - } - }); - - // Read argument array - int n = Integer.parseInt(in.readLine()); - String[] args = new String[n]; - for (int i = 0; i < n; i++) { - args[i] = in.readLine(); - } - - // If there has been any internal errors, notify client - checkInternalErrorLog(); - - // Perform compilation - Result rc = sjavac.compile(args); - - // Send return code back to client - out.println(LINE_TYPE_RC + ":" + rc.name()); - - // Check for internal errors again. - checkInternalErrorLog(); - } catch (Exception ex) { - // Not much to be done at this point. The client side request - // code will most likely throw an IOException and the - // compilation will fail. - Log.error(ex); - } finally { - Log.setLogForCurrentThread(null); - } - } - - private void checkInternalErrorLog() { - Path errorLog = ServerMain.getErrorLog().getLogDestination(); - if (errorLog != null) { - Log.error("Server has encountered an internal error. See " + errorLog.toAbsolutePath() - + " for details."); - } - } -} diff --git a/make/langtools/tools/javacserver/server/Server.java b/make/langtools/tools/javacserver/server/Server.java new file mode 100644 index 00000000000..62247e85656 --- /dev/null +++ b/make/langtools/tools/javacserver/server/Server.java @@ -0,0 +1,281 @@ +/* + * Copyright (c) 2011, 2022, 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. + */ + +package javacserver.server; + +import com.sun.tools.javac.Main; +import java.io.BufferedReader; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.SocketException; +import java.nio.file.Path; +import java.util.Random; +import java.util.concurrent.atomic.AtomicBoolean; +import javacserver.shared.PortFile; +import javacserver.shared.Protocol; +import javacserver.shared.Result; +import javacserver.util.LazyInitFileLog; +import javacserver.util.Log; +import javacserver.util.LoggingOutputStream; +import javacserver.util.Util; + +/** + * Start a new server main thread, that will listen to incoming connection requests from the client, + * and dispatch these on to worker threads in a thread pool, running javac. + */ +public class Server { + private ServerSocket serverSocket; + private PortFile portFile; + private PortFileMonitor portFileMonitor; + private IdleMonitor idleMonitor; + private CompilerThreadPool compilerThreadPool; + + // Set to false break accept loop + final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); + + // For logging server internal (non request specific) errors. + private static LazyInitFileLog errorLog; + + public static void main(String... args) { + initLogging(); + + try { + PortFile portFile = getPortFileFromArguments(args); + if (portFile == null) { + System.exit(Result.CMDERR.exitCode); + return; + } + + Server server = new Server(portFile); + if (!server.start()) { + System.exit(Result.ERROR.exitCode); + } else { + System.exit(Result.OK.exitCode); + } + } catch (IOException | InterruptedException ex) { + ex.printStackTrace(); + System.exit(Result.ERROR.exitCode); + } + } + + private static void initLogging() { + // Under normal operation, all logging messages generated server-side + // are due to compilation requests. These logging messages should + // be relayed back to the requesting client rather than written to the + // server log. The only messages that should be written to the server + // log (in production mode) should be errors, + errorLog = new LazyInitFileLog("server.log"); + Log.setLogForCurrentThread(errorLog); + Log.setLogLevel(Log.Level.ERROR); // should be set to ERROR. + + // Make sure no exceptions go under the radar + Thread.setDefaultUncaughtExceptionHandler((t, e) -> { + restoreServerErrorLog(); + Log.error(e); + }); + + // Inevitably someone will try to print messages using System.{out,err}. + // Make sure this output also ends up in the log. + System.setOut(new PrintStream(new LoggingOutputStream(System.out, Log.Level.INFO, "[stdout] "))); + System.setErr(new PrintStream(new LoggingOutputStream(System.err, Log.Level.ERROR, "[stderr] "))); + } + + private static PortFile getPortFileFromArguments(String[] args) { + if (args.length != 1) { + Log.error("javacserver daemon incorrectly called"); + return null; + } + String portfilename = args[0]; + PortFile portFile = new PortFile(portfilename); + return portFile; + } + + public Server(PortFile portFile) throws FileNotFoundException { + this.portFile = portFile; + } + + /** + * Start the daemon, unless another one is already running, in which it returns + * false and exits immediately. + */ + private boolean start() throws IOException, InterruptedException { + // The port file is locked and the server port and cookie is written into it. + portFile.lock(); + portFile.getValues(); + if (portFile.containsPortInfo()) { + Log.debug("javacserver daemon not started because portfile exists!"); + portFile.unlock(); + return false; + } + + serverSocket = new ServerSocket(); + InetAddress localhost = InetAddress.getByName(null); + serverSocket.bind(new InetSocketAddress(localhost, 0)); + + // At this point the server accepts connections, so it is now safe + // to publish the port / cookie information + + // The secret cookie shared between server and client through the port file. + // Used to prevent clients from believing that they are communicating with + // an old server when a new server has started and reused the same port as + // an old server. + long myCookie = new Random().nextLong(); + portFile.setValues(serverSocket.getLocalPort(), myCookie); + portFile.unlock(); + + portFileMonitor = new PortFileMonitor(portFile, this::shutdownServer); + portFileMonitor.start(); + compilerThreadPool = new CompilerThreadPool(); + idleMonitor = new IdleMonitor(this::shutdownServer); + + Log.debug("javacserver daemon started. Accepting connections..."); + Log.debug(" port: " + serverSocket.getLocalPort()); + Log.debug(" time: " + new java.util.Date()); + Log.debug(" poolsize: " + compilerThreadPool.poolSize()); + + keepAcceptingRequests.set(true); + do { + try { + Socket socket = serverSocket.accept(); + // Handle each incoming request in a separate thread. This is just for socket communication, + // the actual compilation will be done by the threadpool. + Thread requestHandler = new Thread(() -> handleRequest(socket)); + requestHandler.start(); + } catch (SocketException se) { + // Caused by serverSocket.close() and indicates shutdown + } + } while (keepAcceptingRequests.get()); + + Log.debug("Shutting down."); + + // No more connections accepted. If any client managed to connect after + // the accept() was interrupted but before the server socket is closed + // here, any attempt to read or write to the socket will result in an + // IOException on the client side. + + // Shut down + idleMonitor.shutdown(); + compilerThreadPool.shutdown(); + + return true; + } + + private void handleRequest(Socket socket) { + try (BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream())); + PrintWriter out = new PrintWriter(socket.getOutputStream(), true)) { + try { + idleMonitor.startCall(); + + // Set up logging for this thread. Stream back logging messages to + // client on the format "level:msg". + Log.setLogForCurrentThread(new Protocol.ProtocolLog(out)); + + String[] args = Protocol.readCommand(in); + + // If there has been any internal errors, notify client + checkInternalErrorLog(); + + // Perform compilation. This will call runCompiler() on a + // thread in the thread pool + int exitCode = compilerThreadPool.dispatchCompilation(args); + Protocol.sendExitCode(out, exitCode); + + // Check for internal errors again. + checkInternalErrorLog(); + } finally { + idleMonitor.endCall(); + } + } catch (Exception ex) { + // Not much to be done at this point. The client side request + // code will most likely throw an IOException and the + // compilation will fail. + Log.error(ex); + } finally { + Log.setLogForCurrentThread(null); + } + } + + @SuppressWarnings("deprecated") + public static int runCompiler(Log log, String[] args) { + Log.setLogForCurrentThread(log); + + // Direct logging to our byte array stream. + StringWriter strWriter = new StringWriter(); + PrintWriter printWriter = new PrintWriter(strWriter); + + // Compile + int exitcode = Main.compile(args, printWriter); + + // Process compiler output (which is always errors) + printWriter.flush(); + Util.getLines(strWriter.toString()).forEach(Log::error); + + return exitcode; + } + + private void checkInternalErrorLog() { + Path errorLogPath = errorLog.getLogDestination(); + if (errorLogPath != null) { + Log.error("Server has encountered an internal error. See " + errorLogPath.toAbsolutePath() + + " for details."); + } + } + + public static void restoreServerErrorLog() { + Log.setLogForCurrentThread(errorLog); + } + + public void shutdownServer(String quitMsg) { + if (!keepAcceptingRequests.compareAndSet(true, false)) { + // Already stopped, no need to shut down again + return; + } + + Log.debug("Quitting: " + quitMsg); + + portFileMonitor.shutdown(); // No longer any need to monitor port file + + // Unpublish port before shutting down socket to minimize the number of + // failed connection attempts + try { + portFile.delete(); + } catch (IOException | InterruptedException e) { + Log.error(e); + } + try { + serverSocket.close(); + } catch (IOException e) { + Log.error(e); + } + } +} diff --git a/make/langtools/tools/javacserver/server/ServerMain.java b/make/langtools/tools/javacserver/server/ServerMain.java deleted file mode 100644 index 1f5b51755bb..00000000000 --- a/make/langtools/tools/javacserver/server/ServerMain.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2014, 2022, 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. - */ - -package javacserver.server; - -import java.io.IOException; -import java.io.PrintStream; - -import javacserver.Log; -import javacserver.Result; -import javacserver.server.log.LazyInitFileLog; -import javacserver.server.log.LoggingOutputStream; - -import static javacserver.Log.Level.ERROR; -import static javacserver.Log.Level.INFO; - -/** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class ServerMain { - - // For logging server internal (non request specific) errors. - private static LazyInitFileLog errorLog; - - public static int run(String[] args) { - - // Under normal operation, all logging messages generated server-side - // are due to compilation requests. These logging messages should - // be relayed back to the requesting client rather than written to the - // server log. The only messages that should be written to the server - // log (in production mode) should be errors, - Log.setLogForCurrentThread(errorLog = new LazyInitFileLog("server.log")); - Log.setLogLevel(ERROR); // should be set to ERROR. - - // Make sure no exceptions go under the radar - Thread.setDefaultUncaughtExceptionHandler((t, e) -> { - Log.setLogForCurrentThread(errorLog); - Log.error(e); - }); - - // Inevitably someone will try to print messages using System.{out,err}. - // Make sure this output also ends up in the log. - System.setOut(new PrintStream(new LoggingOutputStream(System.out, INFO, "[stdout] "))); - System.setErr(new PrintStream(new LoggingOutputStream(System.err, ERROR, "[stderr] "))); - - // Any options other than --startserver? - if (args.length > 1) { - Log.error("When spawning a background server, only a single --startserver argument is allowed."); - return Result.CMDERR.exitCode; - } - - int exitCode; - try { - SjavacServer server = new SjavacServer(args[0]); - exitCode = server.startServer(); - } catch (IOException | InterruptedException ex) { - ex.printStackTrace(); - exitCode = Result.ERROR.exitCode; - } - - return exitCode; - } - - public static LazyInitFileLog getErrorLog() { - return errorLog; - } -} diff --git a/make/langtools/tools/javacserver/server/SjavacServer.java b/make/langtools/tools/javacserver/server/SjavacServer.java deleted file mode 100644 index d52e274c4ac..00000000000 --- a/make/langtools/tools/javacserver/server/SjavacServer.java +++ /dev/null @@ -1,248 +0,0 @@ -/* - * Copyright (c) 2011, 2022, 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. - */ - -package javacserver.server; - -import java.io.FileNotFoundException; -import java.io.IOException; -import java.net.InetAddress; -import java.net.InetSocketAddress; -import java.net.ServerSocket; -import java.net.Socket; -import java.net.SocketException; -import java.util.HashMap; -import java.util.Map; -import java.util.Random; -import java.util.concurrent.atomic.AtomicBoolean; - -import javacserver.Log; -import javacserver.Result; -import javacserver.Util; -import javacserver.comp.PooledSjavac; -import javacserver.comp.SjavacImpl; - -/** - * The JavacServer class contains methods both to setup a server that responds to requests and methods to connect to this server. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public class SjavacServer implements Terminable { - - // Prefix of line containing return code. - public static final String LINE_TYPE_RC = "RC"; - - private final String portfilename; - private final int poolsize; - private final int keepalive; - - // The secret cookie shared between server and client through the port file. - // Used to prevent clients from believing that they are communicating with - // an old server when a new server has started and reused the same port as - // an old server. - private final long myCookie; - - // Accumulated build time, not counting idle time, used for logging purposes - private long totalBuildTime; - - // The sjavac implementation to delegate requests to - Sjavac sjavac; - - private ServerSocket serverSocket; - - private PortFile portFile; - private PortFileMonitor portFileMonitor; - - // Set to false break accept loop - final AtomicBoolean keepAcceptingRequests = new AtomicBoolean(); - - // For the client, all port files fetched, one per started javac server. - // Though usually only one javac server is started by a client. - private static Map allPortFiles; - - public SjavacServer(String settings) throws FileNotFoundException { - this(Util.extractStringOption("portfile", settings), - Util.extractIntOption("poolsize", settings, Runtime.getRuntime().availableProcessors()), - Util.extractIntOption("keepalive", settings, 120)); - } - - public SjavacServer(String portfilename, - int poolsize, - int keepalive) - throws FileNotFoundException { - this.portfilename = portfilename; - this.poolsize = poolsize; - this.keepalive = keepalive; - this.myCookie = new Random().nextLong(); - } - - - /** - * Acquire the port file. Synchronized since several threads inside an smart javac wrapper client acquires the same port file at the same time. - */ - public static synchronized PortFile getPortFile(String filename) { - if (allPortFiles == null) { - allPortFiles = new HashMap<>(); - } - PortFile pf = allPortFiles.get(filename); - - // Port file known. Does it still exist? - if (pf != null) { - try { - if (!pf.exists()) - pf = null; - } catch (IOException ioex) { - ioex.printStackTrace(); - } - } - - if (pf == null) { - pf = new PortFile(filename); - allPortFiles.put(filename, pf); - } - return pf; - } - - /** - * Get the cookie used for this server. - */ - long getCookie() { - return myCookie; - } - - /** - * Get the port used for this server. - */ - int getPort() { - return serverSocket.getLocalPort(); - } - - /** - * Sum up the total build time for this javac server. - */ - public void addBuildTime(long inc) { - totalBuildTime += inc; - } - - /** - * Start a server using a settings string. Typically: "--startserver:portfile=/tmp/myserver,poolsize=3" and the string "portfile=/tmp/myserver,poolsize=3" - * is sent as the settings parameter. Returns 0 on success, -1 on failure. - */ - public int startServer() throws IOException, InterruptedException { - long serverStart = System.currentTimeMillis(); - - // The port file is locked and the server port and cookie is written into it. - portFile = getPortFile(portfilename); - - synchronized (portFile) { - portFile.lock(); - portFile.getValues(); - if (portFile.containsPortInfo()) { - Log.debug("Javac server not started because portfile exists!"); - portFile.unlock(); - return Result.ERROR.exitCode; - } - - // .-----------. .--------. .------. - // socket -->| IdleReset |-->| Pooled |-->| Impl |--> javac - // '-----------' '--------' '------' - sjavac = new SjavacImpl(); - sjavac = new PooledSjavac(sjavac, poolsize); - sjavac = new IdleResetSjavac(sjavac, - this, - keepalive * 1000); - - serverSocket = new ServerSocket(); - InetAddress localhost = InetAddress.getByName(null); - serverSocket.bind(new InetSocketAddress(localhost, 0)); - - // At this point the server accepts connections, so it is now safe - // to publish the port / cookie information - portFile.setValues(getPort(), getCookie()); - portFile.unlock(); - } - - portFileMonitor = new PortFileMonitor(portFile, this); - portFileMonitor.start(); - - Log.debug("Sjavac server started. Accepting connections..."); - Log.debug(" port: " + getPort()); - Log.debug(" time: " + new java.util.Date()); - Log.debug(" poolsize: " + poolsize); - - - keepAcceptingRequests.set(true); - do { - try { - Socket socket = serverSocket.accept(); - new RequestHandler(socket, sjavac).start(); - } catch (SocketException se) { - // Caused by serverSocket.close() and indicates shutdown - } - } while (keepAcceptingRequests.get()); - - Log.debug("Shutting down."); - - // No more connections accepted. If any client managed to connect after - // the accept() was interrupted but before the server socket is closed - // here, any attempt to read or write to the socket will result in an - // IOException on the client side. - - long realTime = System.currentTimeMillis() - serverStart; - Log.debug("Total wall clock time " + realTime + "ms build time " + totalBuildTime + "ms"); - - // Shut down - sjavac.shutdown(); - - return Result.OK.exitCode; - } - - @Override - public void shutdown(String quitMsg) { - if (!keepAcceptingRequests.compareAndSet(true, false)) { - // Already stopped, no need to shut down again - return; - } - - Log.debug("Quitting: " + quitMsg); - - portFileMonitor.shutdown(); // No longer any need to monitor port file - - // Unpublish port before shutting down socket to minimize the number of - // failed connection attempts - try { - portFile.delete(); - } catch (IOException | InterruptedException e) { - Log.error(e); - } - try { - serverSocket.close(); - } catch (IOException e) { - Log.error(e); - } - } -} diff --git a/make/langtools/tools/javacserver/server/PortFile.java b/make/langtools/tools/javacserver/shared/PortFile.java similarity index 94% rename from make/langtools/tools/javacserver/server/PortFile.java rename to make/langtools/tools/javacserver/shared/PortFile.java index 3874a4c1ee2..2e4283a22b3 100644 --- a/make/langtools/tools/javacserver/server/PortFile.java +++ b/make/langtools/tools/javacserver/shared/PortFile.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.server; +package javacserver.shared; import java.io.File; import java.io.FileNotFoundException; @@ -34,23 +34,15 @@ import java.nio.channels.FileLock; import java.nio.channels.FileLockInterruptionException; import java.util.concurrent.Semaphore; - -import javacserver.Log; -import javacserver.client.PortFileInaccessibleException; +import javacserver.util.Log; /** * The PortFile class mediates access to a short binary file containing the tcp/ip port (for the localhost) * and a cookie necessary for the server answering on that port. The file can be locked using file system * primitives to avoid race conditions when several javac clients are started at the same. Note that file - * system locking is not always supported on a all operating systems and/or file systems. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * system locking is not always supported on all operating systems and/or file systems. */ public class PortFile { - // Port file format: // byte ordering: high byte first = big endian // Magic nr, 4 byte int, first in file. @@ -225,6 +217,19 @@ public void unlock() throws IOException { lockSem.release(); } + public boolean hasValidValues() throws IOException, InterruptedException { + if (exists()) { + lock(); + getValues(); + unlock(); + + if (containsPortInfo()) { + return true; + } + } + return false; + } + /** * Wait for the port file to contain values that look valid. */ @@ -277,7 +282,7 @@ public boolean stillMyValues() throws IOException, FileNotFoundException, Interr continue; } catch (ClosedChannelException e) { - // The channel has been closed since sjavac is exiting. + // The channel has been closed since the server is exiting. return false; } } diff --git a/make/langtools/tools/javacserver/client/PortFileInaccessibleException.java b/make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java similarity index 98% rename from make/langtools/tools/javacserver/client/PortFileInaccessibleException.java rename to make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java index c9db8dfc44a..b306893c20d 100644 --- a/make/langtools/tools/javacserver/client/PortFileInaccessibleException.java +++ b/make/langtools/tools/javacserver/shared/PortFileInaccessibleException.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.client; +package javacserver.shared; import java.io.IOException; diff --git a/make/langtools/tools/javacserver/shared/Protocol.java b/make/langtools/tools/javacserver/shared/Protocol.java new file mode 100644 index 00000000000..f4f0f23cdc6 --- /dev/null +++ b/make/langtools/tools/javacserver/shared/Protocol.java @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2014, 2022, 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. + */ + +package javacserver.shared; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.PrintWriter; +import javacserver.util.Log; +import javacserver.util.Util; + +/** + * Implementation of the wire protocol used by the javacserver client and daemon to communicate. + * Basically, the client sends the argument to javac, one line per string. The server responds + * with log lines (if there is any output), and the exit code from javac. + */ +public class Protocol { + // Prefix of line containing return code. + private static final String LINE_TYPE_RC = "RC"; + + public static void sendCommand(PrintWriter out, String[] args) throws IOException { + // Send args array to server + out.println(args.length); + for (String arg : args) + out.println(arg); + out.flush(); + } + + public static String[] readCommand(BufferedReader in) throws IOException { + // Read argument array + int n = Integer.parseInt(in.readLine()); + String[] args = new String[n]; + for (int i = 0; i < n; i++) { + args[i] = in.readLine(); + } + return args; + } + + public static void sendExitCode(PrintWriter out, int exitCode) { + // Send return code back to client + out.println(LINE_TYPE_RC + ":" + exitCode); + } + + public static int readResponse(BufferedReader in) throws IOException { + // Read server response line by line + String line; + while (null != (line = in.readLine())) { + Line parsedLine = new Line(line); + + try { + String content = parsedLine.getContent(); + if (Log.isDebugging()) { + // Distinguish server generated output if debugging. + content = "[javacserver] " + content; + } + Log.log(Log.Level.valueOf(parsedLine.getType()), content); + continue; + } catch (IllegalArgumentException e) { + // Parsing of 'type' as log level failed. + } + + if (parsedLine.isExitCode()) { + return parsedLine.getExitCode(); + } + } + // No exit code was found. + return Result.ERROR.exitCode; + } + + public static class Line { + private final String type; + + public String getType() { + return type; + } + + public String getContent() { + return content; + } + + public boolean isExitCode() { + return type.equals(LINE_TYPE_RC); + } + + public int getExitCode() { + return Integer.parseInt(content); + } + + private final String content; + + public Line(String line) { + if (!line.contains(":")) { + throw new AssertionError("Could not parse protocol line: >>\"" + line + "\"<<"); + } + String[] typeAndContent = line.split(":", 2); + type = typeAndContent[0]; + content = typeAndContent[1]; + } + } + + public static class ProtocolLog extends Log { + public ProtocolLog(PrintWriter out) { + super(out, out); + } + + @Override + protected boolean isLevelLogged(Level l) { + // Make sure it is up to the client to decide whether or + // not this message should be displayed. + return true; + } + + @Override + protected void printLogMsg(Level msgLevel, String msg) { + // Follow the server/client protocol: Send one line + // at a time and prefix with message with "level:". + Util.getLines(msg) + .map(line -> msgLevel + ":" + line) + .forEach(line -> super.printLogMsg(msgLevel, line)); + } + } +} diff --git a/make/langtools/tools/javacserver/server/Terminable.java b/make/langtools/tools/javacserver/shared/Result.java similarity index 74% rename from make/langtools/tools/javacserver/server/Terminable.java rename to make/langtools/tools/javacserver/shared/Result.java index 5c598ddc420..f15c3dd3765 100644 --- a/make/langtools/tools/javacserver/server/Terminable.java +++ b/make/langtools/tools/javacserver/shared/Result.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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,14 +23,19 @@ * questions. */ -package javacserver.server; +package javacserver.shared; /** - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * Result codes. */ -public interface Terminable { - void shutdown(String quitMsg); +public enum Result { + OK(0), // Compilation completed with no errors. + ERROR(1), // Completed but reported errors. + CMDERR(2); // Bad command-line arguments + + public final int exitCode; + + Result(int exitCode) { + this.exitCode = exitCode; + } } diff --git a/make/langtools/tools/javacserver/AutoFlushWriter.java b/make/langtools/tools/javacserver/util/AutoFlushWriter.java similarity index 98% rename from make/langtools/tools/javacserver/AutoFlushWriter.java rename to make/langtools/tools/javacserver/util/AutoFlushWriter.java index 92d64399690..1c06d558a8c 100644 --- a/make/langtools/tools/javacserver/AutoFlushWriter.java +++ b/make/langtools/tools/javacserver/util/AutoFlushWriter.java @@ -23,14 +23,13 @@ * questions. */ -package javacserver; +package javacserver.util; import java.io.FilterWriter; import java.io.IOException; import java.io.Writer; public class AutoFlushWriter extends FilterWriter { - public AutoFlushWriter(Writer out) { super(out); } diff --git a/make/langtools/tools/javacserver/server/log/LazyInitFileLog.java b/make/langtools/tools/javacserver/util/LazyInitFileLog.java similarity index 97% rename from make/langtools/tools/javacserver/server/log/LazyInitFileLog.java rename to make/langtools/tools/javacserver/util/LazyInitFileLog.java index 5471b8f0196..4de83b63176 100644 --- a/make/langtools/tools/javacserver/server/log/LazyInitFileLog.java +++ b/make/langtools/tools/javacserver/util/LazyInitFileLog.java @@ -23,7 +23,7 @@ * questions. */ -package javacserver.server.log; +package javacserver.util; import java.io.FileWriter; import java.io.IOException; @@ -32,10 +32,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -import javacserver.Log; - public class LazyInitFileLog extends Log { - String baseFilename; Path destination = null; diff --git a/make/langtools/tools/javacserver/Log.java b/make/langtools/tools/javacserver/util/Log.java similarity index 78% rename from make/langtools/tools/javacserver/Log.java rename to make/langtools/tools/javacserver/util/Log.java index 49b62876083..0c9d51e3c86 100644 --- a/make/langtools/tools/javacserver/Log.java +++ b/make/langtools/tools/javacserver/util/Log.java @@ -23,17 +23,16 @@ * questions. */ -package javacserver; +package javacserver.util; import java.io.PrintWriter; import java.io.StringWriter; import java.io.Writer; -import java.util.Locale; /** - * Utility class only for sjavac logging. + * Utility class only for javacserver logging. * - * Logging in sjavac has special requirements when running in server/client + * Logging in javacserver has special requirements when running in server/client * mode. Most of the log messages is generated server-side, but the server * is typically spawned by the client in the background, so the user usually * does not see the server stdout/stderr. For this reason log messages needs @@ -42,16 +41,9 @@ * instance so that each connected client can have its own instance that * relays messages back to the requesting client. * - * On the client-side (or when running sjavac without server-mode) there will - * typically just be one Log instance. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. + * On the client-side there will typically just be one Log instance. */ public class Log { - public enum Level { ERROR, WARN, @@ -61,7 +53,7 @@ public enum Level { } private static Log stdOutErr = new Log(new PrintWriter(System.out), new PrintWriter(System.err)); - private static ThreadLocal loggers = new ThreadLocal<>(); + private static ThreadLocal logger = new ThreadLocal<>(); protected PrintWriter err; // Used for error and warning messages protected PrintWriter out; // Used for other messages @@ -73,31 +65,19 @@ public Log(Writer out, Writer err) { } public static void setLogForCurrentThread(Log log) { - loggers.set(log); - } - - public static void setLogLevel(String l) { - setLogLevel(Level.valueOf(l.toUpperCase(Locale.US))); + logger.set(log); } public static void setLogLevel(Level l) { get().level = l; } - public static void trace(String msg) { - log(Level.TRACE, msg); - } - public static void debug(String msg) { log(Level.DEBUG, msg); } - public static void info(String msg) { - log(Level.INFO, msg); - } - - public static void warn(String msg) { - log(Level.WARN, msg); + public static void debug(Throwable t) { + log(Level.DEBUG, t); } public static void error(String msg) { @@ -112,10 +92,6 @@ public static void log(Level l, String msg) { get().printLogMsg(l, msg); } - public static void debug(Throwable t) { - log(Level.DEBUG, t); - } - public static void log(Level l, Throwable t) { StringWriter sw = new StringWriter(); t.printStackTrace(new PrintWriter(sw, true)); @@ -131,7 +107,7 @@ protected boolean isLevelLogged(Level l) { } public static Log get() { - Log log = loggers.get(); + Log log = logger.get(); return log != null ? log : stdOutErr; } diff --git a/make/langtools/tools/javacserver/server/log/LoggingOutputStream.java b/make/langtools/tools/javacserver/util/LoggingOutputStream.java similarity index 97% rename from make/langtools/tools/javacserver/server/log/LoggingOutputStream.java rename to make/langtools/tools/javacserver/util/LoggingOutputStream.java index 6df616bd5e2..3b3f88d7647 100644 --- a/make/langtools/tools/javacserver/server/log/LoggingOutputStream.java +++ b/make/langtools/tools/javacserver/util/LoggingOutputStream.java @@ -23,17 +23,14 @@ * questions. */ -package javacserver.server.log; +package javacserver.util; import java.io.ByteArrayOutputStream; import java.io.FilterOutputStream; import java.io.IOException; import java.io.OutputStream; -import javacserver.Log; - public class LoggingOutputStream extends FilterOutputStream { - private static final byte[] LINE_SEP = System.lineSeparator().getBytes(); private final Log.Level level; diff --git a/make/langtools/tools/javacserver/Result.java b/make/langtools/tools/javacserver/util/RunnableTimerTask.java similarity index 59% rename from make/langtools/tools/javacserver/Result.java rename to make/langtools/tools/javacserver/util/RunnableTimerTask.java index 084089fb01c..7d8f5aa3a43 100644 --- a/make/langtools/tools/javacserver/Result.java +++ b/make/langtools/tools/javacserver/util/RunnableTimerTask.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 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,34 +23,22 @@ * questions. */ -package javacserver; +package javacserver.util; -/** Result codes. - */ -public enum Result { - OK(0), // Compilation completed with no errors. - ERROR(1), // Completed but reported errors. - CMDERR(2), // Bad command-line arguments - SYSERR(3), // System error or resource exhaustion. - ABNORMAL(4); // Compiler terminated abnormally - - Result(int exitCode) { - this.exitCode = exitCode; - } +import java.util.TimerTask; - public static Result of(int exitcode) { - for (Result result : values()) { - if (result.exitCode == exitcode) { - return result; - } - } +/** + * Wrapper class since TimerTask is not up to modern standards + */ +public class RunnableTimerTask extends TimerTask { + private final Runnable task; - return ABNORMAL; + public RunnableTimerTask(Runnable task) { + this.task = task; } - public boolean isOK() { - return (exitCode == 0); + @Override + public void run() { + task.run(); } - - public final int exitCode; } diff --git a/make/langtools/tools/javacserver/server/Sjavac.java b/make/langtools/tools/javacserver/util/Util.java similarity index 72% rename from make/langtools/tools/javacserver/server/Sjavac.java rename to make/langtools/tools/javacserver/util/Util.java index 9c7c980c2f2..8381b1c3c6d 100644 --- a/make/langtools/tools/javacserver/server/Sjavac.java +++ b/make/langtools/tools/javacserver/util/Util.java @@ -23,20 +23,18 @@ * questions. */ -package javacserver.server; +package javacserver.util; -import javacserver.Result; +import java.util.regex.Pattern; +import java.util.stream.Stream; -/** - * Interface of the SjavacImpl, the sjavac client and all wrappers such as - * PooledSjavac etc. - * - *

This is NOT part of any supported API. - * If you write code that depends on this, you do so at your own risk. - * This code and its internal interfaces are subject to change or - * deletion without notice. - */ -public interface Sjavac { - Result compile(String[] args); - void shutdown(); +public class Util { + /** + * Return a stream of strings, where the input string is split at line separators. + */ + public static Stream getLines(String str) { + return str.isEmpty() + ? Stream.empty() + : Stream.of(str.split(Pattern.quote(System.lineSeparator()))); + } } From b035056d28a1c6c738fed6dd7f3b4d9dac75c6c7 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 2 Dec 2022 00:08:34 +0000 Subject: [PATCH 002/494] 8297455: Use the official ToolProvider API to call javac Reviewed-by: erikj --- make/langtools/tools/javacserver/server/Server.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/make/langtools/tools/javacserver/server/Server.java b/make/langtools/tools/javacserver/server/Server.java index 62247e85656..b213c992667 100644 --- a/make/langtools/tools/javacserver/server/Server.java +++ b/make/langtools/tools/javacserver/server/Server.java @@ -25,7 +25,6 @@ package javacserver.server; -import com.sun.tools.javac.Main; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.IOException; @@ -39,8 +38,10 @@ import java.net.Socket; import java.net.SocketException; import java.nio.file.Path; +import java.util.Optional; import java.util.Random; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.spi.ToolProvider; import javacserver.shared.PortFile; import javacserver.shared.Protocol; import javacserver.shared.Result; @@ -225,7 +226,6 @@ private void handleRequest(Socket socket) { } } - @SuppressWarnings("deprecated") public static int runCompiler(Log log, String[] args) { Log.setLogForCurrentThread(log); @@ -234,7 +234,12 @@ public static int runCompiler(Log log, String[] args) { PrintWriter printWriter = new PrintWriter(strWriter); // Compile - int exitcode = Main.compile(args, printWriter); + Optional tool = ToolProvider.findFirst("javac"); + if (tool.isEmpty()) { + Log.error("Can't find tool javac"); + return Result.ERROR.exitCode; + } + int exitcode = tool.get().run(printWriter, printWriter, args); // Process compiler output (which is always errors) printWriter.flush(); From 11ba7591dfd3f7ca58e2e1ac6d1b3e81391f5bfb Mon Sep 17 00:00:00 2001 From: Jie Fu Date: Fri, 2 Dec 2022 06:04:10 +0000 Subject: [PATCH 003/494] 8297992: Tests fail after JDK-8297215 due to lack of @enablePreview Reviewed-by: darcy --- test/jdk/java/lang/Thread/virtual/HoldsLock.java | 1 + test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java | 1 + test/jdk/jdk/internal/vm/Continuation/Basic.java | 1 + 3 files changed, 3 insertions(+) diff --git a/test/jdk/java/lang/Thread/virtual/HoldsLock.java b/test/jdk/java/lang/Thread/virtual/HoldsLock.java index 727362a11a5..016cc736d2e 100644 --- a/test/jdk/java/lang/Thread/virtual/HoldsLock.java +++ b/test/jdk/java/lang/Thread/virtual/HoldsLock.java @@ -35,6 +35,7 @@ * @summary Test Thread.holdsLock when lock held by carrier thread * @requires vm.continuations & vm.debug * @modules java.base/java.lang:+open + * @enablePreview * @run testng/othervm -XX:+UseHeavyMonitors HoldsLock */ diff --git a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java index 34b19e0e0f3..a81726983ba 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/GetStackTraceALot.java @@ -35,6 +35,7 @@ * @test * @requires vm.debug == true & vm.continuations * @modules java.base/java.lang:+open + * @enablePreview * @compile GetStackTraceALot.java ../ThreadBuilders.java * @run main/timeout=300 GetStackTraceALot 1000 */ diff --git a/test/jdk/jdk/internal/vm/Continuation/Basic.java b/test/jdk/jdk/internal/vm/Continuation/Basic.java index 8965c32fb75..5735a3301c4 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Basic.java +++ b/test/jdk/jdk/internal/vm/Continuation/Basic.java @@ -47,6 +47,7 @@ * @modules java.base/jdk.internal.vm * @build java.base/java.lang.StackWalkerHelper * +* @enablePreview * @run testng/othervm -XX:+VerifyStack -Xint Basic * @run testng/othervm -XX:+VerifyStack -Xcomp -XX:TieredStopAtLevel=3 -XX:CompileOnly=jdk/internal/vm/Continuation,Basic Basic * @run testng/othervm -XX:+VerifyStack -Xcomp -XX:-TieredCompilation -XX:CompileOnly=jdk/internal/vm/Continuation,Basic Basic From 9bbcb546c86b40ae23d46e12a1a03aae7a7a6182 Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Fri, 2 Dec 2022 07:29:27 +0000 Subject: [PATCH 004/494] 8297784: Optimize @Stable field for Method.isCallerSensitive Reviewed-by: redestad, jvernee, alanb --- .../share/classes/java/lang/reflect/Method.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/reflect/Method.java b/src/java.base/share/classes/java/lang/reflect/Method.java index 0a62be40240..f8e7b9fcb20 100644 --- a/src/java.base/share/classes/java/lang/reflect/Method.java +++ b/src/java.base/share/classes/java/lang/reflect/Method.java @@ -605,13 +605,17 @@ private Object invoke(Object obj, Object[] args, Class caller) return callerSensitive ? ma.invoke(obj, args, caller) : ma.invoke(obj, args); } - @Stable private Boolean callerSensitive; // lazily initialize + // 0 = not initialized (@Stable contract) + // 1 = initialized, CS + // -1 = initialized, not CS + @Stable private byte callerSensitive; + private boolean isCallerSensitive() { - Boolean cs = callerSensitive; - if (cs == null) { - callerSensitive = cs = Reflection.isCallerSensitive(this); + byte cs = callerSensitive; + if (cs == 0) { + callerSensitive = cs = (byte)(Reflection.isCallerSensitive(this) ? 1 : -1); } - return cs; + return (cs > 0); } /** From d50015af99f44909bf71fd2de97546d47cda86d6 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Fri, 2 Dec 2022 08:26:22 +0000 Subject: [PATCH 005/494] 8297715: RISC-V: C2: Use single-bit instructions from the Zbs extension Reviewed-by: fjiang, yadongwang, shade --- src/hotspot/cpu/riscv/assembler_riscv.hpp | 3 ++- src/hotspot/cpu/riscv/globals_riscv.hpp | 1 + src/hotspot/cpu/riscv/riscv.ad | 8 ++++++++ src/hotspot/cpu/riscv/riscv_b.ad | 16 +++++++++++++++- 4 files changed, 26 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index b381f727a83..debc809d5ae 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -1670,7 +1670,7 @@ enum Nf { // ==================================== // RISC-V Bit-Manipulation Extension -// Currently only support Zba and Zbb bitmanip extensions. +// Currently only support Zba, Zbb and Zbs bitmanip extensions. // ==================================== #define INSN(NAME, op, funct3, funct7) \ void NAME(Register Rd, Register Rs1, Register Rs2) { \ @@ -1745,6 +1745,7 @@ enum Nf { INSN(rori, 0b0010011, 0b101, 0b011000); INSN(slli_uw, 0b0011011, 0b001, 0b000010); + INSN(bexti, 0b0010011, 0b101, 0b010010); #undef INSN diff --git a/src/hotspot/cpu/riscv/globals_riscv.hpp b/src/hotspot/cpu/riscv/globals_riscv.hpp index 962ba7f8593..cb7bd99dfb2 100644 --- a/src/hotspot/cpu/riscv/globals_riscv.hpp +++ b/src/hotspot/cpu/riscv/globals_riscv.hpp @@ -102,6 +102,7 @@ define_pd_global(intx, InlineSmallCode, 1000); product(bool, UseRVV, false, EXPERIMENTAL, "Use RVV instructions") \ product(bool, UseZba, false, EXPERIMENTAL, "Use Zba instructions") \ product(bool, UseZbb, false, EXPERIMENTAL, "Use Zbb instructions") \ + product(bool, UseZbs, false, EXPERIMENTAL, "Use Zbs instructions") \ product(bool, UseZic64b, false, EXPERIMENTAL, "Use Zic64b instructions") \ product(bool, UseZicbom, false, EXPERIMENTAL, "Use Zicbom instructions") \ product(bool, UseZicbop, false, EXPERIMENTAL, "Use Zicbop instructions") \ diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index c496754d070..a9693980441 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -2984,6 +2984,14 @@ operand immI_16bits() interface(CONST_INTER); %} +operand immIpowerOf2() %{ + predicate(is_power_of_2((juint)(n->get_int()))); + match(ConI); + op_cost(0); + format %{ %} + interface(CONST_INTER); +%} + // Long Immediate: low 32-bit mask operand immL_32bits() %{ diff --git a/src/hotspot/cpu/riscv/riscv_b.ad b/src/hotspot/cpu/riscv/riscv_b.ad index bbebe13f0a8..0d29fc06e00 100644 --- a/src/hotspot/cpu/riscv/riscv_b.ad +++ b/src/hotspot/cpu/riscv/riscv_b.ad @@ -524,4 +524,18 @@ instruct ornL_reg_reg_b(iRegLNoSp dst, iRegL src1, iRegL src2, immL_M1 m1) %{ %} ins_pipe(ialu_reg_reg); -%} \ No newline at end of file +%} + +// AndI 0b0..010..0 + ConvI2B +instruct convI2Bool_andI_reg_immIpowerOf2(iRegINoSp dst, iRegIorL2I src, immIpowerOf2 mask) %{ + predicate(UseZbs); + match(Set dst (Conv2B (AndI src mask))); + ins_cost(ALU_COST); + + format %{ "bexti $dst, $src, $mask\t#@convI2Bool_andI_reg_immIpowerOf2" %} + ins_encode %{ + __ bexti($dst$$Register, $src$$Register, exact_log2((juint)($mask$$constant))); + %} + + ins_pipe(ialu_reg_reg); +%} From 687fd714bbc390f486272e05452f038bc3631be1 Mon Sep 17 00:00:00 2001 From: Dingli Zhang Date: Fri, 2 Dec 2022 08:30:00 +0000 Subject: [PATCH 006/494] 8297549: RISC-V: Add support for Vector API vector load const operation Reviewed-by: fyang, gcao --- src/hotspot/cpu/riscv/riscv_v.ad | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/riscv/riscv_v.ad b/src/hotspot/cpu/riscv/riscv_v.ad index 1132e46c64a..5cdf49dadb8 100644 --- a/src/hotspot/cpu/riscv/riscv_v.ad +++ b/src/hotspot/cpu/riscv/riscv_v.ad @@ -74,7 +74,6 @@ source %{ case Op_VectorCastL2X: case Op_VectorCastS2X: case Op_VectorInsert: - case Op_VectorLoadConst: case Op_VectorLoadMask: case Op_VectorLoadShuffle: case Op_VectorMaskCmp: @@ -2077,3 +2076,20 @@ instruct vclearArray_reg_reg(iRegL_R29 cnt, iRegP_R28 base, Universe dummy, ins_pipe(pipe_class_memory); %} + +// Vector Load Const +instruct vloadcon(vReg dst, immI0 src) %{ + match(Set dst (VectorLoadConst src)); + ins_cost(VEC_COST); + format %{ "vloadcon $dst\t# generate iota indices" %} + ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this); + Assembler::SEW sew = Assembler::elemtype_to_sew(bt); + __ vsetvli(t0, x0, sew); + __ vid_v(as_VectorRegister($dst$$reg)); + if (is_floating_point_type(bt)) { + __ vfcvt_f_x_v(as_VectorRegister($dst$$reg), as_VectorRegister($dst$$reg)); + } + %} + ins_pipe(pipe_slow); +%} \ No newline at end of file From 6d0fbb2c49d904ac353b4a2ebc694e3d1609bd76 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 2 Dec 2022 10:44:29 +0000 Subject: [PATCH 007/494] 8297645: Drop the test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java test Reviewed-by: alanb, jpai, michaelm --- .../BodyPublishersConcat.java | 92 -- .../BodyPublishersFromPublisher.java | 53 - .../BodyPublishersNoBody.java | 53 - .../BodyPublishersOfByteArray.java | 56 - .../BodyPublishersOfByteArrays.java | 53 - .../BodyPublishersOfFile.java | 72 - .../BodyPublishersOfInputStream.java | 51 - .../BodyPublishersOfSubByteArray.java | 60 - .../BodySubscribersBuffering.java | 50 - .../BodySubscribersDiscarding.java | 49 - .../BodySubscribersFromLineSubscriber.java | 51 - .../BodySubscribersFromSubscriber.java | 51 - .../BodySubscribersMapping.java | 50 - .../BodySubscribersOfByteArray.java | 49 - .../BodySubscribersOfByteArrayConsumer.java | 49 - .../BodySubscribersOfFile.java | 50 - .../BodySubscribersOfInputStream.java | 49 - .../BodySubscribersOfLines.java | 51 - .../BodySubscribersOfPublisher.java | 79 -- .../BodySubscribersOfPublisher1.java | 84 -- .../BodySubscribersOfPublisherPublisher.java | 67 - .../BodySubscribersOfString.java | 51 - .../BodySubscribersReplacing.java | 50 - .../reactivestreams-tck-tests/S.java | 277 ---- .../SPublisherOfStream.java | 49 - .../reactivestreams-tck-tests/STest.java | 119 -- .../reactivestreams-tck-tests/TckDriver.java | 158 --- .../org/reactivestreams/FlowAdapters.java | 389 ----- .../org/reactivestreams/Processor.java | 34 - .../org/reactivestreams/Publisher.java | 52 - .../org/reactivestreams/Subscriber.java | 78 -- .../org/reactivestreams/Subscription.java | 56 - .../unicast/AsyncIterablePublisher.java | 281 ---- .../example/unicast/AsyncSubscriber.java | 261 ---- .../InfiniteIncrementNumberPublisher.java | 46 - .../unicast/NumberIterablePublisher.java | 50 - .../example/unicast/RangePublisher.java | 254 ---- .../example/unicast/SyncSubscriber.java | 134 -- .../tck/IdentityProcessorVerification.java | 896 ------------ .../tck/PublisherVerification.java | 1245 ----------------- .../tck/SubscriberBlackboxVerification.java | 516 ------- .../tck/SubscriberWhiteboxVerification.java | 850 ----------- .../reactivestreams/tck/TestEnvironment.java | 1168 ---------------- .../tck/WithHelperPublisher.java | 92 -- .../tck/flow/FlowPublisherVerification.java | 75 - .../FlowSubscriberBlackboxVerification.java | 77 - .../FlowSubscriberWhiteboxVerification.java | 60 - .../IdentityFlowProcessorVerification.java | 80 -- .../tck/flow/support/Function.java | 28 - .../tck/flow/support/HelperPublisher.java | 54 - .../flow/support/InfiniteHelperPublisher.java | 53 - .../tck/flow/support/NonFatal.java | 55 - .../tck/flow/support/Optional.java | 92 -- .../support/PublisherVerificationRules.java | 658 --------- .../SubscriberBlackboxVerificationRules.java | 395 ------ .../SubscriberBufferOverflowException.java | 41 - .../SubscriberWhiteboxVerificationRules.java | 58 - .../tck/flow/support/TestException.java | 34 - 58 files changed, 10085 deletions(-) delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersNoBody.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArray.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArrays.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/InfiniteIncrementNumberPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java delete mode 100644 test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/TestException.java diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java deleted file mode 100644 index 520c16de9a8..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersConcat.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2020, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublisher; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.ArrayList; -import java.util.List; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersConcat - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersConcat() { - super(new TestEnvironment(450L)); - } - - private static BodyPublisher ofByteArrays(int n, byte[] bytes) { - return BodyPublishers.ofByteArrays(Collections.nCopies((int) n, bytes)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - System.out.println("BodyPublishersConcat: %d elements requested" - .formatted(nElements)); - byte[] bytes = S.arrayOfNRandomBytes(ELEMENT_SIZE); - if (nElements == 0) { - System.out.println("BodyPublishersConcat: empty publisher"); - return BodyPublishers.concat(); - } else if (nElements == 1) { - System.out.println("BodyPublishersConcat: singleton publisher"); - return BodyPublishers.concat(ofByteArrays(1, bytes)); - } else if (nElements < 4) { - int left = (int)nElements/2; - int right = (int)nElements - left; - System.out.println("BodyPublishersConcat: dual publisher (%d, %d)".formatted(left, right)); - return BodyPublishers.concat(ofByteArrays(left, bytes), - ofByteArrays(right, bytes)); - } else { - List publishers = new ArrayList<>(); - List sizes = new ArrayList<>(); - long remaining = nElements; - int max = (int) Math.min((long)Integer.MAX_VALUE, nElements/2L); - while (remaining > 0) { - int length = S.randomIntUpTo(max); - if (length == 0) length = 1; - sizes.add(length); - if (remaining > length) { - publishers.add(ofByteArrays(length, bytes)); - remaining = remaining - length; - } else { - publishers.add(ofByteArrays((int)remaining, bytes)); - remaining = 0; - } - } - System.out.println("BodyPublishersConcat: multi publisher " + sizes); - return BodyPublishers.concat(publishers.toArray(BodyPublisher[]::new)); - } - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java deleted file mode 100644 index b997fa6a7fc..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersFromPublisher.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; -import java.util.stream.Stream; - -/* See TckDriver.java for more information */ -public class BodyPublishersFromPublisher - extends FlowPublisherVerification { - - public BodyPublishersFromPublisher() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - Stream buffers = - Stream.generate(() -> S.bufferOfNRandomBytes(1024)) - .limit(nElements); - Publisher pub = S.publisherOfStream(buffers); - return BodyPublishers.fromPublisher(pub); - } - - @Override - public Publisher createFailedFlowPublisher() { - return BodyPublishers.fromPublisher(S.newErroredPublisher()); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersNoBody.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersNoBody.java deleted file mode 100644 index e9eb2482ed9..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersNoBody.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersNoBody - extends FlowPublisherVerification { - - public BodyPublishersNoBody() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - return BodyPublishers.noBody(); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 0; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArray.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArray.java deleted file mode 100644 index 0188b88f26d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArray.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfByteArray - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersOfByteArray() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - byte[] b = S.arrayOfNRandomBytes(nElements * ELEMENT_SIZE); - return BodyPublishers.ofByteArray(b); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArrays.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArrays.java deleted file mode 100644 index 9ad8a0ccdac..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfByteArrays.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.Collections; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfByteArrays - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersOfByteArrays() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - byte[] bytes = S.arrayOfNRandomBytes(ELEMENT_SIZE); - return BodyPublishers.ofByteArrays( - Collections.nCopies((int) nElements, bytes)); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java deleted file mode 100644 index 97b30f4511d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfFile.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.io.IOException; -import java.io.UncheckedIOException; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.atomic.AtomicLong; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfFile - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - private static final AtomicLong UNIQUE_NUMBERS = new AtomicLong(); - - public BodyPublishersOfFile() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - try { - Path f = createFile(nElements * ELEMENT_SIZE); - return BodyPublishers.ofFile(f); - } catch (IOException e) { - throw new UncheckedIOException(e); - } - } - - private static Path createFile(long nBytes) throws IOException { - String name = "f" + UNIQUE_NUMBERS.getAndIncrement(); - Path f = Files.createFile(Path.of(name)); - return Files.write(f, S.arrayOfNRandomBytes(nBytes)); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java deleted file mode 100644 index 3f27782ea5b..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfInputStream.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.io.InputStream; -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; -import java.util.function.Supplier; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfInputStream - extends FlowPublisherVerification { - - public BodyPublishersOfInputStream() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - Supplier s = () -> S.inputStreamOfNReads((int) nElements); - return BodyPublishers.ofInputStream(s); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java deleted file mode 100644 index e0209fe058c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodyPublishersOfSubByteArray.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpRequest.BodyPublishers; -import java.nio.ByteBuffer; -import java.util.concurrent.Flow.Publisher; - -/* See TckDriver.java for more information */ -public class BodyPublishersOfSubByteArray - extends FlowPublisherVerification { - - private static final int ELEMENT_SIZE = 16 * 1024; - - public BodyPublishersOfSubByteArray() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - int prefixLen = S.randomIntUpTo(13); - int postfixLen = S.randomIntUpTo(17); - byte[] b = S.arrayOfNRandomBytes(nElements * ELEMENT_SIZE); - byte[] contents = new byte[prefixLen + b.length + postfixLen]; - System.arraycopy(b, 0, contents, prefixLen, b.length); - return BodyPublishers.ofByteArray(contents, prefixLen, b.length); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java deleted file mode 100644 index baa6b306b9a..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersBuffering.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersBuffering - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersBuffering() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.buffering(BodySubscribers.discarding(), - S.randomIntUpTo(1024) + 1); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java deleted file mode 100644 index 640000a8efc..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersDiscarding.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersDiscarding - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersDiscarding() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.discarding(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java deleted file mode 100644 index 1fbfc5f6717..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromLineSubscriber.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersFromLineSubscriber - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersFromLineSubscriber() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.fromLineSubscriber( - S.nonCompliantSubscriber()); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java deleted file mode 100644 index ca1256cf91c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersFromSubscriber.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersFromSubscriber - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersFromSubscriber() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - Subscriber> sub = S.nonCompliantSubscriber(); - return BodySubscribers.fromSubscriber(sub); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java deleted file mode 100644 index 0fa2ad0b14c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersMapping.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersMapping - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersMapping() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.mapping(BodySubscribers.ofByteArray(), - bytes -> bytes.length); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java deleted file mode 100644 index 18991f63ddb..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArray.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfByteArray - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfByteArray() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofByteArray(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java deleted file mode 100644 index 0dfbdf8eb1a..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfByteArrayConsumer.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfByteArrayConsumer - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfByteArrayConsumer() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofByteArrayConsumer(bytes -> { }); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java deleted file mode 100644 index 76a06dfc171..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfFile.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.file.Path; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfFile - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfFile() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofFile(Path.of("f1.bin")); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java deleted file mode 100644 index b3330d976b1..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfInputStream.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfInputStream - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfInputStream() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofInputStream(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java deleted file mode 100644 index 4933804631a..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfLines.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfLines - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfLines() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofLines(StandardCharsets.UTF_8); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java deleted file mode 100644 index 9b274b543e5..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisher - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfPublisher() { - super(new TestEnvironment(450L)); - } - - /* The reason for overriding this method is that BodySubscribers.ofPublisher - is somewhat tricky. It is not an independent Subscriber, but rather - an adaptor from Subscriber to Publisher. Until the Subscriber that - subscribed to that resulting Publisher requests anything, nothing - happens. */ - @Override - public void triggerFlowRequest( - Subscriber> subscriber) - { - BodySubscriber>> sub = - (BodySubscriber>>) subscriber; - CompletionStage>> body = sub.getBody(); - Publisher> pub = body.toCompletableFuture().join(); - pub.subscribe(new Subscriber<>() { - - @Override - public void onSubscribe(Subscription subscription) { - subscription.request(Integer.MAX_VALUE); - } - - @Override public void onNext(List item) { } - @Override public void onError(Throwable throwable) { } - @Override public void onComplete() { } - }); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofPublisher(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java deleted file mode 100644 index ef2b4e98f2b..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisher1.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.CompletionStage; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisher1 - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfPublisher1() { - super(new TestEnvironment(450L)); - } - - /* The reason for overriding this method is that BodySubscribers.ofPublisher - is somewhat tricky. It is not an independent Subscriber, but rather - an adaptor from Subscriber to Publisher. Until the Subscriber that - subscribed to that resulting Publisher requests anything, nothing - happens. */ - @Override - public void triggerFlowRequest( - Subscriber> subscriber) - { - BodySubscriber>> sub = - (BodySubscriber>>) subscriber; - CompletionStage>> body = sub.getBody(); - Publisher> pub = body.toCompletableFuture().join(); - pub.subscribe(new Subscriber<>() { - - Subscription sub; - - @Override - public void onSubscribe(Subscription subscription) { - (sub = subscription).request(1); - } - - @Override public void onNext(List item) { - sub.request(1); - } - - @Override public void onError(Throwable throwable) { } - @Override public void onComplete() { } - }); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofPublisher(); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java deleted file mode 100644 index 1d8d7aee095..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfPublisherPublisher.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.net.http.HttpResponse.BodySubscriber; -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Publisher; -import java.util.stream.Stream; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfPublisherPublisher - extends FlowPublisherVerification> { - - public BodySubscribersOfPublisherPublisher() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher> createFlowPublisher(long nElements) { - BodySubscriber>> sub = - BodySubscribers.ofPublisher(); - Stream> buffers = - Stream.generate(() -> S.listOfBuffersFromBufferOfNBytes(1024)) - .limit(nElements); - Publisher> pub = S.publisherOfStream(buffers); - pub.subscribe(sub); - return sub.getBody().toCompletableFuture().join(); - } - - @Override - public Publisher> createFailedFlowPublisher() { - BodySubscriber>> sub = - BodySubscribers.ofPublisher(); - Publisher> pub = S.newErroredPublisher(); - pub.subscribe(sub); - return sub.getBody().toCompletableFuture().join(); - } - - @Override - public long maxElementsFromPublisher() { - return 21; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java deleted file mode 100644 index 0d2410ac333..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersOfString.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersOfString - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersOfString() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - return BodySubscribers.ofString(StandardCharsets.UTF_8); - } - - @Override - public List createElement(int element) { - return S.scatterBuffer( - S.bufferOfNRandomASCIIBytes(element % 17)); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java deleted file mode 100644 index cb901f02674..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/BodySubscribersReplacing.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowSubscriberBlackboxVerification; - -import java.net.http.HttpResponse.BodySubscribers; -import java.nio.ByteBuffer; -import java.util.List; -import java.util.concurrent.Flow.Subscriber; - -/* See TckDriver.java for more information */ -public class BodySubscribersReplacing - extends FlowSubscriberBlackboxVerification> { - - public BodySubscribersReplacing() { - super(new TestEnvironment(450L)); - } - - @Override - public Subscriber> createFlowSubscriber() { - /* it doesn't matter what we are replacing with */ - return BodySubscribers.replacing(Boolean.TRUE); - } - - @Override - public List createElement(int element) { - return S.listOfBuffersFromBufferOfNBytes(element % 17); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java deleted file mode 100644 index c3f86b753d9..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/S.java +++ /dev/null @@ -1,277 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.charset.StandardCharsets; -import java.security.SecureRandom; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.Random; -import java.util.concurrent.Flow.Publisher; -import java.util.concurrent.Flow.Subscriber; -import java.util.concurrent.Flow.Subscription; -import java.util.stream.Stream; - -/* - * S for Support. - * - * Auxiliary methods for tests that check conformance with reactive streams - * specification. - * - * Short name is for the sake of convenience calling this class' static methods. - * It could've been called Support or TckSupport, but then we would need to - * place this class in its own package so as to use "import static". - */ -public class S { - - private static final Random RANDOM = new SecureRandom(); - - private S() { } - - public static List listOfBuffersFromBufferOfNBytes(int nBytes) { - return scatterBuffer(bufferOfNRandomBytes(nBytes)); - } - - /* - * Spreads the remaining contents of the given byte buffer across a number - * of buffers put into a list. - */ - public static List scatterBuffer(ByteBuffer src) { - List buffers = new ArrayList<>(); - while (src.hasRemaining()) { - // We do not allow empty buffers ~~~~~~~~~~~~~~~~v - int capacity = RANDOM.nextInt(src.remaining()) + 1; - ByteBuffer b = ByteBuffer.allocate(capacity); - for (int i = 0; i < capacity; i++) { - b.put(src.get()); - } - b.flip(); - buffers.add(b); - } - return List.copyOf(buffers); - } - - public static ByteBuffer bufferOfNRandomBytes(int capacity) { - return ByteBuffer.wrap(arrayOfNRandomBytes(capacity)); - } - - public static byte[] arrayOfNRandomBytes(int nBytes) { - byte[] contents = new byte[nBytes]; - RANDOM.nextBytes(contents); - return contents; - } - - public static InputStream inputStreamOfNReads(long n) { - return new NReadsInputStream(n); - } - - /* - * Convenience method for testing publishers. - */ - public static byte[] arrayOfNRandomBytes(long nBytes) { - return arrayOfNRandomBytes((int) nBytes); - } - - public static ByteBuffer bufferOfNRandomASCIIBytes(int capacity) { - String alphaNumeric = "abcdefghijklmnopqrstuvwxyz1234567890"; - StringBuilder builder = new StringBuilder(capacity); - for (int i = 0; i < capacity; i++) { - int idx = RANDOM.nextInt(alphaNumeric.length()); - builder.append(alphaNumeric.charAt(idx)); - } - return ByteBuffer.wrap(builder.toString().getBytes( - StandardCharsets.US_ASCII)); - } - - /* - * Returns a simple non-compliant Subscriber. - * - * This Subscriber is useful for testing our adaptors and wrappers, to make - * sure they do not delegate RS compliance to the underlying (and foreign to - * java.net.http codebase) Subscribers, but rather comply themselves. - * - * Here's an example: - * - * public void onSubscribe(Subscription s) { - * delegate.onSubscribe(s); - * } - * - * The snippet above cannot be considered a good implementation of a - * Subscriber if `delegate` is an unknown Subscriber. In this case the - * implementation should independently check all the rules from the RS spec - * related to subscribers. - */ - public static Subscriber nonCompliantSubscriber() { - return new Subscriber<>() { - - @Override - public void onSubscribe(Subscription subscription) { - subscription.request(Long.MAX_VALUE); - } - - @Override - public void onNext(T item) { } - - @Override - public void onError(Throwable throwable) { } - - @Override - public void onComplete() { } - }; - } - - public static int randomIntUpTo(int bound) { - return RANDOM.nextInt(bound); - } - - /* - * Signals an error to its subscribers immediately after subscription. - */ - public static Publisher newErroredPublisher() { - return subscriber -> { - subscriber.onSubscribe(new Subscription() { - @Override - public void request(long n) { } - - @Override - public void cancel() { } - }); - subscriber.onError(new IOException()); - }; - } - - /* - * Publishes the elements obtained from the stream and signals completion. - * Can be cancelled, but cannot signal an error. - * - * This trivial ad-hoc implementation of Publisher was created so as to - * publish lists of byte buffers. We can publish ByteBuffer, but we can't - * seem to publish List since there's no readily available - * publisher of those, nor there's a simple adaptor. - */ - public static Publisher publisherOfStream(Stream stream) - { - if (stream == null) { - throw new NullPointerException(); - } - return new Publisher() { - @Override - public void subscribe(Subscriber subscriber) { - if (subscriber == null) { - throw new NullPointerException(); - } - Subscription subscription = new Subscription() { - - boolean inOnNext; // recursion control - volatile boolean cancelled; - long demand; - final Iterator supply = stream.iterator(); - - @Override - public void request(long n) { - demand = demand + n < 0 ? Long.MAX_VALUE : demand + n; - if (inOnNext) { - return; - } - if (cancelled) - return; - if (n <= 0) { - cancelled = true; - subscriber.onError(new IllegalArgumentException( - "non-positive subscription request")); - return; - } - while (supply.hasNext() && demand > 0 && !cancelled) { - demand--; - inOnNext = true; - try { - T item = supply.next(); - subscriber.onNext(item); - } finally { - inOnNext = false; - } - } - if (!supply.hasNext()) { - cancelled = true; - subscriber.onComplete(); - } - } - - @Override - public void cancel() { - cancelled = true; - } - }; - subscriber.onSubscribe(subscription); - } - }; - } - - static final class NReadsInputStream extends InputStream { - - private static final int EOF = -1; - private long readsLeft; - - NReadsInputStream(long n) { - if (n < 0) { - throw new IllegalArgumentException(String.valueOf(n)); - } - this.readsLeft = n; - } - - @Override - public int read() { - if (readsLeft == 0L) { - return EOF; - } - readsLeft--; - return S.randomIntUpTo(256); - } - - @Override - public int read(byte[] b, int off, int len) { - Objects.checkFromIndexSize(off, len, b.length); - // Must return 0 if len == 0, - // even if there are no more reads left - if (len == 0) { - return 0; - } - if (readsLeft == 0L) { - return EOF; - } - readsLeft--; - // At least one byte MUST be read, but we can read - // less than `len` bytes - int r = RANDOM.nextInt(len) + 1; - for (int i = 0; i < r; i++) { - b[i] = (byte) randomIntUpTo(256); - } - return r; - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java deleted file mode 100644 index 555906461a2..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/SPublisherOfStream.java +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.FlowPublisherVerification; - -import java.util.concurrent.Flow.Publisher; -import java.util.stream.LongStream; -import java.util.stream.Stream; - -/* See TckDriver.java for more information */ -public class SPublisherOfStream - extends FlowPublisherVerification { - - public SPublisherOfStream() { - super(new TestEnvironment(450L)); - } - - @Override - public Publisher createFlowPublisher(long nElements) { - Stream s = LongStream.range(0, nElements).boxed(); - return S.publisherOfStream(s); - } - - @Override - public Publisher createFailedFlowPublisher() { - return null; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java deleted file mode 100644 index a762b4edf1e..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/STest.java +++ /dev/null @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2019, 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. - */ - -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -import java.io.IOException; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.util.Arrays; -import java.util.List; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -public class STest { - - @DataProvider(name = "bufferSizes") - public static Object[][] bufferSizes() { - return new Object[][]{ - { 1}, - { 2}, - { 3}, - { 4}, - {16}, - {17}, - }; - } - - @DataProvider - public static Object[][] inputStream() { - return new Object[][] { - { 0, 1}, - { 1, 2}, - { 1, 3}, - { 1, 4}, - { 2, 1}, - { 2, 2}, - { 2, 3}, - { 2, 4}, - { 2, 13}, - { 3, 1}, - { 3, 2}, - { 3, 3}, - { 3, 4}, - { 3, 17}, - { 4, 1}, - { 4, 2}, - { 4, 3}, - { 4, 4}, - { 4, 5}, - { 13, 1}, - { 13, 2}, - { 13, 13}, - { 16, 18}, - { 17, 2}, - {255, 1}, - {256, 255}, - {257, 267}, - }; - } - - @Test - public void testScatter0() { - List buffers = S.scatterBuffer( - ByteBuffer.allocate(0)); - assertEquals(buffers.size(), 0); - } - - @Test(dataProvider = "bufferSizes") - public void testScatterN(int n) { - final ByteBuffer src = S.bufferOfNRandomBytes(n); - final int srcLength = src.remaining(); - ByteBuffer copy = ByteBuffer.wrap(Arrays.copyOf(src.array(), - src.array().length)); - List buffers = S.scatterBuffer(src); - int m = 0; - for (ByteBuffer b : buffers) { - m += b.remaining(); - while (b.hasRemaining() & copy.hasRemaining()) { - assertEquals(b.get(), copy.get()); - } - } - assertEquals(m, srcLength); - } - - @Test(dataProvider = "inputStream") - public void testInputStreamOfNReads(int n, int capacity) throws IOException { - InputStream s = S.inputStreamOfNReads(n); - int count = 0; - byte[] b = new byte[capacity]; - while (s.read(b) != -1) { - count++; - } - assertEquals(count, n); - assertTrue(s.read() == -1); - assertTrue(s.read(b) == -1); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java b/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java deleted file mode 100644 index c7e08eff523..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck-tests/TckDriver.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (c) 2019, 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 8226602 - * @summary Tests convenience reactive primitives with RS TCK - * - * @library ../reactivestreams-tck - * @build S - * - * @compile -encoding UTF-8 SPublisherOfStream.java - * - * @compile -encoding UTF-8 BodyPublishersFromPublisher.java - * @compile -encoding UTF-8 BodyPublishersNoBody.java - * @compile -encoding UTF-8 BodyPublishersOfByteArray.java - * @compile -encoding UTF-8 BodyPublishersOfByteArrays.java - * @compile -encoding UTF-8 BodyPublishersOfFile.java - * @compile -encoding UTF-8 BodyPublishersOfInputStream.java - * @compile -encoding UTF-8 BodyPublishersOfSubByteArray.java - * @compile -encoding UTF-8 BodyPublishersConcat.java - * - * @compile -encoding UTF-8 BodySubscribersBuffering.java - * @compile -encoding UTF-8 BodySubscribersDiscarding.java - * @compile -encoding UTF-8 BodySubscribersFromLineSubscriber.java - * @compile -encoding UTF-8 BodySubscribersFromSubscriber.java - * @compile -encoding UTF-8 BodySubscribersMapping.java - * @compile -encoding UTF-8 BodySubscribersOfByteArray.java - * @compile -encoding UTF-8 BodySubscribersOfByteArrayConsumer.java - * @compile -encoding UTF-8 BodySubscribersOfFile.java - * @compile -encoding UTF-8 BodySubscribersOfInputStream.java - * @compile -encoding UTF-8 BodySubscribersOfLines.java - * @compile -encoding UTF-8 BodySubscribersOfPublisher.java - * @compile -encoding UTF-8 BodySubscribersOfPublisher1.java - * @compile -encoding UTF-8 BodySubscribersOfPublisherPublisher.java - * @compile -encoding UTF-8 BodySubscribersOfString.java - * @compile -encoding UTF-8 BodySubscribersReplacing.java - * - * @run testng/othervm STest - * @run testng/othervm SPublisherOfStream - * - * @run testng/othervm BodyPublishersFromPublisher - * @run testng/othervm BodyPublishersNoBody - * @run testng/othervm BodyPublishersOfByteArray - * @run testng/othervm BodyPublishersOfByteArrays - * @run testng/othervm BodyPublishersOfFile - * @run testng/othervm BodyPublishersOfInputStream - * @run testng/othervm BodyPublishersOfSubByteArray - * @run testng/othervm BodyPublishersConcat - * - * @run testng/othervm BodySubscribersBuffering - * @run testng/othervm BodySubscribersDiscarding - * @run testng/othervm BodySubscribersFromLineSubscriber - * @run testng/othervm BodySubscribersFromSubscriber - * @run testng/othervm BodySubscribersMapping - * @run testng/othervm BodySubscribersOfByteArray - * @run testng/othervm BodySubscribersOfByteArrayConsumer - * @run testng/othervm BodySubscribersOfFile - * @run testng/othervm BodySubscribersOfInputStream - * @run testng/othervm BodySubscribersOfLines - * @run testng/othervm BodySubscribersOfPublisher - * @run testng/othervm BodySubscribersOfPublisher1 - * @run testng/othervm BodySubscribersOfPublisherPublisher - * @run testng/othervm BodySubscribersOfString - * @run testng/othervm BodySubscribersReplacing - * - * @key randomness - */ -public class TckDriver { - /* - #### General Information - - 1. This JTREG test aggregates multiple TestNG tests. This is because - these tests share a common library (reactivestreams-tck), and we don't - want this library to be compiled separately for each of those tests. - - 2. Tests that use RS TCK are compiled with the UTF-8 encoding. This is - performed for the sake of reactivestreams-tck. We don't want to patch - the TCK because of the extra merging work in the future, should we bring - update(s) from the RS repo. - - #### Tests - - 1. The purpose of each test should be easily digestible. The name of the - test is derived from the very entity the test exercises. For example, - - the BodyPublishersOfFile test exercises the BodyPublisher obtained - by calling BodyPublishers.ofFile(Path) - - the BodySubscribersOfFile test exercises the BodySubscriber obtained - by calling BodySubscribers.ofFile(Path) - - 2. RS TCK requires PublisherVerification tests to produce publishers - capable of emitting a certain number of elements. In order to achieve - this, we use some knowledge of the internal workings of our publishers. - An example would be a chunk size a publisher uses to deliver a portion - of data. Without knowing that it is not possible to guarantee that the - publisher will emit a particular number of elements. - - 3. Typically our publishers cannot be created in a known failed state. - In this case the corresponding `createFailedFlowPublisher` method - returns `null`. - - 4. SubscriberBlackBoxVerification uses the `createElement(int element)` - method. Our implementations usually cap the amount of data created by - this method, because it's not known beforehand how big the `element` - value is. Hence, sometimes there's code like as follows: - - @Override - public List createElement(int element) { - return scatterBuffer( - bufferOfNRandomASCIIBytes(element % 17)); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ - } - - 5. The amount of testing RS TCK performs on a publisher seems to depend - on the number of elements this publisher reports it can emit. Sometimes - a code like the following can be seen in the tests: - - @Override public long maxElementsFromPublisher() { - return 21; - ~~~~~~~~~~~^ - } - - This magic number is a result of trial and error and seems to unlock - most of the tests. Reporting big values (e.g. Long.MAX_VALUE - 1) is - not an option for most of our publishers because they require to have - all the elements upfront. - - 6. It doesn't seem currently feasible to provide SubscriberWhiteboxVerification - tests as a) it's not clear how much better the coverage is and b) it's - significantly harder to code that. - - #### S (Support) - - Support utilities are being tested (STest) too. - */ -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java deleted file mode 100644 index 8452dcd5539..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/FlowAdapters.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams; - -import java.util.concurrent.Flow; -import static java.util.Objects.requireNonNull; - -/** - * Bridge between Reactive Streams API and the Java 9 {@link java.util.concurrent.Flow} API. - */ -public final class FlowAdapters { - /** Utility class. */ - private FlowAdapters() { - throw new IllegalStateException("No instances!"); - } - - /** - * Converts a Flow Publisher into a Reactive Streams Publisher. - * @param the element type - * @param flowPublisher the source Flow Publisher to convert - * @return the equivalent Reactive Streams Publisher - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Publisher toPublisher( - Flow.Publisher flowPublisher) { - requireNonNull(flowPublisher, "flowPublisher"); - final org.reactivestreams.Publisher publisher; - if (flowPublisher instanceof FlowPublisherFromReactive) { - publisher = (org.reactivestreams.Publisher)(((FlowPublisherFromReactive)flowPublisher).reactiveStreams); - } else if (flowPublisher instanceof org.reactivestreams.Publisher) { - publisher = (org.reactivestreams.Publisher)flowPublisher; - } else { - publisher = new ReactivePublisherFromFlow(flowPublisher); - } - return publisher; - } - - /** - * Converts a Reactive Streams Publisher into a Flow Publisher. - * @param the element type - * @param reactiveStreamsPublisher the source Reactive Streams Publisher to convert - * @return the equivalent Flow Publisher - */ - @SuppressWarnings("unchecked") - public static Flow.Publisher toFlowPublisher( - org.reactivestreams.Publisher reactiveStreamsPublisher - ) { - requireNonNull(reactiveStreamsPublisher, "reactiveStreamsPublisher"); - final Flow.Publisher flowPublisher; - if (reactiveStreamsPublisher instanceof ReactivePublisherFromFlow) { - flowPublisher = (Flow.Publisher)(((ReactivePublisherFromFlow)reactiveStreamsPublisher).flow); - } else if (reactiveStreamsPublisher instanceof Flow.Publisher) { - flowPublisher = (Flow.Publisher)reactiveStreamsPublisher; - } else { - flowPublisher = new FlowPublisherFromReactive(reactiveStreamsPublisher); - } - return flowPublisher; - } - - /** - * Converts a Flow Processor into a Reactive Streams Processor. - * @param the input value type - * @param the output value type - * @param flowProcessor the source Flow Processor to convert - * @return the equivalent Reactive Streams Processor - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Processor toProcessor( - Flow.Processor flowProcessor - ) { - requireNonNull(flowProcessor, "flowProcessor"); - final org.reactivestreams.Processor processor; - if (flowProcessor instanceof FlowToReactiveProcessor) { - processor = (org.reactivestreams.Processor)(((FlowToReactiveProcessor)flowProcessor).reactiveStreams); - } else if (flowProcessor instanceof org.reactivestreams.Processor) { - processor = (org.reactivestreams.Processor)flowProcessor; - } else { - processor = new ReactiveToFlowProcessor(flowProcessor); - } - return processor; - } - - /** - * Converts a Reactive Streams Processor into a Flow Processor. - * @param the input value type - * @param the output value type - * @param reactiveStreamsProcessor the source Reactive Streams Processor to convert - * @return the equivalent Flow Processor - */ - @SuppressWarnings("unchecked") - public static Flow.Processor toFlowProcessor( - org.reactivestreams.Processor reactiveStreamsProcessor - ) { - requireNonNull(reactiveStreamsProcessor, "reactiveStreamsProcessor"); - final Flow.Processor flowProcessor; - if (reactiveStreamsProcessor instanceof ReactiveToFlowProcessor) { - flowProcessor = (Flow.Processor)(((ReactiveToFlowProcessor)reactiveStreamsProcessor).flow); - } else if (reactiveStreamsProcessor instanceof Flow.Processor) { - flowProcessor = (Flow.Processor)reactiveStreamsProcessor; - } else { - flowProcessor = new FlowToReactiveProcessor(reactiveStreamsProcessor); - } - return flowProcessor; - } - - /** - * Converts a Reactive Streams Subscriber into a Flow Subscriber. - * @param the input and output value type - * @param reactiveStreamsSubscriber the Reactive Streams Subscriber instance to convert - * @return the equivalent Flow Subscriber - */ - @SuppressWarnings("unchecked") - public static Flow.Subscriber toFlowSubscriber(org.reactivestreams.Subscriber reactiveStreamsSubscriber) { - requireNonNull(reactiveStreamsSubscriber, "reactiveStreamsSubscriber"); - final Flow.Subscriber flowSubscriber; - if (reactiveStreamsSubscriber instanceof ReactiveToFlowSubscriber) { - flowSubscriber = (Flow.Subscriber)((ReactiveToFlowSubscriber)reactiveStreamsSubscriber).flow; - } else if (reactiveStreamsSubscriber instanceof Flow.Subscriber) { - flowSubscriber = (Flow.Subscriber)reactiveStreamsSubscriber; - } else { - flowSubscriber = new FlowToReactiveSubscriber(reactiveStreamsSubscriber); - } - return flowSubscriber; - } - - /** - * Converts a Flow Subscriber into a Reactive Streams Subscriber. - * @param the input and output value type - * @param flowSubscriber the Flow Subscriber instance to convert - * @return the equivalent Reactive Streams Subscriber - */ - @SuppressWarnings("unchecked") - public static org.reactivestreams.Subscriber toSubscriber(Flow.Subscriber flowSubscriber) { - requireNonNull(flowSubscriber, "flowSubscriber"); - final org.reactivestreams.Subscriber subscriber; - if (flowSubscriber instanceof FlowToReactiveSubscriber) { - subscriber = (org.reactivestreams.Subscriber)((FlowToReactiveSubscriber)flowSubscriber).reactiveStreams; - } else if (flowSubscriber instanceof org.reactivestreams.Subscriber) { - subscriber = (org.reactivestreams.Subscriber)flowSubscriber; - } else { - subscriber = new ReactiveToFlowSubscriber(flowSubscriber); - } - return subscriber; - } - - /** - * Wraps a Reactive Streams Subscription and converts the calls to a Flow Subscription. - */ - static final class FlowToReactiveSubscription implements Flow.Subscription { - final org.reactivestreams.Subscription reactiveStreams; - - public FlowToReactiveSubscription(org.reactivestreams.Subscription reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void request(long n) { - reactiveStreams.request(n); - } - - @Override - public void cancel() { - reactiveStreams.cancel(); - } - - } - - /** - * Wraps a Flow Subscription and converts the calls to a Reactive Streams Subscription. - */ - static final class ReactiveToFlowSubscription implements org.reactivestreams.Subscription { - final Flow.Subscription flow; - - public ReactiveToFlowSubscription(Flow.Subscription flow) { - this.flow = flow; - } - - @Override - public void request(long n) { - flow.request(n); - } - - @Override - public void cancel() { - flow.cancel(); - } - - - } - - /** - * Wraps a Reactive Streams Subscriber and forwards methods of the Flow Subscriber to it. - * @param the element type - */ - static final class FlowToReactiveSubscriber implements Flow.Subscriber { - final org.reactivestreams.Subscriber reactiveStreams; - - public FlowToReactiveSubscriber(org.reactivestreams.Subscriber reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription)); - } - - @Override - public void onNext(T item) { - reactiveStreams.onNext(item); - } - - @Override - public void onError(Throwable throwable) { - reactiveStreams.onError(throwable); - } - - @Override - public void onComplete() { - reactiveStreams.onComplete(); - } - - } - - /** - * Wraps a Flow Subscriber and forwards methods of the Reactive Streams Subscriber to it. - * @param the element type - */ - static final class ReactiveToFlowSubscriber implements org.reactivestreams.Subscriber { - final Flow.Subscriber flow; - - public ReactiveToFlowSubscriber(Flow.Subscriber flow) { - this.flow = flow; - } - - @Override - public void onSubscribe(org.reactivestreams.Subscription subscription) { - flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription)); - } - - @Override - public void onNext(T item) { - flow.onNext(item); - } - - @Override - public void onError(Throwable throwable) { - flow.onError(throwable); - } - - @Override - public void onComplete() { - flow.onComplete(); - } - - } - - /** - * Wraps a Flow Processor and forwards methods of the Reactive Streams Processor to it. - * @param the input type - * @param the output type - */ - static final class ReactiveToFlowProcessor implements org.reactivestreams.Processor { - final Flow.Processor flow; - - public ReactiveToFlowProcessor(Flow.Processor flow) { - this.flow = flow; - } - - @Override - public void onSubscribe(org.reactivestreams.Subscription subscription) { - flow.onSubscribe((subscription == null) ? null : new FlowToReactiveSubscription(subscription)); - } - - @Override - public void onNext(T t) { - flow.onNext(t); - } - - @Override - public void onError(Throwable t) { - flow.onError(t); - } - - @Override - public void onComplete() { - flow.onComplete(); - } - - @Override - public void subscribe(org.reactivestreams.Subscriber s) { - flow.subscribe((s == null) ? null : new FlowToReactiveSubscriber(s)); - } - } - - /** - * Wraps a Reactive Streams Processor and forwards methods of the Flow Processor to it. - * @param the input type - * @param the output type - */ - static final class FlowToReactiveProcessor implements Flow.Processor { - final org.reactivestreams.Processor reactiveStreams; - - public FlowToReactiveProcessor(org.reactivestreams.Processor reactive) { - this.reactiveStreams = reactive; - } - - @Override - public void onSubscribe(Flow.Subscription subscription) { - reactiveStreams.onSubscribe((subscription == null) ? null : new ReactiveToFlowSubscription(subscription)); - } - - @Override - public void onNext(T t) { - reactiveStreams.onNext(t); - } - - @Override - public void onError(Throwable t) { - reactiveStreams.onError(t); - } - - @Override - public void onComplete() { - reactiveStreams.onComplete(); - } - - @Override - public void subscribe(Flow.Subscriber s) { - reactiveStreams.subscribe((s == null) ? null : new ReactiveToFlowSubscriber(s)); - } - } - - /** - * Reactive Streams Publisher that wraps a Flow Publisher. - * @param the element type - */ - static final class ReactivePublisherFromFlow implements org.reactivestreams.Publisher { - final Flow.Publisher flow; - - public ReactivePublisherFromFlow(Flow.Publisher flowPublisher) { - this.flow = flowPublisher; - } - - @Override - public void subscribe(org.reactivestreams.Subscriber reactive) { - flow.subscribe((reactive == null) ? null : new FlowToReactiveSubscriber(reactive)); - } - } - - /** - * Flow Publisher that wraps a Reactive Streams Publisher. - * @param the element type - */ - static final class FlowPublisherFromReactive implements Flow.Publisher { - - final org.reactivestreams.Publisher reactiveStreams; - - public FlowPublisherFromReactive(org.reactivestreams.Publisher reactivePublisher) { - this.reactiveStreams = reactivePublisher; - } - - @Override - public void subscribe(Flow.Subscriber flow) { - reactiveStreams.subscribe((flow == null) ? null : new ReactiveToFlowSubscriber(flow)); - } - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java deleted file mode 100644 index 0b76901b4f5..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Processor.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams; - -/** - * A Processor represents a processing stage—which is both a {@link Subscriber} - * and a {@link Publisher} and obeys the contracts of both. - * - * @param the type of element signaled to the {@link Subscriber} - * @param the type of element signaled by the {@link Publisher} - */ -public interface Processor extends Subscriber, Publisher { -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java deleted file mode 100644 index ea6eb2908e0..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Publisher.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams; - -/** - * A {@link Publisher} is a provider of a potentially unbounded number of sequenced elements, publishing them according to - * the demand received from its {@link Subscriber}(s). - *

- * A {@link Publisher} can serve multiple {@link Subscriber}s subscribed {@link #subscribe(Subscriber)} dynamically - * at various points in time. - * - * @param the type of element signaled. - */ -public interface Publisher { - - /** - * Request {@link Publisher} to start streaming data. - *

- * This is a "factory method" and can be called multiple times, each time starting a new {@link Subscription}. - *

- * Each {@link Subscription} will work for only a single {@link Subscriber}. - *

- * A {@link Subscriber} should only subscribe once to a single {@link Publisher}. - *

- * If the {@link Publisher} rejects the subscription attempt or otherwise fails it will - * signal the error via {@link Subscriber#onError}. - * - * @param s the {@link Subscriber} that will consume signals from this {@link Publisher} - */ - public void subscribe(Subscriber s); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java deleted file mode 100644 index 5ce405aa430..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscriber.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams; - -/** - * Will receive call to {@link #onSubscribe(Subscription)} once after passing an instance of {@link Subscriber} to {@link Publisher#subscribe(Subscriber)}. - *

- * No further notifications will be received until {@link Subscription#request(long)} is called. - *

- * After signaling demand: - *

- *

- * Demand can be signaled via {@link Subscription#request(long)} whenever the {@link Subscriber} instance is capable of handling more. - * - * @param the type of element signaled. - */ -public interface Subscriber { - /** - * Invoked after calling {@link Publisher#subscribe(Subscriber)}. - *

- * No data will start flowing until {@link Subscription#request(long)} is invoked. - *

- * It is the responsibility of this {@link Subscriber} instance to call {@link Subscription#request(long)} whenever more data is wanted. - *

- * The {@link Publisher} will send notifications only in response to {@link Subscription#request(long)}. - * - * @param s - * {@link Subscription} that allows requesting data via {@link Subscription#request(long)} - */ - public void onSubscribe(Subscription s); - - /** - * Data notification sent by the {@link Publisher} in response to requests to {@link Subscription#request(long)}. - * - * @param t the element signaled - */ - public void onNext(T t); - - /** - * Failed terminal state. - *

- * No further events will be sent even if {@link Subscription#request(long)} is invoked again. - * - * @param t the throwable signaled - */ - public void onError(Throwable t); - - /** - * Successful terminal state. - *

- * No further events will be sent even if {@link Subscription#request(long)} is invoked again. - */ - public void onComplete(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java deleted file mode 100644 index 244ac672e05..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/Subscription.java +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams; - -/** - * A {@link Subscription} represents a one-to-one lifecycle of a {@link Subscriber} subscribing to a {@link Publisher}. - *

- * It can only be used once by a single {@link Subscriber}. - *

- * It is used to both signal desire for data and cancel demand (and allow resource cleanup). - * - */ -public interface Subscription { - /** - * No events will be sent by a {@link Publisher} until demand is signaled via this method. - *

- * It can be called however often and whenever needed—but if the outstanding cumulative demand ever becomes Long.MAX_VALUE or more, - * it may be treated by the {@link Publisher} as "effectively unbounded". - *

- * Whatever has been requested can be sent by the {@link Publisher} so only signal demand for what can be safely handled. - *

- * A {@link Publisher} can send less than is requested if the stream ends but - * then must emit either {@link Subscriber#onError(Throwable)} or {@link Subscriber#onComplete()}. - * - * @param n the strictly positive number of elements to requests to the upstream {@link Publisher} - */ - public void request(long n); - - /** - * Request the {@link Publisher} to stop sending data and clean up resources. - *

- * Data may still be sent to meet previously signalled demand after calling cancel. - */ - public void cancel(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java deleted file mode 100644 index ed09f07bd84..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncIterablePublisher.java +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.Iterator; -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * AsyncIterablePublisher is an implementation of Reactive Streams `Publisher` - * which executes asynchronously, using a provided `Executor` and produces elements - * from a given `Iterable` in a "unicast" configuration to its `Subscribers`. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public class AsyncIterablePublisher implements Publisher { - private final static int DEFAULT_BATCHSIZE = 1024; - - private final Iterable elements; // This is our data source / generator - private final Executor executor; // This is our thread pool, which will make sure that our Publisher runs asynchronously to its Subscribers - private final int batchSize; // In general, if one uses an `Executor`, one should be nice nad not hog a thread for too long, this is the cap for that, in elements - - public AsyncIterablePublisher(final Iterable elements, final Executor executor) { - this(elements, DEFAULT_BATCHSIZE, executor); - } - - public AsyncIterablePublisher(final Iterable elements, final int batchSize, final Executor executor) { - if (elements == null) throw null; - if (executor == null) throw null; - if (batchSize < 1) throw new IllegalArgumentException("batchSize must be greater than zero!"); - this.elements = elements; - this.executor = executor; - this.batchSize = batchSize; - } - - @Override - public void subscribe(final Subscriber s) { - // As per rule 1.11, we have decided to support multiple subscribers in a unicast configuration - // for this `Publisher` implementation. - // As per 2.13, this method must return normally (i.e. not throw) - new SubscriptionImpl(s).init(); - } - - // These represent the protocol of the `AsyncIterablePublishers` SubscriptionImpls - static interface Signal {}; - enum Cancel implements Signal { Instance; }; - enum Subscribe implements Signal { Instance; }; - enum Send implements Signal { Instance; }; - static final class Request implements Signal { - final long n; - Request(final long n) { - this.n = n; - } - }; - - // This is our implementation of the Reactive Streams `Subscription`, - // which represents the association between a `Publisher` and a `Subscriber`. - final class SubscriptionImpl implements Subscription, Runnable { - final Subscriber subscriber; // We need a reference to the `Subscriber` so we can talk to it - private boolean cancelled = false; // This flag will track whether this `Subscription` is to be considered cancelled or not - private long demand = 0; // Here we track the current demand, i.e. what has been requested but not yet delivered - private Iterator iterator; // This is our cursor into the data stream, which we will send to the `Subscriber` - - SubscriptionImpl(final Subscriber subscriber) { - // As per rule 1.09, we need to throw a `java.lang.NullPointerException` if the `Subscriber` is `null` - if (subscriber == null) throw null; - this.subscriber = subscriber; - } - - // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscription`, like `request` and `cancel` - private final ConcurrentLinkedQueue inboundSignals = new ConcurrentLinkedQueue(); - - // We are using this `AtomicBoolean` to make sure that this `Subscription` doesn't run concurrently with itself, - // which would violate rule 1.3 among others (no concurrent notifications). - private final AtomicBoolean on = new AtomicBoolean(false); - - // This method will register inbound demand from our `Subscriber` and validate it against rule 3.9 and rule 3.17 - private void doRequest(final long n) { - if (n < 1) - terminateDueTo(new IllegalArgumentException(subscriber + " violated the Reactive Streams rule 3.9 by requesting a non-positive number of elements.")); - else if (demand + n < 1) { - // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE` we treat the signalled demand as "effectively unbounded" - demand = Long.MAX_VALUE; // Here we protect from the overflow and treat it as "effectively unbounded" - doSend(); // Then we proceed with sending data downstream - } else { - demand += n; // Here we record the downstream demand - doSend(); // Then we can proceed with sending data downstream - } - } - - // This handles cancellation requests, and is idempotent, thread-safe and not synchronously performing heavy computations as specified in rule 3.5 - private void doCancel() { - cancelled = true; - } - - // Instead of executing `subscriber.onSubscribe` synchronously from within `Publisher.subscribe` - // we execute it asynchronously, this is to avoid executing the user code (`Iterable.iterator`) on the calling thread. - // It also makes it easier to follow rule 1.9 - private void doSubscribe() { - try { - iterator = elements.iterator(); - if (iterator == null) - iterator = Collections.emptyList().iterator(); // So we can assume that `iterator` is never null - } catch(final Throwable t) { - subscriber.onSubscribe(new Subscription() { // We need to make sure we signal onSubscribe before onError, obeying rule 1.9 - @Override public void cancel() {} - @Override public void request(long n) {} - }); - terminateDueTo(t); // Here we send onError, obeying rule 1.09 - } - - if (!cancelled) { - // Deal with setting up the subscription with the subscriber - try { - subscriber.onSubscribe(this); - } catch(final Throwable t) { // Due diligence to obey 2.13 - terminateDueTo(new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onSubscribe.", t)); - } - - // Deal with already complete iterators promptly - boolean hasElements = false; - try { - hasElements = iterator.hasNext(); - } catch(final Throwable t) { - terminateDueTo(t); // If hasNext throws, there's something wrong and we need to signal onError as per 1.2, 1.4, - } - - // If we don't have anything to deliver, we're already done, so lets do the right thing and - // not wait for demand to deliver `onComplete` as per rule 1.2 and 1.3 - if (!hasElements) { - try { - doCancel(); // Rule 1.6 says we need to consider the `Subscription` cancelled when `onComplete` is signalled - subscriber.onComplete(); - } catch(final Throwable t) { // As per rule 2.13, `onComplete` is not allowed to throw exceptions, so we do what we can, and log this. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onComplete.", t)).printStackTrace(System.err); - } - } - } - } - - // This is our behavior for producing elements downstream - private void doSend() { - try { - // In order to play nice with the `Executor` we will only send at-most `batchSize` before - // rescheduing ourselves and relinquishing the current thread. - int leftInBatch = batchSize; - do { - T next; - boolean hasNext; - try { - next = iterator.next(); // We have already checked `hasNext` when subscribing, so we can fall back to testing -after- `next` is called. - hasNext = iterator.hasNext(); // Need to keep track of End-of-Stream - } catch (final Throwable t) { - terminateDueTo(t); // If `next` or `hasNext` throws (they can, since it is user-provided), we need to treat the stream as errored as per rule 1.4 - return; - } - subscriber.onNext(next); // Then we signal the next element downstream to the `Subscriber` - if (!hasNext) { // If we are at End-of-Stream - doCancel(); // We need to consider this `Subscription` as cancelled as per rule 1.6 - subscriber.onComplete(); // Then we signal `onComplete` as per rule 1.2 and 1.5 - } - } while (!cancelled // This makes sure that rule 1.8 is upheld, i.e. we need to stop signalling "eventually" - && --leftInBatch > 0 // This makes sure that we only send `batchSize` number of elements in one go (so we can yield to other Runnables) - && --demand > 0); // This makes sure that rule 1.1 is upheld (sending more than was demanded) - - if (!cancelled && demand > 0) // If the `Subscription` is still alive and well, and we have demand to satisfy, we signal ourselves to send more data - signal(Send.Instance); - } catch(final Throwable t) { - // We can only get here if `onNext` or `onComplete` threw, and they are not allowed to according to 2.13, so we can only cancel and log here. - doCancel(); // Make sure that we are cancelled, since we cannot do anything else since the `Subscriber` is faulty. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onNext or onComplete.", t)).printStackTrace(System.err); - } - } - - // This is a helper method to ensure that we always `cancel` when we signal `onError` as per rule 1.6 - private void terminateDueTo(final Throwable t) { - cancelled = true; // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6 - try { - subscriber.onError(t); // Then we signal the error downstream, to the `Subscriber` - } catch(final Throwable t2) { // If `onError` throws an exception, this is a spec violation according to rule 1.9, and all we can do is to log it. - (new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - - // What `signal` does is that it sends signals to the `Subscription` asynchronously - private void signal(final Signal signal) { - if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us - tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already - } - - // This is the main "event loop" if you so will - @Override public final void run() { - if(on.get()) { // establishes a happens-before relationship with the end of the previous run - try { - final Signal s = inboundSignals.poll(); // We take a signal off the queue - if (!cancelled) { // to make sure that we follow rule 1.8, 3.6 and 3.7 - - // Below we simply unpack the `Signal`s and invoke the corresponding methods - if (s instanceof Request) - doRequest(((Request)s).n); - else if (s == Send.Instance) - doSend(); - else if (s == Cancel.Instance) - doCancel(); - else if (s == Subscribe.Instance) - doSubscribe(); - } - } finally { - on.set(false); // establishes a happens-before relationship with the beginning of the next run - if(!inboundSignals.isEmpty()) // If we still have signals to process - tryScheduleToExecute(); // Then we try to schedule ourselves to execute again - } - } - } - - // This method makes sure that this `Subscription` is only running on one Thread at a time, - // this is important to make sure that we follow rule 1.3 - private final void tryScheduleToExecute() { - if(on.compareAndSet(false, true)) { - try { - executor.execute(this); - } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully - if (!cancelled) { - doCancel(); // First of all, this failure is not recoverable, so we need to follow rule 1.4 and 1.6 - try { - terminateDueTo(new IllegalStateException("Publisher terminated due to unavailable Executor.", t)); - } finally { - inboundSignals.clear(); // We're not going to need these anymore - // This subscription is cancelled by now, but letting it become schedulable again means - // that we can drain the inboundSignals queue if anything arrives after clearing - on.set(false); - } - } - } - } - } - - // Our implementation of `Subscription.request` sends a signal to the Subscription that more elements are in demand - @Override public void request(final long n) { - signal(new Request(n)); - } - // Our implementation of `Subscription.cancel` sends a signal to the Subscription that the `Subscriber` is not interested in any more elements - @Override public void cancel() { - signal(Cancel.Instance); - } - // The reason for the `init` method is that we want to ensure the `SubscriptionImpl` - // is completely constructed before it is exposed to the thread pool, therefor this - // method is only intended to be invoked once, and immediately after the constructor has - // finished. - void init() { - signal(Subscribe.Instance); - } - }; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java deleted file mode 100644 index a610a93cca4..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/AsyncSubscriber.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -import java.util.concurrent.Executor; -import java.util.concurrent.atomic.AtomicBoolean; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * AsyncSubscriber is an implementation of Reactive Streams `Subscriber`, - * it runs asynchronously (on an Executor), requests one element - * at a time, and invokes a user-defined method to process each element. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public abstract class AsyncSubscriber implements Subscriber, Runnable { - - // Signal represents the asynchronous protocol between the Publisher and Subscriber - private static interface Signal {} - - private enum OnComplete implements Signal { Instance; } - - private static class OnError implements Signal { - public final Throwable error; - public OnError(final Throwable error) { this.error = error; } - } - - private static class OnNext implements Signal { - public final T next; - public OnNext(final T next) { this.next = next; } - } - - private static class OnSubscribe implements Signal { - public final Subscription subscription; - public OnSubscribe(final Subscription subscription) { this.subscription = subscription; } - } - - private Subscription subscription; // Obeying rule 3.1, we make this private! - private boolean done; // It's useful to keep track of whether this Subscriber is done or not - private final Executor executor; // This is the Executor we'll use to be asynchronous, obeying rule 2.2 - - // Only one constructor, and it's only accessible for the subclasses - protected AsyncSubscriber(Executor executor) { - if (executor == null) throw null; - this.executor = executor; - } - - // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements - // herefor we also need to cancel our `Subscription`. - private final void done() { - //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to. - done = true; // If `whenNext` throws an exception, let's consider ourselves done (not accepting more elements) - if (subscription != null) { // If we are bailing out before we got a `Subscription` there's little need for cancelling it. - try { - subscription.cancel(); // Cancel the subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } - } - - // This method is invoked when the OnNext signals arrive - // Returns whether more elements are desired or not, and if no more elements are desired, - // for convenience. - protected abstract boolean whenNext(final T element); - - // This method is invoked when the OnComplete signal arrives - // override this method to implement your own custom onComplete logic. - protected void whenComplete() { } - - // This method is invoked if the OnError signal arrives - // override this method to implement your own custom onError logic. - protected void whenError(Throwable error) { } - - private final void handleOnSubscribe(final Subscription s) { - if (s == null) { - // Getting a null `Subscription` here is not valid so lets just ignore it. - } else if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully - try { - s.cancel(); // Cancel the additional subscription to follow rule 2.5 - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } else { - // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber` - // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request` - subscription = s; - try { - // If we want elements, according to rule 2.1 we need to call `request` - // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method - s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } - } - - private final void handleOnNext(final T element) { - if (!done) { // If we aren't already done - if(subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Check for spec violation of 2.1 and 1.09 - (new IllegalStateException("Someone violated the Reactive Streams rule 1.09 and 2.1 by signalling OnNext before `Subscription.request`. (no Subscription)")).printStackTrace(System.err); - } else { - try { - if (whenNext(element)) { - try { - subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } else { - done(); // This is legal according to rule 2.6 - } - } catch(final Throwable t) { - done(); - try { - onError(t); - } catch(final Throwable t2) { - //Subscriber.onError is not allowed to throw an exception, according to rule 2.13 - (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - } - } - } - - // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher` - private void handleOnComplete() { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Publisher is not allowed to signal onComplete before onSubscribe according to rule 1.09 - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err); - } else { - done = true; // Obey rule 2.4 - whenComplete(); - } - } - - // Here it is important that we do not violate 2.2 and 2.3 by calling methods on the `Subscription` or `Publisher` - private void handleOnError(final Throwable error) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - // Publisher is not allowed to signal onError before onSubscribe according to rule 1.09 - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err); - } else { - done = true; // Obey rule 2.4 - whenError(error); - } - } - - // We implement the OnX methods on `Subscriber` to send Signals that we will process asycnhronously, but only one at a time - - @Override public final void onSubscribe(final Subscription s) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null` - if (s == null) throw null; - - signal(new OnSubscribe(s)); - } - - @Override public final void onNext(final T element) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null` - if (element == null) throw null; - - signal(new OnNext(element)); - } - - @Override public final void onError(final Throwable t) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null` - if (t == null) throw null; - - signal(new OnError(t)); - } - - @Override public final void onComplete() { - signal(OnComplete.Instance); - } - - // This `ConcurrentLinkedQueue` will track signals that are sent to this `Subscriber`, like `OnComplete` and `OnNext` , - // and obeying rule 2.11 - private final ConcurrentLinkedQueue inboundSignals = new ConcurrentLinkedQueue(); - - // We are using this `AtomicBoolean` to make sure that this `Subscriber` doesn't run concurrently with itself, - // obeying rule 2.7 and 2.11 - private final AtomicBoolean on = new AtomicBoolean(false); - - @SuppressWarnings("unchecked") - @Override public final void run() { - if(on.get()) { // establishes a happens-before relationship with the end of the previous run - try { - final Signal s = inboundSignals.poll(); // We take a signal off the queue - if (!done) { // If we're done, we shouldn't process any more signals, obeying rule 2.8 - // Below we simply unpack the `Signal`s and invoke the corresponding methods - if (s instanceof OnNext) - handleOnNext(((OnNext)s).next); - else if (s instanceof OnSubscribe) - handleOnSubscribe(((OnSubscribe)s).subscription); - else if (s instanceof OnError) // We are always able to handle OnError, obeying rule 2.10 - handleOnError(((OnError)s).error); - else if (s == OnComplete.Instance) // We are always able to handle OnComplete, obeying rule 2.9 - handleOnComplete(); - } - } finally { - on.set(false); // establishes a happens-before relationship with the beginning of the next run - if(!inboundSignals.isEmpty()) // If we still have signals to process - tryScheduleToExecute(); // Then we try to schedule ourselves to execute again - } - } - } - - // What `signal` does is that it sends signals to the `Subscription` asynchronously - private void signal(final Signal signal) { - if (inboundSignals.offer(signal)) // No need to null-check here as ConcurrentLinkedQueue does this for us - tryScheduleToExecute(); // Then we try to schedule it for execution, if it isn't already - } - - // This method makes sure that this `Subscriber` is only executing on one Thread at a time - private final void tryScheduleToExecute() { - if(on.compareAndSet(false, true)) { - try { - executor.execute(this); - } catch(Throwable t) { // If we can't run on the `Executor`, we need to fail gracefully and not violate rule 2.13 - if (!done) { - try { - done(); // First of all, this failure is not recoverable, so we need to cancel our subscription - } finally { - inboundSignals.clear(); // We're not going to need these anymore - // This subscription is cancelled by now, but letting the Subscriber become schedulable again means - // that we can drain the inboundSignals queue if anything arrives after clearing - on.set(false); - } - } - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/InfiniteIncrementNumberPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/InfiniteIncrementNumberPublisher.java deleted file mode 100644 index c1db3e66186..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/InfiniteIncrementNumberPublisher.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import java.util.Iterator; -import java.util.concurrent.Executor; - -import org.reactivestreams.Subscription; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Publisher; - -public class InfiniteIncrementNumberPublisher extends AsyncIterablePublisher { - public InfiniteIncrementNumberPublisher(final Executor executor) { - super(new Iterable() { - @Override public Iterator iterator() { - return new Iterator() { - private int at = 0; - @Override public boolean hasNext() { return true; } - @Override public Integer next() { return at++; } // Wraps around on overflow - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java deleted file mode 100644 index 3ac116b6d14..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/NumberIterablePublisher.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.Executor; -import org.reactivestreams.Subscription; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Publisher; - -public class NumberIterablePublisher extends AsyncIterablePublisher { - public NumberIterablePublisher(final int from, final int to, final Executor executor) { - super(new Iterable() { - { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); } - @Override public Iterator iterator() { - return new Iterator() { - private int at = from; - @Override public boolean hasNext() { return at < to; } - @Override public Integer next() { - if (!hasNext()) return Collections.emptyList().iterator().next(); - else return at++; - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java deleted file mode 100644 index 18c13b2aa86..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/RangePublisher.java +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import org.reactivestreams.*; - -import java.util.concurrent.atomic.AtomicLong; - -/** - * A synchronous implementation of the {@link Publisher} that can - * be subscribed to multiple times and each individual subscription - * will receive range of monotonically increasing integer values on demand. - */ -public final class RangePublisher implements Publisher { - - /** The starting value of the range. */ - final int start; - - /** The number of items to emit. */ - final int count; - - /** - * Constructs a RangePublisher instance with the given start and count values - * that yields a sequence of [start, start + count). - * @param start the starting value of the range - * @param count the number of items to emit - */ - public RangePublisher(int start, int count) { - this.start = start; - this.count = count; - } - - @Override - public void subscribe(Subscriber subscriber) { - // As per rule 1.11, we have decided to support multiple subscribers - // in a unicast configuration for this `Publisher` implementation. - - // As per rule 1.09, we need to throw a `java.lang.NullPointerException` - // if the `Subscriber` is `null` - if (subscriber == null) throw null; - - // As per 2.13, this method must return normally (i.e. not throw). - try { - subscriber.onSubscribe(new RangeSubscription(subscriber, start, start + count)); - } catch (Throwable ex) { - new IllegalStateException(subscriber + " violated the Reactive Streams rule 2.13 " + - "by throwing an exception from onSubscribe.", ex) - // When onSubscribe fails this way, we don't know what state the - // subscriber is thus calling onError may cause more crashes. - .printStackTrace(); - } - } - - /** - * A Subscription implementation that holds the current downstream - * requested amount and responds to the downstream's request() and - * cancel() calls. - */ - static final class RangeSubscription - // We are using this `AtomicLong` to make sure that this `Subscription` - // doesn't run concurrently with itself, which would violate rule 1.3 - // among others (no concurrent notifications). - // The atomic transition from 0L to N > 0L will ensure this. - extends AtomicLong implements Subscription { - - private static final long serialVersionUID = -9000845542177067735L; - - /** The Subscriber we are emitting integer values to. */ - final Subscriber downstream; - - /** The end index (exclusive). */ - final int end; - - /** - * The current index and within the [start, start + count) range that - * will be emitted as downstream.onNext(). - */ - int index; - - /** - * Indicates the emission should stop. - */ - volatile boolean cancelled; - - /** - * Holds onto the IllegalArgumentException (containing the offending stacktrace) - * indicating there was a non-positive request() call from the downstream. - */ - volatile Throwable invalidRequest; - - /** - * Constructs a stateful RangeSubscription that emits signals to the given - * downstream from an integer range of [start, end). - * @param downstream the Subscriber receiving the integer values and the completion signal. - * @param start the first integer value emitted, start of the range - * @param end the end of the range, exclusive - */ - RangeSubscription(Subscriber downstream, int start, int end) { - this.downstream = downstream; - this.index = start; - this.end = end; - } - - // This method will register inbound demand from our `Subscriber` and - // validate it against rule 3.9 and rule 3.17 - @Override - public void request(long n) { - // Non-positive requests should be honored with IllegalArgumentException - if (n <= 0L) { - invalidRequest = new IllegalArgumentException("§3.9: non-positive requests are not allowed!"); - n = 1; - } - // Downstream requests are cumulative and may come from any thread - for (;;) { - long requested = get(); - long update = requested + n; - // As governed by rule 3.17, when demand overflows `Long.MAX_VALUE` - // we treat the signalled demand as "effectively unbounded" - if (update < 0L) { - update = Long.MAX_VALUE; - } - // atomically update the current requested amount - if (compareAndSet(requested, update)) { - // if there was no prior request amount, we start the emission loop - if (requested == 0L) { - emit(update); - } - break; - } - } - } - - // This handles cancellation requests, and is idempotent, thread-safe and not - // synchronously performing heavy computations as specified in rule 3.5 - @Override - public void cancel() { - // Indicate to the emission loop it should stop. - cancelled = true; - } - - void emit(long currentRequested) { - // Load fields to avoid re-reading them from memory due to volatile accesses in the loop. - Subscriber downstream = this.downstream; - int index = this.index; - int end = this.end; - int emitted = 0; - - try { - for (; ; ) { - // Check if there was an invalid request and then report its exception - // as mandated by rule 3.9. The stacktrace in it should - // help locate the faulty logic in the Subscriber. - Throwable invalidRequest = this.invalidRequest; - if (invalidRequest != null) { - // When we signal onError, the subscription must be considered as cancelled, as per rule 1.6 - cancelled = true; - - downstream.onError(invalidRequest); - return; - } - - // Loop while the index hasn't reached the end and we haven't - // emitted all that's been requested - while (index != end && emitted != currentRequested) { - // to make sure that we follow rule 1.8, 3.6 and 3.7 - // We stop if cancellation was requested. - if (cancelled) { - return; - } - - downstream.onNext(index); - - // Increment the index for the next possible emission. - index++; - // Increment the emitted count to prevent overflowing the downstream. - emitted++; - } - - // If the index reached the end, we complete the downstream. - if (index == end) { - // to make sure that we follow rule 1.8, 3.6 and 3.7 - // Unless cancellation was requested by the last onNext. - if (!cancelled) { - // We need to consider this `Subscription` as cancelled as per rule 1.6 - // Note, however, that this state is not observable from the outside - // world and since we leave the loop with requested > 0L, any - // further request() will never trigger the loop. - cancelled = true; - - downstream.onComplete(); - } - return; - } - - // Did the requested amount change while we were looping? - long freshRequested = get(); - if (freshRequested == currentRequested) { - // Save where the loop has left off: the next value to be emitted - this.index = index; - // Atomically subtract the previously requested (also emitted) amount - currentRequested = addAndGet(-currentRequested); - // If there was no new request in between get() and addAndGet(), we simply quit - // The next 0 to N transition in request() will trigger the next emission loop. - if (currentRequested == 0L) { - break; - } - // Looks like there were more async requests, reset the emitted count and continue. - emitted = 0; - } else { - // Yes, avoid the atomic subtraction and resume. - // emitted != currentRequest in this case and index - // still points to the next value to be emitted - currentRequested = freshRequested; - } - } - } catch (Throwable ex) { - // We can only get here if `onNext`, `onError` or `onComplete` threw, and they - // are not allowed to according to 2.13, so we can only cancel and log here. - // If `onError` throws an exception, this is a spec violation according to rule 1.9, - // and all we can do is to log it. - - // Make sure that we are cancelled, since we cannot do anything else - // since the `Subscriber` is faulty. - cancelled = true; - - // We can't report the failure to onError as the Subscriber is unreliable. - (new IllegalStateException(downstream + " violated the Reactive Streams rule 2.13 by " + - "throwing an exception from onNext, onError or onComplete.", ex)) - .printStackTrace(); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java deleted file mode 100644 index 98817a200d5..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/example/unicast/SyncSubscriber.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.example.unicast; - -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; - -/** - * SyncSubscriber is an implementation of Reactive Streams `Subscriber`, - * it runs synchronously (on the Publisher's thread) and requests one element - * at a time and invokes a user-defined method to process each element. - * - * NOTE: The code below uses a lot of try-catches to show the reader where exceptions can be expected, and where they are forbidden. - */ -public abstract class SyncSubscriber implements Subscriber { - private Subscription subscription; // Obeying rule 3.1, we make this private! - private boolean done = false; - - @Override public void onSubscribe(final Subscription s) { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Subscription` is `null` - if (s == null) throw null; - - if (subscription != null) { // If someone has made a mistake and added this Subscriber multiple times, let's handle it gracefully - try { - s.cancel(); // Cancel the additional subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } else { - // We have to assign it locally before we use it, if we want to be a synchronous `Subscriber` - // Because according to rule 3.10, the Subscription is allowed to call `onNext` synchronously from within `request` - subscription = s; - try { - // If we want elements, according to rule 2.1 we need to call `request` - // And, according to rule 3.2 we are allowed to call this synchronously from within the `onSubscribe` method - s.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch(final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(s + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } - } - - @Override public void onNext(final T element) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onNext prior to onSubscribe.")).printStackTrace(System.err); - } else { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `element` is `null` - if (element == null) throw null; - - if (!done) { // If we aren't already done - try { - if (whenNext(element)) { - try { - subscription.request(1); // Our Subscriber is unbuffered and modest, it requests one element at a time - } catch (final Throwable t) { - // Subscription.request is not allowed to throw according to rule 3.16 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.16 by throwing an exception from request.", t)).printStackTrace(System.err); - } - } else { - done(); - } - } catch (final Throwable t) { - done(); - try { - onError(t); - } catch (final Throwable t2) { - //Subscriber.onError is not allowed to throw an exception, according to rule 2.13 - (new IllegalStateException(this + " violated the Reactive Streams rule 2.13 by throwing an exception from onError.", t2)).printStackTrace(System.err); - } - } - } - } - } - - // Showcases a convenience method to idempotently marking the Subscriber as "done", so we don't want to process more elements - // herefor we also need to cancel our `Subscription`. - private void done() { - //On this line we could add a guard against `!done`, but since rule 3.7 says that `Subscription.cancel()` is idempotent, we don't need to. - done = true; // If we `whenNext` throws an exception, let's consider ourselves done (not accepting more elements) - try { - subscription.cancel(); // Cancel the subscription - } catch(final Throwable t) { - //Subscription.cancel is not allowed to throw an exception, according to rule 3.15 - (new IllegalStateException(subscription + " violated the Reactive Streams rule 3.15 by throwing an exception from cancel.", t)).printStackTrace(System.err); - } - } - - // This method is left as an exercise to the reader/extension point - // Returns whether more elements are desired or not, and if no more elements are desired - protected abstract boolean whenNext(final T element); - - @Override public void onError(final Throwable t) { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onError prior to onSubscribe.")).printStackTrace(System.err); - } else { - // As per rule 2.13, we need to throw a `java.lang.NullPointerException` if the `Throwable` is `null` - if (t == null) throw null; - // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3 - // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4 - } - } - - @Override public void onComplete() { - if (subscription == null) { // Technically this check is not needed, since we are expecting Publishers to conform to the spec - (new IllegalStateException("Publisher violated the Reactive Streams rule 1.09 signalling onComplete prior to onSubscribe.")).printStackTrace(System.err); - } else { - // Here we are not allowed to call any methods on the `Subscription` or the `Publisher`, as per rule 2.3 - // And anyway, the `Subscription` is considered to be cancelled if this method gets called, as per rule 2.4 - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java deleted file mode 100644 index 25a99ec9a8d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/IdentityProcessorVerification.java +++ /dev/null @@ -1,896 +0,0 @@ -/* - * Copyright (c) 2019, 2022, 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.reactivestreams.tck; - -import org.reactivestreams.Processor; -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.ManualPublisher; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.TestEnvironment.Promise; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.HashSet; -import java.util.Set; - -public abstract class IdentityProcessorVerification extends WithHelperPublisher - implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules { - - private final TestEnvironment env; - - ////////////////////// DELEGATED TO SPECS ////////////////////// - - // for delegating tests - private final SubscriberWhiteboxVerification subscriberVerification; - - // for delegating tests - private final PublisherVerification publisherVerification; - - ////////////////// END OF DELEGATED TO SPECS ////////////////// - - // number of elements the processor under test must be able ot buffer, - // without dropping elements. Defaults to `TestEnvironment.TEST_BUFFER_SIZE`. - private final int processorBufferSize; - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements. - */ - @SuppressWarnings("unused") - public IdentityProcessorVerification(final TestEnvironment env) { - this(env, PublisherVerification.envPublisherReferenceGCTimeoutMillis(), TestEnvironment.TEST_BUFFER_SIZE); - } - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * The processor will be required to be able to buffer {@code TestEnvironment.TEST_BUFFER_SIZE} elements. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - */ - @SuppressWarnings("unused") - public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - this(env, publisherReferenceGCTimeoutMillis, TestEnvironment.TEST_BUFFER_SIZE); - } - - /** - * Test class must specify the expected time it takes for the publisher to - * shut itself down when the last downstream {@code Subscription} is cancelled. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - * @param processorBufferSize number of elements the processor is required to be able to buffer. - */ - public IdentityProcessorVerification(final TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) { - this.env = env; - this.processorBufferSize = processorBufferSize; - - this.subscriberVerification = new SubscriberWhiteboxVerification(env) { - @Override - public Subscriber createSubscriber(WhiteboxSubscriberProbe probe) { - return IdentityProcessorVerification.this.createSubscriber(probe); - } - - @Override public T createElement(int element) { - return IdentityProcessorVerification.this.createElement(element); - } - - @Override - public Publisher createHelperPublisher(long elements) { - return IdentityProcessorVerification.this.createHelperPublisher(elements); - } - }; - - publisherVerification = new PublisherVerification(env, publisherReferenceGCTimeoutMillis) { - @Override - public Publisher createPublisher(long elements) { - return IdentityProcessorVerification.this.createPublisher(elements); - } - - @Override - public Publisher createFailedPublisher() { - return IdentityProcessorVerification.this.createFailedPublisher(); - } - - @Override - public long maxElementsFromPublisher() { - return IdentityProcessorVerification.this.maxElementsFromPublisher(); - } - - @Override - public long boundedDepthOfOnNextAndRequestRecursion() { - return IdentityProcessorVerification.this.boundedDepthOfOnNextAndRequestRecursion(); - } - - @Override - public boolean skipStochasticTests() { - return IdentityProcessorVerification.this.skipStochasticTests(); - } - }; - } - - /** - * This is the main method you must implement in your test incarnation. - * It must create a {@link Processor}, which simply forwards all stream elements from its upstream - * to its downstream. It must be able to internally buffer the given number of elements. - * - * @param bufferSize number of elements the processor is required to be able to buffer. - */ - public abstract Processor createIdentityProcessor(int bufferSize); - - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you want to ignore these additional tests, return {@code null} from this method. - */ - public abstract Publisher createFailedPublisher(); - - /** - * Override and return lower value if your Publisher is only able to produce a known number of elements. - * For example, if it is designed to return at-most-one element, return {@code 1} from this method. - * - * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements. - * - * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE}, - * which will result in *skipping all tests which require an onComplete to be triggered* (!). - */ - public long maxElementsFromPublisher() { - return Long.MAX_VALUE - 1; - } - - /** - * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a - * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of - * recursive calls to exceed the number returned by this method. - * - * @see reactive streams spec, rule 3.3 - * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion() - */ - public long boundedDepthOfOnNextAndRequestRecursion() { - return 1; - } - - /** - * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}. - * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify— - * usually this means that this test case can yield false positives ("be green") even if for some case, - * the given implementation may violate the tested behaviour. - */ - public boolean skipStochasticTests() { - return false; - } - - /** - * Describes the tested implementation in terms of how many subscribers they can support. - * Some tests require the {@code Publisher} under test to support multiple Subscribers, - * yet the spec does not require all publishers to be able to do so, thus – if an implementation - * supports only a limited number of subscribers (e.g. only 1 subscriber, also known as "no fanout") - * you MUST return that number from this method by overriding it. - */ - public long maxSupportedSubscribers() { - return Long.MAX_VALUE; - } - - /** - * Override this method and return {@code true} if the {@link Processor} returned by the - * {@link #createIdentityProcessor(int)} coordinates its {@link Subscriber}s - * request amounts and only delivers onNext signals if all Subscribers have - * indicated (via their Subscription#request(long)) they are ready to receive elements. - */ - public boolean doesCoordinatedEmission() { - return false; - } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - publisherVerification.setUp(); - subscriberVerification.setUp(); - } - - ////////////////////// PUBLISHER RULES VERIFICATION /////////////////////////// - - // A Processor - // must obey all Publisher rules on its publishing side - public Publisher createPublisher(long elements) { - final Processor processor = createIdentityProcessor(processorBufferSize); - final Publisher pub = createHelperPublisher(elements); - pub.subscribe(processor); - return processor; // we run the PublisherVerification against this - } - - @Override @Test - public void required_validate_maxElementsFromPublisher() throws Exception { - publisherVerification.required_validate_maxElementsFromPublisher(); - } - - @Override @Test - public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception { - publisherVerification.required_validate_boundedDepthOfOnNextAndRequestRecursion(); - } - - /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" PUBLISHER ////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - @Test - public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable { - publisherVerification.required_createPublisher1MustProduceAStreamOfExactly1Element(); - } - - @Test - public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable { - publisherVerification.required_createPublisher3MustProduceAStreamOfExactly3Elements(); - } - - @Override @Test - public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable { - publisherVerification.required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements(); - } - - @Override @Test - public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable { - publisherVerification.required_spec102_maySignalLessThanRequestedAndTerminateSubscription(); - } - - @Override @Test - public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable { - publisherVerification.stochastic_spec103_mustSignalOnMethodsSequentially(); - } - - @Override @Test - public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable { - publisherVerification.optional_spec104_mustSignalOnErrorWhenFails(); - } - - @Override @Test - public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable { - publisherVerification.required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates(); - } - - @Override @Test - public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable { - publisherVerification.optional_spec105_emptyStreamMustTerminateBySignallingOnComplete(); - } - - @Override @Test - public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable { - publisherVerification.untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled(); - } - - @Override @Test - public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable { - publisherVerification.required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled(); - } - - @Override @Test - public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable { - publisherVerification.untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled(); - } - - @Override @Test - public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable { - publisherVerification.untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals(); - } - - @Override @Test - public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable { - publisherVerification.untested_spec109_subscribeShouldNotThrowNonFatalThrowable(); - } - - @Override @Test - public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable { - publisherVerification.required_spec109_subscribeThrowNPEOnNullSubscriber(); - } - - @Override @Test - public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable { - publisherVerification.required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe(); - } - - @Override @Test - public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable { - publisherVerification.required_spec109_mustIssueOnSubscribeForNonNullSubscriber(); - } - - @Override @Test - public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable { - publisherVerification.untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice(); - } - - @Override @Test - public void optional_spec111_maySupportMultiSubscribe() throws Throwable { - publisherVerification.optional_spec111_maySupportMultiSubscribe(); - } - - @Override @Test - public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable { - publisherVerification.optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront(); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable { - publisherVerification.optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected(); - } - - @Override @Test - public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable { - publisherVerification.required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe(); - } - - @Override @Test - public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable { - publisherVerification.required_spec303_mustNotAllowUnboundedRecursion(); - } - - @Override @Test - public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception { - publisherVerification.untested_spec304_requestShouldNotPerformHeavyComputations(); - } - - @Override @Test - public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception { - publisherVerification.untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation(); - } - - @Override @Test - public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable { - publisherVerification.required_spec306_afterSubscriptionIsCancelledRequestMustBeNops(); - } - - @Override @Test - public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable { - publisherVerification.required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops(); - } - - @Override @Test - public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable { - publisherVerification.required_spec309_requestZeroMustSignalIllegalArgumentException(); - } - - @Override @Test - public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable { - publisherVerification.required_spec309_requestNegativeNumberMustSignalIllegalArgumentException(); - } - - @Override @Test - public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable { - publisherVerification.optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage(); - } - - @Override @Test - public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable { - publisherVerification.required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling(); - } - - @Override @Test - public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable { - publisherVerification.required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber(); - } - - @Override @Test - public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustSupportAPendingElementCountUpToLongMaxValue(); - } - - @Override @Test - public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue(); - } - - @Override @Test - public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable { - publisherVerification.required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue(); - } - - - /** - * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks if two {@code Subscriber}s - * receive the same items and a terminal {@code Exception}. - *

- * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested, - * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property. - *

- * Verifies rule: 1.4 with multiple - * {@code Subscriber}s. - *

- * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2. - *

- * If this test fails, the following could be checked within the {@code Processor} implementation: - *

    - *
  • The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.
  • - *
  • The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or - * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s - * both have to request first.
  • - *
- */ - @Test - public void required_spec104_mustCallOnErrorOnAllItsSubscribersIfItEncountersANonRecoverableError() throws Throwable { - optionalMultipleSubscribersTest(2, new Function() { - @Override - public TestSetup apply(Long aLong) throws Throwable { - return new TestSetup(env, processorBufferSize) {{ - final ManualSubscriberWithErrorCollection sub1 = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub1); - - final ManualSubscriberWithErrorCollection sub2 = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub2); - - final Exception ex = new RuntimeException("Test exception"); - - if (doesCoordinatedEmission()) { - sub1.request(1); - sub2.request(1); - - expectRequest(); - - final T x = sendNextTFromUpstream(); - - expectNextElement(sub1, x); - expectNextElement(sub2, x); - - sub1.request(1); - sub2.request(1); - } else { - sub1.request(1); - - expectRequest(env.defaultTimeoutMillis(), - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - - final T x = sendNextTFromUpstream(); - expectNextElement(sub1, x, - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - - sub1.request(1); - - // sub1 has received one element, and has one demand pending - // sub2 has not yet requested anything - } - sendError(ex); - - sub1.expectError(ex); - sub2.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - }); - } - - ////////////////////// SUBSCRIBER RULES VERIFICATION /////////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - // A Processor - // must obey all Subscriber rules on its consuming side - public Subscriber createSubscriber(final SubscriberWhiteboxVerification.WhiteboxSubscriberProbe probe) { - final Processor processor = createIdentityProcessor(processorBufferSize); - processor.subscribe( - new Subscriber() { - private final Promise subs = new Promise(env); - - @Override - public void onSubscribe(final Subscription subscription) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onSubscribe(%s)", subscription)); - } - if (subs.isCompleted()) subscription.cancel(); // the Probe must also pass subscriber verification - - probe.registerOnSubscribe(new SubscriberWhiteboxVerification.SubscriberPuppet() { - - @Override - public void triggerRequest(long elements) { - subscription.request(elements); - } - - @Override - public void signalCancel() { - subscription.cancel(); - } - }); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onNext(%s)", element)); - } - probe.registerOnNext(element); - } - - @Override - public void onComplete() { - if (env.debugEnabled()) { - env.debug("whiteboxSubscriber::onComplete()"); - } - probe.registerOnComplete(); - } - - @Override - public void onError(Throwable cause) { - if (env.debugEnabled()) { - env.debug(String.format("whiteboxSubscriber::onError(%s)", cause)); - } - probe.registerOnError(cause); - } - }); - - return processor; // we run the SubscriberVerification against this - } - - ////////////////////// OTHER RULE VERIFICATION /////////////////////////// - - // A Processor - // must immediately pass on `onError` events received from its upstream to its downstream - @Test - public void mustImmediatelyPassOnOnErrorEventsReceivedFromItsUpstreamToItsDownstream() throws Exception { - new TestSetup(env, processorBufferSize) {{ - final ManualSubscriberWithErrorCollection sub = new ManualSubscriberWithErrorCollection(env); - env.subscribe(processor, sub); - - final Exception ex = new RuntimeException("Test exception"); - sendError(ex); - sub.expectError(ex); // "immediately", i.e. without a preceding request - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - - /////////////////////// DELEGATED TESTS, A PROCESSOR "IS A" SUBSCRIBER ////////////////////// - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#4.1 - - @Test - public void required_exerciseWhiteboxHappyPath() throws Throwable { - subscriberVerification.required_exerciseWhiteboxHappyPath(); - } - - @Override @Test - public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable { - subscriberVerification.required_spec201_mustSignalDemandViaSubscriptionRequest(); - } - - @Override @Test - public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception { - subscriberVerification.untested_spec202_shouldAsynchronouslyDispatch(); - } - - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete(); - } - - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - subscriberVerification.required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError(); - } - - @Override @Test - public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - subscriberVerification.untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError(); - } - - @Override @Test - public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable { - subscriberVerification.required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal(); - } - - @Override @Test - public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - subscriberVerification.untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid(); - } - - @Override @Test - public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - subscriberVerification.untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization(); - } - - @Override @Test - public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - subscriberVerification.required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel(); - } - - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall(); - } - - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall(); - } - - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall(); - } - - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberVerification.required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall(); - } - - @Override @Test - public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - subscriberVerification.untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents(); - } - - @Override @Test - public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable { - subscriberVerification.untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation(); - } - - @Override @Test - public void untested_spec213_failingOnSignalInvocation() throws Exception { - subscriberVerification.untested_spec213_failingOnSignalInvocation(); - } - - @Override @Test - public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - @Override @Test - public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - @Override @Test - public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberVerification.required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull(); - } - - @Override @Test - public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception { - subscriberVerification.untested_spec301_mustNotBeCalledOutsideSubscriberContext(); - } - - @Override @Test - public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - subscriberVerification.required_spec308_requestMustRegisterGivenNumberElementsToBeProduced(); - } - - @Override @Test - public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - subscriberVerification.untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber(); - } - - @Override @Test - public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - subscriberVerification.untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError(); - } - - @Override @Test - public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - subscriberVerification.untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists(); - } - - @Override @Test - public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - subscriberVerification.untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError(); - } - - @Override @Test - public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - subscriberVerification.untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber(); - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS ////////////////////// - - /** - * Asks for a {@code Processor} that supports at least 2 {@code Subscriber}s at once and checks requests - * from {@code Subscriber}s will eventually lead to requests towards the upstream of the {@code Processor}. - *

- * If the {@code Processor} requests and/or emits items only when all of its {@code Subscriber}s have requested, - * override {@link #doesCoordinatedEmission()} and return {@code true} to indicate this property. - *

- * Verifies rule: 2.1 with multiple - * {@code Subscriber}s. - *

- * The test is not executed if {@link IdentityProcessorVerification#maxSupportedSubscribers()} is less than 2. - *

- * If this test fails, the following could be checked within the {@code Processor} implementation: - *

    - *
  • The {@code TestEnvironment} has large enough timeout specified in case the {@code Processor} has some time-delay behavior.
  • - *
  • The {@code Processor} is able to fulfill requests of its {@code Subscriber}s independently of each other's requests or - * else override {@link #doesCoordinatedEmission()} and return {@code true} to indicate the test {@code Subscriber}s - * both have to request first.
  • - *
- */ - @Test - public void required_mustRequestFromUpstreamForElementsThatHaveBeenRequestedLongAgo() throws Throwable { - optionalMultipleSubscribersTest(2, new Function() { - @Override - public TestSetup apply(Long subscribers) throws Throwable { - return new TestSetup(env, processorBufferSize) {{ - ManualSubscriber sub1 = newSubscriber(); - sub1.request(20); - - long totalRequests = expectRequest(); - final T x = sendNextTFromUpstream(); - expectNextElement(sub1, x); - - if (totalRequests == 1) { - totalRequests += expectRequest(); - } - final T y = sendNextTFromUpstream(); - expectNextElement(sub1, y); - - if (totalRequests == 2) { - totalRequests += expectRequest(); - } - - final ManualSubscriber sub2 = newSubscriber(); - - // sub1 now has 18 pending - // sub2 has 0 pending - - if (doesCoordinatedEmission()) { - sub2.expectNone(); // since sub2 hasn't requested anything yet - - sub2.request(1); - - final T z = sendNextTFromUpstream(); - expectNextElement(sub1, z); - expectNextElement(sub2, z); - } else { - final T z = sendNextTFromUpstream(); - expectNextElement(sub1, z, - "If the Processor coordinates requests/emissions when having multiple Subscribers" - + " at once, please override doesCoordinatedEmission() to return true in this " - + "IdentityProcessorVerification to allow this test to pass."); - sub2.expectNone(); // since sub2 hasn't requested anything yet - - sub2.request(1); - expectNextElement(sub2, z); - } - if (totalRequests == 3) { - expectRequest(); - } - - // to avoid error messages during test harness shutdown - sendCompletion(); - sub1.expectCompletion(env.defaultTimeoutMillis()); - sub2.expectCompletion(env.defaultTimeoutMillis()); - - env.verifyNoAsyncErrorsNoDelay(); - }}; - } - }); - } - - /////////////////////// TEST INFRASTRUCTURE ////////////////////// - - public void notVerified() { - publisherVerification.notVerified(); - } - - public void notVerified(String message) { - publisherVerification.notVerified(message); - } - - /** - * Test for feature that REQUIRES multiple subscribers to be supported by Publisher. - */ - public void optionalMultipleSubscribersTest(long requiredSubscribersSupport, Function body) throws Throwable { - if (requiredSubscribersSupport > maxSupportedSubscribers()) - notVerified(String.format("The Publisher under test only supports %d subscribers, while this test requires at least %d to run.", - maxSupportedSubscribers(), requiredSubscribersSupport)); - else body.apply(requiredSubscribersSupport); - } - - public abstract class TestSetup extends ManualPublisher { - final private ManualSubscriber tees; // gives us access to an infinite stream of T values - private Set seenTees = new HashSet(); - - final Processor processor; - - public TestSetup(TestEnvironment env, int testBufferSize) throws InterruptedException { - super(env); - tees = env.newManualSubscriber(createHelperPublisher(Long.MAX_VALUE)); - processor = createIdentityProcessor(testBufferSize); - subscribe(processor); - } - - public ManualSubscriber newSubscriber() throws InterruptedException { - return env.newManualSubscriber(processor); - } - - public T nextT() throws InterruptedException { - final T t = tees.requestNextElement(); - if (seenTees.contains(t)) { - env.flop(String.format("Helper publisher illegally produced the same element %s twice", t)); - } - seenTees.add(t); - return t; - } - - public void expectNextElement(ManualSubscriber sub, T expected) throws InterruptedException { - final T elem = sub.nextElement(String.format("timeout while awaiting %s", expected)); - if (!elem.equals(expected)) { - env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected)); - } - } - - public void expectNextElement(ManualSubscriber sub, T expected, String errorMessageAddendum) throws InterruptedException { - final T elem = sub.nextElement(String.format("timeout while awaiting %s. %s", expected, errorMessageAddendum)); - if (!elem.equals(expected)) { - env.flop(String.format("Received `onNext(%s)` on downstream but expected `onNext(%s)`", elem, expected)); - } - } - - public T sendNextTFromUpstream() throws InterruptedException { - final T x = nextT(); - sendNext(x); - return x; - } - } - - public class ManualSubscriberWithErrorCollection extends ManualSubscriberWithSubscriptionSupport { - Promise error; - - public ManualSubscriberWithErrorCollection(TestEnvironment env) { - super(env); - error = new Promise(env); - } - - @Override - public void onError(Throwable cause) { - error.complete(cause); - } - - public void expectError(Throwable cause) throws InterruptedException { - expectError(cause, env.defaultTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectError(Throwable cause, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, "Did not receive expected error on downstream"); - if (!cause.equals(error.value())) { - env.flop(String.format("Expected error %s but got %s", cause, error.value())); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java deleted file mode 100644 index fdfd24582ef..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/PublisherVerification.java +++ /dev/null @@ -1,1245 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.BlackholeSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.TestEnvironment.Latch; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; -import org.testng.SkipException; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.lang.Override; -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Random; -import java.util.concurrent.atomic.AtomicInteger; -import java.util.concurrent.atomic.AtomicReference; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertTrue; - -/** - * Provides tests for verifying {@code Publisher} specification rules. - * - * @see org.reactivestreams.Publisher - */ -public abstract class PublisherVerification implements PublisherVerificationRules { - - private static final String PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV = "PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS"; - private static final long DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS = 300L; - - private final TestEnvironment env; - - /** - * The amount of time after which a cancelled Subscriber reference should be dropped. - * See Rule 3.13 for details. - */ - private final long publisherReferenceGCTimeoutMillis; - - /** - * Constructs a new verification class using the given env and configuration. - * - * @param publisherReferenceGCTimeoutMillis used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - */ - public PublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - this.env = env; - this.publisherReferenceGCTimeoutMillis = publisherReferenceGCTimeoutMillis; - } - - /** - * Constructs a new verification class using the given env and configuration. - * - * The value for {@code publisherReferenceGCTimeoutMillis} will be obtained by using {@link PublisherVerification#envPublisherReferenceGCTimeoutMillis()}. - */ - public PublisherVerification(TestEnvironment env) { - this.env = env; - this.publisherReferenceGCTimeoutMillis = envPublisherReferenceGCTimeoutMillis(); - } - - /** - * Tries to parse the env variable {@code PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS} as long and returns the value if present, - * OR its default value ({@link PublisherVerification#DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS}). - * - * This value is used to determine after how much time a reference to a Subscriber should be already dropped by the Publisher. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envPublisherReferenceGCTimeoutMillis() { - final String envMillis = System.getenv(PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return DEFAULT_PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS; - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", PUBLISHER_REFERENCE_GC_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * This is the main method you must implement in your test incarnation. - * It must create a Publisher for a stream with exactly the given number of elements. - * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite. - */ - public abstract Publisher createPublisher(long elements); - - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you ignore these additional tests, return {@code null} from this method. - */ - public abstract Publisher createFailedPublisher(); - - - /** - * Override and return lower value if your Publisher is only able to produce a known number of elements. - * For example, if it is designed to return at-most-one element, return {@code 1} from this method. - * - * Defaults to {@code Long.MAX_VALUE - 1}, meaning that the Publisher can be produce a huge but NOT an unbounded number of elements. - * - * To mark your Publisher will *never* signal an {@code onComplete} override this method and return {@code Long.MAX_VALUE}, - * which will result in *skipping all tests which require an onComplete to be triggered* (!). - */ - public long maxElementsFromPublisher() { - return Long.MAX_VALUE - 1; - } - - /** - * Override and return {@code true} in order to skip executing tests marked as {@code Stochastic}. - * Stochastic in this case means that the Rule is impossible or infeasible to deterministically verify— - * usually this means that this test case can yield false positives ("be green") even if for some case, - * the given implementation may violate the tested behaviour. - */ - public boolean skipStochasticTests() { - return false; - } - - /** - * In order to verify rule 3.3 of the reactive streams spec, this number will be used to check if a - * {@code Subscription} actually solves the "unbounded recursion" problem by not allowing the number of - * recursive calls to exceed the number returned by this method. - * - * @see reactive streams spec, rule 3.3 - * @see PublisherVerification#required_spec303_mustNotAllowUnboundedRecursion() - */ - public long boundedDepthOfOnNextAndRequestRecursion() { - return 1; - } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// TEST SETUP VERIFICATION ////////////////////////////// - - @Override @Test - public void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable { - activePublisherTest(1, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub = env.newManualSubscriber(pub); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub)); - sub.requestEndOfStream(); - } - - Optional requestNextElementOrEndOfStream(Publisher pub, ManualSubscriber sub) throws InterruptedException { - return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub)); - } - - }); - } - - @Override @Test - public void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable { - activePublisherTest(3, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub = env.newManualSubscriber(pub); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced no elements", pub)); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 1 element", pub)); - assertTrue(requestNextElementOrEndOfStream(pub, sub).isDefined(), String.format("Publisher %s produced only 2 elements", pub)); - sub.requestEndOfStream(); - } - - Optional requestNextElementOrEndOfStream(Publisher pub, ManualSubscriber sub) throws InterruptedException { - return sub.requestNextElementOrEndOfStream(String.format("Timeout while waiting for next element from Publisher %s", pub)); - } - - }); - } - - @Override @Test - public void required_validate_maxElementsFromPublisher() throws Exception { - assertTrue(maxElementsFromPublisher() >= 0, "maxElementsFromPublisher MUST return a number >= 0"); - } - - @Override @Test - public void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception { - assertTrue(boundedDepthOfOnNextAndRequestRecursion() >= 1, "boundedDepthOfOnNextAndRequestRecursion must return a number >= 1"); - } - - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - @Override @Test - public void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable { - activePublisherTest(5, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws InterruptedException { - - ManualSubscriber sub = env.newManualSubscriber(pub); - try { - sub.expectNone(String.format("Publisher %s produced value before the first `request`: ", pub)); - sub.request(1); - sub.nextElement(String.format("Publisher %s produced no element after first `request`", pub)); - sub.expectNone(String.format("Publisher %s produced unrequested: ", pub)); - - sub.request(1); - sub.request(2); - sub.nextElements(3, env.defaultTimeoutMillis(), String.format("Publisher %s produced less than 3 elements after two respective `request` calls", pub)); - - sub.expectNone(String.format("Publisher %sproduced unrequested ", pub)); - } finally { - sub.cancel(); - } - } - }); - } - - @Override @Test - public void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable { - final int elements = 3; - final int requested = 10; - - activePublisherTest(elements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(requested); - sub.nextElements(elements); - sub.expectCompletion(); - } - }); - } - - @Override @Test - public void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable { - final int iterations = 100; - final int elements = 10; - - stochasticTest(iterations, new Function() { - @Override - public Void apply(final Integer runNumber) throws Throwable { - activePublisherTest(elements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch completionLatch = new Latch(env); - - final AtomicInteger gotElements = new AtomicInteger(0); - pub.subscribe(new Subscriber() { - private Subscription subs; - - private ConcurrentAccessBarrier concurrentAccessBarrier = new ConcurrentAccessBarrier(); - - /** - * Concept wise very similar to a {@link org.reactivestreams.tck.TestEnvironment.Latch}, serves to protect - * a critical section from concurrent access, with the added benefit of Thread tracking and same-thread-access awareness. - * - * Since a Synchronous Publisher may choose to synchronously (using the same {@link Thread}) call - * {@code onNext} directly from either {@code subscribe} or {@code request} a plain Latch is not enough - * to verify concurrent access safety - one needs to track if the caller is not still using the calling thread - * to enter subsequent critical sections ("nesting" them effectively). - */ - final class ConcurrentAccessBarrier { - private AtomicReference currentlySignallingThread = new AtomicReference(null); - private volatile String previousSignal = null; - - public void enterSignal(String signalName) { - if((!currentlySignallingThread.compareAndSet(null, Thread.currentThread())) && !isSynchronousSignal()) { - env.flop(String.format( - "Illegal concurrent access detected (entering critical section)! " + - "%s emited %s signal, before %s finished its %s signal.", - Thread.currentThread(), signalName, currentlySignallingThread.get(), previousSignal)); - } - this.previousSignal = signalName; - } - - public void leaveSignal(String signalName) { - currentlySignallingThread.set(null); - this.previousSignal = signalName; - } - - private boolean isSynchronousSignal() { - return (previousSignal != null) && Thread.currentThread().equals(currentlySignallingThread.get()); - } - - } - - @Override - public void onSubscribe(Subscription s) { - final String signal = "onSubscribe()"; - concurrentAccessBarrier.enterSignal(signal); - - subs = s; - subs.request(1); - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onNext(T ignore) { - final String signal = String.format("onNext(%s)", ignore); - concurrentAccessBarrier.enterSignal(signal); - - if (gotElements.incrementAndGet() <= elements) // requesting one more than we know are in the stream (some Publishers need this) - subs.request(1); - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onError(Throwable t) { - final String signal = String.format("onError(%s)", t.getMessage()); - concurrentAccessBarrier.enterSignal(signal); - - // ignore value - - concurrentAccessBarrier.leaveSignal(signal); - } - - @Override - public void onComplete() { - final String signal = "onComplete()"; - concurrentAccessBarrier.enterSignal(signal); - - // entering for completeness - - concurrentAccessBarrier.leaveSignal(signal); - completionLatch.close(); - } - }); - - completionLatch.expectClose( - elements * env.defaultTimeoutMillis(), - String.format("Failed in iteration %d of %d. Expected completion signal after signalling %d elements (signalled %d), yet did not receive it", - runNumber, iterations, elements, gotElements.get())); - } - }); - return null; - } - }); - } - - @Override @Test - public void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable { - try { - whenHasErrorPublisherTest(new PublisherTestRun() { - @Override - public void run(final Publisher pub) throws InterruptedException { - final Latch onErrorlatch = new Latch(env); - final Latch onSubscribeLatch = new Latch(env); - pub.subscribe(new TestEnvironment.TestSubscriber(env) { - @Override - public void onSubscribe(Subscription subs) { - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - onErrorlatch.assertOpen(String.format("Error-state Publisher %s called `onError` twice on new Subscriber", pub)); - onErrorlatch.close(); - } - }); - - onSubscribeLatch.expectClose("Should have received onSubscribe"); - onErrorlatch.expectClose(String.format("Error-state Publisher %s did not call `onError` on new Subscriber", pub)); - - env.verifyNoAsyncErrors(); - } - }); - } catch (SkipException se) { - throw se; - } catch (Throwable ex) { - // we also want to catch AssertionErrors and anything the publisher may have thrown inside subscribe - // which was wrong of him - he should have signalled on error using onError - throw new RuntimeException(String.format("Publisher threw exception (%s) instead of signalling error via onError!", ex.getMessage()), ex); - } - } - - @Override @Test - public void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable { - activePublisherTest(3, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.requestNextElement(); - sub.requestNextElement(); - sub.requestNextElement(); - sub.requestEndOfStream(); - sub.expectNone(); - } - }); - } - - @Override @Test - public void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable { - optionalActivePublisherTest(0, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(1); - sub.expectCompletion(); - sub.expectNone(); - } - }); - } - - @Override @Test - public void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable { - notVerified(); // not really testable without more control over the Publisher - } - - @Override @Test - public void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable { - activePublisherTest(1, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(10); - sub.nextElement(); - sub.expectCompletion(); - - sub.request(10); - sub.expectNone(); - } - }); - } - - @Override @Test - public void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable { - notVerified(); // can we meaningfully test this, without more control over the publisher? - } - - @Override @Test - public void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - @Override @Test - public void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - @Override @Test - public void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable { - activePublisherTest(0, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - try { - pub.subscribe(null); - env.flop("Publisher did not throw a NullPointerException when given a null Subscribe in subscribe"); - } catch (NullPointerException ignored) { - // valid behaviour - } - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable { - activePublisherTest(0, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch onSubscribeLatch = new Latch(env); - final AtomicReference cancel = new AtomicReference(); - try { - pub.subscribe(new Subscriber() { - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - } - - @Override - public void onSubscribe(Subscription subs) { - cancel.set(subs); - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - - @Override - public void onNext(T elem) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onNext always"); - } - - @Override - public void onComplete() { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onComplete always"); - } - }); - onSubscribeLatch.expectClose("Should have received onSubscribe"); - env.verifyNoAsyncErrorsNoDelay(); - } finally { - Subscription s = cancel.getAndSet(null); - if (s != null) { - s.cancel(); - } - } - } - }); - } - - @Override @Test - public void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable { - whenHasErrorPublisherTest(new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final Latch onErrorLatch = new Latch(env); - final Latch onSubscribeLatch = new Latch(env); - ManualSubscriberWithSubscriptionSupport sub = new ManualSubscriberWithSubscriptionSupport(env) { - @Override - public void onError(Throwable cause) { - onSubscribeLatch.assertClosed("onSubscribe should be called prior to onError always"); - onErrorLatch.assertOpen("Only one onError call expected"); - onErrorLatch.close(); - } - - @Override - public void onSubscribe(Subscription subs) { - onSubscribeLatch.assertOpen("Only one onSubscribe call expected"); - onSubscribeLatch.close(); - } - }; - pub.subscribe(sub); - onSubscribeLatch.expectClose("Should have received onSubscribe"); - onErrorLatch.expectClose("Should have received onError"); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable { - notVerified(); // can we meaningfully test this? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#1.11 - @Override @Test - public void optional_spec111_maySupportMultiSubscribe() throws Throwable { - optionalActivePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - - try { - env.verifyNoAsyncErrors(); - } finally { - try { - sub1.cancel(); - } finally { - sub2.cancel(); - } - } - } - }); - } - - @Override @Test - public void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable { - optionalActivePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - // Since we're testing the case when the Publisher DOES support the optional multi-subscribers scenario, - // and decides if it handles them uni-cast or multi-cast, we don't know which subscriber will receive an - // onNext (and optional onComplete) signal(s) and which just onComplete signal. - // Plus, even if subscription assumed to be unicast, it's implementation choice, which one will be signalled - // with onNext. - sub1.requestNextElementOrEndOfStream(); - sub2.requestNextElementOrEndOfStream(); - try { - env.verifyNoAsyncErrors(); - } finally { - try { - sub1.cancel(); - } finally { - sub2.cancel(); - } - } - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable { - optionalActivePublisherTest(5, true, new PublisherTestRun() { // This test is skipped if the publisher is unbounded (never sends onComplete) - @Override - public void run(Publisher pub) throws InterruptedException { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - sub1.request(1); - T x1 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub2.request(2); - List y1 = sub2.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 2nd subscriber", pub)); - sub1.request(1); - T x2 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub3.request(3); - List z1 = sub3.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 3rd subscriber", pub)); - sub3.request(1); - T z2 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub)); - sub3.request(1); - T z3 = sub3.nextElement(String.format("Publisher %s did not produce the requested 1 element on 3rd subscriber", pub)); - sub3.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 3rd subscriber", pub)); - sub2.request(3); - List y2 = sub2.nextElements(3, String.format("Publisher %s did not produce the requested 3 elements on 2nd subscriber", pub)); - sub2.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 2nd subscriber", pub)); - sub1.request(2); - List x3 = sub1.nextElements(2, String.format("Publisher %s did not produce the requested 2 elements on 1st subscriber", pub)); - sub1.request(1); - T x4 = sub1.nextElement(String.format("Publisher %s did not produce the requested 1 element on 1st subscriber", pub)); - sub1.requestEndOfStream(String.format("Publisher %s did not complete the stream as expected on 1st subscriber", pub)); - - @SuppressWarnings("unchecked") - List r = new ArrayList(Arrays.asList(x1, x2)); - r.addAll(x3); - r.addAll(Collections.singleton(x4)); - - List check1 = new ArrayList(y1); - check1.addAll(y2); - - //noinspection unchecked - List check2 = new ArrayList(z1); - check2.add(z2); - check2.add(z3); - - assertEquals(r, check1, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 2", pub)); - assertEquals(r, check2, String.format("Publisher %s did not produce the same element sequence for subscribers 1 and 3", pub)); - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable { - optionalActivePublisherTest(3, false, new PublisherTestRun() { // This test is skipped if the publisher cannot produce enough elements - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - List received1 = new ArrayList(); - List received2 = new ArrayList(); - List received3 = new ArrayList(); - - // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains... - // edgy edge case? - sub1.request(4); - sub2.request(4); - sub3.request(4); - - received1.addAll(sub1.nextElements(3)); - received2.addAll(sub2.nextElements(3)); - received3.addAll(sub3.nextElements(3)); - - // NOTE: can't check completion, the Publisher may not be able to signal it - // a similar test *with* completion checking is implemented - - assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers")); - assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers")); - } - }); - } - - @Override @Test - public void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable { - optionalActivePublisherTest(3, true, new PublisherTestRun() { // This test is skipped if the publisher is unbounded (never sends onComplete) - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub1 = env.newManualSubscriber(pub); - ManualSubscriber sub2 = env.newManualSubscriber(pub); - ManualSubscriber sub3 = env.newManualSubscriber(pub); - - List received1 = new ArrayList(); - List received2 = new ArrayList(); - List received3 = new ArrayList(); - - // if the publisher must touch it's source to notice it's been drained, the OnComplete won't come until we ask for more than it actually contains... - // edgy edge case? - sub1.request(4); - sub2.request(4); - sub3.request(4); - - received1.addAll(sub1.nextElements(3)); - received2.addAll(sub2.nextElements(3)); - received3.addAll(sub3.nextElements(3)); - - sub1.expectCompletion(); - sub2.expectCompletion(); - sub3.expectCompletion(); - - assertEquals(received1, received2, String.format("Expected elements to be signaled in the same sequence to 1st and 2nd subscribers")); - assertEquals(received2, received3, String.format("Expected elements to be signaled in the same sequence to 2nd and 3rd subscribers")); - } - }); - } - - ///////////////////// SUBSCRIPTION TESTS ////////////////////////////////// - - @Override @Test - public void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable { - activePublisherTest(6, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = new ManualSubscriber(env) { - @Override - public void onSubscribe(Subscription subs) { - this.subscription.completeImmediatly(subs); - - subs.request(1); - subs.request(1); - subs.request(1); - } - - @Override - public void onNext(T element) { - Subscription subs = this.subscription.value(); - subs.request(1); - } - }; - - env.subscribe(pub, sub); - - env.verifyNoAsyncErrors(); - } - }); - } - - @Override @Test - public void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable { - final long oneMoreThanBoundedLimit = boundedDepthOfOnNextAndRequestRecursion() + 1; - - activePublisherTest(oneMoreThanBoundedLimit, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ThreadLocal stackDepthCounter = new ThreadLocal() { - @Override - protected Long initialValue() { - return 0L; - } - }; - - final Latch runCompleted = new Latch(env); - - final ManualSubscriber sub = new ManualSubscriberWithSubscriptionSupport(env) { - // counts the number of signals received, used to break out from possibly infinite request/onNext loops - long signalsReceived = 0L; - - @Override - public void onNext(T element) { - // NOT calling super.onNext as this test only cares about stack depths, not the actual values of elements - // which also simplifies this test as we do not have to drain the test buffer, which would otherwise be in danger of overflowing - - signalsReceived += 1; - stackDepthCounter.set(stackDepthCounter.get() + 1); - if (env.debugEnabled()) { - env.debug(String.format("%s(recursion depth: %d)::onNext(%s)", this, stackDepthCounter.get(), element)); - } - - final long callsUntilNow = stackDepthCounter.get(); - if (callsUntilNow > boundedDepthOfOnNextAndRequestRecursion()) { - env.flop(String.format("Got %d onNext calls within thread: %s, yet expected recursive bound was %d", - callsUntilNow, Thread.currentThread(), boundedDepthOfOnNextAndRequestRecursion())); - - // stop the recursive call chain - runCompleted.close(); - return; - } else if (signalsReceived >= oneMoreThanBoundedLimit) { - // since max number of signals reached, and recursion depth not exceeded, we judge this as a success and - // stop the recursive call chain - runCompleted.close(); - return; - } - - // request more right away, the Publisher must break the recursion - subscription.value().request(1); - - stackDepthCounter.set(stackDepthCounter.get() - 1); - } - - @Override - public void onComplete() { - super.onComplete(); - runCompleted.close(); - } - - @Override - public void onError(Throwable cause) { - super.onError(cause); - runCompleted.close(); - } - }; - - try { - env.subscribe(pub, sub); - - sub.request(1); // kick-off the `request -> onNext -> request -> onNext -> ...` - - final String msg = String.format("Unable to validate call stack depth safety, " + - "awaited at-most %s signals (`maxOnNextSignalsInRecursionTest()`) or completion", - oneMoreThanBoundedLimit); - runCompleted.expectClose(env.defaultTimeoutMillis(), msg); - env.verifyNoAsyncErrorsNoDelay(); - } finally { - // since the request/onNext recursive calls may keep the publisher running "forever", - // we MUST cancel it manually before exiting this test case - sub.cancel(); - } - } - }); - } - - @Override @Test - public void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable { - activePublisherTest(3, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - - // override ManualSubscriberWithSubscriptionSupport#cancel because by default a ManualSubscriber will drop the - // subscription once it's cancelled (as expected). - // In this test however it must keep the cancelled Subscription and keep issuing `request(long)` to it. - ManualSubscriber sub = new ManualSubscriberWithSubscriptionSupport(env) { - @Override - public void cancel() { - if (subscription.isCompleted()) { - subscription.value().cancel(); - } else { - env.flop("Cannot cancel a subscription before having received it"); - } - } - }; - - env.subscribe(pub, sub); - - sub.cancel(); - sub.request(1); - sub.request(1); - sub.request(1); - - sub.expectNone(); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable { - activePublisherTest(1, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - - // leak the Subscription - final Subscription subs = sub.subscription.value(); - - subs.cancel(); - subs.cancel(); - subs.cancel(); - - sub.expectNone(); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable { - activePublisherTest(10, false, new PublisherTestRun() { - @Override public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(0); - sub.expectError(IllegalArgumentException.class); - } - }); - } - - @Override @Test - public void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable { - activePublisherTest(10, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final Random r = new Random(); - sub.request(-r.nextInt(Integer.MAX_VALUE) - 1); - // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem - sub.expectError(IllegalArgumentException.class); - } - }); - } - - @Override @Test - public void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable { - optionalActivePublisherTest(10, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final Random r = new Random(); - sub.request(-r.nextInt(Integer.MAX_VALUE) - 1); - // we do require implementations to mention the rule number at the very least, or mentioning that the non-negative request is the problem - sub.expectErrorWithMessage(IllegalArgumentException.class, Arrays.asList("3.9", "non-positive subscription request", "negative subscription request")); - } - }); - } - - @Override @Test - public void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable { - // the publisher is able to signal more elements than the subscriber will be requesting in total - final int publisherElements = 20; - - final int demand1 = 10; - final int demand2 = 5; - final int totalDemand = demand1 + demand2; - - activePublisherTest(publisherElements, false, new PublisherTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - - sub.request(demand1); - sub.request(demand2); - - /* - NOTE: The order of the nextElement/cancel calls below is very important (!) - - If this ordering was reversed, given an asynchronous publisher, - the following scenario would be *legal* and would break this test: - - > AsyncPublisher receives request(10) - it does not emit data right away, it's asynchronous - > AsyncPublisher receives request(5) - demand is now 15 - ! AsyncPublisher didn't emit any onNext yet (!) - > AsyncPublisher receives cancel() - handles it right away, by "stopping itself" for example - ! cancel was handled hefore the AsyncPublisher ever got the chance to emit data - ! the subscriber ends up never receiving even one element - the test is stuck (and fails, even on valid Publisher) - - Which is why we must first expect an element, and then cancel, once the producing is "running". - */ - sub.nextElement(); - sub.cancel(); - - int onNextsSignalled = 1; - - boolean stillBeingSignalled; - do { - // put asyncError if onNext signal received - sub.expectNone(); - Throwable error = env.dropAsyncError(); - - if (error == null) { - stillBeingSignalled = false; - } else { - onNextsSignalled += 1; - stillBeingSignalled = true; - } - - // if the Publisher tries to emit more elements than was requested (and/or ignores cancellation) this will throw - assertTrue(onNextsSignalled <= totalDemand, - String.format("Publisher signalled [%d] elements, which is more than the signalled demand: %d", - onNextsSignalled, totalDemand)); - - } while (stillBeingSignalled); - } - }); - - env.verifyNoAsyncErrorsNoDelay(); - } - - @Override @Test - public void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable { - final ReferenceQueue> queue = new ReferenceQueue>(); - - final Function, WeakReference>> run = new Function, WeakReference>>() { - @Override - public WeakReference> apply(Publisher pub) throws Exception { - final ManualSubscriber sub = env.newManualSubscriber(pub); - final WeakReference> ref = new WeakReference>(sub, queue); - - sub.request(1); - sub.nextElement(); - sub.cancel(); - - return ref; - } - }; - - activePublisherTest(3, false, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final WeakReference> ref = run.apply(pub); - - // cancel may be run asynchronously so we add a sleep before running the GC - // to "resolve" the race - Thread.sleep(publisherReferenceGCTimeoutMillis); - System.gc(); - - if (!ref.equals(queue.remove(100))) { - env.flop(String.format("Publisher %s did not drop reference to test subscriber after subscription cancellation", pub)); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable { - final int totalElements = 3; - - activePublisherTest(totalElements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(Long.MAX_VALUE); - - sub.nextElements(totalElements); - sub.expectCompletion(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable { - final int totalElements = 3; - - activePublisherTest(totalElements, true, new PublisherTestRun() { - @Override - public void run(Publisher pub) throws Throwable { - final ManualSubscriber sub = env.newManualSubscriber(pub); - sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE / 2 - sub.request(Long.MAX_VALUE / 2); // pending = Long.MAX_VALUE - 1 - sub.request(1); // pending = Long.MAX_VALUE - - sub.nextElements(totalElements); - sub.expectCompletion(); - - try { - env.verifyNoAsyncErrorsNoDelay(); - } finally { - sub.cancel(); - } - - } - }); - } - - @Override @Test - public void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable { - activePublisherTest(Integer.MAX_VALUE, false, new PublisherTestRun() { - @Override public void run(Publisher pub) throws Throwable { - final ManualSubscriberWithSubscriptionSupport sub = new BlackholeSubscriberWithSubscriptionSupport(env) { - // arbitrarily set limit on nuber of request calls signalled, we expect overflow after already 2 calls, - // so 10 is relatively high and safe even if arbitrarily chosen - int callsCounter = 10; - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (subscription.isCompleted()) { - if (callsCounter > 0) { - subscription.value().request(Long.MAX_VALUE - 1); - callsCounter--; - } else { - subscription.value().cancel(); - } - } else { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - }; - env.subscribe(pub, sub, env.defaultTimeoutMillis()); - - // eventually triggers `onNext`, which will then trigger up to `callsCounter` times `request(Long.MAX_VALUE - 1)` - // we're pretty sure to overflow from those - sub.request(1); - - // no onError should be signalled - try { - env.verifyNoAsyncErrors(); - } finally { - sub.cancel(); - } - } - }); - } - - ///////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - ///////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - public interface PublisherTestRun { - public void run(Publisher pub) throws Throwable; - } - - /** - * Test for feature that SHOULD/MUST be implemented, using a live publisher. - * - * @param elements the number of elements the Publisher under test must be able to emit to run this test - * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run. - * If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped. - * To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}. - */ - public void activePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun body) throws Throwable { - if (elements > maxElementsFromPublisher()) { - throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher())); - } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) { - throw new SkipException("Unable to run this test, as it requires an onComplete signal, " + - "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)"); - } else { - Publisher pub = createPublisher(elements); - body.run(pub); - env.verifyNoAsyncErrorsNoDelay(); - } - } - - /** - * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails. - * - * @param elements the number of elements the Publisher under test must be able to emit to run this test - * @param completionSignalRequired true if an {@code onComplete} signal is required by this test to run. - * If the tested Publisher is unable to signal completion, tests requireing onComplete signals will be skipped. - * To signal if your Publisher is able to signal completion see {@link PublisherVerification#maxElementsFromPublisher()}. - */ - public void optionalActivePublisherTest(long elements, boolean completionSignalRequired, PublisherTestRun body) throws Throwable { - if (elements > maxElementsFromPublisher()) { - throw new SkipException(String.format("Unable to run this test, as required elements nr: %d is higher than supported by given producer: %d", elements, maxElementsFromPublisher())); - } else if (completionSignalRequired && maxElementsFromPublisher() == Long.MAX_VALUE) { - throw new SkipException("Unable to run this test, as it requires an onComplete signal, " + - "which this Publisher is unable to provide (as signalled by returning Long.MAX_VALUE from `maxElementsFromPublisher()`)"); - } else { - - final Publisher pub = createPublisher(elements); - final String skipMessage = "Skipped because tested publisher does NOT implement this OPTIONAL requirement."; - - try { - potentiallyPendingTest(pub, body); - } catch (Exception ex) { - notVerified(skipMessage); - } catch (AssertionError ex) { - notVerified(skipMessage + " Reason for skipping was: " + ex.getMessage()); - } - } - } - - public static final String SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE = - "Skipping because no error state Publisher provided, and the test requires it. " + - "Please implement PublisherVerification#createFailedPublisher to run this test."; - - public static final String SKIPPING_OPTIONAL_TEST_FAILED = - "Skipping, because provided Publisher does not pass this *additional* verification."; - /** - * Additional test for Publisher in error state - */ - public void whenHasErrorPublisherTest(PublisherTestRun body) throws Throwable { - potentiallyPendingTest(createFailedPublisher(), body, SKIPPING_NO_ERROR_PUBLISHER_AVAILABLE); - } - - public void potentiallyPendingTest(Publisher pub, PublisherTestRun body) throws Throwable { - potentiallyPendingTest(pub, body, SKIPPING_OPTIONAL_TEST_FAILED); - } - - public void potentiallyPendingTest(Publisher pub, PublisherTestRun body, String message) throws Throwable { - if (pub != null) { - body.run(pub); - } else { - throw new SkipException(message); - } - } - - /** - * Executes a given test body {@code n} times. - * All the test runs must pass in order for the stochastic test to pass. - */ - public void stochasticTest(int n, Function body) throws Throwable { - if (skipStochasticTests()) { - notVerified("Skipping @Stochastic test because `skipStochasticTests()` returned `true`!"); - } - - for (int i = 0; i < n; i++) { - body.apply(i); - } - } - - public void notVerified() { - throw new SkipException("Not verified by this TCK."); - } - - /** - * Return this value from {@link PublisherVerification#maxElementsFromPublisher()} to mark that the given {@link org.reactivestreams.Publisher}, - * is not able to signal completion. For example it is strictly a time-bound or unbounded source of data. - * - * Returning this value from {@link PublisherVerification#maxElementsFromPublisher()} will result in skipping all TCK tests which require onComplete signals! - */ - public long publisherUnableToSignalOnComplete() { - return Long.MAX_VALUE; - } - - public void notVerified(String message) { - throw new SkipException(message); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java deleted file mode 100644 index 62c899a7847..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberBlackboxVerification.java +++ /dev/null @@ -1,516 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.ManualPublisher; -import org.reactivestreams.tck.TestEnvironment.ManualSubscriber; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules; -import org.reactivestreams.tck.flow.support.TestException; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.reactivestreams.tck.SubscriberWhiteboxVerification.BlackboxSubscriberProxy; -import static org.testng.Assert.assertTrue; - -/** - * Provides tests for verifying {@link org.reactivestreams.Subscriber} and {@link org.reactivestreams.Subscription} - * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing). - * - * This verification is NOT able to check many of the rules of the spec, and if you want more - * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification} - * instead. - * - * @see org.reactivestreams.Subscriber - * @see org.reactivestreams.Subscription - */ -public abstract class SubscriberBlackboxVerification extends WithHelperPublisher - implements SubscriberBlackboxVerificationRules { - - protected final TestEnvironment env; - - protected SubscriberBlackboxVerification(TestEnvironment env) { - this.env = env; - } - - // USER API - - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - */ - public abstract Subscriber createSubscriber(); - - /** - * Override this method if the Subscriber implementation you are verifying - * needs an external signal before it signals demand to its Publisher. - * - * By default this method does nothing. - */ - public void triggerRequest(final Subscriber subscriber) { - // this method is intentionally left blank - } - - // ENV SETUP - - /** - * Executor service used by the default provided asynchronous Publisher. - * @see #createHelperPublisher(long) - */ - private ExecutorService publisherExecutor; - @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); } - @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); } - @Override public ExecutorService publisherExecutorService() { return publisherExecutor; } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - @Override @Test - public void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws InterruptedException { - triggerRequest(stage.subProxy().sub()); - final long requested = stage.expectRequest();// assuming subscriber wants to consume elements... - final long signalsToEmit = Math.min(requested, 512); // protecting against Subscriber which sends ridiculous large demand - - // should cope with up to requested number of elements - for (int i = 0; i < signalsToEmit && sampleIsCancelled(stage, i, 10); i++) - stage.signalNext(); - - // we complete after `signalsToEmit` (which can be less than `requested`), - // which is legal under https://github.com/reactive-streams/reactive-streams-jvm#1.2 - stage.sendCompletion(); - } - - /** - * In order to allow some "skid" and not check state on each iteration, - * only check {@code stage.isCancelled} every {@code checkInterval}'th iteration. - */ - private boolean sampleIsCancelled(BlackboxTestStage stage, int i, int checkInterval) throws InterruptedException { - if (i % checkInterval == 0) return stage.isCancelled(); - else return false; - } - }); - } - - @Override @Test - public void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - final Optional onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackTraceElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackTraceElement.get(); - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - - @Override - public void cancel() { - final Optional onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackElement.get(); - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - }; - - final Subscriber sub = createSubscriber(); - sub.onSubscribe(subs); - sub.onComplete(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - - @Override - public void cancel() { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - }; - - final Subscriber sub = createSubscriber(); - sub.onSubscribe(subs); - sub.onError(new TestException()); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception { - new BlackboxTestStage(env) {{ - // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail - final TestEnvironment.Latch secondSubscriptionCancelled = new TestEnvironment.Latch(env); - sub().onSubscribe( - new Subscription() { - @Override - public void request(long elements) { - env.flop(String.format("Subscriber %s illegally called `subscription.request(%s)`!", sub(), elements)); - } - - @Override - public void cancel() { - secondSubscriptionCancelled.close(); - } - - @Override - public String toString() { - return "SecondSubscription(should get cancelled)"; - } - }); - - secondSubscriptionCancelled.expectClose("Expected SecondSubscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called."); - env.verifyNoAsyncErrorsNoDelay(); - sendCompletion(); // we're done, complete the subscriber under test - }}; - } - - @Override @Test - public void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - // the same thread part of the clause can be verified but that is not very useful, or is it? - } - - @Override @Test - public void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - triggerRequest(stage.subProxy().sub()); - final long notUsed = stage.expectRequest(); // received request signal - stage.sub().onComplete(); - stage.subProxy().expectCompletion(); - } - }); - } - - @Override @Test - public void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - final Subscriber sub = stage.sub(); - sub.onComplete(); - stage.subProxy().expectCompletion(); - } - }); - } - - @Override @Test - public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - triggerRequest(stage.subProxy().sub()); - final long notUsed = stage.expectRequest(); // received request signal - stage.sub().onError(new TestException()); // in response to that, we fail - stage.subProxy().expectError(Throwable.class); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - blackboxSubscriberTest(new BlackboxTestStageTestRun() { - @Override @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void run(BlackboxTestStage stage) throws Throwable { - - stage.sub().onError(new TestException()); - stage.subProxy().expectError(Throwable.class); - } - }); - } - - @Override @Test - public void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - try { - sub.onSubscribe(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subscription = new Subscription() { - @Override public void request(final long elements) {} - @Override public void cancel() {} - }; - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - sub.onSubscribe(subscription); - try { - sub.onNext(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onNext(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - @Override @Test - public void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - blackboxSubscriberWithoutSetupTest(new BlackboxTestStageTestRun() { - @Override - public void run(BlackboxTestStage stage) throws Throwable { - final Subscription subscription = new Subscription() { - @Override public void request(final long elements) {} - @Override public void cancel() {} - }; - - { - final Subscriber sub = createSubscriber(); - boolean gotNPE = false; - sub.onSubscribe(subscription); - try { - sub.onError(null); - } catch(final NullPointerException expected) { - gotNPE = true; - } - assertTrue(gotNPE, "onError(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION ////////////////// - - @Override @Test - public void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - notVerified(); // cannot be meaningfully tested as black box, or can it? - } - - @Override @Test - public void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - @Override @Test - public void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - /////////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - abstract class BlackboxTestStageTestRun { - public abstract void run(BlackboxTestStage stage) throws Throwable; - } - - public void blackboxSubscriberTest(BlackboxTestStageTestRun body) throws Throwable { - BlackboxTestStage stage = new BlackboxTestStage(env, true); - body.run(stage); - } - - public void blackboxSubscriberWithoutSetupTest(BlackboxTestStageTestRun body) throws Throwable { - BlackboxTestStage stage = new BlackboxTestStage(env, false); - body.run(stage); - } - - public class BlackboxTestStage extends ManualPublisher { - public Publisher pub; - public ManualSubscriber tees; // gives us access to an infinite stream of T values - - public T lastT = null; - private Optional> subProxy = Optional.empty(); - - public BlackboxTestStage(TestEnvironment env) throws InterruptedException { - this(env, true); - } - - public BlackboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException { - super(env); - if (runDefaultInit) { - pub = this.createHelperPublisher(Long.MAX_VALUE); - tees = env.newManualSubscriber(pub); - Subscriber sub = createSubscriber(); - subProxy = Optional.of(createBlackboxSubscriberProxy(env, sub)); - subscribe(subProxy.get()); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - /** - * Proxy for the {@link #sub()} {@code Subscriber}, providing certain assertions on methods being called on the Subscriber. - */ - public BlackboxSubscriberProxy subProxy() { - return subProxy.get(); - } - - public Publisher createHelperPublisher(long elements) { - return SubscriberBlackboxVerification.this.createHelperPublisher(elements); - } - - public BlackboxSubscriberProxy createBlackboxSubscriberProxy(TestEnvironment env, Subscriber sub) { - return new BlackboxSubscriberProxy(env, sub); - } - - public T signalNext() throws InterruptedException { - T element = nextT(); - sendNext(element); - return element; - } - - public T nextT() throws InterruptedException { - lastT = tees.requestNextElement(); - return lastT; - } - - } - - public void notVerified() { - throw new SkipException("Not verified using this TCK."); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java deleted file mode 100644 index f2304a11dc3..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/SubscriberWhiteboxVerification.java +++ /dev/null @@ -1,850 +0,0 @@ -/* - * Copyright (c) 2019, 2022, 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.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.TestEnvironment.*; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.TestException; -import org.testng.SkipException; -import org.testng.annotations.AfterClass; -import org.testng.annotations.BeforeClass; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; - -import static org.testng.Assert.assertTrue; - -/** - * Provides whitebox style tests for verifying {@link org.reactivestreams.Subscriber} - * and {@link org.reactivestreams.Subscription} specification rules. - * - * @see org.reactivestreams.Subscriber - * @see org.reactivestreams.Subscription - */ -public abstract class SubscriberWhiteboxVerification extends WithHelperPublisher - implements SubscriberWhiteboxVerificationRules { - - private final TestEnvironment env; - - protected SubscriberWhiteboxVerification(TestEnvironment env) { - this.env = env; - } - - // USER API - - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - * - * In order to be meaningfully testable your Subscriber must inform the given - * `WhiteboxSubscriberProbe` of the respective events having been received. - */ - public abstract Subscriber createSubscriber(WhiteboxSubscriberProbe probe); - - // ENV SETUP - - /** - * Executor service used by the default provided asynchronous Publisher. - * @see #createHelperPublisher(long) - */ - private ExecutorService publisherExecutor; - @BeforeClass public void startPublisherExecutorService() { publisherExecutor = Executors.newFixedThreadPool(4); } - @AfterClass public void shutdownPublisherExecutorService() { if (publisherExecutor != null) publisherExecutor.shutdown(); } - @Override public ExecutorService publisherExecutorService() { return publisherExecutor; } - - ////////////////////// TEST ENV CLEANUP ///////////////////////////////////// - - @BeforeMethod - public void setUp() throws Exception { - env.clearAsyncErrors(); - } - - ////////////////////// TEST SETUP VERIFICATION ////////////////////////////// - - @Test - public void required_exerciseWhiteboxHappyPath() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - long receivedRequests = stage.expectRequest(); - - stage.signalNext(); - stage.probe.expectNext(stage.lastT); - - stage.puppet().triggerRequest(1); - if (receivedRequests == 1) { - stage.expectRequest(); - } - - stage.signalNext(); - stage.probe.expectNext(stage.lastT); - - stage.puppet().signalCancel(); - stage.expectCancelling(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - ////////////////////// SPEC RULE VERIFICATION /////////////////////////////// - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.1 - @Override @Test - public void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.expectRequest(); - - stage.signalNext(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.2 - @Override @Test - public void untested_spec202_shouldAsynchronouslyDispatch() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3 - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable { - subscriberTestWithoutSetup(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - final Optional onCompleteStackTraceElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackTraceElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackTraceElement.get(); - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - - @Override - public void cancel() { - final Optional onCompleteStackElement = env.findCallerMethodInStackTrace("onComplete"); - if (onCompleteStackElement.isDefined()) { - final StackTraceElement stackElem = onCompleteStackElement.get(); - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onComplete (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - }; - - stage.probe = stage.createWhiteboxSubscriberProbe(env); - final Subscriber sub = createSubscriber(stage.probe); - - sub.onSubscribe(subs); - sub.onComplete(); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.3 - @Override @Test - public void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable { - subscriberTestWithoutSetup(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - final Subscription subs = new Subscription() { - @Override - public void request(long n) { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::request MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - - @Override - public void cancel() { - Throwable thr = new Throwable(); - for (StackTraceElement stackElem : thr.getStackTrace()) { - if (stackElem.getMethodName().equals("onError")) { - env.flop(String.format("Subscription::cancel MUST NOT be called from Subscriber::onError (Rule 2.3)! (Caller: %s::%s line %d)", - stackElem.getClassName(), stackElem.getMethodName(), stackElem.getLineNumber())); - } - } - } - }; - - stage.probe = stage.createWhiteboxSubscriberProbe(env); - final Subscriber sub = createSubscriber(stage.probe); - - sub.onSubscribe(subs); - sub.onError(new TestException()); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.4 - @Override @Test - public void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.5 - @Override @Test - public void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - // try to subscribe another time, if the subscriber calls `probe.registerOnSubscribe` the test will fail - final Latch secondSubscriptionCancelled = new Latch(env); - final Subscriber sub = stage.sub(); - final Subscription subscription = new Subscription() { - @Override - public void request(long elements) { - // ignore... - } - - @Override - public void cancel() { - secondSubscriptionCancelled.close(); - } - - @Override - public String toString() { - return "SecondSubscription(should get cancelled)"; - } - }; - sub.onSubscribe(subscription); - - secondSubscriptionCancelled.expectClose("Expected 2nd Subscription given to subscriber to be cancelled, but `Subscription.cancel()` was not called"); - env.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.6 - @Override @Test - public void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.7 - @Override @Test - public void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - // the same thread part of the clause can be verified but that is not very useful, or is it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.8 - @Override @Test - public void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.expectRequest(); - stage.puppet().signalCancel(); - stage.expectCancelling(); - stage.signalNext(); - - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9 - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.sendCompletion(); - stage.probe.expectCompletion(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.9 - @Override @Test - public void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.sendCompletion(); - stage.probe.expectCompletion(); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(1); - stage.puppet().triggerRequest(1); - - Exception ex = new TestException(); - stage.sendError(ex); - stage.probe.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.10 - @Override @Test - public void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - Exception ex = new TestException(); - stage.sendError(ex); - stage.probe.expectError(ex); - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.11 - @Override @Test - public void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.12 - @Override @Test - public void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void untested_spec213_failingOnSignalInvocation() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onSubscribe(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } - - assertTrue(gotNPE, "onSubscribe(null) did not throw NullPointerException"); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onNext(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } - - assertTrue(gotNPE, "onNext(null) did not throw NullPointerException"); - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#2.13 - @Override @Test - public void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws Throwable { - - final Subscriber sub = stage.sub(); - boolean gotNPE = false; - try { - sub.onError(null); - } catch (final NullPointerException expected) { - gotNPE = true; - } finally { - assertTrue(gotNPE, "onError(null) did not throw NullPointerException"); - } - - env.verifyNoAsyncErrorsNoDelay(); - } - }); - } - - - ////////////////////// SUBSCRIPTION SPEC RULE VERIFICATION ////////////////// - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.1 - @Override @Test - public void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.8 - @Override @Test - public void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable { - subscriberTest(new TestStageTestRun() { - @Override - public void run(WhiteboxTestStage stage) throws InterruptedException { - stage.puppet().triggerRequest(2); - long requestedElements = stage.expectRequest(); - stage.probe.expectNext(stage.signalNext()); - // Some subscribers may only request one element at a time. - if (requestedElements < 2) { - stage.expectRequest(); - } - stage.probe.expectNext(stage.signalNext()); - - stage.probe.expectNone(); - stage.puppet().triggerRequest(3); - - stage.verifyNoAsyncErrors(); - } - }); - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.10 - @Override @Test - public void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.11 - @Override @Test - public void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.14 - @Override @Test - public void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.15 - @Override @Test - public void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - // Verifies rule: https://github.com/reactive-streams/reactive-streams-jvm#3.16 - @Override @Test - public void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception { - notVerified(); // cannot be meaningfully tested, or can it? - } - - /////////////////////// ADDITIONAL "COROLLARY" TESTS //////////////////////// - - /////////////////////// TEST INFRASTRUCTURE ///////////////////////////////// - - abstract class TestStageTestRun { - public abstract void run(WhiteboxTestStage stage) throws Throwable; - } - - /** - * Prepares subscriber and publisher pair (by subscribing the first to the latter), - * and then hands over the tests {@link WhiteboxTestStage} over to the test. - * - * The test stage is, like in a puppet show, used to orchestrate what each participant should do. - * Since this is a whitebox test, this allows the stage to completely control when and how to signal / expect signals. - */ - public void subscriberTest(TestStageTestRun body) throws Throwable { - WhiteboxTestStage stage = new WhiteboxTestStage(env, true); - body.run(stage); - } - - /** - * Provides a {@link WhiteboxTestStage} without performing any additional setup, - * like the {@link #subscriberTest(SubscriberWhiteboxVerification.TestStageTestRun)} would. - * - * Use this method to write tests in which you need full control over when and how the initial {@code subscribe} is signalled. - */ - public void subscriberTestWithoutSetup(TestStageTestRun body) throws Throwable { - WhiteboxTestStage stage = new WhiteboxTestStage(env, false); - body.run(stage); - } - - /** - * Test for feature that MAY be implemented. This test will be marked as SKIPPED if it fails. - */ - public void optionalSubscriberTestWithoutSetup(TestStageTestRun body) throws Throwable { - try { - subscriberTestWithoutSetup(body); - } catch (Exception ex) { - notVerified("Skipped because tested publisher does NOT implement this OPTIONAL requirement."); - } - } - - public class WhiteboxTestStage extends ManualPublisher { - public Publisher pub; - public ManualSubscriber tees; // gives us access to a stream T values - public WhiteboxSubscriberProbe probe; - - public T lastT = null; - - public WhiteboxTestStage(TestEnvironment env) throws InterruptedException { - this(env, true); - } - - public WhiteboxTestStage(TestEnvironment env, boolean runDefaultInit) throws InterruptedException { - super(env); - if (runDefaultInit) { - pub = this.createHelperPublisher(Long.MAX_VALUE); - tees = env.newManualSubscriber(pub); - probe = new WhiteboxSubscriberProbe(env, subscriber); - subscribe(createSubscriber(probe)); - probe.puppet.expectCompletion(env.defaultTimeoutMillis(), String.format("Subscriber %s did not `registerOnSubscribe`", sub())); - env.verifyNoAsyncErrorsNoDelay(); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - public SubscriberPuppet puppet() { - return probe.puppet(); - } - - public WhiteboxSubscriberProbe probe() { - return probe; - } - - public Publisher createHelperPublisher(long elements) { - return SubscriberWhiteboxVerification.this.createHelperPublisher(elements); - } - - public WhiteboxSubscriberProbe createWhiteboxSubscriberProbe(TestEnvironment env) { - return new WhiteboxSubscriberProbe(env, subscriber); - } - - public T signalNext() throws InterruptedException { - return signalNext(nextT()); - } - - private T signalNext(T element) throws InterruptedException { - sendNext(element); - return element; - } - - public T nextT() throws InterruptedException { - lastT = tees.requestNextElement(); - return lastT; - } - - public void verifyNoAsyncErrors() { - env.verifyNoAsyncErrors(); - } - } - - /** - * This class is intented to be used as {@code Subscriber} decorator and should be used in {@code pub.subscriber(...)} calls, - * in order to allow intercepting calls on the underlying {@code Subscriber}. - * This delegation allows the proxy to implement {@link BlackboxProbe} assertions. - */ - public static class BlackboxSubscriberProxy extends BlackboxProbe implements Subscriber { - - public BlackboxSubscriberProxy(TestEnvironment env, Subscriber subscriber) { - super(env, Promise.>completed(env, subscriber)); - } - - @Override - public void onSubscribe(Subscription s) { - sub().onSubscribe(s); - } - - @Override - public void onNext(T t) { - registerOnNext(t); - sub().onNext(t); - } - - @Override - public void onError(Throwable cause) { - registerOnError(cause); - sub().onError(cause); - } - - @Override - public void onComplete() { - registerOnComplete(); - sub().onComplete(); - } - } - - public static class BlackboxProbe implements SubscriberProbe { - protected final TestEnvironment env; - protected final Promise> subscriber; - - protected final Receptacle elements; - protected final Promise error; - - public BlackboxProbe(TestEnvironment env, Promise> subscriber) { - this.env = env; - this.subscriber = subscriber; - elements = new Receptacle(env); - error = new Promise(env); - } - - @Override - public void registerOnNext(T element) { - elements.add(element); - } - - @Override - public void registerOnComplete() { - try { - elements.complete(); - } catch (IllegalStateException ex) { - // "Queue full", onComplete was already called - env.flop("subscriber::onComplete was called a second time, which is illegal according to Rule 1.7"); - } - } - - @Override - public void registerOnError(Throwable cause) { - try { - error.complete(cause); - } catch (IllegalStateException ex) { - // "Queue full", onError was already called - env.flop("subscriber::onError was called a second time, which is illegal according to Rule 1.7"); - } - } - - public T expectNext() throws InterruptedException { - return elements.next(env.defaultTimeoutMillis(), String.format("Subscriber %s did not call `registerOnNext(_)`", sub())); - } - - public void expectNext(T expected) throws InterruptedException { - expectNext(expected, env.defaultTimeoutMillis()); - } - - public void expectNext(T expected, long timeoutMillis) throws InterruptedException { - T received = elements.next(timeoutMillis, String.format("Subscriber %s did not call `registerOnNext(%s)`", sub(), expected)); - if (!received.equals(expected)) { - env.flop(String.format("Subscriber %s called `registerOnNext(%s)` rather than `registerOnNext(%s)`", sub(), received, expected)); - } - } - - public Subscriber sub() { - return subscriber.value(); - } - - public void expectCompletion() throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis()); - } - - public void expectCompletion(long timeoutMillis) throws InterruptedException { - expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnComplete()`", sub())); - } - - public void expectCompletion(long timeoutMillis, String msg) throws InterruptedException { - elements.expectCompletion(timeoutMillis, msg); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectErrorWithMessage(Class expected, String requiredMessagePart) throws InterruptedException { - final E err = expectError(expected); - String message = err.getMessage(); - assertTrue(message.contains(requiredMessagePart), - String.format("Got expected exception %s but missing message [%s], was: %s", err.getClass(), requiredMessagePart, expected)); - } - - public E expectError(Class expected) throws InterruptedException { - return expectError(expected, env.defaultTimeoutMillis()); - } - - @SuppressWarnings({"unchecked", "ThrowableResultOfMethodCallIgnored"}) - public E expectError(Class expected, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - if (error.value() == null) { - return env.flopAndFail(String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - } else if (expected.isInstance(error.value())) { - return (E) error.value(); - } else { - return env.flopAndFail(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected)); - } - } - - public void expectError(Throwable expected) throws InterruptedException { - expectError(expected, env.defaultTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectError(Throwable expected, long timeoutMillis) throws InterruptedException { - error.expectCompletion(timeoutMillis, String.format("Subscriber %s did not call `registerOnError(%s)`", sub(), expected)); - if (error.value() != expected) { - env.flop(String.format("Subscriber %s called `registerOnError(%s)` rather than `registerOnError(%s)`", sub(), error.value(), expected)); - } - } - - public void expectNone() throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis()); - } - - public void expectNone(long withinMillis) throws InterruptedException { - elements.expectNone(withinMillis, "Expected nothing"); - } - - } - - public static class WhiteboxSubscriberProbe extends BlackboxProbe implements SubscriberPuppeteer { - protected Promise puppet; - - public WhiteboxSubscriberProbe(TestEnvironment env, Promise> subscriber) { - super(env, subscriber); - puppet = new Promise(env); - } - - private SubscriberPuppet puppet() { - return puppet.value(); - } - - @Override - public void registerOnSubscribe(SubscriberPuppet p) { - if (!puppet.isCompleted()) { - puppet.complete(p); - } - } - - } - - public interface SubscriberPuppeteer { - - /** - * Must be called by the test subscriber when it has successfully registered a subscription - * inside the `onSubscribe` method. - */ - void registerOnSubscribe(SubscriberPuppet puppet); - } - - public interface SubscriberProbe { - - /** - * Must be called by the test subscriber when it has received an`onNext` event. - */ - void registerOnNext(T element); - - /** - * Must be called by the test subscriber when it has received an `onComplete` event. - */ - void registerOnComplete(); - - /** - * Must be called by the test subscriber when it has received an `onError` event. - */ - void registerOnError(Throwable cause); - - } - - /** - * Implement this puppet in your Whitebox style tests. - * The test suite will invoke the specific trigger/signal methods requesting you to execute the specific action. - * Since this is a whitebox style test, you're allowed and expected to use knowladge about your implementation to - * make implement these calls. - */ - public interface SubscriberPuppet { - - /** - * Ensure that at least {@code elements} are eventually requested by your {@link Subscriber}, if it hasn't already - * requested that many elements. - *

- * This does not necessarily have to correlate 1:1 with a {@code Subscription.request(elements)} call, but the sum - * of the elements requested by your {@code Subscriber} must eventually be at least the sum of the elements - * triggered to be requested by all the invocations of this method. - *

- * Additionally, subscribers are permitted to delay requesting elements until previous requests for elements have - * been fulfilled. For example, a subscriber that only requests one element at a time may fulfill the request made - * by this method by requesting one element {@code elements} times, waiting for each element to arrive before the - * next request is made. - *

- * Before sending any element to the subscriber, the TCK must wait for the subscriber to request that element, and - * must be prepared for the subscriber to only request one element at a time, it is not enough for the TCK to - * simply invoke this method before sending elements. - *

- * An invocation of {@link #signalCancel()} may be coalesced into any elements that have not yet been requested, - * such that only a cancel signal is emitted. - */ - void triggerRequest(long elements); - - /** - * Trigger {@code cancel()} on your {@link Subscriber}. - *

- * An invocation of this method may be coalesced into any outstanding requests, as requested by - *{@link #triggerRequest(long)}, such that only a cancel signal is emitted. - */ - void signalCancel(); - } - - public void notVerified() { - throw new SkipException("Not verified using this TCK."); - } - - public void notVerified(String msg) { - throw new SkipException(msg); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java deleted file mode 100644 index e32b58cbd13..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/TestEnvironment.java +++ /dev/null @@ -1,1168 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.flow.support.Optional; -import org.reactivestreams.tck.flow.support.SubscriberBufferOverflowException; - -import java.util.Collections; -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.ArrayBlockingQueue; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicReference; - -import static java.util.concurrent.TimeUnit.MILLISECONDS; -import static java.util.concurrent.TimeUnit.NANOSECONDS; -import static org.testng.Assert.assertTrue; -import static org.testng.Assert.fail; - -public class TestEnvironment { - public static final int TEST_BUFFER_SIZE = 16; - - private static final String DEFAULT_TIMEOUT_MILLIS_ENV = "DEFAULT_TIMEOUT_MILLIS"; - private static final long DEFAULT_TIMEOUT_MILLIS = 100; - - private static final String DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV = "DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS"; - private static final String DEFAULT_POLL_TIMEOUT_MILLIS_ENV = "DEFAULT_POLL_TIMEOUT_MILLIS_ENV"; - - private final long defaultTimeoutMillis; - private final long defaultPollTimeoutMillis; - private final long defaultNoSignalsTimeoutMillis; - private final boolean printlnDebug; - - private CopyOnWriteArrayList asyncErrors = new CopyOnWriteArrayList(); - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't - * preempted by an asynchronous event. - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis, - boolean printlnDebug) { - this.defaultTimeoutMillis = defaultTimeoutMillis; - this.defaultPollTimeoutMillis = defaultPollTimeoutMillis; - this.defaultNoSignalsTimeoutMillis = defaultNoSignalsTimeoutMillis; - this.printlnDebug = printlnDebug; - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, boolean printlnDebug) { - this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultTimeoutMillis, printlnDebug); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - * @param defaultPollTimeoutMillis default amount of time to poll for events if {@code defaultTimeoutMillis} isn't - * preempted by an asynchronous event. - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis, long defaultPollTimeoutMillis) { - this(defaultTimeoutMillis, defaultNoSignalsTimeoutMillis, defaultPollTimeoutMillis, false); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - * @param defaultNoSignalsTimeoutMillis default timeout to be used when no further signals are expected anymore - */ - public TestEnvironment(long defaultTimeoutMillis, long defaultNoSignalsTimeoutMillis) { - this(defaultTimeoutMillis, defaultTimeoutMillis, defaultNoSignalsTimeoutMillis); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * @param defaultTimeoutMillis default timeout to be used in all expect* methods - */ - public TestEnvironment(long defaultTimeoutMillis) { - this(defaultTimeoutMillis, defaultTimeoutMillis, defaultTimeoutMillis); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS} - * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used. - * - * @param printlnDebug if true, signals such as OnNext / Request / OnComplete etc will be printed to standard output, - * often helpful to pinpoint simple race conditions etc. - */ - public TestEnvironment(boolean printlnDebug) { - this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis(), envDefaultPollTimeoutMillis(), printlnDebug); - } - - /** - * Tests must specify the timeout for expected outcome of asynchronous - * interactions. Longer timeout does not invalidate the correctness of - * the implementation, but can in some cases result in longer time to - * run the tests. - * - * The default timeout for all expect* methods will be obtained by either the env variable {@code DEFAULT_TIMEOUT_MILLIS} - * or the default value ({@link TestEnvironment#DEFAULT_TIMEOUT_MILLIS}) will be used. - */ - public TestEnvironment() { - this(envDefaultTimeoutMillis(), envDefaultNoSignalsTimeoutMillis()); - } - - /** This timeout is used when waiting for a signal to arrive. */ - public long defaultTimeoutMillis() { - return defaultTimeoutMillis; - } - - /** - * This timeout is used when asserting that no further signals are emitted. - * Note that this timeout default - */ - public long defaultNoSignalsTimeoutMillis() { - return defaultNoSignalsTimeoutMillis; - } - - /** - * The default amount of time to poll for events if {@code defaultTimeoutMillis} isn't preempted by an asynchronous - * event. - */ - public long defaultPollTimeoutMillis() { - return defaultPollTimeoutMillis; - } - - /** - * Tries to parse the env variable {@code DEFAULT_TIMEOUT_MILLIS} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return DEFAULT_TIMEOUT_MILLIS; - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * Tries to parse the env variable {@code DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultNoSignalsTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return envDefaultTimeoutMillis(); - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_NO_SIGNALS_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * Tries to parse the env variable {@code DEFAULT_POLL_TIMEOUT_MILLIS_ENV} as long and returns the value if present OR its default value. - * - * @throws java.lang.IllegalArgumentException when unable to parse the env variable - */ - public static long envDefaultPollTimeoutMillis() { - final String envMillis = System.getenv(DEFAULT_POLL_TIMEOUT_MILLIS_ENV); - if (envMillis == null) return envDefaultTimeoutMillis(); - else try { - return Long.parseLong(envMillis); - } catch (NumberFormatException ex) { - throw new IllegalArgumentException(String.format("Unable to parse %s env value [%s] as long!", DEFAULT_POLL_TIMEOUT_MILLIS_ENV, envMillis), ex); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(String msg) { - try { - fail(msg); - } catch (Throwable t) { - asyncErrors.add(t); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(Throwable thr, String msg) { - try { - fail(msg, thr); - } catch (Throwable t) { - asyncErrors.add(thr); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * This method does *NOT* fail the test - it's up to inspections of the error to fail the test if required. - * - * This overload keeps the passed in throwable as the asyncError, instead of creating an AssertionError for this. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public void flop(Throwable thr) { - try { - fail(thr.getMessage(), thr); - } catch (Throwable t) { - asyncErrors.add(thr); - } - } - - /** - * To flop means to "fail asynchronously", either by onErroring or by failing some TCK check triggered asynchronously. - * - * This method DOES fail the test right away (it tries to, by throwing an AssertionException), - * in such it is different from {@link org.reactivestreams.tck.TestEnvironment#flop} which only records the error. - * - * Use {@code env.verifyNoAsyncErrorsNoDelay()} at the end of your TCK tests to verify there no flops called during it's execution. - * To check investigate asyncErrors more closely you can use {@code expectError} methods or collect the error directly - * from the environment using {@code env.dropAsyncError()}. - * - * To clear asyncErrors you can call {@link org.reactivestreams.tck.TestEnvironment#clearAsyncErrors()} - */ - public T flopAndFail(String msg) { - try { - fail(msg); - } catch (Throwable t) { - asyncErrors.add(t); - fail(msg, t); - } - return null; // unreachable, the previous block will always exit by throwing - } - - - - public void subscribe(Publisher pub, TestSubscriber sub) throws InterruptedException { - subscribe(pub, sub, defaultTimeoutMillis); - } - - public void subscribe(Publisher pub, TestSubscriber sub, long timeoutMillis) throws InterruptedException { - pub.subscribe(sub); - sub.subscription.expectCompletion(timeoutMillis, String.format("Could not subscribe %s to Publisher %s", sub, pub)); - verifyNoAsyncErrorsNoDelay(); - } - - public ManualSubscriber newBlackholeSubscriber(Publisher pub) throws InterruptedException { - ManualSubscriberWithSubscriptionSupport sub = new BlackholeSubscriberWithSubscriptionSupport(this); - subscribe(pub, sub, defaultTimeoutMillis()); - return sub; - } - - public ManualSubscriber newManualSubscriber(Publisher pub) throws InterruptedException { - return newManualSubscriber(pub, defaultTimeoutMillis()); - } - - public ManualSubscriber newManualSubscriber(Publisher pub, long timeoutMillis) throws InterruptedException { - ManualSubscriberWithSubscriptionSupport sub = new ManualSubscriberWithSubscriptionSupport(this); - subscribe(pub, sub, timeoutMillis); - return sub; - } - - public void clearAsyncErrors() { - asyncErrors.clear(); - } - - public Throwable dropAsyncError() { - try { - return asyncErrors.remove(0); - } catch (IndexOutOfBoundsException ex) { - return null; - } - } - - /** - * Waits for {@link TestEnvironment#defaultNoSignalsTimeoutMillis()} and then verifies that no asynchronous errors - * were signalled pior to, or during that time (by calling {@code flop()}). - */ - public void verifyNoAsyncErrors() { - verifyNoAsyncErrors(defaultNoSignalsTimeoutMillis()); - } - - /** - * This version of {@code verifyNoAsyncErrors} should be used when errors still could be signalled - * asynchronously during {@link TestEnvironment#defaultTimeoutMillis()} time. - *

- * It will immediatly check if any async errors were signaled (using {@link TestEnvironment#flop(String)}, - * and if no errors encountered wait for another default timeout as the errors may yet be signalled. - * The initial check is performed in order to fail-fast in case of an already failed test. - */ - public void verifyNoAsyncErrors(long delay) { - try { - verifyNoAsyncErrorsNoDelay(); - - Thread.sleep(delay); - verifyNoAsyncErrorsNoDelay(); - } catch (InterruptedException e) { - throw new RuntimeException(e); - } - } - - /** - * Verifies that no asynchronous errors were signalled pior to calling this method (by calling {@code flop()}). - * This version of verifyNoAsyncError does not wait before checking for asynchronous errors, and is to be used - * for example in tight loops etc. - */ - public void verifyNoAsyncErrorsNoDelay() { - for (Throwable e : asyncErrors) { - if (e instanceof AssertionError) { - throw (AssertionError) e; - } else { - fail(String.format("Async error during test execution: %s", e.getMessage()), e); - } - } - } - - /** If {@code TestEnvironment#printlnDebug} is true, print debug message to std out. */ - public void debug(String msg) { - if (debugEnabled()) { - System.out.printf("[TCK-DEBUG] %s%n", msg); - } - } - - public final boolean debugEnabled() { - return printlnDebug; - } - - /** - * Looks for given {@code method} method in stack trace. - * Can be used to answer questions like "was this method called from onComplete?". - * - * @return the caller's StackTraceElement at which he the looked for method was found in the call stack, EMPTY otherwise - */ - public Optional findCallerMethodInStackTrace(String method) { - final Throwable thr = new Throwable(); // gets the stacktrace - - for (StackTraceElement stackElement : thr.getStackTrace()) { - if (stackElement.getMethodName().equals(method)) { - return Optional.of(stackElement); - } - } - return Optional.empty(); - } - - // ---- classes ---- - - /** - * {@link Subscriber} implementation which can be steered by test code and asserted on. - */ - public static class ManualSubscriber extends TestSubscriber { - Receptacle received; - - public ManualSubscriber(TestEnvironment env) { - super(env); - received = new Receptacle(this.env); - } - - @Override - public void onNext(T element) { - try { - received.add(element); - } catch (IllegalStateException ex) { - // error message refinement - throw new SubscriberBufferOverflowException( - String.format("Received more than bufferSize (%d) onNext signals. " + - "The Publisher probably emited more signals than expected!", - received.QUEUE_SIZE), ex); - } - } - - @Override - public void onComplete() { - received.complete(); - } - - public void request(long elements) { - subscription.value().request(elements); - } - - public T requestNextElement() throws InterruptedException { - return requestNextElement(env.defaultTimeoutMillis()); - } - - public T requestNextElement(long timeoutMillis) throws InterruptedException { - return requestNextElement(timeoutMillis, "Did not receive expected element"); - } - - public T requestNextElement(String errorMsg) throws InterruptedException { - return requestNextElement(env.defaultTimeoutMillis(), errorMsg); - } - - public T requestNextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - return nextElement(timeoutMillis, errorMsg); - } - - public Optional requestNextElementOrEndOfStream() throws InterruptedException { - return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public Optional requestNextElementOrEndOfStream(String errorMsg) throws InterruptedException { - return requestNextElementOrEndOfStream(env.defaultTimeoutMillis(), errorMsg); - } - - public Optional requestNextElementOrEndOfStream(long timeoutMillis) throws InterruptedException { - return requestNextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public Optional requestNextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - return nextElementOrEndOfStream(timeoutMillis, errorMsg); - } - - public void requestEndOfStream() throws InterruptedException { - requestEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public void requestEndOfStream(long timeoutMillis) throws InterruptedException { - requestEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public void requestEndOfStream(String errorMsg) throws InterruptedException { - requestEndOfStream(env.defaultTimeoutMillis(), errorMsg); - } - - public void requestEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - request(1); - expectCompletion(timeoutMillis, errorMsg); - } - - public List requestNextElements(long elements) throws InterruptedException { - request(elements); - return nextElements(elements, env.defaultTimeoutMillis()); - } - - public List requestNextElements(long elements, long timeoutMillis) throws InterruptedException { - request(elements); - return nextElements(elements, timeoutMillis, String.format("Did not receive %d expected elements", elements)); - } - - public List requestNextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - request(elements); - return nextElements(elements, timeoutMillis, errorMsg); - } - - public T nextElement() throws InterruptedException { - return nextElement(env.defaultTimeoutMillis()); - } - - public T nextElement(long timeoutMillis) throws InterruptedException { - return nextElement(timeoutMillis, "Did not receive expected element"); - } - - public T nextElement(String errorMsg) throws InterruptedException { - return nextElement(env.defaultTimeoutMillis(), errorMsg); - } - - public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - return received.next(timeoutMillis, errorMsg); - } - - public Optional nextElementOrEndOfStream() throws InterruptedException { - return nextElementOrEndOfStream(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public Optional nextElementOrEndOfStream(long timeoutMillis) throws InterruptedException { - return nextElementOrEndOfStream(timeoutMillis, "Did not receive expected stream completion"); - } - - public Optional nextElementOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - return received.nextOrEndOfStream(timeoutMillis, errorMsg); - } - - public List nextElements(long elements) throws InterruptedException { - return nextElements(elements, env.defaultTimeoutMillis(), "Did not receive expected element or completion"); - } - - public List nextElements(long elements, String errorMsg) throws InterruptedException { - return nextElements(elements, env.defaultTimeoutMillis(), errorMsg); - } - - public List nextElements(long elements, long timeoutMillis) throws InterruptedException { - return nextElements(elements, timeoutMillis, "Did not receive expected element or completion"); - } - - public List nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - return received.nextN(elements, timeoutMillis, errorMsg); - } - - public void expectNext(T expected) throws InterruptedException { - expectNext(expected, env.defaultTimeoutMillis()); - } - - public void expectNext(T expected, long timeoutMillis) throws InterruptedException { - T received = nextElement(timeoutMillis, "Did not receive expected element on downstream"); - if (!received.equals(expected)) { - env.flop(String.format("Expected element %s on downstream but received %s", expected, received)); - } - } - - public void expectCompletion() throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis(), "Did not receive expected stream completion"); - } - - public void expectCompletion(long timeoutMillis) throws InterruptedException { - expectCompletion(timeoutMillis, "Did not receive expected stream completion"); - } - - public void expectCompletion(String errorMsg) throws InterruptedException { - expectCompletion(env.defaultTimeoutMillis(), errorMsg); - } - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - received.expectCompletion(timeoutMillis, errorMsg); - } - - public void expectErrorWithMessage(Class expected, String requiredMessagePart) throws Exception { - expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis()); - } - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives) throws Exception { - expectErrorWithMessage(expected, requiredMessagePartAlternatives, env.defaultTimeoutMillis(), env.defaultPollTimeoutMillis()); - } - - @SuppressWarnings("ThrowableResultOfMethodCallIgnored") - public void expectErrorWithMessage(Class expected, String requiredMessagePart, long timeoutMillis) throws Exception { - expectErrorWithMessage(expected, Collections.singletonList(requiredMessagePart), timeoutMillis); - } - - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives, long timeoutMillis) throws Exception { - expectErrorWithMessage(expected, requiredMessagePartAlternatives, timeoutMillis, timeoutMillis); - } - - public void expectErrorWithMessage(Class expected, List requiredMessagePartAlternatives, - long totalTimeoutMillis, long pollTimeoutMillis) throws Exception { - final E err = expectError(expected, totalTimeoutMillis, pollTimeoutMillis); - final String message = err.getMessage(); - - boolean contains = false; - for (String requiredMessagePart : requiredMessagePartAlternatives) - if (message.contains(requiredMessagePart)) contains = true; // not short-circuting loop, it is expected to - assertTrue(contains, - String.format("Got expected exception [%s] but missing message part [%s], was: %s", - err.getClass(), "anyOf: " + requiredMessagePartAlternatives, err.getMessage())); - } - - public E expectError(Class expected) throws Exception { - return expectError(expected, env.defaultTimeoutMillis()); - } - - public E expectError(Class expected, long timeoutMillis) throws Exception { - return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis()); - } - - public E expectError(Class expected, String errorMsg) throws Exception { - return expectError(expected, env.defaultTimeoutMillis(), errorMsg); - } - - public E expectError(Class expected, long timeoutMillis, String errorMsg) throws Exception { - return expectError(expected, timeoutMillis, env.defaultPollTimeoutMillis(), errorMsg); - } - - public E expectError(Class expected, long totalTimeoutMillis, long pollTimeoutMillis) throws Exception { - return expectError(expected, totalTimeoutMillis, pollTimeoutMillis, String.format("Expected onError(%s)", expected.getName())); - } - - public E expectError(Class expected, long totalTimeoutMillis, long pollTimeoutMillis, - String errorMsg) throws Exception { - return received.expectError(expected, totalTimeoutMillis, pollTimeoutMillis, errorMsg); - } - - public void expectNone() throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis()); - } - - public void expectNone(String errMsgPrefix) throws InterruptedException { - expectNone(env.defaultNoSignalsTimeoutMillis(), errMsgPrefix); - } - - public void expectNone(long withinMillis) throws InterruptedException { - expectNone(withinMillis, "Did not expect an element but got element"); - } - - public void expectNone(long withinMillis, String errMsgPrefix) throws InterruptedException { - received.expectNone(withinMillis, errMsgPrefix); - } - - } - - public static class ManualSubscriberWithSubscriptionSupport extends ManualSubscriber { - - public ManualSubscriberWithSubscriptionSupport(TestEnvironment env) { - super(env); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (subscription.isCompleted()) { - super.onNext(element); - } else { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - - @Override - public void onComplete() { - if (env.debugEnabled()) { - env.debug(this + "::onComplete()"); - } - if (subscription.isCompleted()) { - super.onComplete(); - } else { - env.flop("Subscriber::onComplete() called before Subscriber::onSubscribe"); - } - } - - @Override - public void onSubscribe(Subscription s) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onSubscribe(%s)", this, s)); - } - if (!subscription.isCompleted()) { - subscription.complete(s); - } else { - env.flop("Subscriber::onSubscribe called on an already-subscribed Subscriber"); - } - } - - @Override - public void onError(Throwable cause) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onError(%s)", this, cause)); - } - if (subscription.isCompleted()) { - super.onError(cause); - } else { - env.flop(cause, String.format("Subscriber::onError(%s) called before Subscriber::onSubscribe", cause)); - } - } - } - - /** - * Similar to {@link org.reactivestreams.tck.TestEnvironment.ManualSubscriberWithSubscriptionSupport} - * but does not accumulate values signalled via onNext, thus it can not be used to assert - * values signalled to this subscriber. Instead it may be used to quickly drain a given publisher. - */ - public static class BlackholeSubscriberWithSubscriptionSupport - extends ManualSubscriberWithSubscriptionSupport { - - public BlackholeSubscriberWithSubscriptionSupport(TestEnvironment env) { - super(env); - } - - @Override - public void onNext(T element) { - if (env.debugEnabled()) { - env.debug(String.format("%s::onNext(%s)", this, element)); - } - if (!subscription.isCompleted()) { - env.flop(String.format("Subscriber::onNext(%s) called before Subscriber::onSubscribe", element)); - } - } - - @Override - public T nextElement(long timeoutMillis, String errorMsg) throws InterruptedException { - throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!"); - } - - @Override - public List nextElements(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - throw new RuntimeException("Can not expect elements from BlackholeSubscriber, use ManualSubscriber instead!"); - } - } - - public static class TestSubscriber implements Subscriber { - final Promise subscription; - - protected final TestEnvironment env; - - public TestSubscriber(TestEnvironment env) { - this.env = env; - subscription = new Promise(env); - } - - @Override - public void onError(Throwable cause) { - env.flop(cause, String.format("Unexpected Subscriber::onError(%s)", cause)); - } - - @Override - public void onComplete() { - env.flop("Unexpected Subscriber::onComplete()"); - } - - @Override - public void onNext(T element) { - env.flop(String.format("Unexpected Subscriber::onNext(%s)", element)); - } - - @Override - public void onSubscribe(Subscription subscription) { - env.flop(String.format("Unexpected Subscriber::onSubscribe(%s)", subscription)); - } - - public void cancel() { - if (subscription.isCompleted()) { - subscription.value().cancel(); - } else { - env.flop("Cannot cancel a subscription before having received it"); - } - } - } - - public static class ManualPublisher implements Publisher { - protected final TestEnvironment env; - - protected long pendingDemand = 0L; - protected Promise> subscriber; - - protected final Receptacle requests; - - protected final Latch cancelled; - - public ManualPublisher(TestEnvironment env) { - this.env = env; - requests = new Receptacle(env); - cancelled = new Latch(env); - subscriber = new Promise>(this.env); - } - - @Override - public void subscribe(Subscriber s) { - if (!subscriber.isCompleted()) { - subscriber.completeImmediatly(s); - - Subscription subs = new Subscription() { - @Override - public void request(long elements) { - requests.add(elements); - } - - @Override - public void cancel() { - cancelled.close(); - } - }; - s.onSubscribe(subs); - - } else { - env.flop("TestPublisher doesn't support more than one Subscriber"); - } - } - - public void sendNext(T element) { - if (subscriber.isCompleted()) { - subscriber.value().onNext(element); - } else { - env.flop("Cannot sendNext before having a Subscriber"); - } - } - - public void sendCompletion() { - if (subscriber.isCompleted()) { - subscriber.value().onComplete(); - } else { - env.flop("Cannot sendCompletion before having a Subscriber"); - } - } - - public void sendError(Throwable cause) { - if (subscriber.isCompleted()) { - subscriber.value().onError(cause); - } else { - env.flop("Cannot sendError before having a Subscriber"); - } - } - - public long expectRequest() throws InterruptedException { - return expectRequest(env.defaultTimeoutMillis()); - } - - public long expectRequest(long timeoutMillis) throws InterruptedException { - long requested = requests.next(timeoutMillis, "Did not receive expected `request` call"); - if (requested <= 0) { - return env.flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested)); - } else { - pendingDemand += requested; - return requested; - } - } - - - public long expectRequest(long timeoutMillis, String errorMessageAddendum) throws InterruptedException { - long requested = requests.next(timeoutMillis, String.format("Did not receive expected `request` call. %s", errorMessageAddendum)); - if (requested <= 0) { - return env.flopAndFail(String.format("Requests cannot be zero or negative but received request(%s)", requested)); - } else { - pendingDemand += requested; - return requested; - } - } - - public void expectExactRequest(long expected) throws InterruptedException { - expectExactRequest(expected, env.defaultTimeoutMillis()); - } - - public void expectExactRequest(long expected, long timeoutMillis) throws InterruptedException { - long requested = expectRequest(timeoutMillis); - if (requested != expected) { - env.flop(String.format("Received `request(%d)` on upstream but expected `request(%d)`", requested, expected)); - } - pendingDemand += requested; - } - - public void expectNoRequest() throws InterruptedException { - expectNoRequest(env.defaultTimeoutMillis()); - } - - public void expectNoRequest(long timeoutMillis) throws InterruptedException { - requests.expectNone(timeoutMillis, "Received an unexpected call to: request: "); - } - - public void expectCancelling() throws InterruptedException { - expectCancelling(env.defaultTimeoutMillis()); - } - - public void expectCancelling(long timeoutMillis) throws InterruptedException { - cancelled.expectClose(timeoutMillis, "Did not receive expected cancelling of upstream subscription"); - } - - public boolean isCancelled() throws InterruptedException { - return cancelled.isClosed(); - } - } - - /** - * Like a CountDownLatch, but resettable and with some convenience methods - */ - public static class Latch { - private final TestEnvironment env; - volatile private CountDownLatch countDownLatch = new CountDownLatch(1); - - public Latch(TestEnvironment env) { - this.env = env; - } - - public void reOpen() { - countDownLatch = new CountDownLatch(1); - } - - public boolean isClosed() { - return countDownLatch.getCount() == 0; - } - - public void close() { - countDownLatch.countDown(); - } - - public void assertClosed(String openErrorMsg) { - if (!isClosed()) { - env.flop(new ExpectedClosedLatchException(openErrorMsg)); - } - } - - public void assertOpen(String closedErrorMsg) { - if (isClosed()) { - env.flop(new ExpectedOpenLatchException(closedErrorMsg)); - } - } - - public void expectClose(String notClosedErrorMsg) throws InterruptedException { - expectClose(env.defaultTimeoutMillis(), notClosedErrorMsg); - } - - public void expectClose(long timeoutMillis, String notClosedErrorMsg) throws InterruptedException { - countDownLatch.await(timeoutMillis, TimeUnit.MILLISECONDS); - if (countDownLatch.getCount() > 0) { - env.flop(String.format("%s within %d ms", notClosedErrorMsg, timeoutMillis)); - } - } - - static final class ExpectedOpenLatchException extends RuntimeException { - public ExpectedOpenLatchException(String message) { - super(message); - } - } - - static final class ExpectedClosedLatchException extends RuntimeException { - public ExpectedClosedLatchException(String message) { - super(message); - } - } - - } - - // simple promise for *one* value, which cannot be reset - public static class Promise { - private final TestEnvironment env; - - public static Promise completed(TestEnvironment env, T value) { - Promise promise = new Promise(env); - promise.completeImmediatly(value); - return promise; - } - - public Promise(TestEnvironment env) { - this.env = env; - } - - private ArrayBlockingQueue abq = new ArrayBlockingQueue(1); - private AtomicReference _value = new AtomicReference(); - - public T value() { - final T value = _value.get(); - if (value != null) { - return value; - } else { - env.flop("Cannot access promise value before completion"); - return null; - } - } - - public boolean isCompleted() { - return _value.get() != null; - } - - /** - * Allows using expectCompletion to await for completion of the value and complete it _then_ - */ - public void complete(T value) { - if (_value.compareAndSet(null, value)) { - // we add the value to the queue such to wake up any expectCompletion which was triggered before complete() was called - abq.add(value); - } else { - env.flop(String.format("Cannot complete a promise more than once! Present value: %s, attempted to set: %s", _value.get(), value)); - } - } - - /** - * Same as complete. - * - * Keeping this method for binary compatibility. - */ - public void completeImmediatly(T value) { - complete(value); - } - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - if (!isCompleted()) { - T val = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (val == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } - } - } - } - - // a "Promise" for multiple values, which also supports "end-of-stream reached" - public static class Receptacle { - final int QUEUE_SIZE = 2 * TEST_BUFFER_SIZE; - private final TestEnvironment env; - - private final ArrayBlockingQueue> abq = new ArrayBlockingQueue>(QUEUE_SIZE); - - private final Latch completedLatch; - - Receptacle(TestEnvironment env) { - this.env = env; - this.completedLatch = new Latch(env); - } - - public void add(T value) { - completedLatch.assertOpen(String.format("Unexpected element %s received after stream completed", value)); - - abq.add(Optional.of(value)); - } - - public void complete() { - completedLatch.assertOpen("Unexpected additional complete signal received!"); - completedLatch.close(); - - abq.add(Optional.empty()); - } - - public T next(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - return env.flopAndFail(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } else if (value.isDefined()) { - return value.get(); - } else { - return env.flopAndFail("Expected element but got end-of-stream"); - } - } - - public Optional nextOrEndOfStream(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - return Optional.empty(); - } - - return value; - } - - /** - * @param timeoutMillis total timeout time for awaiting all {@code elements} number of elements - */ - public List nextN(long elements, long timeoutMillis, String errorMsg) throws InterruptedException { - List result = new LinkedList(); - long remaining = elements; - long deadline = System.currentTimeMillis() + timeoutMillis; - while (remaining > 0) { - long remainingMillis = deadline - System.currentTimeMillis(); - - result.add(next(remainingMillis, errorMsg)); - remaining--; - } - - return result; - } - - - public void expectCompletion(long timeoutMillis, String errorMsg) throws InterruptedException { - Optional value = abq.poll(timeoutMillis, TimeUnit.MILLISECONDS); - - if (value == null) { - env.flop(String.format("%s within %d ms", errorMsg, timeoutMillis)); - } else if (value.isDefined()) { - env.flop(String.format("Expected end-of-stream but got element [%s]", value.get())); - } // else, ok - } - - /** - * @deprecated Deprecated in favor of {@link #expectError(Class, long, long, String)}. - */ - @Deprecated - public E expectError(Class clazz, long timeoutMillis, String errorMsg) throws Exception { - return expectError(clazz, timeoutMillis, timeoutMillis, errorMsg); - } - - @SuppressWarnings("unchecked") - final E expectError(Class clazz, final long totalTimeoutMillis, - long pollTimeoutMillis, - String errorMsg) throws Exception { - long totalTimeoutRemainingNs = MILLISECONDS.toNanos(totalTimeoutMillis); - long timeStampANs = System.nanoTime(); - long timeStampBNs; - - for (;;) { - Thread.sleep(Math.min(pollTimeoutMillis, NANOSECONDS.toMillis(totalTimeoutRemainingNs))); - - if (env.asyncErrors.isEmpty()) { - timeStampBNs = System.nanoTime(); - totalTimeoutRemainingNs =- timeStampBNs - timeStampANs; - timeStampANs = timeStampBNs; - - if (totalTimeoutRemainingNs <= 0) { - return env.flopAndFail(String.format("%s within %d ms", errorMsg, totalTimeoutMillis)); - } - } else { - // ok, there was an expected error - Throwable thrown = env.asyncErrors.remove(0); - - if (clazz.isInstance(thrown)) { - return (E) thrown; - } else { - - return env.flopAndFail(String.format("%s within %d ms; Got %s but expected %s", - errorMsg, totalTimeoutMillis, thrown.getClass().getCanonicalName(), clazz.getCanonicalName())); - } - } - } - } - - public void expectNone(long withinMillis, String errorMsgPrefix) throws InterruptedException { - Thread.sleep(withinMillis); - Optional value = abq.poll(); - - if (value == null) { - // ok - } else if (value.isDefined()) { - env.flop(String.format("%s [%s]", errorMsgPrefix, value.get())); - } else { - env.flop("Expected no element but got end-of-stream"); - } - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java deleted file mode 100644 index 2441a87f20c..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/WithHelperPublisher.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck; - -import org.reactivestreams.Publisher; -import org.reactivestreams.tck.flow.support.Function; -import org.reactivestreams.tck.flow.support.HelperPublisher; -import org.reactivestreams.tck.flow.support.InfiniteHelperPublisher; - -import java.util.concurrent.ExecutorService; - -/** - * Type which is able to create elements based on a seed {@code id} value. - *

- * Simplest implementations will simply return the incoming id as the element. - * - * @param type of element to be delivered to the Subscriber - */ -public abstract class WithHelperPublisher { - - /** ExecutorService to be used by the provided helper {@link org.reactivestreams.Publisher} */ - public abstract ExecutorService publisherExecutorService(); - - /** - * Implement this method to match your expected element type. - * In case of implementing a simple Subscriber which is able to consume any kind of element simply return the - * incoming {@code element} element. - *

- * Sometimes the Subscriber may be limited in what type of element it is able to consume, this you may have to implement - * this method such that the emitted element matches the Subscribers requirements. Simplest implementations would be - * to simply pass in the {@code element} as payload of your custom element, such as appending it to a String or other identifier. - *

- * Warning: This method may be called concurrently by the helper publisher, thus it should be implemented in a - * thread-safe manner. - * - * @return element of the matching type {@code T} that will be delivered to the tested Subscriber - */ - public abstract T createElement(int element); - - /** - * Helper method required for creating the Publisher to which the tested Subscriber will be subscribed and tested against. - *

- * By default an asynchronously signalling Publisher is provided, which will use {@link #createElement(int)} - * to generate elements type your Subscriber is able to consume. - *

- * Sometimes you may want to implement your own custom custom helper Publisher - to validate behaviour of a Subscriber - * when facing a synchronous Publisher for example. If you do, it MUST emit the exact number of elements asked for - * (via the {@code elements} parameter) and MUST also must treat the following numbers of elements in these specific ways: - *

    - *
  • - * If {@code elements} is {@code Long.MAX_VALUE} the produced stream must be infinite. - *
  • - *
  • - * If {@code elements} is {@code 0} the {@code Publisher} should signal {@code onComplete} immediatly. - * In other words, it should represent a "completed stream". - *
  • - *
- */ - @SuppressWarnings("unchecked") - public Publisher createHelperPublisher(long elements) { - final Function mkElement = new Function() { - @Override public T apply(Integer id) throws Throwable { - return createElement(id); - } - }; - - if (elements > Integer.MAX_VALUE) return new InfiniteHelperPublisher(mkElement, publisherExecutorService()); - else return new HelperPublisher(0, (int) elements, mkElement, publisherExecutorService()); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java deleted file mode 100644 index 67bd47d67d4..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowPublisherVerification.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow; - -import org.reactivestreams.Publisher; -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.tck.PublisherVerification; -import org.reactivestreams.tck.TestEnvironment; - -import java.util.concurrent.Flow; - -/** - * Provides tests for verifying a Java 9+ {@link java.util.concurrent.Flow.Publisher} specification rules. - * - * @see java.util.concurrent.Flow.Publisher - */ -public abstract class FlowPublisherVerification extends PublisherVerification { - - public FlowPublisherVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - super(env, publisherReferenceGCTimeoutMillis); - } - - public FlowPublisherVerification(TestEnvironment env) { - super(env); - } - - @Override - final public Publisher createPublisher(long elements) { - final Flow.Publisher flowPublisher = createFlowPublisher(elements); - return FlowAdapters.toPublisher(flowPublisher); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a Publisher for a stream with exactly the given number of elements. - * If `elements` is `Long.MAX_VALUE` the produced stream must be infinite. - */ - public abstract Flow.Publisher createFlowPublisher(long elements); - - @Override - final public Publisher createFailedPublisher() { - final Flow.Publisher failed = createFailedFlowPublisher(); - if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher - else return FlowAdapters.toPublisher(failed); - } - /** - * By implementing this method, additional TCK tests concerning a "failed" publishers will be run. - * - * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you ignore these additional tests, return {@code null} from this method. - */ - public abstract Flow.Publisher createFailedFlowPublisher(); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java deleted file mode 100644 index 810ba85d0ff..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberBlackboxVerification.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow; - -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.Subscriber; -import org.reactivestreams.Subscription; -import org.reactivestreams.tck.SubscriberBlackboxVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberBlackboxVerificationRules; - -import java.util.concurrent.Flow; - -/** - * Provides tests for verifying {@link java.util.concurrent.Flow.Subscriber} and {@link java.util.concurrent.Flow.Subscription} - * specification rules, without any modifications to the tested implementation (also known as "Black Box" testing). - * - * This verification is NOT able to check many of the rules of the spec, and if you want more - * verification of your implementation you'll have to implement {@code org.reactivestreams.tck.SubscriberWhiteboxVerification} - * instead. - * - * @see java.util.concurrent.Flow.Subscriber - * @see java.util.concurrent.Flow.Subscription - */ -public abstract class FlowSubscriberBlackboxVerification extends SubscriberBlackboxVerification - implements SubscriberBlackboxVerificationRules { - - protected FlowSubscriberBlackboxVerification(TestEnvironment env) { - super(env); - } - - @Override - public final void triggerRequest(Subscriber subscriber) { - triggerFlowRequest(FlowAdapters.toFlowSubscriber(subscriber)); - } - /** - * Override this method if the {@link java.util.concurrent.Flow.Subscriber} implementation you are verifying - * needs an external signal before it signals demand to its Publisher. - * - * By default this method does nothing. - */ - public void triggerFlowRequest(Flow.Subscriber subscriber) { - // this method is intentionally left blank - } - - @Override - public final Subscriber createSubscriber() { - return FlowAdapters.toSubscriber(createFlowSubscriber()); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link Flow.Subscriber} instance to be subjected to the testing logic. - */ - abstract public Flow.Subscriber createFlowSubscriber(); - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java deleted file mode 100644 index 9b382700d4f..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/FlowSubscriberWhiteboxVerification.java +++ /dev/null @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow; - -import org.reactivestreams.FlowAdapters; -import org.reactivestreams.Subscriber; -import org.reactivestreams.tck.SubscriberWhiteboxVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; - -import java.util.concurrent.Flow; - -/** - * Provides whitebox style tests for verifying {@link java.util.concurrent.Flow.Subscriber} - * and {@link java.util.concurrent.Flow.Subscription} specification rules. - * - * @see java.util.concurrent.Flow.Subscriber - * @see java.util.concurrent.Flow.Subscription - */ -public abstract class FlowSubscriberWhiteboxVerification extends SubscriberWhiteboxVerification - implements SubscriberWhiteboxVerificationRules { - - protected FlowSubscriberWhiteboxVerification(TestEnvironment env) { - super(env); - } - - @Override - final public Subscriber createSubscriber(WhiteboxSubscriberProbe probe) { - return FlowAdapters.toSubscriber(createFlowSubscriber(probe)); - } - /** - * This is the main method you must implement in your test incarnation. - * It must create a new {@link org.reactivestreams.Subscriber} instance to be subjected to the testing logic. - * - * In order to be meaningfully testable your Subscriber must inform the given - * `WhiteboxSubscriberProbe` of the respective events having been received. - */ - protected abstract Flow.Subscriber createFlowSubscriber(WhiteboxSubscriberProbe probe); -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java deleted file mode 100644 index 20dd71499eb..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/IdentityFlowProcessorVerification.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow; - -import org.reactivestreams.*; -import org.reactivestreams.tck.IdentityProcessorVerification; -import org.reactivestreams.tck.TestEnvironment; -import org.reactivestreams.tck.flow.support.SubscriberWhiteboxVerificationRules; -import org.reactivestreams.tck.flow.support.PublisherVerificationRules; - -import java.util.concurrent.Flow; - -public abstract class IdentityFlowProcessorVerification extends IdentityProcessorVerification - implements SubscriberWhiteboxVerificationRules, PublisherVerificationRules { - - public IdentityFlowProcessorVerification(TestEnvironment env) { - super(env); - } - - public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis) { - super(env, publisherReferenceGCTimeoutMillis); - } - - public IdentityFlowProcessorVerification(TestEnvironment env, long publisherReferenceGCTimeoutMillis, int processorBufferSize) { - super(env, publisherReferenceGCTimeoutMillis, processorBufferSize); - } - - /** - * By implementing this method, additional TCK tests concerning a "failed" Flow publishers will be run. - * - * The expected behaviour of the {@link Flow.Publisher} returned by this method is hand out a subscription, - * followed by signalling {@code onError} on it, as specified by Rule 1.9. - * - * If you want to ignore these additional tests, return {@code null} from this method. - */ - protected abstract Flow.Publisher createFailedFlowPublisher(); - - /** - * This is the main method you must implement in your test incarnation. - * It must create a {@link Flow.Processor}, which simply forwards all stream elements from its upstream - * to its downstream. It must be able to internally buffer the given number of elements. - * - * @param bufferSize number of elements the processor is required to be able to buffer. - */ - protected abstract Flow.Processor createIdentityFlowProcessor(int bufferSize); - - @Override - public final Processor createIdentityProcessor(int bufferSize) { - return FlowAdapters.toProcessor(createIdentityFlowProcessor(bufferSize)); - } - - @Override - public final Publisher createFailedPublisher() { - Flow.Publisher failed = createFailedFlowPublisher(); - if (failed == null) return null; // because `null` means "SKIP" in createFailedPublisher - else return FlowAdapters.toPublisher(failed); - } - -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java deleted file mode 100644 index c3d26a5bdd8..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -public interface Function { - public Out apply(In in) throws Throwable; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java deleted file mode 100644 index 120fd43e694..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/HelperPublisher.java +++ /dev/null @@ -1,54 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -import java.util.Collections; -import java.util.Iterator; -import java.util.concurrent.Executor; - -import org.reactivestreams.example.unicast.AsyncIterablePublisher; - -public class HelperPublisher extends AsyncIterablePublisher { - - public HelperPublisher(final int from, final int to, final Function create, final Executor executor) { - super(new Iterable() { - { if(from > to) throw new IllegalArgumentException("from must be equal or greater than to!"); } - @Override public Iterator iterator() { - return new Iterator() { - private int at = from; - @Override public boolean hasNext() { return at < to; } - @Override public T next() { - if (!hasNext()) return Collections.emptyList().iterator().next(); - else try { - return create.apply(at++); - } catch (Throwable t) { - throw new IllegalStateException(String.format("Failed to create element for id %d!", at - 1), t); - } - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java deleted file mode 100644 index e3cfccb5978..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/InfiniteHelperPublisher.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -import org.reactivestreams.example.unicast.AsyncIterablePublisher; - -import java.util.Iterator; -import java.util.concurrent.Executor; - -public class InfiniteHelperPublisher extends AsyncIterablePublisher { - - public InfiniteHelperPublisher(final Function create, final Executor executor) { - super(new Iterable() { - @Override public Iterator iterator() { - return new Iterator() { - private int at = 0; - - @Override public boolean hasNext() { return true; } - @Override public T next() { - try { - return create.apply(at++); // Wraps around on overflow - } catch (Throwable t) { - throw new IllegalStateException( - String.format("Failed to create element in %s for id %s!", getClass().getSimpleName(), at - 1), t); - } - } - @Override public void remove() { throw new UnsupportedOperationException(); } - }; - } - }, executor); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java deleted file mode 100644 index ee315931f72..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/NonFatal.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - - -/** - * Copy of scala.control.util.NonFatal in order to not depend on scala-library - */ -public class NonFatal { - private NonFatal() { - // no instances, please. - } - - /** - * Returns true if the provided `Throwable` is to be considered non-fatal, or false if it is to be considered fatal - * - * @param t throwable to be matched for fatal-ness - * @return true if is a non-fatal throwable, false otherwise - */ - public static boolean isNonFatal(Throwable t) { - if (t instanceof StackOverflowError) { - // StackOverflowError ok even though it is a VirtualMachineError - return true; - } else if (t instanceof VirtualMachineError || - t instanceof ThreadDeath || - t instanceof InterruptedException || - t instanceof LinkageError) { - // VirtualMachineError includes OutOfMemoryError and other fatal errors - return false; - } else { - return true; - } - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java deleted file mode 100644 index d191fe0a39d..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/Optional.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -import java.util.NoSuchElementException; - -// simplest possible version of Scala's Option type -public abstract class Optional { - - private static final Optional NONE = new Optional() { - @Override - public Object get() { - throw new NoSuchElementException(".get call on None!"); - } - - @Override - public boolean isEmpty() { - return true; - } - }; - - private Optional() { - } - - @SuppressWarnings("unchecked") - public static Optional empty() { - return (Optional) NONE; - } - - @SuppressWarnings("unchecked") - public static Optional of(T it) { - if (it == null) return (Optional) Optional.NONE; - else return new Some(it); - } - - public abstract T get(); - - public abstract boolean isEmpty(); - - public boolean isDefined() { - return !isEmpty(); - } - - public static class Some extends Optional { - private final T value; - - Some(T value) { - this.value = value; - } - - @Override - public T get() { - return value; - } - - @Override - public boolean isEmpty() { - return false; - } - - @Override - public String toString() { - return String.format("Some(%s)", value); - } - } - - @Override - public String toString() { - return "None"; - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java deleted file mode 100644 index 3af007cb9e1..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/PublisherVerificationRules.java +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -/** - * Internal TCK use only. - * Add / Remove tests for PublisherVerification here to make sure that they arre added/removed in the other places. - */ -public interface PublisherVerificationRules { - /** - * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} - * returns a non-negative value. - */ - void required_validate_maxElementsFromPublisher() throws Exception; - /** - * Validates that the override of {@link org.reactivestreams.tck.PublisherVerification#boundedDepthOfOnNextAndRequestRecursion()} - * returns a positive value. - */ - void required_validate_boundedDepthOfOnNextAndRequestRecursion() throws Exception; - /** - * Asks for a {@code Publisher} that should emit exactly one item and complete (both within a - * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()}) - * in response to a request(1). - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} returns zero. - * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
  • - *
  • if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call - * in response to the test subscriber or by default to their upstream,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s),
  • - *
  • if the {@code Publisher} implementation works for a consumer that calls {@code request(1)},
  • - *
  • if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests,
  • - *
  • that the {@code Publisher} implementation does not emit more than the allowed elements (exactly one).
  • - *
- */ - void required_createPublisher1MustProduceAStreamOfExactly1Element() throws Throwable; - /** - * Asks for a {@code Publisher} that should emit exactly three items and complete (all within a - * timeout specified by {@link org.reactivestreams.tck.TestEnvironment#defaultTimeoutMillis()}). - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * The tests requests one-by-one and verifies each single response item arrives in time. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
  • - *
  • if the {@code Publisher} is part of a chain, all elements actually issue a {@code request()} call - * in response to the test subscriber or by default to their upstream,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s),
  • - *
  • if the {@code Publisher} implementation works for a subscriber that calls {@code request(1)} after consuming an item,
  • - *
  • if the {@code Publisher} implementation is able to emit an {@code onComplete} without requests.
  • - *
- */ - void required_createPublisher3MustProduceAStreamOfExactly3Elements() throws Throwable; - /** - * Asks for a {@code Publisher} that responds to a request pattern of 0 (not requesting upfront), 1, 1 and 2 - * in a timely manner. - *

- * Verifies rule: 1.1 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5. - *

- * This test ensures that the {@code Publisher} implementation correctly responds to {@code request()} calls that in - * total are less than the number of elements this {@code Publisher} could emit (thus the completion event won't be emitted). - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void required_spec101_subscriptionRequestMustResultInTheCorrectNumberOfProducedElements() throws Throwable; - /** - * Asks for a short {@code Publisher} and verifies that requesting once and with more than the length (but bounded) results in the - * correct number of items to be emitted (i.e., length 3 and request 10) followed by an {@code onComplete} signal. - *

- * Verifies rule: 1.2 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * This test ensures that the {@code Publisher} implementation can deal with larger requests than the number of items it can produce. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass.
  • - *
- */ - void required_spec102_maySignalLessThanRequestedAndTerminateSubscription() throws Throwable; - /** - * Asks for a short {@code Publisher} (i.e., length 10), repeatedly subscribes to this {@code Publisher}, requests items - * one by one and verifies the {@code Publisher} calls the {@code onXXX} methods non-overlappingly. - *

- * Verifies rule: 1.3 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

- * Note that this test is probabilistic, that is, may not capture any concurrent invocation in a {@code Publisher} implementation. - * Note also that this test is sensitive to cases when a {@code request()} call in {@code onSubscribe()} triggers an asynchronous - * call to the other {@code onXXX} methods. In contrast, the test allows synchronous call chain of - * {@code onSubscribe -> request -> onNext}. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if a {@code request()} call from {@code onSubscribe()} could trigger an asynchronous call to {@code onNext()} and if so, make sure - * such {@code request()} calls are deferred until the call to {@code onSubscribe()} returns normally.
  • - *
- */ - void stochastic_spec103_mustSignalOnMethodsSequentially() throws Throwable; - /** - * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once - * followed by a single call to {@code onError()} without receiving any requests and otherwise - * not throwing any exception. - *

- * Verifies rule: 1.4 - *

- * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null. - *

- * If this test fails, the following could be checked within the error {@code Publisher} implementation: - *

    - *
  • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
  • - *
  • if the {@code Publisher} implementation does signal an {@code onSubscribe} before signalling {@code onError},
  • - *
  • if the {@code Publisher} implementation is able to emit an {@code onError} without requests,
  • - *
  • if the {@code Publisher} is non-empty as this test requires a {@code Publisher} to signal an - * {@code onError} eagerly.
  • - *
- */ - void optional_spec104_mustSignalOnErrorWhenFails() throws Throwable; - /** - * Asks for a short {@code Publisher} (i.e., length 3) and verifies, after requesting one by one, the sequence - * completes normally. - *

- * Verifies rule: 1.5 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * Note that the tests requests 1 after the items have been received and before expecting an {@code onComplete} signal. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
- */ - void required_spec105_mustSignalOnCompleteWhenFiniteStreamTerminates() throws Throwable; - /** - * Asks for an empty {@code Publisher} (i.e., length 0) and verifies it completes in a timely manner. - *

- * Verifies rule: 1.5 - *

- * Note that the tests requests 1 before expecting an {@code onComplete} signal. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • if the {@code Publisher} is non-empty as this test requires a {@code Publisher} without items.
  • - *
- */ - void optional_spec105_emptyStreamMustTerminateBySignallingOnComplete() throws Throwable; - /** - * Currently, this test is skipped because it is unclear this rule can be effectively checked - * on a {@code Publisher} instance without looking into or hooking into the implementation of it. - *

- * Verifies rule: 1.6 - */ - void untested_spec106_mustConsiderSubscriptionCancelledAfterOnErrorOrOnCompleteHasBeenCalled() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and checks if requesting after the terminal event doesn't - * lead to more items or terminal signals to be emitted. - *

- * Verifies rule: 1.7 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

- * The tests requests more items than the expected {@code Publisher} length upfront and some more items after its completion. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • the indication for the terminal state is properly persisted and a request call can't trigger emission of more items or another - * terminal signal.
  • - *
- */ - void required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled() throws Throwable; - /** - * Currently, this test is skipped, although it is possible to validate an error {@code Publisher} along - * the same lines as {@link #required_spec107_mustNotEmitFurtherSignalsOnceOnCompleteHasBeenSignalled()}. - *

- * Verifies rule: 1.7 - */ - void untested_spec107_mustNotEmitFurtherSignalsOnceOnErrorHasBeenSignalled() throws Throwable; - /** - * Currently, this test is skipped because there was no agreement on how to verify its "eventually" requirement. - *

- * Verifies rule: 1.8 - */ - void untested_spec108_possiblyCanceledSubscriptionShouldNotReceiveOnErrorOrOnCompleteSignals() throws Throwable; - /** - * Asks for an empty {@code Publisher} and verifies if {@code onSubscribe} signal was emitted before - * any other {@code onNext}, {@code onError} or {@code onComplete} signal. - *

- * Verifies rule: 1.9 - *

- * Note that this test doesn't request anything, however, an {@code onNext} is not considered as a failure. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, the {@code Subscriber.onSubscribe} is called - * as part of the preparation process (usually before subscribing to other {@code Publisher}s).
  • - *
- */ - void required_spec109_mustIssueOnSubscribeForNonNullSubscriber() throws Throwable; - /** - * Currently, this test is skipped because there is no common agreement on what is to be considered a fatal exception and - * besides, {@code Publisher.subscribe} is only allowed throw a {@code NullPointerException} and any other - * exception would require looking into or hooking into the implementation of the {@code Publisher}. - *

- * Verifies rule: 1.9 - */ - void untested_spec109_subscribeShouldNotThrowNonFatalThrowable() throws Throwable; - /** - * Asks for an empty {@code Publisher} and calls {@code subscribe} on it with {@code null} that should result in - * a {@code NullPointerException} to be thrown. - *

- * Verifies rule: 1.9 - *

- * If this test fails, check if the {@code subscribe()} implementation has an explicit null check (or a method dereference - * on the {@code Subscriber}), especially if the incoming {@code Subscriber} is wrapped or stored to be used later. - */ - void required_spec109_subscribeThrowNPEOnNullSubscriber() throws Throwable; - /** - * Asks for an error {@code Publisher} that should call {@code onSubscribe} exactly once - * followed by a single call to {@code onError()} without receiving any requests. - *

- * Verifies rule: 1.9 - *

- * The test is not executed if {@code PublisherVerification.createErrorPublisher()} returns null. - *

- * The difference between this test and {@link #optional_spec104_mustSignalOnErrorWhenFails()} is that there is - * no explicit verification if exceptions were thrown in addition to the regular {@code onSubscribe+onError} signal pair. - *

- * If this test fails, the following could be checked within the error {@code Publisher} implementation: - *

    - *
  • the {@code Publisher.subscribe(Subscriber)} method has actual implementation,
  • - *
  • in the {@code Publisher.subscribe(Subscriber)} method, if there is an upstream {@code Publisher}, - * that {@code Publisher} is actually subscribed to,
  • - *
  • if the {@code Publisher} implementation is able to emit an {@code onError} without requests,
  • - *
  • if the {@code Publisher} is non-empty as this test expects a {@code Publisher} without items.
  • - *
- */ - void required_spec109_mayRejectCallsToSubscribeIfPublisherIsUnableOrUnwillingToServeThemRejectionMustTriggerOnErrorAfterOnSubscribe() throws Throwable; - /** - * Currently, this test is skipped because enforcing rule §1.10 requires unlimited retention and reference-equal checks on - * all incoming {@code Subscriber} which is generally infeasible, plus reusing the same {@code Subscriber} instance is - * better detected (or ignored) inside {@code Subscriber.onSubscribe} when the method is called multiple times. - *

- * Verifies rule: 1.10 - */ - void untested_spec110_rejectASubscriptionRequestIfTheSameSubscriberSubscribesTwice() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and subscribes to it twice, without consuming with either - * {@code Subscriber} instance - * (i.e., no requests are issued). - *

- * Verifies rule: 1.11 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

- * Note that this test ignores what signals the {@code Publisher} emits. Any exception thrown through non-regular - * means will indicate a skipped test. - */ - void optional_spec111_maySupportMultiSubscribe() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and subscribes to it twice. - * Each {@code Subscriber} requests for 1 element and checks if onNext or onComplete signals was received. - *

- * Verifies rule: 1.11, - * and depends on valid implementation of rule 1.5 - * in order to verify this. - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

- * Any exception thrown through non-regular means will indicate a skipped test. - */ - void optional_spec111_registeredSubscribersMustReceiveOnNextOrOnCompleteSignals() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 5), subscribes 3 {@code Subscriber}s to it, requests with different - * patterns and checks if all 3 received the same events in the same order. - *

- * Verifies rule: 1.11 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 5. - *

- * The request pattern for the first {@code Subscriber} is (1, 1, 2, 1); for the second is (2, 3) and for the third is (3, 1, 1). - *

- * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

- * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingOneByOne() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items - * upfront with each and verifies they all received the same items in the same order (but does not verify they all complete). - *

- * Verifies rule: 1.11 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

- * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfront() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3), subscribes 3 {@code Subscriber}s to it, requests more than the length items - * upfront with each and verifies they all received the same items in the same order followed by an {@code onComplete} signal. - *

- * Verifies rule: 1.11 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * Note that this test requires a {@code Publisher} that always emits the same signals to any {@code Subscriber}, regardless of - * when they subscribe and how they request elements. I.e., a "live" {@code Publisher} emitting the current time would not pass this test. - *

- * Note that this test is optional and may appear skipped even if the behavior should be actually supported by the {@code Publisher}, - * see the skip message for an indication of this. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void optional_spec111_multicast_mustProduceTheSameElementsInTheSameSequenceToAllOfItsSubscribersWhenRequestingManyUpfrontAndCompleteAsExpected() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 6), requests several times from within {@code onSubscribe} and then requests - * one-by-one from {@code onNext}. - *

- * Verifies rule: 3.2 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 6. - *

- * The request pattern is 3 x 1 from within {@code onSubscribe} and one from within each {@code onNext} invocation. - *

- * The test consumes the {@code Publisher} but otherwise doesn't verify the {@code Publisher} completes (however, it checks - * for errors). - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void required_spec302_mustAllowSynchronousRequestCallsFromOnNextAndOnSubscribe() throws Throwable; - /** - * Asks for a {@code Publisher} with length equal to the value returned by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1, - * calls {@code request(1)} externally and then from within {@code onNext} and checks if the stack depth did not increase beyond the - * amount permitted by {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()}. - *

- * Verifies rule: 3.3 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than - * {@link #required_validate_boundedDepthOfOnNextAndRequestRecursion()} plus 1. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the implementation doesn't allow unbounded recursion when {@code request()} is called from within {@code onNext}, i.e., the lack of - * reentrant-safe state machine around the request amount (such as a for loop with a bound on the parameter {@code n} that calls {@code onNext}). - *
- */ - void required_spec303_mustNotAllowUnboundedRecursion() throws Throwable; - /** - * Currently, this test is skipped because a {@code request} could enter into a synchronous computation via {@code onNext} - * legally and otherwise there is no common agreement how to detect such heavy computation reliably. - *

- * Verifies rule: 3.4 - */ - void untested_spec304_requestShouldNotPerformHeavyComputations() throws Exception; - /** - * Currently, this test is skipped because there is no reliable agreed upon way to detect a heavy computation. - *

- * Verifies rule: 3.5 - */ - void untested_spec305_cancelMustNotSynchronouslyPerformHeavyComputation() throws Exception; - /** - * Asks for a short {@code Publisher} (length 3) and verifies that cancelling without requesting anything, then requesting - * items should result in no signals to be emitted. - *

- * Verifies rule: 3.6 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * The post-cancellation request pattern is (1, 1, 1). - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
  • - *
- */ - void required_spec306_afterSubscriptionIsCancelledRequestMustBeNops() throws Throwable; - /** - * Asks for a single-element {@code Publisher} and verifies that without requesting anything, cancelling the sequence - * multiple times should result in no signals to be emitted and should result in an thrown exception. - *

- * Verifies rule: 3.7 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 1. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
  • - *
- */ - void required_spec307_afterSubscriptionIsCancelledAdditionalCancelationsMustBeNops() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a {@code request(0)} which should trigger an {@code onError} call - * with an {@code IllegalArgumentException}. - *

- * Verifies rule: 3.9 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

- * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

- * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
- */ - void required_spec309_requestZeroMustSignalIllegalArgumentException() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should - * trigger an {@code onError} call with an {@code IllegalArgumentException}. - *

- * Verifies rule: 3.9 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

- * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

- * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
- */ - void required_spec309_requestNegativeNumberMustSignalIllegalArgumentException() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 10) and issues a random, negative {@code request()} call which should - * trigger an {@code onError} call with an {@code IllegalArgumentException}. - *

- * Verifies rule: 3.9 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 10. - *

- * Note that this test expects the {@code IllegalArgumentException} being signalled through {@code onError}, not by - * throwing from {@code request()} (which is also forbidden) or signalling the error by any other means (i.e., through the - * {@code Thread.currentThread().getUncaughtExceptionHandler()} for example). - *

- * Note also that requesting and emission may happen concurrently and honoring this rule may require extra coordination within - * the {@code Publisher}. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the {@code Publisher} can emit an {@code onError} in this particular case, even if there was no prior and legal - * {@code request} call and even if the {@code Publisher} would like to emit items first before emitting an {@code onError} - * in general. - *
- */ - void optional_spec309_requestNegativeNumberMaySignalIllegalArgumentExceptionWithSpecificMessage() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 20), requests some items (less than the length), consumes one item then - * cancels the sequence and verifies the publisher emitted at most the requested amount and stopped emitting (or terminated). - *

- * Verifies rule: 3.12 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 20. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
  • - *
- */ - void required_spec312_cancelMustMakeThePublisherToEventuallyStopSignaling() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) requests and consumes one element from it, cancels the {@code Subscription} - * , calls {@code System.gc()} and then checks if all references to the test {@code Subscriber} has been dropped (by checking - * the {@code WeakReference} has been emptied). - *

- * Verifies rule: 3.13 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • the cancellation indicator flag is properly persisted (may require volatile) and checked as part of the signal emission process.
  • - *
  • the {@code Publisher} stores the {@code Subscriber} reference somewhere which is then not cleaned up when the {@code Subscriber} is cancelled. - * Note that this may happen on many code paths in a {@code Publisher}, for example in an emission loop that terminates because of the - * {@code cancel} signal or because reaching a terminal state. Note also that eagerly nulling {@code Subscriber} references may not be necessary - * for this test to pass in case there is a self-contained chain of them (i.e., {@code Publisher.subscribe()} creates a chain of fresh - * {@code Subscriber} instances where each of them only references their downstream {@code Subscriber} thus the chain can get GC'd - * when the reference to the final {@code Subscriber} is dropped). - *
- */ - void required_spec313_cancelMustMakeThePublisherEventuallyDropAllReferencesToTheSubscriber() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it, verifying that the - * {@code Publisher} emits all of its items and completes normally - * and does not keep spinning attempting to fulfill the {@code Long.MAX_VALUE} demand by some means. - *

- * Verifies rule: 3.17 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void required_spec317_mustSupportAPendingElementCountUpToLongMaxValue() throws Throwable; - /** - * Asks for a short {@code Publisher} (length 3) and requests {@code Long.MAX_VALUE} from it in total (split across - * two {@code Long.MAX_VALUE / 2} and one {@code request(1)}), verifying that the - * {@code Publisher} emits all of its items and completes normally. - *

- * Verifies rule: 3.17 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than 3. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts) - * or not properly deducing the number of emitted items from the pending amount,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void required_spec317_mustSupportACumulativePendingElementCountUpToLongMaxValue() throws Throwable; - /** - * Asks for a very long {@code Publisher} (up to {@code Integer.MAX_VALUE}), requests {@code Long.MAX_VALUE - 1} after - * each received item and expects no failure due to a potential overflow in the pending emission count while consuming - * 10 items and cancelling the sequence. - *

- * Verifies rule: 3.17 - *

- * The test is not executed if {@link org.reactivestreams.tck.PublisherVerification#maxElementsFromPublisher()} is less than {@code Integer.MAX_VALUE}. - *

- * The request pattern is one {@code request(1)} upfront and ten {@code request(Long.MAX_VALUE - 1)} after. - *

- * If this test fails, the following could be checked within the {@code Publisher} implementation: - *

    - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Publisher} has some time-delay behavior,
  • - *
  • make sure the {@link #required_createPublisher1MustProduceAStreamOfExactly1Element()} and {@link #required_createPublisher3MustProduceAStreamOfExactly3Elements()} tests pass,
  • - *
  • if the {@code Publisher} implementation considers the cumulative request amount it receives,
  • - *
  • if the {@code Publisher} implements adding individual request amounts together properly (not overflowing into zero or negative pending request amounts) - * or not properly deducing the number of emitted items from the pending amount,
  • - *
  • if the {@code Publisher} doesn't lose any {@code request()} signal and the state transition from idle -> emitting or emitting -> keep emitting works properly.
  • - *
- */ - void required_spec317_mustNotSignalOnErrorWhenPendingAboveLongMaxValue() throws Throwable; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java deleted file mode 100644 index 6526e238621..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBlackboxVerificationRules.java +++ /dev/null @@ -1,395 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -import org.reactivestreams.tck.SubscriberBlackboxVerification; - -/** - * Internal TCK use only. - * Add / Remove tests for SubscriberBlackboxVerification here to make sure that they arre added/removed in the other places. - */ -public interface SubscriberBlackboxVerificationRules { - /** - * Asks for a {@code Subscriber} instance, expects it to call {@code request()} in - * a timely manner and signals as many {@code onNext} items as the very first request - * amount specified by the {@code Subscriber}. - *

- * Verifies rule: 2.1 - *

- * Notes: - *

    - *
  • This test emits the number of items requested thus the {@code Subscriber} implementation - * should not request too much.
  • - *
  • Only the very first {@code request} amount is considered.
  • - *
  • This test doesn't signal {@code onComplete} after the first set of {@code onNext} signals - * has been emitted and may cause resource leak in - * {@code Subscriber}s that expect a finite {@code Publisher}.
  • - *
  • The test ignores cancellation from the {@code Subscriber} and emits the requested amount regardless.
  • - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} requires external stimulus to begin requesting; override the - * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method - * in this case,
  • - *
  • the {@code TestEnvironment} has large enough timeout specified in case the {@code Subscriber} has some time-delay behavior,
  • - *
  • if the {@code Subscriber} requests zero or a negative value in some circumstances,
  • - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onNext} methods. - *
- */ - void required_spec201_blackbox_mustSignalDemandViaSubscriptionRequest() throws Throwable; - /** - * Currently, this test is skipped because there is no agreed upon approach how - * to detect if the {@code Subscriber} really goes async or just responds in - * a timely manner. - *

- * Verifies rule: 2.2 - */ - void untested_spec202_blackbox_shouldAsynchronouslyDispatch() throws Exception; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onComplete} synchronously, - * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s - * {@code onComplete} implementation. - *

- * Verifies rule: 2.3 - *

- * Notes: - *

    - *
  • The test checks for the presensce of method named "onComplete" in the current stacktrace when handling - * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • no calls happen to {@code request} or {@code cancel} in response to an {@code onComplete} - * directly or indirectly,
  • - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
- */ - void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} followed by an {@code onError} synchronously, - * and checks if neither {@code request} nor {@code cancel} was called from within the {@code Subscriber}'s - * {@code onComplete} implementation. - *

- * Verifies rule: 2.3 - *

- * Notes: - *

    - *
  • The test checks for the presensce of method named "onError" in the current stacktrace when handling - * the {@code request} or {@code cancel} calls in the test's own {@code Subscription}. - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • no calls happen to {@code request} or {@code cancel} in response to an {@code onError} - * directly or indirectly,
  • - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
- */ - void required_spec203_blackbox_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable; - /** - * Currently, this test is skipped because there is no way to check what the {@code Subscriber} "considers" - * since rule §2.3 forbids interaction from within the {@code onError} and {@code onComplete} methods. - *

- * Verifies rule: 2.4 - *

- * Notes: - *

    - *
  • It would be possible to check if there was an async interaction with the test's {@code Subscription} - * within a grace period but such check is still not generally decisive.
  • - *
- */ - void untested_spec204_blackbox_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception; - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} twice synchronously and expects the second {@code Subscription} gets - * cancelled in a timely manner and without any calls to its {@code request} method. - *

- * Verifies rule: 2.5 - *

- * Notes: - *

    - *
  • The test doesn't signal any other events than {@code onSubscribe} and may cause resource leak in - * {@code Subscriber}s that expect a finite {@code Publisher}. - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscribe.onSubscribe} implementation actually tries to detect multiple calls to it,
  • - *
  • if the second {@code Subscription} is cancelled asynchronously and that takes longer time than - * the {@code TestEnvironment}'s timeout permits.
  • - *
- */ - void required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Exception; - - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * to make it cancel the {@code Subscription} for some external condition. - *

- * Verifies rule: 2.6 - */ - void untested_spec206_blackbox_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * to issue requests based on external stimulus. - *

- * Verifies rule: 2.7 - */ - void untested_spec207_blackbox_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception; - /** - * Currently, this test is skipped because there is no way to make the {@code Subscriber} implementation - * cancel the test's {@code Subscription} and check the outcome of sending {@code onNext}s after such - * cancel. - *

- * Verifies rule: 2.8 - */ - void untested_spec208_blackbox_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable; - /** - * Asks for a {@code Subscriber}, expects it to request some amount and in turn be able to receive an {@code onComplete} - * synchronously from the {@code request} call without any {@code onNext} signals before that. - *

- * Verifies rule: 2.9 - *

- * Notes: - *

    - *
  • The test ignores cancellation from the {@code Subscriber}.
  • - *
  • Invalid request amounts are ignored by this test.
  • - *
  • Concurrent calls to the test's {@code Subscription.request()} must be externally synchronized, otherwise - * such case results probabilistically in multiple {@code onComplete} calls by the test.
  • - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
  • if the {@code Subscriber} requires external stimulus to begin requesting; override the - * {@link SubscriberBlackboxVerification#triggerRequest(org.reactivestreams.Subscriber)} method - * in this case,
  • - *
- */ - void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable; - /** - * Asks for a {@code Subscriber} and expects it to handle {@code onComplete} independent of whether the {@code Subscriber} - * requests items or not. - *

- * Verifies rule: 2.9 - *

- * Notes: - *

    - *
  • Currently, the test doesn't call {@code onSubscribe} on the {@code Subscriber} which violates §1.9. - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onComplete} methods. - *
- */ - void required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. - *

- * Verifies rule: 2.10 - *

- * Notes: - *

    - *
  • Despite the method name, the test doesn't expect a request signal from {@code Subscriber} and emits the - * {@code onError} signal anyway. - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
- */ - void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable; - - /** - * Asks for a {@code Subscriber}, signals {@code onSubscribe} followed by an {@code onError} synchronously. - *

- * Verifies rule: 2.10 - *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws an unchecked exception from its {@code onSubscribe} or - * {@code onError} methods. - *
- */ - void required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable; - - /** - * Currently, this test is skipped because it would require analyzing what the {@code Subscriber} implementation - * does. - *

- * Verifies rule: 2.11 - */ - void untested_spec211_blackbox_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception; - /** - * Currently, this test is skipped because the test for - * {@link #required_spec205_blackbox_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal §2.5} - * is in a better position to test for handling the reuse of the same {@code Subscriber}. - *

- * Verifies rule: 2.12 - *

- * Notes: - *

    - *
  • In addition to §2.5, this rule could be better verified when testing a {@code Publisher}'s subscription behavior. - *
- */ - void untested_spec212_blackbox_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality() throws Throwable; - /** - * Currently, this test is skipped because it would require more control over the {@code Subscriber} to - * fail internally in response to a set of legal event emissions, not throw any exception from the {@code Subscriber} - * methods and have it cancel the {@code Subscription}. - *

- * Verifies rule: 2.13 - */ - void untested_spec213_blackbox_failingOnSignalInvocation() throws Exception; - /** - * Asks for a {@code Subscriber} and signals an {@code onSubscribe} event with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onSubscribe} method. - *

- * Verifies rule: 2.13 - *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onSubscribe} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
- */ - void required_spec213_blackbox_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a - * {@code onNext} with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onNext} method. - *

- * Verifies rule: 2.13 - *

- * Notes: - *

    - *
  • The test ignores cancellation and requests from the {@code Subscriber} and emits the {@code onNext} - * signal with a {@code null} parameter anyway.
  • - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
- */ - void required_spec213_blackbox_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Asks for a {@code Subscriber}, signals an {@code onSubscribe} event followed by a - * {@code onError} with {@code null} as a parameter and - * expects an immediate {@code NullPointerException} to be thrown by the {@code Subscriber.onError} method. - *

- * Verifies rule: 2.13 - *

- * Notes: - *

    - *
  • The test ignores cancellation from the {@code Subscriber} and emits the {@code onError} - * signal with a {@code null} parameter anyway.
  • - *
- *

- * If this test fails, the following could be checked within the {@code Subscriber} implementation: - *

    - *
  • if the {@code Subscriber} throws a {@code NullPointerException} from its {@code onNext} method - * in response to a {@code null} parameter and not some other unchecked exception or no exception at all. - *
- */ - void required_spec213_blackbox_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - /** - * Currently, this test is skipped because there is no agreed upon way for specifying, enforcing and testing - * a {@code Subscriber} with an arbitrary context. - *

- * Verifies rule: 3.1 - */ - void untested_spec301_blackbox_mustNotBeCalledOutsideSubscriberContext() throws Exception; - /** - * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

- * Verifies rule: 3.8 - */ - void untested_spec308_blackbox_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable; - /** - * Currently, this test is skipped because element production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

- * Verifies rule: 3.10 - *

- * Notes: - *

    - *
  • This could be tested with a synchronous source currently not available within the TCK.
  • - *
- */ - void untested_spec310_blackbox_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception; - /** - * Currently, this test is skipped because signal production is the responsibility of the {@code Publisher} and - * a {@code Subscription} is not expected to be the active element in an established subscription. - *

- * Verifies rule: 3.11 - *

- * Notes: - *

    - *
  • Tests {@link #required_spec209_blackbox_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() §2.9} - * and {@link #required_spec210_blackbox_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() §2.10} are - * supposed to cover this case from the {@code Subscriber's} perspective.
  • - *
- */ - void untested_spec311_blackbox_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception; - /** - * Currently, this test is skipped because it is the responsibility of the {@code Publisher} deal with the case - * that all subscribers have cancelled their subscription. - *

- * Verifies rule: 3.14 - *

- * Notes: - *

    - *
  • The specification lists this as an optional behavior because only some {@code Publisher} implementations - * (most likely {@code Processor}s) would coordinate with multiple {@code Subscriber}s.
  • - *
- */ - void untested_spec314_blackbox_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response - * to an exception thrown from {@code Subscription.cancel}. - *

- * Verifies rule: 3.15 - */ - void untested_spec315_blackbox_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception; - /** - * Currently, this test is skipped because it requires more control over the {@code Subscriber} implementation - * thus there is no way to detect that the {@code Subscriber} called its own {@code onError} method in response - * to an exception thrown from {@code Subscription.request}. - *

- * Verifies rule: 3.16 - */ - void untested_spec316_blackbox_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java deleted file mode 100644 index 822493619cb..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberBufferOverflowException.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -public final class SubscriberBufferOverflowException extends RuntimeException { - public SubscriberBufferOverflowException() { - } - - public SubscriberBufferOverflowException(String message) { - super(message); - } - - public SubscriberBufferOverflowException(String message, Throwable cause) { - super(message, cause); - } - - public SubscriberBufferOverflowException(Throwable cause) { - super(cause); - } -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java deleted file mode 100644 index e8f1e835a06..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/SubscriberWhiteboxVerificationRules.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -/** - * Internal TCK use only. - * Add / Remove tests for PublisherVerificaSubscriberWhiteboxVerification here to make sure that they arre added/removed in the other places. - */ -public interface SubscriberWhiteboxVerificationRules { - void required_exerciseWhiteboxHappyPath() throws Throwable; - void required_spec201_mustSignalDemandViaSubscriptionRequest() throws Throwable; - void untested_spec202_shouldAsynchronouslyDispatch() throws Exception; - void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnComplete() throws Throwable; - void required_spec203_mustNotCallMethodsOnSubscriptionOrPublisherInOnError() throws Throwable; - void untested_spec204_mustConsiderTheSubscriptionAsCancelledInAfterRecievingOnCompleteOrOnError() throws Exception; - void required_spec205_mustCallSubscriptionCancelIfItAlreadyHasAnSubscriptionAndReceivesAnotherOnSubscribeSignal() throws Throwable; - void untested_spec206_mustCallSubscriptionCancelIfItIsNoLongerValid() throws Exception; - void untested_spec207_mustEnsureAllCallsOnItsSubscriptionTakePlaceFromTheSameThreadOrTakeCareOfSynchronization() throws Exception; - void required_spec208_mustBePreparedToReceiveOnNextSignalsAfterHavingCalledSubscriptionCancel() throws Throwable; - void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithPrecedingRequestCall() throws Throwable; - void required_spec209_mustBePreparedToReceiveAnOnCompleteSignalWithoutPrecedingRequestCall() throws Throwable; - void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithPrecedingRequestCall() throws Throwable; - void required_spec210_mustBePreparedToReceiveAnOnErrorSignalWithoutPrecedingRequestCall() throws Throwable; - void untested_spec211_mustMakeSureThatAllCallsOnItsMethodsHappenBeforeTheProcessingOfTheRespectiveEvents() throws Exception; - void untested_spec212_mustNotCallOnSubscribeMoreThanOnceBasedOnObjectEquality_specViolation() throws Throwable; - void untested_spec213_failingOnSignalInvocation() throws Exception; - void required_spec213_onSubscribe_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void required_spec213_onNext_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void required_spec213_onError_mustThrowNullPointerExceptionWhenParametersAreNull() throws Throwable; - void untested_spec301_mustNotBeCalledOutsideSubscriberContext() throws Exception; - void required_spec308_requestMustRegisterGivenNumberElementsToBeProduced() throws Throwable; - void untested_spec310_requestMaySynchronouslyCallOnNextOnSubscriber() throws Exception; - void untested_spec311_requestMaySynchronouslyCallOnCompleteOrOnError() throws Exception; - void untested_spec314_cancelMayCauseThePublisherToShutdownIfNoOtherSubscriptionExists() throws Exception; - void untested_spec315_cancelMustNotThrowExceptionAndMustSignalOnError() throws Exception; - void untested_spec316_requestMustNotThrowExceptionAndMustOnErrorTheSubscriber() throws Exception; -} diff --git a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/TestException.java b/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/TestException.java deleted file mode 100644 index 8b4fbb44406..00000000000 --- a/test/jdk/java/net/httpclient/reactivestreams-tck/org/reactivestreams/tck/flow/support/TestException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright (c) 2019, 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.reactivestreams.tck.flow.support; - -/** - * Exception used by the TCK to signal failures. - * May be thrown or signalled through {@link org.reactivestreams.Subscriber#onError(Throwable)}. - */ -public final class TestException extends RuntimeException { - public TestException() { - super("Test Exception: Boom!"); - } -} From 5c0ff26f321ad36daa34bfc5b2d013b6c4a03810 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Fri, 2 Dec 2022 11:03:53 +0000 Subject: [PATCH 008/494] 8291444: GHA builds/tests won't run manually if disabled from automatic running Reviewed-by: serb, erikj, ihse --- .github/workflows/main.yml | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index ab22d1c7f45..33b8550baf3 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -77,19 +77,17 @@ jobs: # 'false' otherwise. # arg $1: platform name or names to look for function check_platform() { - if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then - # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything - echo 'false' - return - fi - if [[ $GITHUB_EVENT_NAME == workflow_dispatch ]]; then input='${{ github.event.inputs.platforms }}' elif [[ $GITHUB_EVENT_NAME == push ]]; then - input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' - else - echo 'Internal error in GHA' - exit 1 + if [[ '${{ !secrets.JDK_SUBMIT_FILTER || startsWith(github.ref, 'refs/heads/submit/') }}' == 'false' ]]; then + # If JDK_SUBMIT_FILTER is set, and this is not a "submit/" branch, don't run anything + >&2 echo 'JDK_SUBMIT_FILTER is set and not a "submit/" branch' + echo 'false' + return + else + input='${{ secrets.JDK_SUBMIT_PLATFORMS }}' + fi fi normalized_input="$(echo ,$input, | tr -d ' ')" From 1376f330119c832d24a986cc915cb2f82768a02c Mon Sep 17 00:00:00 2001 From: Justin King Date: Fri, 2 Dec 2022 11:31:19 +0000 Subject: [PATCH 009/494] 8297911: Memory leak in JfrUpcalls::on_retransform Reviewed-by: mgronlun --- .../jfrEventClassTransformer.cpp | 29 +++++++++---------- src/hotspot/share/jfr/jni/jfrUpcalls.cpp | 4 +-- 2 files changed, 14 insertions(+), 19 deletions(-) diff --git a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp index 54f056dc432..4e4856b84d5 100644 --- a/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp +++ b/src/hotspot/share/jfr/instrumentation/jfrEventClassTransformer.cpp @@ -1524,22 +1524,19 @@ static ClassFileStream* retransform_bytes(const Klass* existing_klass, const Cla DEBUG_ONLY(JfrJavaSupport::check_java_thread_in_vm(THREAD)); jint size_of_new_bytes = 0; unsigned char* new_bytes = NULL; - { - ResourceMark rm(THREAD); - const ClassFileStream* const stream = parser.clone_stream(); - assert(stream != NULL, "invariant"); - const jclass clazz = static_cast(JfrJavaSupport::local_jni_handle(existing_klass->java_mirror(), THREAD)); - JfrUpcalls::on_retransform(JfrTraceId::load_raw(existing_klass), - clazz, - stream->length(), - stream->buffer(), - &size_of_new_bytes, - &new_bytes, - THREAD); - JfrJavaSupport::destroy_local_jni_handle(clazz); - if (has_pending_exception(THREAD)) { - return NULL; - } + const ClassFileStream* const stream = parser.clone_stream(); + assert(stream != NULL, "invariant"); + const jclass clazz = static_cast(JfrJavaSupport::local_jni_handle(existing_klass->java_mirror(), THREAD)); + JfrUpcalls::on_retransform(JfrTraceId::load_raw(existing_klass), + clazz, + stream->length(), + stream->buffer(), + &size_of_new_bytes, + &new_bytes, + THREAD); + JfrJavaSupport::destroy_local_jni_handle(clazz); + if (has_pending_exception(THREAD)) { + return NULL; } assert(new_bytes != NULL, "invariant"); assert(size_of_new_bytes > 0, "invariant"); diff --git a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp index 673b647e309..480c01ed2fe 100644 --- a/src/hotspot/share/jfr/jni/jfrUpcalls.cpp +++ b/src/hotspot/share/jfr/jni/jfrUpcalls.cpp @@ -141,9 +141,7 @@ void JfrUpcalls::on_retransform(jlong trace_id, CHECK); assert(new_byte_array != NULL, "invariant"); assert(new_bytes_length > 0, "invariant"); - // memory space must be malloced as mtInternal - // as it will be deallocated by JVMTI routines - unsigned char* const new_bytes = (unsigned char* const)os::malloc(new_bytes_length, mtInternal); + unsigned char* const new_bytes = NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, unsigned char, new_bytes_length); if (new_bytes == NULL) { log_error_and_throw_oom(new_bytes_length, THREAD); // unwinds } From b73363fd7b3295635a2ccce0cea72586643c5bb4 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 2 Dec 2022 11:35:15 +0000 Subject: [PATCH 010/494] 8297686: JFR: Improve documentation of EventStream::onMetadata(Consumer) Reviewed-by: mgronlun --- .../classes/jdk/jfr/consumer/EventStream.java | 18 +++++++++++++++ .../jfr/consumer/snippet-files/Snippets.java | 23 ++++++++++++++++++- 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java index 49a0c66c7f2..06f25dd6f61 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/EventStream.java @@ -192,6 +192,15 @@ static EventStream openFile(Path file) throws IOException { * * The event type of an event always arrives sometime before the actual event. * The action must be registered before the stream is started. + *

+ * The following example shows how to listen to new event types, register + * an action if the event type name matches a regular expression and increase a + * counter if a matching event is found. A benefit of using an action per + * event type, instead of the generic {@link #onEvent(Consumer)} method, + * is that a stream implementation can avoid reading events that are of no + * interest. + * + * {@snippet class = "Snippets" region = "EventStreamMetadata"} * * @implSpec The default implementation of this method is empty. * @@ -199,15 +208,24 @@ static EventStream openFile(Path file) throws IOException { * * @throws IllegalStateException if an action is added after the stream has * started + * @since 16 */ default void onMetadata(Consumer action) { } /** * Registers an action to perform on all events in the stream. + *

+ * To perform an action on a subset of event types, consider using + * {@link #onEvent(String, Consumer)} and {@link #onMetadata(Consumer)} as it is + * likely more performant than any selection or filtering mechanism implemented + * in a generic action. * * @param action an action to perform on each {@code RecordedEvent}, not * {@code null} + * + * @see #onEvent(Consumer) + * @see #onMetadata(Consumer) */ void onEvent(Consumer action); diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java index bbff60213c9..0b0ff55e65e 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/snippet-files/Snippets.java @@ -28,6 +28,7 @@ import java.nio.file.Path; import java.nio.file.Paths; import java.time.Duration; +import java.util.regex.Pattern; import java.util.concurrent.atomic.AtomicBoolean; import java.util.stream.Collectors; import jdk.jfr.consumer.EventStream; @@ -36,11 +37,12 @@ import jdk.jfr.consumer.RecordedThread; import jdk.jfr.consumer.RecordingStream; import jdk.jfr.Configuration; +import jdk.jfr.EventType; import jdk.jfr.consumer.RecordedEvent; public class Snippets { - class PackageOveriview { + class PackageOverview { // @start region="PackageOverview" public static void main(String[] args) throws IOException { if (args.length != 1) { @@ -88,6 +90,25 @@ void EventStreamOverview() throws Exception { // @end } + class EventStreamMetadata { + // @start region="EventStreamMetadata" + static long count = 0; + public static void main(String... args) throws IOException { + Path file = Path.of(args[0]); + String regExp = args[1]; + var pr = Pattern.compile(regExp).asMatchPredicate(); + try (var s = EventStream.openFile(file)) { + s.setOrdered(false); + s.onMetadata(metadata -> metadata.getAddedEventTypes() + .stream().map(EventType::getName).filter(pr) + .forEach(eventName -> s.onEvent(eventName, event -> count++))); + s.start(); + System.out.println(count + " events matches " + regExp); + } + } + // @end + } + void RecordingFileOverview() throws Exception { // @start region="RecordingFileOverview" try (RecordingFile recordingFile = new RecordingFile(Paths.get("recording.jfr"))) { From 319faa5afc37df5fd9ce4305e6e38a7bd4b39c65 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Fri, 2 Dec 2022 11:48:28 +0000 Subject: [PATCH 011/494] 8296084: javax/swing/JSpinner/4788637/bug4788637.java fails intermittently on a VM Reviewed-by: tr, serb --- test/jdk/ProblemList.txt | 1 - .../swing/JSpinner/4788637/bug4788637.java | 36 +++++++++++++++---- 2 files changed, 29 insertions(+), 8 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 1c6bc65b894..b66355d49f8 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -649,7 +649,6 @@ javax/swing/JWindow/ShapedAndTranslucentWindows/TranslucentJComboBox.java 802462 # The next test below is an intermittent failure javax/swing/JTree/DnD/LastNodeLowerHalfDrop.java 8159131 linux-all javax/swing/JTree/4633594/JTreeFocusTest.java 7105441 macosx-all -javax/swing/JSpinner/4788637/bug4788637.java 8296084 linux-all javax/swing/AbstractButton/6711682/bug6711682.java 8060765 windows-all,macosx-all javax/swing/JFileChooser/6396844/TwentyThousandTest.java 8198003 generic-all javax/swing/JPopupMenu/6800513/bug6800513.java 7184956 macosx-all diff --git a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java index 597f5962587..3afddc3e37a 100644 --- a/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java +++ b/test/jdk/javax/swing/JSpinner/4788637/bug4788637.java @@ -21,11 +21,16 @@ * questions. */ +import java.io.File; + +import java.awt.image.BufferedImage; +import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Point; import java.awt.Rectangle; import java.awt.Robot; +import java.awt.Toolkit; import java.awt.event.InputEvent; import javax.swing.JFrame; @@ -38,8 +43,10 @@ import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; +import javax.imageio.ImageIO; import static javax.swing.UIManager.getInstalledLookAndFeels; + /** * @test * @bug 4788637 7124307 @@ -52,15 +59,15 @@ public final class bug4788637 { private static JFrame fr; private static Robot robot; - private int step; - private boolean spinnerValueChanged[] = {false, false, false}; + private int step = 0; + private volatile boolean spinnerValueChanged[] = {false, false, false}; - private static Point p; - private static Rectangle rect; + private static volatile Point p; + private static volatile Rectangle rect; public static void main(final String[] args) throws Exception { robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); robot.setAutoWaitForIdle(true); for (final UIManager.LookAndFeelInfo laf : getInstalledLookAndFeels()) { SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); @@ -68,6 +75,7 @@ public static void main(final String[] args) throws Exception { try { SwingUtilities.invokeAndWait(app::createAndShowGUI); robot.waitForIdle(); + robot.delay(1000); SwingUtilities.invokeAndWait(()-> { spinner.requestFocus(); p = spinner.getLocationOnScreen(); @@ -106,9 +114,11 @@ public void stateChanged(ChangeEvent e) { public void start() { try { Thread.sleep(1000); + System.out.println("p " + p + " rect " + rect); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); - robot.mousePress(InputEvent.BUTTON1_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + synchronized (bug4788637.this) { if (!spinnerValueChanged[step]) { bug4788637.this.wait(3000); @@ -123,6 +133,7 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); // Move mouse to the up arrow button robot.mouseMove(p.x+rect.width-3, p.y+3); @@ -132,8 +143,10 @@ public void start() { bug4788637.this.wait(3000); } } + robot.waitForIdle(); - robot.mouseRelease(InputEvent.BUTTON1_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.waitForIdle(); } catch(Throwable t) { throw new RuntimeException(t); } @@ -145,6 +158,15 @@ public void destroy() { if (!spinnerValueChanged[0] || spinnerValueChanged[1] || !spinnerValueChanged[2]) { + System.out.println("!spinnerValueChanged[0] " + !spinnerValueChanged[0] + + " spinnerValueChanged[1] " + spinnerValueChanged[1] + + " !spinnerValueChanged[2] " + !spinnerValueChanged[2]); + try { + Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize(); + Rectangle screen = new Rectangle(0, 0, (int) screenSize.getWidth(), (int) screenSize.getHeight()); + BufferedImage fullScreen = robot.createScreenCapture(screen); + ImageIO.write(fullScreen, "png", new File("fullScreen.png")); + } catch (Exception e) {} throw new Error("JSpinner buttons don't conform to most platform conventions"); } } From 1370228cd718736f0c822d50b85a0b27c8ca40de Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 2 Dec 2022 12:30:29 +0000 Subject: [PATCH 012/494] 8297941: Add override modifier in space.hpp Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/shared/space.hpp | 76 +++++++++++++-------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 466d3ff5748..adeb539a073 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -286,7 +286,7 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { NOT_PRODUCT(_last_explicit_min_done = NULL); } - void do_MemRegion(MemRegion mr); + void do_MemRegion(MemRegion mr) override; void set_min_done(HeapWord* min_done) { _min_done = min_done; @@ -330,8 +330,8 @@ class CompactibleSpace: public Space { CompactibleSpace() : _compaction_top(NULL), _next_compaction_space(NULL) {} - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); - virtual void clear(bool mangle_space); + void initialize(MemRegion mr, bool clear_space, bool mangle_space) override; + void clear(bool mangle_space) override; // Used temporarily during a compaction phase to hold the value // top should have when compaction is complete. @@ -372,7 +372,7 @@ class CompactibleSpace: public Space { // indicates when the next such action should be taken. virtual void prepare_for_compaction(CompactPoint* cp) = 0; // MarkSweep support phase3 - virtual void adjust_pointers(); + void adjust_pointers() override; // MarkSweep support phase4 virtual void compact(); #endif // INCLUDE_SERIALGC @@ -438,8 +438,8 @@ class ContiguousSpace: public CompactibleSpace { ContiguousSpace(); ~ContiguousSpace(); - virtual void initialize(MemRegion mr, bool clear_space, bool mangle_space); - virtual void clear(bool mangle_space); + void initialize(MemRegion mr, bool clear_space, bool mangle_space) override; + void clear(bool mangle_space) override; // Accessors HeapWord* top() const { return _top; } @@ -460,9 +460,9 @@ class ContiguousSpace: public CompactibleSpace { // Mangle regions in the space from the current top up to the // previously mangled part of the space. - void mangle_unused_area() PRODUCT_RETURN; + void mangle_unused_area() override PRODUCT_RETURN; // Mangle [top, end) - void mangle_unused_area_complete() PRODUCT_RETURN; + void mangle_unused_area_complete() override PRODUCT_RETURN; // Do some sparse checking on the area that should have been mangled. void check_mangled_unused_area(HeapWord* limit) PRODUCT_RETURN; @@ -472,25 +472,25 @@ class ContiguousSpace: public CompactibleSpace { // Size computations: sizes in bytes. size_t capacity() const { return byte_size(bottom(), end()); } - size_t used() const { return byte_size(bottom(), top()); } - size_t free() const { return byte_size(top(), end()); } + size_t used() const override { return byte_size(bottom(), top()); } + size_t free() const override { return byte_size(top(), end()); } - virtual bool is_free_block(const HeapWord* p) const; + bool is_free_block(const HeapWord* p) const override; // In a contiguous space we have a more obvious bound on what parts // contain objects. - MemRegion used_region() const { return MemRegion(bottom(), top()); } + MemRegion used_region() const override { return MemRegion(bottom(), top()); } // Allocation (return NULL if full) - virtual HeapWord* allocate(size_t word_size); - virtual HeapWord* par_allocate(size_t word_size); + HeapWord* allocate(size_t word_size) override; + HeapWord* par_allocate(size_t word_size) override; // Iteration - void oop_iterate(OopIterateClosure* cl); - void object_iterate(ObjectClosure* blk); + void oop_iterate(OopIterateClosure* cl) override; + void object_iterate(ObjectClosure* blk) override; // Compaction support - virtual void reset_after_compaction() { + void reset_after_compaction() override { assert(compaction_top() >= bottom() && compaction_top() <= end(), "should point inside space"); set_top(compaction_top()); } @@ -498,7 +498,7 @@ class ContiguousSpace: public CompactibleSpace { // Override. DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, CardTable::PrecisionStyle precision, - HeapWord* boundary); + HeapWord* boundary) override; // Apply "blk->do_oop" to the addresses of all reference fields in objects // starting with the _saved_mark_word, which was noted during a generation's @@ -516,10 +516,10 @@ class ContiguousSpace: public CompactibleSpace { virtual void object_iterate_from(HeapWord* mark, ObjectClosure* blk); // Very inefficient implementation. - virtual HeapWord* block_start_const(const void* p) const; - size_t block_size(const HeapWord* p) const; + HeapWord* block_start_const(const void* p) const override; + size_t block_size(const HeapWord* p) const override; // If a block is in the allocated area, it is an object. - bool block_is_obj(const HeapWord* p) const { return p < top(); } + bool block_is_obj(const HeapWord* p) const override { return p < top(); } // Addresses for inlined allocation HeapWord** top_addr() { return &_top; } @@ -527,18 +527,18 @@ class ContiguousSpace: public CompactibleSpace { #if INCLUDE_SERIALGC // Overrides for more efficient compaction support. - void prepare_for_compaction(CompactPoint* cp); + void prepare_for_compaction(CompactPoint* cp) override; #endif - virtual void print_on(outputStream* st) const; + void print_on(outputStream* st) const override; // Checked dynamic downcasts. - virtual ContiguousSpace* toContiguousSpace() { + ContiguousSpace* toContiguousSpace() override { return this; } // Debugging - virtual void verify() const; + void verify() const override; }; // A dirty card to oop closure for contiguous spaces (ContiguousSpace and @@ -554,9 +554,9 @@ class ContiguousSpace: public CompactibleSpace { class ContiguousSpaceDCTOC : public DirtyCardToOopClosure { // Overrides. void walk_mem_region(MemRegion mr, - HeapWord* bottom, HeapWord* top); + HeapWord* bottom, HeapWord* top) override; - HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj); + HeapWord* get_actual_top(HeapWord* top, HeapWord* top_obj) override; // Walk the given memory region, from bottom to top, applying // the given oop closure to (possibly) all objects found. The @@ -597,25 +597,25 @@ class OffsetTableContigSpace: public ContiguousSpace { OffsetTableContigSpace(BlockOffsetSharedArray* sharedOffsetArray, MemRegion mr); - void set_bottom(HeapWord* value); - void set_end(HeapWord* value); + void set_bottom(HeapWord* value) override; + void set_end(HeapWord* value) override; - void clear(bool mangle_space); + void clear(bool mangle_space) override; - inline HeapWord* block_start_const(const void* p) const; + inline HeapWord* block_start_const(const void* p) const override; // Add offset table update. - virtual inline HeapWord* allocate(size_t word_size); - inline HeapWord* par_allocate(size_t word_size); + inline HeapWord* allocate(size_t word_size) override; + inline HeapWord* par_allocate(size_t word_size) override; // MarkSweep support phase3 - virtual void initialize_threshold(); - virtual void alloc_block(HeapWord* start, HeapWord* end); + void initialize_threshold() override; + void alloc_block(HeapWord* start, HeapWord* end) override; - virtual void print_on(outputStream* st) const; + void print_on(outputStream* st) const override; // Debugging - void verify() const; + void verify() const override; }; @@ -625,7 +625,7 @@ class TenuredSpace: public OffsetTableContigSpace { friend class VMStructs; protected: // Mark sweep support - size_t allowed_dead_ratio() const; + size_t allowed_dead_ratio() const override; public: // Constructor TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, From 227364d5927f94764fdb84f7d0b4c88c8dc25d89 Mon Sep 17 00:00:00 2001 From: Feilong Jiang Date: Fri, 2 Dec 2022 12:48:42 +0000 Subject: [PATCH 013/494] 8297953: Fix several C2 IR matching tests for RISC-V Reviewed-by: fyang, chagedorn --- .../compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java | 2 +- .../c2/irTests/RotateLeftNodeLongIdealizationTests.java | 2 +- test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java | 1 + test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java | 1 + 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java index 5d8b2475ee0..7ec9d98aae0 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeIntIdealizationTests.java @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeIntIdealizationTests - * @requires os.arch == "x86_64" | os.arch == "aarch64" | os.arch == "riscv64" + * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.opt.UseZbb == true) */ public class RotateLeftNodeIntIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java index c9705c8ad64..dcc69d5721a 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/RotateLeftNodeLongIdealizationTests.java @@ -31,7 +31,7 @@ * @summary Test that Ideal transformations of RotateLeftNode* are being performed as expected. * @library /test/lib / * @run driver compiler.c2.irTests.RotateLeftNodeLongIdealizationTests - * @requires os.arch == "x86_64" | os.arch == "aarch64" | os.arch == "riscv64" + * @requires os.arch == "x86_64" | os.arch == "aarch64" | (os.arch == "riscv64" & vm.opt.UseZbb == true) */ public class RotateLeftNodeLongIdealizationTests { diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java index a06cb45d59e..8445c856b4e 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestFPComparison.java @@ -31,6 +31,7 @@ * @summary Test that code generation for fp comparison works as intended * @library /test/lib / * @run driver compiler.c2.irTests.TestFPComparison + * @requires os.arch != "riscv64" */ public class TestFPComparison { static final double[] DOUBLES = new double[] { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 091a5d65425..76b9fdb5c0e 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -139,6 +139,7 @@ public class TestFramework { "UseAVX", "UseSSE", "UseSVE", + "UseZbb", "Xlog", "LogCompilation" ) From df072556a5a155adfe89a2504c2cf680fe4ffac7 Mon Sep 17 00:00:00 2001 From: Magnus Ihse Bursie Date: Fri, 2 Dec 2022 14:00:44 +0000 Subject: [PATCH 014/494] 8297984: Turn on warnings as errors for javadoc Reviewed-by: serb, erikj --- .github/workflows/main.yml | 21 ++++++++++++++++++- make/Docs.gmk | 5 +++++ .../jdk/jfr/consumer/RecordingStream.java | 2 +- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 33b8550baf3..cf6d69afefd 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -35,7 +35,7 @@ on: platforms: description: 'Platform(s) to execute on (comma separated, e.g. "linux-x64, macos, aarch64")' required: true - default: 'linux-x64, linux-x86, linux-x64-variants, linux-cross-compile, macos-x64, macos-aarch64, windows-x64, windows-aarch64' + default: 'linux-x64, linux-x86, linux-x64-variants, linux-cross-compile, macos-x64, macos-aarch64, windows-x64, windows-aarch64, docs' configure-arguments: description: 'Additional configure arguments' required: false @@ -65,6 +65,7 @@ jobs: macos-aarch64: ${{ steps.include.outputs.macos-aarch64 }} windows-x64: ${{ steps.include.outputs.windows-x64 }} windows-aarch64: ${{ steps.include.outputs.windows-aarch64 }} + docs: ${{ steps.include.outputs.docs }} steps: # This function must be inlined in main.yml, or we'd be forced to checkout the repo @@ -116,6 +117,7 @@ jobs: echo "macos-aarch64=$(check_platform macos-aarch64 macos aarch64)" >> $GITHUB_OUTPUT echo "windows-x64=$(check_platform windows-x64 windows x64)" >> $GITHUB_OUTPUT echo "windows-aarch64=$(check_platform windows-aarch64 windows aarch64)" >> $GITHUB_OUTPUT + echo "docs=$(check_platform docs)" >> $GITHUB_OUTPUT ### ### Build jobs @@ -276,6 +278,23 @@ jobs: make-arguments: ${{ github.event.inputs.make-arguments }} if: needs.select.outputs.windows-aarch64 == 'true' + build-docs: + name: docs + needs: select + uses: ./.github/workflows/build-linux.yml + with: + platform: linux-x64 + debug-levels: '[ "debug" ]' + make-target: 'docs-jdk-bundles' + # Make sure we never try to make full docs, since that would require a + # build JDK, and we do not need the additional testing of the graphs. + extra-conf-options: '--disable-full-docs' + gcc-major-version: '10' + apt-gcc-version: '10.4.0-4ubuntu1~22.04' + configure-arguments: ${{ github.event.inputs.configure-arguments }} + make-arguments: ${{ github.event.inputs.make-arguments }} + if: needs.select.outputs.docs == 'true' + ### ### Test jobs ### diff --git a/make/Docs.gmk b/make/Docs.gmk index 0cc5309813f..416a83d2de3 100644 --- a/make/Docs.gmk +++ b/make/Docs.gmk @@ -102,6 +102,10 @@ REFERENCE_TAGS := $(JAVADOC_TAGS) JAVADOC_DISABLED_DOCLINT_WARNINGS := missing JAVADOC_DISABLED_DOCLINT_PACKAGES := org.w3c.* javax.smartcardio +# Allow overriding on the command line +# (intentionally sharing name with the javac option) +JAVA_WARNINGS_ARE_ERRORS ?= -Werror + # The initial set of options for javadoc JAVADOC_OPTIONS := -use -keywords -notimestamp \ -encoding ISO-8859-1 -docencoding UTF-8 -breakiterator \ @@ -333,6 +337,7 @@ define SetupApiDocsGenerationBody # Ignore the doclint warnings in certain packages $1_OPTIONS += -Xdoclint/package:$$(call CommaList, $$(addprefix -, \ $$(JAVADOC_DISABLED_DOCLINT_PACKAGES))) + $1_OPTIONS += $$(JAVA_WARNINGS_ARE_ERRORS) $1_DOC_TITLE := $$($1_LONG_NAME)
Version $$(VERSION_SPECIFICATION) API \ Specification diff --git a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java index 233b7634aa2..c77bbd9a2b9 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/consumer/RecordingStream.java @@ -394,7 +394,7 @@ public void startAsync() { * The following code snippet illustrates how this method can be used in * conjunction with the {@link #startAsync()} method to monitor what happens * during a test method: - *

+ * * {@snippet class="Snippets" region="RecordingStreamStop"} * * @return {@code true} if recording is stopped, {@code false} otherwise From 415cfd2e28e6b7613712ab63a1ab66522e9bf0f2 Mon Sep 17 00:00:00 2001 From: Ashutosh Mehra Date: Fri, 2 Dec 2022 14:22:52 +0000 Subject: [PATCH 015/494] 8297285: Shenandoah pacing causes assertion failure during VM initialization Reviewed-by: rkennke, phh --- src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp index b7553b7125c..208656c6015 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahPacer.cpp @@ -29,6 +29,7 @@ #include "gc/shenandoah/shenandoahPacer.hpp" #include "gc/shenandoah/shenandoahPhaseTimings.hpp" #include "runtime/atomic.hpp" +#include "runtime/javaThread.inline.hpp" #include "runtime/mutexLocker.hpp" #include "runtime/threadSMR.hpp" @@ -241,7 +242,13 @@ void ShenandoahPacer::pace_for_alloc(size_t words) { // Threads that are attaching should not block at all: they are not // fully initialized yet. Blocking them would be awkward. // This is probably the path that allocates the thread oop itself. - if (JavaThread::current()->is_attaching_via_jni()) { + // + // Thread which is not an active Java thread should also not block. + // This can happen during VM init when main thread is still not an + // active Java thread. + JavaThread* current = JavaThread::current(); + if (current->is_attaching_via_jni() || + !current->is_active_Java_thread()) { return; } From 6065696e5df2cde8c313083217ead3417d04c365 Mon Sep 17 00:00:00 2001 From: Leonid Mesnik Date: Fri, 2 Dec 2022 15:11:41 +0000 Subject: [PATCH 016/494] 8297982: Exclude vmTestbase/nsk/monitoring/stress/lowmem/ with ZGC until 8297979 is fixed Reviewed-by: tschatzl --- test/hotspot/jtreg/ProblemList-zgc.txt | 37 ++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 61eb7251fcc..0d8414feba8 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -46,3 +46,40 @@ serviceability/sa/ClhsdbPstack.java#process 8248912 generic- serviceability/sa/ClhsdbPstack.java#core 8248912 generic-all vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64 + +vmTestbase/nsk/monitoring/stress/lowmem/lowmem001/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem002/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem003/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem004/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem005/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem006/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem007/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem008/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem009/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem010/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem011/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem012/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem013/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem014/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem015/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem016/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem017/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem018/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem019/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem020/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem021/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem022/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem023/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem024/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem025/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem026/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem027/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem028/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem029/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem030/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem031/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem032/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem033/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem034/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem035/TestDescription.java 8297979 generic-all +vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 generic-all From 1b924659c87045796f62e66d69ff388b79c4467f Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 2 Dec 2022 17:21:48 +0000 Subject: [PATCH 017/494] 8297608: JFR: Incorrect duration after chunk rotation Reviewed-by: mgronlun --- .../jfr/internal/EventInstrumentation.java | 17 ++--- test/jdk/jdk/jfr/jvm/TestEventDuration.java | 74 +++++++++++++++++++ 2 files changed, 82 insertions(+), 9 deletions(-) create mode 100644 test/jdk/jdk/jfr/jvm/TestEventDuration.java diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java index b562c5739a6..3d02032370a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/EventInstrumentation.java @@ -478,18 +478,20 @@ private void makeInstrumented() { methodVisitor.visitInsn(Opcodes.RETURN); methodVisitor.visitLabel(l0); methodVisitor.visitFrame(Opcodes.F_SAME, 0, null, 0, null); + // long startTime = this.startTime + methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); + methodVisitor.visitFieldInsn(Opcodes.GETFIELD, getInternalClassName(), FIELD_START_TIME, "J"); + methodVisitor.visitVarInsn(Opcodes.LSTORE, 1); // if (startTime == 0) { // startTime = EventWriter.timestamp(); // } else { - methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); - methodVisitor.visitFieldInsn(Opcodes.GETFIELD, getInternalClassName(), FIELD_START_TIME, "J"); + methodVisitor.visitVarInsn(Opcodes.LLOAD, 1); methodVisitor.visitInsn(Opcodes.LCONST_0); methodVisitor.visitInsn(Opcodes.LCMP); Label durationalEvent = new Label(); methodVisitor.visitJumpInsn(Opcodes.IFNE, durationalEvent); - methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, TYPE_EVENT_CONFIGURATION.getInternalName(), METHOD_TIME_STAMP.getName(), METHOD_TIME_STAMP.getDescriptor(), false); - methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, getInternalClassName(), FIELD_START_TIME, "J"); + methodVisitor.visitVarInsn(Opcodes.LSTORE, 1); Label commit = new Label(); methodVisitor.visitJumpInsn(Opcodes.GOTO, commit); // if (duration == 0) { @@ -505,8 +507,7 @@ private void makeInstrumented() { methodVisitor.visitJumpInsn(Opcodes.IFNE, commit); methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); methodVisitor.visitMethodInsn(Opcodes.INVOKESTATIC, TYPE_EVENT_CONFIGURATION.getInternalName(), METHOD_TIME_STAMP.getName(), METHOD_TIME_STAMP.getDescriptor(), false); - methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); - methodVisitor.visitFieldInsn(Opcodes.GETFIELD, getInternalClassName(), FIELD_START_TIME, "J"); + methodVisitor.visitVarInsn(Opcodes.LLOAD, 1); methodVisitor.visitInsn(Opcodes.LSUB); methodVisitor.visitFieldInsn(Opcodes.PUTFIELD, getInternalClassName(), FIELD_DURATION, "J"); methodVisitor.visitLabel(commit); @@ -531,9 +532,7 @@ private void makeInstrumented() { int fieldIndex = 0; methodVisitor.visitInsn(Opcodes.DUP); // stack: [EW] [EW] - methodVisitor.visitVarInsn(Opcodes.ALOAD, 0); - // stack: [EW] [EW] [this] - methodVisitor.visitFieldInsn(Opcodes.GETFIELD, getInternalClassName(), FIELD_START_TIME, "J"); + methodVisitor.visitVarInsn(Opcodes.LLOAD, 1); // stack: [EW] [EW] [long] invokeVirtual(methodVisitor, TYPE_EVENT_WRITER, EventWriterMethod.PUT_LONG.asmMethod); // stack: [EW] diff --git a/test/jdk/jdk/jfr/jvm/TestEventDuration.java b/test/jdk/jdk/jfr/jvm/TestEventDuration.java new file mode 100644 index 00000000000..53a7af9e323 --- /dev/null +++ b/test/jdk/jdk/jfr/jvm/TestEventDuration.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, 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.jvm; + +import jdk.jfr.Event; +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordingFile; +import java.nio.file.Path; + +/** + * @test Tests that the event duration is zero after a chunk rotation + * @key jfr + * @requires vm.hasJFR + * @library /test/lib + * @modules jdk.jfr/jdk.jfr.internal + * @run main/othervm jdk.jfr.jvm.TestEventDuration + */ +public class TestEventDuration { + + static class InstantEvent extends Event { + long id; + } + + public static void main(String... args) throws Exception { + try (Recording r1 = new Recording()) { + r1.start(); + long counter = 0; + for (int i = 0; i < 10; i ++) { + try (Recording r2 = new Recording()) { + r2.start(); + InstantEvent e1 = new InstantEvent(); + e1.id = counter++; + e1.commit(); + InstantEvent e2 = new InstantEvent(); + e2.id = counter++; + e2.commit(); + } + } + Path p = Path.of("dump.jfr"); + r1.dump(p); + var events = RecordingFile.readAllEvents(p); + if (events.isEmpty()) { + throw new AssertionError("Expected at least one event"); + } + events.forEach(System.out::println); + for (var event : events) { + if (event.getDuration().toNanos() != 0) { + throw new AssertionError("Expected all events to have zero duration"); + } + } + } + } +} From fb6fd03233b0eb001e2995d20a079b6af31d2b9b Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 2 Dec 2022 19:09:05 +0000 Subject: [PATCH 018/494] 8291830: jvmti/RedefineClasses/StressRedefine failed: assert(!is_null(v)) failed: narrow klass value can never be zero Reviewed-by: sspitsyn, eosterlund, kbarrett --- src/hotspot/share/classfile/classLoaderData.cpp | 1 + src/hotspot/share/oops/klass.cpp | 8 ++------ src/hotspot/share/oops/klass.hpp | 3 ++- src/hotspot/share/oops/oopHandle.hpp | 6 +++++- src/hotspot/share/prims/jvmtiRedefineClasses.cpp | 8 ++++---- 5 files changed, 14 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/classfile/classLoaderData.cpp b/src/hotspot/share/classfile/classLoaderData.cpp index adb7463b6bf..c09c7023671 100644 --- a/src/hotspot/share/classfile/classLoaderData.cpp +++ b/src/hotspot/share/classfile/classLoaderData.cpp @@ -824,6 +824,7 @@ void ClassLoaderData::add_to_deallocate_list(Metadata* m) { _deallocate_list = new (mtClass) GrowableArray(100, mtClass); } _deallocate_list->append_if_missing(m); + ResourceMark rm; log_debug(class, loader, data)("deallocate added for %s", m->print_value_string()); ClassLoaderDataGraph::set_should_clean_deallocate_lists(); } diff --git a/src/hotspot/share/oops/klass.cpp b/src/hotspot/share/oops/klass.cpp index 521d688833d..00d55fce477 100644 --- a/src/hotspot/share/oops/klass.cpp +++ b/src/hotspot/share/oops/klass.cpp @@ -27,7 +27,7 @@ #include "cds/heapShared.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderDataGraph.inline.hpp" -#include "classfile/javaClasses.hpp" +#include "classfile/javaClasses.inline.hpp" #include "classfile/moduleEntry.hpp" #include "classfile/systemDictionary.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -65,10 +65,6 @@ oop Klass::java_mirror_no_keepalive() const { return _java_mirror.peek(); } -void Klass::replace_java_mirror(oop mirror) { - _java_mirror.replace(mirror); -} - bool Klass::is_cloneable() const { return _access_flags.is_cloneable_fast() || is_subtype_of(vmClasses::Cloneable_klass()); @@ -788,7 +784,7 @@ void Klass::verify_on(outputStream* st) { } if (java_mirror_no_keepalive() != NULL) { - guarantee(oopDesc::is_oop(java_mirror_no_keepalive()), "should be instance"); + guarantee(java_lang_Class::is_instance(java_mirror_no_keepalive()), "should be instance"); } } diff --git a/src/hotspot/share/oops/klass.hpp b/src/hotspot/share/oops/klass.hpp index d624acbcb15..d251c998ebf 100644 --- a/src/hotspot/share/oops/klass.hpp +++ b/src/hotspot/share/oops/klass.hpp @@ -269,7 +269,8 @@ class Klass : public Metadata { void set_archived_java_mirror(oop m) NOT_CDS_JAVA_HEAP_RETURN; // Temporary mirror switch used by RedefineClasses - void replace_java_mirror(oop mirror); + OopHandle java_mirror_handle() const { return _java_mirror; } + void swap_java_mirror_handle(OopHandle& mirror) { _java_mirror.swap(mirror); } // Set java mirror OopHandle to NULL for CDS // This leaves the OopHandle in the CLD, but that's ok, you can't release them. diff --git a/src/hotspot/share/oops/oopHandle.hpp b/src/hotspot/share/oops/oopHandle.hpp index 4a304b968f2..fd4c9679219 100644 --- a/src/hotspot/share/oops/oopHandle.hpp +++ b/src/hotspot/share/oops/oopHandle.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, 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,6 +55,10 @@ class OopHandle { return *this; } + void swap(OopHandle& copy) { + ::swap(_obj, copy._obj); + } + inline oop resolve() const; inline oop peek() const; diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 189a9b12167..9cea6247112 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -1324,7 +1324,7 @@ class RedefineVerifyMark : public StackObj { private: JvmtiThreadState* _state; Klass* _scratch_class; - Handle _scratch_mirror; + OopHandle _scratch_mirror; public: @@ -1332,14 +1332,14 @@ class RedefineVerifyMark : public StackObj { JvmtiThreadState* state) : _state(state), _scratch_class(scratch_class) { _state->set_class_versions_map(the_class, scratch_class); - _scratch_mirror = Handle(_state->get_thread(), _scratch_class->java_mirror()); - _scratch_class->replace_java_mirror(the_class->java_mirror()); + _scratch_mirror = the_class->java_mirror_handle(); // this is a copy that is swapped + _scratch_class->swap_java_mirror_handle(_scratch_mirror); } ~RedefineVerifyMark() { // Restore the scratch class's mirror, so when scratch_class is removed // the correct mirror pointing to it can be cleared. - _scratch_class->replace_java_mirror(_scratch_mirror()); + _scratch_class->swap_java_mirror_handle(_scratch_mirror); _state->clear_class_versions_map(); } }; From 2821fa9883cc9687b53e3bb5655732a614cff8fc Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Fri, 2 Dec 2022 20:16:51 +0000 Subject: [PATCH 019/494] 8280798: com.sun.jdi.ObjectReference::setValue spec should prohibit any final field modification Reviewed-by: alanb, cjplummer, sspitsyn --- .../classes/com/sun/jdi/ObjectReference.java | 6 ++--- .../ObjectReference/setValue/setvalue004.java | 26 +++++++++++++------ .../setValue/setvalue004/TestDescription.java | 5 ++-- .../setValue/setvalue004t.java | 13 +++++++++- 4 files changed, 35 insertions(+), 15 deletions(-) diff --git a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java index f5b8848b484..13662aa252b 100644 --- a/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java +++ b/src/jdk.jdi/share/classes/com/sun/jdi/ObjectReference.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1998, 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1998, 2022, 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 @@ -114,7 +114,7 @@ public interface ObjectReference extends Value { * Sets the value of a given instance or static field in this object. * The {@link Field} must be valid for this ObjectReference; that is, * it must be from the mirrored object's class or a superclass of that class. - * If static, the field must not be final. + * The field must not be final. *

* Object values must be assignment compatible with the field type * (This implies that the field type must be loaded through the @@ -129,7 +129,7 @@ public interface ObjectReference extends Value { * @param field the field containing the requested value * @param value the new value to assign * @throws java.lang.IllegalArgumentException if the field is not valid for - * this object's class. + * this object's class or the field is final. * @throws InvalidTypeException if the value's type does not match * the field's type. * @throws ClassNotLoadedException if 'value' is not null, and the field diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java index 9256f28003e..d14b635c39f 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/ObjectReference/setValue/setvalue004.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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,7 +45,7 @@ * com.sun.jdi.ObjectReference.setValue() * properly throws IllegalArgumentException when a * debugger part of the test attempts to set value of - * debuggee's static field which is declared as final.
+ * debuggee's final field. */ public class setvalue004 { static final String DEBUGGEE_CLASS = @@ -62,8 +62,8 @@ public class setvalue004 { static final String COMMAND_READY = "ready"; static final String COMMAND_QUIT = "quit"; - static final int FLDS_NUM = 9; static final String DEBUGGEE_FLDS[] = { + // static final fields "sByteFld", "sShortFld", "sIntFld", @@ -72,7 +72,17 @@ public class setvalue004 { "sDoubleFld", "sCharFld", "sBooleanFld", - "sStrFld" + "sStrFld", + // instance final fields + "iByteFld", + "iShortFld", + "iIntFld", + "iLongFld", + "iFloatFld", + "iDoubleFld", + "iCharFld", + "iBooleanFld", + "iStrFld" }; private Log log; @@ -141,16 +151,16 @@ private int runIt(String args[], PrintStream out) { rType = objRef.referenceType(); // provoke the IllegalArgumentException - for (int i=0; i Date: Fri, 2 Dec 2022 22:15:27 +0000 Subject: [PATCH 020/494] 8291359: Specification of method j.l.foreign.VaList::skip still deserves clarification Reviewed-by: mcimadamore --- src/java.base/share/classes/java/lang/foreign/VaList.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/java.base/share/classes/java/lang/foreign/VaList.java b/src/java.base/share/classes/java/lang/foreign/VaList.java index 209ae0f8788..872031dcc68 100644 --- a/src/java.base/share/classes/java/lang/foreign/VaList.java +++ b/src/java.base/share/classes/java/lang/foreign/VaList.java @@ -52,6 +52,13 @@ * As such, this interface only supports reading {@code int}, {@code double}, * and any other type that fits into a {@code long}. *

Safety considerations

+ * Accessing a value through a variable argument list using the wrong memory layout will result in undefined behavior. + * For instance, if a variable argument list currently points at a C {@code int} value, then accessing it using + * {@link #nextVarg(ValueLayout.OfLong)} is illegal. Similarly, accessing the variable argument list with + * {@link #skip(MemoryLayout...)}, and providing a layout other than {@link ValueLayout.OfInt} is illegal. + * Any such illegal accesses might not be detected by the implementation, and can corrupt the variable argument list, + * so that the behavior of subsequent accesses is also undefined. + *

* It is possible for clients to access elements outside the spatial bounds of a variable argument list. * Variable argument list implementations will try to detect out-of-bounds reads on a best-effort basis. *

From 6e5470525d5236901c219146f363d4860e6b8008 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 2 Dec 2022 22:29:21 +0000 Subject: [PATCH 021/494] 8295424: adjust timeout for another JLI GetObjectSizeIntrinsicsTest.java subtest 8297367: disable TestRedirectLinks.java in slowdebug mode 8297369: disable Fuzz.java in slowdebug mode Reviewed-by: sspitsyn, jjg, cjplummer, lmesnik --- .../lang/instrument/GetObjectSizeIntrinsicsTest.java | 2 +- test/jdk/jdk/internal/vm/Continuation/Fuzz.java | 7 +++++++ .../javadoc/doclet/testLinkOption/TestRedirectLinks.java | 9 +++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java index 403c8d2d2b4..c80e3304613 100644 --- a/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java +++ b/test/jdk/java/lang/instrument/GetObjectSizeIntrinsicsTest.java @@ -288,7 +288,7 @@ * -Xbatch -XX:TieredStopAtLevel=1 * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large * - * @run main/othervm -Xmx8g + * @run main/othervm/timeout=180 -Xmx8g * -XX:+UnlockDiagnosticVMOptions -XX:+AbortVMOnCompilationFailure -XX:+WhiteBoxAPI -Xbootclasspath/a:. * -Xbatch -XX:-TieredCompilation * -javaagent:basicAgent.jar GetObjectSizeIntrinsicsTest GetObjectSizeIntrinsicsTest large diff --git a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java index 3998891622f..77da319579f 100644 --- a/test/jdk/jdk/internal/vm/Continuation/Fuzz.java +++ b/test/jdk/jdk/internal/vm/Continuation/Fuzz.java @@ -72,6 +72,9 @@ import jdk.test.lib.Utils; import jdk.test.whitebox.WhiteBox; +import jdk.test.lib.Platform; +import jtreg.SkippedException; + public class Fuzz implements Runnable { static final boolean VERIFY_STACK = true; // could add significant time static final boolean FILE = true; @@ -84,6 +87,10 @@ public class Fuzz implements Runnable { static final Path TEST_DIR = Path.of(System.getProperty("test.src", ".")); public static void main(String[] args) { + if (Platform.isSlowDebugBuild() && Platform.isOSX() && Platform.isAArch64()) { + throw new SkippedException("Test is unstable with slowdebug bits " + + "on macosx-aarch64"); + } warmup(); for (int compileLevel : new int[]{4}) { for (boolean compileRun : new boolean[]{true}) { diff --git a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java index ce7192cced9..d123fd2734e 100644 --- a/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java +++ b/test/langtools/jdk/javadoc/doclet/testLinkOption/TestRedirectLinks.java @@ -26,11 +26,14 @@ * @bug 8190312 * @summary test redirected URLs for -link * @library /tools/lib ../../lib + * @library /test/lib * @modules jdk.compiler/com.sun.tools.javac.api * jdk.compiler/com.sun.tools.javac.main * jdk.javadoc/jdk.javadoc.internal.api * jdk.javadoc/jdk.javadoc.internal.tool * @build toolbox.ToolBox toolbox.JavacTask javadoc.tester.* + * @build jtreg.SkippedException + * @build jdk.test.lib.Platform * @run main TestRedirectLinks */ @@ -66,12 +69,18 @@ import toolbox.JavacTask; import toolbox.ToolBox; +import jdk.test.lib.Platform; +import jtreg.SkippedException; + public class TestRedirectLinks extends JavadocTester { /** * The entry point of the test. * @param args the array of command line arguments. */ public static void main(String... args) throws Exception { + if (Platform.isSlowDebugBuild()) { + throw new SkippedException("Test is unstable with slowdebug bits"); + } TestRedirectLinks tester = new TestRedirectLinks(); tester.runTests(); } From 6065516bb3e0e445e9383718f539ec48440d6290 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 2 Dec 2022 22:31:08 +0000 Subject: [PATCH 022/494] 8291418: adjust monitor deflation logging and deflate_idle_monitors use Reviewed-by: dholmes, stuefe, pchilanomate --- src/hotspot/share/runtime/synchronizer.cpp | 20 +++++++++++--------- src/hotspot/share/runtime/vmOperations.cpp | 2 +- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 0c5ea4cd24b..225ae9cc083 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -1497,6 +1497,8 @@ size_t ObjectSynchronizer::deflate_idle_monitors(ObjectMonitorsHashtable* table) // Deflate some idle ObjectMonitors. size_t deflated_count = deflate_monitor_list(current, ls, &timer, table); + size_t unlinked_count = 0; + size_t deleted_count = 0; if (deflated_count > 0 || is_final_audit()) { // There are ObjectMonitors that have been deflated or this is the // final audit and all the remaining ObjectMonitors have been @@ -1506,8 +1508,7 @@ size_t ObjectSynchronizer::deflate_idle_monitors(ObjectMonitorsHashtable* table) // Unlink deflated ObjectMonitors from the in-use list. ResourceMark rm; GrowableArray delete_list((int)deflated_count); - size_t unlinked_count = _in_use_list.unlink_deflated(current, ls, &timer, - &delete_list); + unlinked_count = _in_use_list.unlink_deflated(current, ls, &timer, &delete_list); if (current->is_Java_thread()) { if (ls != NULL) { timer.stop(); @@ -1533,7 +1534,6 @@ size_t ObjectSynchronizer::deflate_idle_monitors(ObjectMonitorsHashtable* table) // After the handshake, safely free the ObjectMonitors that were // deflated in this cycle. - size_t deleted_count = 0; for (ObjectMonitor* monitor: delete_list) { delete monitor; deleted_count++; @@ -1544,13 +1544,14 @@ size_t ObjectSynchronizer::deflate_idle_monitors(ObjectMonitorsHashtable* table) deleted_count, ls, &timer); } } + assert(unlinked_count == deleted_count, "must be"); } if (ls != NULL) { timer.stop(); - if (deflated_count != 0 || log_is_enabled(Debug, monitorinflation)) { - ls->print_cr("deflated " SIZE_FORMAT " monitors in %3.7f secs", - deflated_count, timer.seconds()); + if (deflated_count != 0 || unlinked_count != 0 || log_is_enabled(Debug, monitorinflation)) { + ls->print_cr("deflated_count=" SIZE_FORMAT ", {unlinked,deleted}_count=" SIZE_FORMAT " monitors in %3.7f secs", + deflated_count, unlinked_count, timer.seconds()); } ls->print_cr("end deflating: in_use_list stats: ceiling=" SIZE_FORMAT ", count=" SIZE_FORMAT ", max=" SIZE_FORMAT, in_use_list_ceiling(), _in_use_list.count(), _in_use_list.max()); @@ -1659,17 +1660,18 @@ void ObjectSynchronizer::do_final_audit_and_print_stats() { return; } set_is_final_audit(); + log_info(monitorinflation)("Starting the final audit."); if (log_is_enabled(Info, monitorinflation)) { - // Do a deflation in order to reduce the in-use monitor population + // Do deflations in order to reduce the in-use monitor population // that is reported by ObjectSynchronizer::log_in_use_monitor_details() // which is called by ObjectSynchronizer::audit_and_print_stats(). - while (ObjectSynchronizer::deflate_idle_monitors(/* ObjectMonitorsHashtable is not needed here */ nullptr) >= (size_t)MonitorDeflationMax) { + while (deflate_idle_monitors(/* ObjectMonitorsHashtable is not needed here */ nullptr) > 0) { ; // empty } // The other audit_and_print_stats() call is done at the Debug // level at a safepoint in SafepointSynchronize::do_cleanup_tasks. - ObjectSynchronizer::audit_and_print_stats(true /* on_exit */); + audit_and_print_stats(true /* on_exit */); } } diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index 3e1599b5662..c49cadd0e76 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -287,7 +287,7 @@ void VM_ThreadDump::doit() { // when there are a lot of inflated monitors. So we deflate idle monitors and // gather information about owned monitors at the same time. tablep = &table; - while (ObjectSynchronizer::deflate_idle_monitors(tablep) >= (size_t)MonitorDeflationMax) { + while (ObjectSynchronizer::deflate_idle_monitors(tablep) > 0) { ; /* empty */ } } From 99e2ef49a87fe88212fc2090ec5b5f4b3493025a Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Sat, 3 Dec 2022 04:13:33 +0000 Subject: [PATCH 023/494] 8298054: ProblemList jdk/jfr/api/consumer/recordingstream/TestStop.java Reviewed-by: lmesnik --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index b66355d49f8..666704047c7 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -749,6 +749,7 @@ jdk/jfr/startupargs/TestStartDuration.java 8214685 windows- jdk/jfr/jvm/TestWaste.java 8282427 generic-all jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 jdk/jfr/api/consumer/TestRecordingFileWrite.java 8287699 generic-all +jdk/jfr/api/consumer/recordingstream/TestStop.java 8298043 generic-all ############################################################################ From c67166f1205c1123497a8895c2952c4d9933645e Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Sat, 3 Dec 2022 06:53:56 +0000 Subject: [PATCH 024/494] 8298003: NMT: fatal block printout does not show the correct corruption address Reviewed-by: shade, mbaesken --- src/hotspot/share/services/mallocHeader.inline.hpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/hotspot/share/services/mallocHeader.inline.hpp b/src/hotspot/share/services/mallocHeader.inline.hpp index 6ceefaac78d..5ec37be680b 100644 --- a/src/hotspot/share/services/mallocHeader.inline.hpp +++ b/src/hotspot/share/services/mallocHeader.inline.hpp @@ -55,9 +55,7 @@ inline void MallocHeader::assert_block_integrity() const { char msg[256]; address corruption = NULL; if (!check_block_integrity(msg, sizeof(msg), &corruption)) { - if (corruption != NULL) { - print_block_on_error(tty, (address)this); - } + print_block_on_error(tty, corruption != NULL ? corruption : (address)this); fatal("NMT corruption: Block at " PTR_FORMAT ": %s", p2i(this), msg); } } From 0edb5d08055d8c06ed318a6c32e44a070ab4d002 Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Sun, 4 Dec 2022 12:07:42 +0000 Subject: [PATCH 025/494] 8297683: Use enhanced-for cycle instead of Enumeration in java.security.jgss Reviewed-by: weijun --- .../sun/security/jgss/GSSCredentialImpl.java | 29 ++++--------------- .../sun/security/jgss/ProviderList.java | 10 ++----- 2 files changed, 8 insertions(+), 31 deletions(-) diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java b/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java index 05017638b9e..d6f3816c86b 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/GSSCredentialImpl.java @@ -134,10 +134,7 @@ void init(GSSManagerImpl gssManager) { public void dispose() throws GSSException { if (!destroyed) { - GSSCredentialSpi element; - Enumeration values = hashtable.elements(); - while (values.hasMoreElements()) { - element = values.nextElement(); + for (GSSCredentialSpi element : hashtable.values()) { element.dispose(); } destroyed = true; @@ -211,14 +208,11 @@ public int getRemainingLifetime() throws GSSException { "no longer valid"); } - SearchKey tempKey; GSSCredentialSpi tempCred; int tempLife, tempInitLife, tempAcceptLife; int min = INDEFINITE_LIFETIME; - for (Enumeration e = hashtable.keys(); - e.hasMoreElements(); ) { - tempKey = e.nextElement(); + for (SearchKey tempKey : hashtable.keySet()) { tempCred = hashtable.get(tempKey); if (tempKey.getUsage() == INITIATE_ONLY) tempLife = tempCred.getInitLifetime(); @@ -329,13 +323,10 @@ public int getUsage() throws GSSException { "no longer valid"); } - SearchKey tempKey; boolean initiate = false; boolean accept = false; - for (Enumeration e = hashtable.keys(); - e.hasMoreElements(); ) { - tempKey = e.nextElement(); + for (SearchKey tempKey : hashtable.keySet()) { if (tempKey.getUsage() == INITIATE_ONLY) initiate = true; else if (tempKey.getUsage() == ACCEPT_ONLY) @@ -406,10 +397,7 @@ public Oid[] getMechs() throws GSSException { "no longer valid"); } ArrayList result = new ArrayList(hashtable.size()); - - for (Enumeration e = hashtable.keys(); - e.hasMoreElements(); ) { - SearchKey tempKey = e.nextElement(); + for (SearchKey tempKey : hashtable.keySet()) { result.add(tempKey.getMech()); } return result.toArray(new Oid[0]); @@ -615,14 +603,7 @@ public GSSCredentialSpi getElement(Oid mechOid, boolean initiate) } Set getElements() { - HashSet retVal = - new HashSet<>(hashtable.size()); - Enumeration values = hashtable.elements(); - while (values.hasMoreElements()) { - GSSCredentialSpi o = values.nextElement(); - retVal.add(o); - } - return retVal; + return new HashSet<>(hashtable.values()); } private static String getElementStr(Oid mechOid, int usage) { diff --git a/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java b/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java index 4cce06db1c1..1813cf1c3ea 100644 --- a/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java +++ b/src/java.security.jgss/share/classes/sun/security/jgss/ProviderList.java @@ -32,7 +32,6 @@ import java.util.ArrayList; import java.util.HashSet; import java.util.HashMap; -import java.util.Enumeration; import java.util.Iterator; import sun.security.jgss.spi.*; import sun.security.jgss.wrapper.NativeGSSFactory; @@ -408,12 +407,9 @@ private boolean addAllMechsFromProvider(Provider p) { String prop; boolean retVal = false; - // Get all props for this provider - Enumeration props = p.keys(); - // See if there are any GSS prop's - while (props.hasMoreElements()) { - prop = (String) props.nextElement(); + for (Object o : p.keySet()) { + prop = (String) o; if (isMechFactoryProperty(prop)) { // Ok! This is a GSS provider! try { @@ -428,7 +424,7 @@ private boolean addAllMechsFromProvider(Provider p) { } } } // Processed GSS property - } // while loop + } // for loop return retVal; From 87572d43befd7d868489ba0a2cfefad5cd605ef3 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Sun, 4 Dec 2022 16:37:09 +0000 Subject: [PATCH 026/494] 8298068: ProblemList tests failing due to JDK-8297235 8298070: ProblemList jdk/internal/vm/Continuation/Fuzz.java#default with ZGC on X64 8298071: ProblemList tests failing due to JDK-8298059 8298072: ProblemList compiler/c1/TestPrintC1Statistics.java in Xcomp mode on linux-aarch64 Reviewed-by: azvegint --- test/hotspot/jtreg/ProblemList-Xcomp.txt | 2 + test/hotspot/jtreg/ProblemList-zgc.txt | 3 ++ test/jdk/ProblemList-zgc.txt | 69 +++++++++++++++++++++++- 3 files changed, 73 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList-Xcomp.txt b/test/hotspot/jtreg/ProblemList-Xcomp.txt index d950646a539..3596de61c22 100644 --- a/test/hotspot/jtreg/ProblemList-Xcomp.txt +++ b/test/hotspot/jtreg/ProblemList-Xcomp.txt @@ -38,3 +38,5 @@ serviceability/sa/TestJhsdbJstackMixed.java 8248675 linux-aarch64 serviceability/jvmti/VMObjectAlloc/VMObjectAllocTest.java 8288430 generic-all gc/cslocker/TestCSLocker.java 8293289 generic-x64 + +compiler/c1/TestPrintC1Statistics.java 8298053 linux-aarch64 diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 0d8414feba8..887eb36e0d4 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -83,3 +83,6 @@ vmTestbase/nsk/monitoring/stress/lowmem/lowmem033/TestDescription.java 8297979 g vmTestbase/nsk/monitoring/stress/lowmem/lowmem034/TestDescription.java 8297979 generic-all vmTestbase/nsk/monitoring/stress/lowmem/lowmem035/TestDescription.java 8297979 generic-all vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 generic-all + +vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java 8298059 generic-x64 +vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java 8298059 generic-x64 diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index 076d247637b..f4b2f9ae4e8 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -1,5 +1,5 @@ # -# Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2020, 2022, 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,3 +27,70 @@ # ############################################################################# +java/lang/StackWalker/AcrossThreads.java 8297235 generic-x64 +java/math/BigInteger/BigIntegerParallelMultiplyTest.java 8297235 generic-x64 +java/util/Arrays/SetAllTest.java 8297235 generic-x64 +java/util/Arrays/Sorting.java 8297235 generic-x64 +java/util/Arrays/largeMemory/ParallelPrefix.java 8297235 generic-x64 +java/util/BitSet/stream/BitSetStreamTest.java 8297235 generic-x64 +java/util/Collection/IteratorMicroBenchmark.java 8297235 generic-x64 +java/util/Collections/UnmodifiableMapEntrySet.java 8297235 generic-x64 +java/util/DoubleStreamSums/CompensatedSums.java 8297235 generic-x64 +java/util/Random/RandomTest.java 8297235 generic-x64 +java/util/Scanner/ScannerStreamTest.java 8297235 generic-x64 +java/util/concurrent/forkjoin/AsyncShutdownNow.java 8297235 generic-x64 +java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAny.java 8297235 generic-x64 +java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAnyRace.java 8297235 generic-x64 +java/util/concurrent/forkjoin/Integrate.java 8297235 generic-x64 +java/util/concurrent/forkjoin/NQueensCS.java 8297235 generic-x64 +java/util/concurrent/tck/JSR166TestCase.java 8297235 generic-x64 +java/util/regex/PatternStreamTest.java 8297235 generic-x64 +java/util/stream/CustomFJPoolTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/DoubleNodeTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/FlagOpTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/IntNodeTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/LongNodeTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/NodeTest.java 8297235 generic-x64 +java/util/stream/boottest/java.base/java/util/stream/StreamReuseTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpStatefulTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java 8297235 generic-x64 +java/util/stream/test/org/openjdk/tests/java/util/stream/mapMultiOpTest.java 8297235 generic-x64 + +jdk/internal/vm/Continuation/Fuzz.java#default 8298058 generic-x64 From a71d91b96f7936dd1b84e4c1e167e2e5fa4ad4b1 Mon Sep 17 00:00:00 2001 From: Julian Waters Date: Sun, 4 Dec 2022 17:32:20 +0000 Subject: [PATCH 027/494] 8298067: Persistent test failures after 8296012 Reviewed-by: alanb --- test/langtools/jdk/jshell/Test8296012.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/langtools/jdk/jshell/Test8296012.java b/test/langtools/jdk/jshell/Test8296012.java index 8aa7b2e0ef7..923d7fb400f 100644 --- a/test/langtools/jdk/jshell/Test8296012.java +++ b/test/langtools/jdk/jshell/Test8296012.java @@ -25,6 +25,7 @@ * @test * @bug 8296012 * @summary jshell crashes on mismatched record pattern + * @requires vm.continuations * @build KullaTesting TestingInputStream * @run testng Test8296012 */ @@ -44,4 +45,4 @@ public void test() { public void setUp() { super.setUp(bc -> bc.compilerOptions("--source", System.getProperty("java.specification.version"), "--enable-preview").remoteVMOptions("--enable-preview")); } -} \ No newline at end of file +} From 914ef07fed960f940e1591318b9f00938b37bf09 Mon Sep 17 00:00:00 2001 From: Michal Karm Babacek Date: Mon, 5 Dec 2022 01:59:20 +0000 Subject: [PATCH 028/494] 8297609: Add application/wasm MIME type for wasm file extension Reviewed-by: jpai, michaelm --- .../sun/net/www/content-types.properties | 18 +++++++++++------- .../sun/net/www/content-types.properties | 14 +++++++++----- .../nio/file/Files/probeContentType/Basic.java | 3 ++- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/src/java.base/unix/classes/sun/net/www/content-types.properties b/src/java.base/unix/classes/sun/net/www/content-types.properties index 27e4f4004d9..0dbece5902f 100644 --- a/src/java.base/unix/classes/sun/net/www/content-types.properties +++ b/src/java.base/unix/classes/sun/net/www/content-types.properties @@ -258,8 +258,8 @@ image/webp: \ file_extensions=.webp; text/css: \ - description=CSS File;\ - file_extensions=.css; + description=CSS File;\ + file_extensions=.css; text/html: \ description=HTML Document;\ @@ -267,8 +267,8 @@ text/html: \ icon=html text/javascript: \ - description=JavaScript File;\ - file_extensions=.js; + description=JavaScript File;\ + file_extensions=.js; text/plain: \ description=Plain Text;\ @@ -289,8 +289,8 @@ text/csv: \ file_extensions=.csv; text/markdown: \ - description=Markdown File;\ - file_extensions=.md,.markdown + description=Markdown File;\ + file_extensions=.md,.markdown video/mp4: \ description=MPEG-4 Video;\ @@ -353,7 +353,7 @@ application/vnd.oasis.opendocument.text: \ file_extensions=.odt; application/vnd.ms-excel: \ - description=Microsoft Excel File;\ + description=Microsoft Excel File;\ file_extensions=.xls; application/vnd.openxmlformats-officedocument.spreadsheetml.sheet: \ @@ -395,3 +395,7 @@ application/bz2: \ application/java-archive: \ description=JAR File;\ file_extensions=.jar; + +application/wasm: \ + description=WebAssembly File;\ + file_extensions=.wasm; diff --git a/src/java.base/windows/classes/sun/net/www/content-types.properties b/src/java.base/windows/classes/sun/net/www/content-types.properties index 9e27d3d1af5..dcd2e5843c0 100644 --- a/src/java.base/windows/classes/sun/net/www/content-types.properties +++ b/src/java.base/windows/classes/sun/net/www/content-types.properties @@ -259,8 +259,8 @@ image/webp: \ file_extensions=.webp; text/css: \ - description=CSS File;\ - file_extensions=.css; + description=CSS File;\ + file_extensions=.css; text/html: \ description=HTML Document;\ @@ -290,8 +290,8 @@ text/csv: \ file_extensions=.csv; text/markdown: \ - description=Markdown File;\ - file_extensions=.md,.markdown + description=Markdown File;\ + file_extensions=.md,.markdown video/mp4: \ description=MPEG-4 Video;\ @@ -387,4 +387,8 @@ application/bz2: \ application/java-archive: \ description=JAR File;\ - file_extensions=.jar; + file_extensions=.jar; + +application/wasm: \ + description=WebAssembly File;\ + file_extensions=.wasm; diff --git a/test/jdk/java/nio/file/Files/probeContentType/Basic.java b/test/jdk/java/nio/file/Files/probeContentType/Basic.java index 13cf1d135ad..8bf86320b3f 100644 --- a/test/jdk/java/nio/file/Files/probeContentType/Basic.java +++ b/test/jdk/java/nio/file/Files/probeContentType/Basic.java @@ -22,7 +22,7 @@ */ /* @test - * @bug 4313887 8129632 8129633 8162624 8146215 8162745 8273655 8274171 8287237 + * @bug 4313887 8129632 8129633 8162624 8146215 8162745 8273655 8274171 8287237 8297609 * @summary Unit test for probeContentType method * @library ../.. * @build Basic SimpleFileTypeDetector @@ -187,6 +187,7 @@ public static void main(String[] args) throws IOException { new ExType("xls", List.of("application/vnd.ms-excel")), new ExType("xlsx", List.of("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")), new ExType("7z", List.of("application/x-7z-compressed")), + new ExType("wasm", List.of("application/wasm")), }; failures += checkContentTypes(exTypes); From b49fd920b6690a8b828c85e45c10e5c4c54d2022 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Mon, 5 Dec 2022 03:40:07 +0000 Subject: [PATCH 029/494] 8298055: AArch64: fastdebug build fails after JDK-8247645 Reviewed-by: aph, haosun --- src/hotspot/cpu/aarch64/assembler_aarch64.hpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp index b05c0e800e8..5c0adf45d27 100644 --- a/src/hotspot/cpu/aarch64/assembler_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/assembler_aarch64.hpp @@ -2435,6 +2435,7 @@ void mvnw(Register Rd, Register Rm, break; default: ShouldNotReachHere(); + Rm = 0; // unreachable } starti; From a57392390b0abe5db496775efcc369bafdf420f1 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Mon, 5 Dec 2022 07:09:04 +0000 Subject: [PATCH 030/494] 8297264: C2: Cast node is not processed again in CCP and keeps a wrong too narrow type which is later replaced by top Reviewed-by: thartmann, rcastanedalo, kvn --- src/hotspot/share/opto/phaseX.cpp | 17 +++++ src/hotspot/share/opto/phaseX.hpp | 1 + .../compiler/ccp/TestCastIIWrongTypeCCP.java | 63 +++++++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/ccp/TestCastIIWrongTypeCCP.java diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index 425a93e8bb5..a22a20d1371 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1847,6 +1847,7 @@ void PhaseCCP::push_more_uses(Unique_Node_List& worklist, Node* parent, const No push_counted_loop_phi(worklist, parent, use); push_loadp(worklist, use); push_and(worklist, parent, use); + push_cast_ii(worklist, parent, use); } @@ -1950,6 +1951,22 @@ void PhaseCCP::push_and(Unique_Node_List& worklist, const Node* parent, const No } } +// CastII::Value() optimizes CmpI/If patterns if the right input of the CmpI has a constant type. If the CastII input is +// the same node as the left input into the CmpI node, the type of the CastII node can be improved accordingly. Add the +// CastII node back to the worklist to re-apply Value() to either not miss this optimization or to undo it because it +// cannot be applied anymore. We could have optimized the type of the CastII before but now the type of the right input +// of the CmpI (i.e. 'parent') is no longer constant. The type of the CastII must be widened in this case. +void PhaseCCP::push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const { + if (use->Opcode() == Op_CmpI && use->in(2) == parent) { + Node* other_cmp_input = use->in(1); + for (DUIterator_Fast imax, i = other_cmp_input->fast_outs(imax); i < imax; i++) { + Node* cast_ii = other_cmp_input->fast_out(i); + if (cast_ii->is_CastII()) { + push_if_not_bottom_type(worklist, cast_ii); + } + } + } +} //------------------------------do_transform----------------------------------- // Top level driver for the recursive transformer diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index 3c4f4e2a71b..c51aed5b762 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -595,6 +595,7 @@ class PhaseCCP : public PhaseIterGVN { void push_loadp(Unique_Node_List& worklist, const Node* use) const; static void push_load_barrier(Unique_Node_List& worklist, const BarrierSetC2* barrier_set, const Node* use); void push_and(Unique_Node_List& worklist, const Node* parent, const Node* use) const; + void push_cast_ii(Unique_Node_List& worklist, const Node* parent, const Node* use) const; public: PhaseCCP( PhaseIterGVN *igvn ); // Compute conditional constants diff --git a/test/hotspot/jtreg/compiler/ccp/TestCastIIWrongTypeCCP.java b/test/hotspot/jtreg/compiler/ccp/TestCastIIWrongTypeCCP.java new file mode 100644 index 00000000000..976e85133f1 --- /dev/null +++ b/test/hotspot/jtreg/compiler/ccp/TestCastIIWrongTypeCCP.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, 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 8297264 + * @summary Test that CastII nodes are added to the CCP worklist if they could have been + * optimized due to a CmpI/If pattern. + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.ccp.TestCastIIWrongTypeCCP::* + * compiler.ccp.TestCastIIWrongTypeCCP + */ +package compiler.ccp; + +public class TestCastIIWrongTypeCCP { + + static int x; + + public static void main(String[] args) { + test(); + } + + static void test() { + int iArr[] = new int[400]; + int i = 0; + do { + for (int i5 = 1; i5 < 4; i5++) { + for (int i9 = 2; i9 > i5; i9 -= 3) { + if (x != 0) { + A.unloaded(); // unloaded UCT + } + x = 1; + iArr[5] = 1; + } + } + i++; + } while (i < 10000); + } +} + +class A { + public static void unloaded() { + } +} From 3b3bbe5487c0d86305f953528884b1ee78ca359f Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Mon, 5 Dec 2022 07:10:31 +0000 Subject: [PATCH 031/494] 8296907: VMError: add optional callstacks, siginfo for secondary errors Reviewed-by: aboldtch, rschmelter --- src/hotspot/share/runtime/globals.hpp | 3 + src/hotspot/share/utilities/debug.cpp | 4 +- src/hotspot/share/utilities/vmError.cpp | 57 +++++++++++----- src/hotspot/share/utilities/vmError.hpp | 5 +- .../ErrorHandling/SecondaryErrorTest.java | 67 +++++++++++++++---- 5 files changed, 102 insertions(+), 34 deletions(-) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index f54f59494e8..ab64c9bc6a1 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -517,6 +517,9 @@ const int ObjectAlignmentInBytes = 8; "error log in case of a crash.") \ range(0, (uint64_t)max_jlong/1000) \ \ + product(bool, ErrorLogSecondaryErrorDetails, false, DIAGNOSTIC, \ + "If enabled, show details on secondary crashes in the error log") \ + \ develop(intx, TraceDwarfLevel, 0, \ "Debug levels for the dwarf parser") \ range(0, 4) \ diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 30fc75736da..3fc8cb9acbc 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -745,7 +745,7 @@ extern "C" JNIEXPORT void pns(void* sp, void* fp, void* pc) { // print native st Thread* t = Thread::current_or_null(); // Call generic frame constructor (certain arguments may be ignored) frame fr(sp, fp, pc); - VMError::print_native_stack(tty, fr, t, false, buf, sizeof(buf)); + VMError::print_native_stack(tty, fr, t, false, -1, buf, sizeof(buf)); } // @@ -765,7 +765,7 @@ extern "C" JNIEXPORT void pns2() { // print native stack } else { Thread* t = Thread::current_or_null(); frame fr = os::current_frame(); - VMError::print_native_stack(tty, fr, t, false, buf, sizeof(buf)); + VMError::print_native_stack(tty, fr, t, false, -1, buf, sizeof(buf)); } } #endif diff --git a/src/hotspot/share/utilities/vmError.cpp b/src/hotspot/share/utilities/vmError.cpp index 345548c0a26..35168589636 100644 --- a/src/hotspot/share/utilities/vmError.cpp +++ b/src/hotspot/share/utilities/vmError.cpp @@ -347,14 +347,14 @@ static frame next_frame(frame fr, Thread* t) { } } -void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, bool print_source_info, char* buf, int buf_size) { +void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, bool print_source_info, int max_frames, char* buf, int buf_size) { // see if it's a valid frame if (fr.pc()) { st->print_cr("Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)"); - + const int limit = max_frames == -1 ? StackPrintLimit : MIN2(max_frames, (int)StackPrintLimit); int count = 0; - while (count++ < StackPrintLimit) { + while (count++ < limit) { fr.print_on_error(st, buf, buf_size); if (fr.pc()) { // print source file and line, if available char filename[128]; @@ -374,11 +374,10 @@ void VMError::print_native_stack(outputStream* st, frame fr, Thread* t, bool pri } } - if (count > StackPrintLimit) { + if (count > limit) { st->print_cr("......"); } - st->cr(); } } @@ -818,7 +817,7 @@ void VMError::report(outputStream* st, bool _verbose) { frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); - print_native_stack(st, fr, _thread, true, buf, sizeof(buf)); + print_native_stack(st, fr, _thread, true, -1, buf, sizeof(buf)); _print_native_stack_used = true; } print_native_stack_succeeded = true; @@ -827,7 +826,7 @@ void VMError::report(outputStream* st, bool _verbose) { st->cr(); st->print_cr("Retrying call stack printing without source information..."); frame fr = _context ? os::fetch_frame_from_context(_context) : os::current_frame(); - print_native_stack(st, fr, _thread, false, buf, sizeof(buf)); + print_native_stack(st, fr, _thread, false, -1, buf, sizeof(buf)); _print_native_stack_used = true; STEP_IF("printing Java stack", _verbose && _thread && _thread->is_Java_thread()) @@ -1501,27 +1500,49 @@ void VMError::report_and_die(int id, const char* message, const char* detail_fmt // Watcherthread is about to call os::die. Lets just wait. os::infinite_sleep(); } else { - // Crash or assert during error reporting. Lets continue reporting with the next step. - stringStream ss(buffer, sizeof(buffer)); + // A secondary error happened. Print brief information, but take care, since crashing + // here would just recurse endlessly. + // Any information (signal, context, siginfo etc) printed here should use the function + // arguments, not the information stored in *this, since those describe the primary crash. + static char tmp[256]; // cannot use global scratch buffer // Note: this string does get parsed by a number of jtreg tests, // see hotspot/jtreg/runtime/ErrorHandling. - ss.print("[error occurred during error reporting (%s), id 0x%x", + st->print("[error occurred during error reporting (%s), id 0x%x", _current_step_info, id); - char signal_name[64]; - if (os::exception_name(id, signal_name, sizeof(signal_name))) { - ss.print(", %s (0x%x) at pc=" PTR_FORMAT, signal_name, id, p2i(pc)); + if (os::exception_name(id, tmp, sizeof(tmp))) { + st->print(", %s (0x%x) at pc=" PTR_FORMAT, tmp, id, p2i(pc)); } else { if (should_report_bug(id)) { - ss.print(", Internal Error (%s:%d)", + st->print(", Internal Error (%s:%d)", filename == NULL ? "??" : filename, lineno); } else { - ss.print(", Out of Memory Error (%s:%d)", + st->print(", Out of Memory Error (%s:%d)", filename == NULL ? "??" : filename, lineno); } } - ss.print("]"); - st->print_raw_cr(buffer); - st->cr(); + st->print_cr("]"); + if (ErrorLogSecondaryErrorDetails) { + static bool recursed = false; + if (!recursed) { + recursed = true; + // Print even more information for secondary errors. This may generate a lot of output + // and possibly disturb error reporting, therefore its optional and only available in debug builds. + if (siginfo != nullptr) { + st->print("["); + os::print_siginfo(st, siginfo); + st->print_cr("]"); + } + st->print("[stack: "); + frame fr = context ? os::fetch_frame_from_context(context) : os::current_frame(); + // Subsequent secondary errors build up stack; to avoid flooding the hs-err file with irrelevant + // call stacks, limit the stack we print here (we are only interested in what happened before the + // last assert/fault). + const int max_stack_size = 15; + print_native_stack(st, fr, _thread, true, max_stack_size, tmp, sizeof(tmp)); + st->print_cr("]"); + } // !recursed + recursed = false; // Note: reset outside !recursed + } } } } diff --git a/src/hotspot/share/utilities/vmError.hpp b/src/hotspot/share/utilities/vmError.hpp index 4afd9d3a5c5..402e0d0e396 100644 --- a/src/hotspot/share/utilities/vmError.hpp +++ b/src/hotspot/share/utilities/vmError.hpp @@ -105,8 +105,11 @@ class VMError : public AllStatic { // public for use by the internal non-product debugger. NOT_PRODUCT(public:) + // print_source_info: if true, we try to resolve the source information on platforms that support it + // (useful but may slow down, timeout or misfunction in error situations) + // max_frames: if not -1, overrides StackPrintLimit static void print_native_stack(outputStream* st, frame fr, Thread* t, bool print_source_info, - char* buf, int buf_size); + int max_frames, char* buf, int buf_size); NOT_PRODUCT(private:) static const char* get_filename_only() { diff --git a/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java b/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java index 59325adc9f8..2a3ddd808e9 100644 --- a/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java +++ b/test/hotspot/jtreg/runtime/ErrorHandling/SecondaryErrorTest.java @@ -25,21 +25,28 @@ /* * @test - * @bug 8065895 - * @summary Synchronous signals during error reporting may terminate or hang VM process + * @summary Check secondary error handling * @library /test/lib * @requires vm.debug * @requires os.family != "windows" - * @author Thomas Stuefe (SAP) * @modules java.base/jdk.internal.misc * java.management - * @run driver SecondaryErrorTest + * @run driver SecondaryErrorTest no_callstacks + */ + +/* + * @test + * @summary Check secondary error handling + * @library /test/lib + * @requires vm.debug + * @requires os.family != "windows" + * @modules java.base/jdk.internal.misc + * java.management + * @run driver SecondaryErrorTest with_callstacks */ -import java.io.BufferedReader; import java.io.File; -import java.io.FileInputStream; -import java.io.InputStreamReader; +import java.util.ArrayList; import java.util.regex.Pattern; import jdk.test.lib.process.OutputAnalyzer; @@ -49,12 +56,35 @@ public class SecondaryErrorTest { public static void main(String[] args) throws Exception { + + boolean with_callstacks = false; + if (args.length != 1) { + throw new IllegalArgumentException("Missing argument"); + } else if (args[0].equals("with_callstacks")) { + with_callstacks = true; + } else if (args[0].equals("no_callstacks")) { + with_callstacks = false; + } else { + throw new IllegalArgumentException("unknown argument (" + args[0] + ")"); + } + + // How this works: + // The test will fault with SIGFPE (ErrorHandlerTest=15) and then, during error handling, + // fault twice with SIGSEGV (TestCrashInErrorHandler=14). The point is not only to test + // secondary crashes, but secondary crashes with a *different* error signal. This should + // be handled correctly and not hang/end the process (so the signal mask must be set correctly). + // See JDK-8065895. + // We do this twice, to check that secondary signal handling works repeatedly. + // We also check, optionally, that +ErrorLogSecondaryErrorDetails produces callstacks for + // the secondary error. + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( "-XX:+UnlockDiagnosticVMOptions", "-Xmx100M", "-XX:-CreateCoredumpOnCrash", "-XX:ErrorHandlerTest=15", "-XX:TestCrashInErrorHandler=14", + "-XX:" + (with_callstacks ? "+" : "-") + "ErrorLogSecondaryErrorDetails", "-version"); OutputAnalyzer output_detail = new OutputAnalyzer(pb.start()); @@ -72,12 +102,23 @@ public static void main(String[] args) throws Exception { // which is an end marker written in the last step and proves that hs-err file was // completely written. - Pattern [] pattern = new Pattern[] { - Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)..."), - Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 1\\).*\\]"), - Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)..."), - Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 2\\).*\\]"), - }; + ArrayList patternlist = new ArrayList<>(); + patternlist.add(Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)...")); + patternlist.add(Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 1\\).*\\]")); + if (with_callstacks) { + patternlist.add(Pattern.compile("\\[siginfo:.*\\(SIGSEGV\\).*\\]")); + patternlist.add(Pattern.compile("\\[stack: Native frames:.*")); + patternlist.add(Pattern.compile(".*VMError::controlled_crash.*")); + } + // and again, to see that repeated error reporting steps work + patternlist.add(Pattern.compile("Will crash now \\(TestCrashInErrorHandler=14\\)...")); + patternlist.add(Pattern.compile("\\[error occurred during error reporting \\(test secondary crash 2\\).*\\]")); + if (with_callstacks) { + patternlist.add(Pattern.compile("\\[siginfo:.*\\(SIGSEGV\\).*\\]")); + patternlist.add(Pattern.compile("\\[stack: Native frames:.*")); + patternlist.add(Pattern.compile(".*VMError::controlled_crash.*")); + } + Pattern[] pattern = patternlist.toArray(new Pattern[] {}); HsErrFileUtils.checkHsErrFileContent(hs_err_file, pattern, false); From 61b7093123b780f87509cffe286cf6949afbb45d Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Mon, 5 Dec 2022 07:16:56 +0000 Subject: [PATCH 032/494] 8297872: Non-local G1MonotonicArenaFreePool::_freelist_pool has non-trivial ctor/dtor Co-authored-by: Thomas Schatzl Reviewed-by: kbarrett, tschatzl --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 1 + src/hotspot/share/gc/g1/g1CollectedHeap.hpp | 6 ++++++ src/hotspot/share/gc/g1/g1ConcurrentMark.cpp | 4 +++- .../share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp | 7 +++++-- src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp | 11 ++++------- src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp | 9 ++------- src/hotspot/share/gc/g1/g1RemSetSummary.cpp | 3 ++- src/hotspot/share/gc/g1/heapRegionRemSet.cpp | 2 +- src/hotspot/share/gc/g1/heapRegionRemSet.hpp | 2 +- 9 files changed, 25 insertions(+), 20 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index db2012e9596..fa92c72ca46 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -1466,6 +1466,7 @@ G1CollectedHeap::G1CollectedHeap() : _hot_card_cache(NULL), _rem_set(NULL), _card_set_config(), + _card_set_freelist_pool(G1CardSetConfiguration::num_mem_object_types()), _cm(NULL), _cm_thread(NULL), _cr(NULL), diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp index c52e84b1f92..4cfa5c6928d 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.hpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.hpp @@ -41,6 +41,7 @@ #include "gc/g1/g1HRPrinter.hpp" #include "gc/g1/g1MonitoringSupport.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" +#include "gc/g1/g1MonotonicArenaFreePool.hpp" #include "gc/g1/g1NUMA.hpp" #include "gc/g1/g1SurvivorRegions.hpp" #include "gc/g1/g1YoungGCEvacFailureInjector.hpp" @@ -787,6 +788,8 @@ class G1CollectedHeap : public CollectedHeap { // Global card set configuration G1CardSetConfiguration _card_set_config; + G1MonotonicArenaFreePool _card_set_freelist_pool; + public: // After a collection pause, reset eden and the collection set. void clear_eden(); @@ -913,6 +916,9 @@ class G1CollectedHeap : public CollectedHeap { // The remembered set. G1RemSet* rem_set() const { return _rem_set; } + const G1MonotonicArenaFreePool* card_set_freelist_pool() const { return &_card_set_freelist_pool; } + G1MonotonicArenaFreePool* card_set_freelist_pool() { return &_card_set_freelist_pool; } + inline G1GCPhaseTimes* phase_times() const; const G1CollectionSet* collection_set() const { return &_collection_set; } diff --git a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp index 46af08bbfc8..a5a435da78f 100644 --- a/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp +++ b/src/hotspot/share/gc/g1/g1ConcurrentMark.cpp @@ -3052,8 +3052,10 @@ G1PrintRegionLivenessInfoClosure::~G1PrintRegionLivenessInfoClosure() { return; } + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + _total_remset_bytes += g1h->card_set_freelist_pool()->mem_size(); // add static memory usages to remembered set sizes - _total_remset_bytes += G1CardSetFreePool::free_list_pool()->mem_size() + HeapRegionRemSet::static_mem_size(); + _total_remset_bytes += HeapRegionRemSet::static_mem_size(); // Print the footer of the output. log_trace(gc, liveness)(G1PPRL_LINE_PREFIX); log_trace(gc, liveness)(G1PPRL_LINE_PREFIX diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp index e73c386025e..4ba4469bd96 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreeMemoryTask.cpp @@ -27,6 +27,7 @@ #include "gc/g1/g1CardSetMemory.inline.hpp" #include "gc/g1/g1CollectedHeap.hpp" #include "gc/g1/g1MonotonicArenaFreeMemoryTask.hpp" +#include "gc/g1/g1MonotonicArenaFreePool.hpp" #include "gc/g1/g1_globals.hpp" #include "gc/g1/heapRegionRemSet.hpp" #include "gc/shared/gc_globals.hpp" @@ -53,7 +54,9 @@ bool G1MonotonicArenaFreeMemoryTask::calculate_return_infos(jlong deadline) { // Ignore the deadline in this step as it is very short. G1MonotonicArenaMemoryStats used = _total_used; - G1MonotonicArenaMemoryStats free = G1MonotonicArenaFreePool::free_list_sizes(); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + G1MonotonicArenaFreePool* freelist_pool = g1h->card_set_freelist_pool(); + G1MonotonicArenaMemoryStats free = freelist_pool->memory_sizes(); _return_info = new G1ReturnMemoryProcessorSet(used.num_pools()); for (uint i = 0; i < used.num_pools(); i++) { @@ -69,7 +72,7 @@ bool G1MonotonicArenaFreeMemoryTask::calculate_return_infos(jlong deadline) { _return_info->append(new G1ReturnMemoryProcessor(return_to_vm_size)); } - G1MonotonicArenaFreePool::update_unlink_processors(_return_info); + freelist_pool->update_unlink_processors(_return_info); return false; } diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp index 1f85c265e47..76df02d2a71 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.cpp @@ -44,10 +44,9 @@ void G1MonotonicArenaMemoryStats::clear() { } void G1MonotonicArenaFreePool::update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processor) { - uint num_free_lists = _freelist_pool.num_free_lists(); - for (uint i = 0; i < num_free_lists; i++) { - unlink_processor->at(i)->visit_free_list(_freelist_pool.free_list(i)); + for (uint i = 0; i < num_free_lists(); i++) { + unlink_processor->at(i)->visit_free_list(free_list(i)); } } @@ -148,8 +147,6 @@ bool G1MonotonicArenaFreePool::G1ReturnMemoryProcessor::return_to_os(jlong deadl return _first != nullptr; } -G1MonotonicArenaFreePool G1MonotonicArenaFreePool::_freelist_pool(G1CardSetConfiguration::num_mem_object_types()); - G1MonotonicArenaFreePool::G1MonotonicArenaFreePool(uint num_free_lists) : _num_free_lists(num_free_lists) { @@ -184,8 +181,8 @@ size_t G1MonotonicArenaFreePool::mem_size() const { return result; } -void G1MonotonicArenaFreePool::print_on(outputStream* out) { - out->print_cr(" Free Pool: size %zu", free_list_pool()->mem_size()); +void G1MonotonicArenaFreePool::print_on(outputStream* out) const { + out->print_cr(" Free Pool: size %zu", mem_size()); for (uint i = 0; i < _num_free_lists; i++) { FormatBuffer<> fmt(" %s", G1CardSetConfiguration::mem_object_type_name_str(i)); _free_lists[i].print_on(out, fmt); diff --git a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp index 91486bf7927..2746315a8a8 100644 --- a/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp +++ b/src/hotspot/share/gc/g1/g1MonotonicArenaFreePool.hpp @@ -58,20 +58,15 @@ class G1MonotonicArenaMemoryStats { // e.g. G1CardSetAllocators::_arena class G1MonotonicArenaFreePool { using SegmentFreeList = G1MonotonicArena::SegmentFreeList; - // The global free pool. - static G1MonotonicArenaFreePool _freelist_pool; const uint _num_free_lists; SegmentFreeList* _free_lists; public: - static G1MonotonicArenaFreePool* free_list_pool() { return &_freelist_pool; } - static G1MonotonicArenaMemoryStats free_list_sizes() { return _freelist_pool.memory_sizes(); } - class G1ReturnMemoryProcessor; typedef GrowableArrayCHeap G1ReturnMemoryProcessorSet; - static void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors); + void update_unlink_processors(G1ReturnMemoryProcessorSet* unlink_processors); explicit G1MonotonicArenaFreePool(uint num_free_lists); ~G1MonotonicArenaFreePool(); @@ -86,7 +81,7 @@ class G1MonotonicArenaFreePool { G1MonotonicArenaMemoryStats memory_sizes() const; size_t mem_size() const; - void print_on(outputStream* out); + void print_on(outputStream* out) const; }; // Data structure containing current in-progress state for returning memory to the diff --git a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp index a4b517111f7..d8ec513957a 100644 --- a/src/hotspot/share/gc/g1/g1RemSetSummary.cpp +++ b/src/hotspot/share/gc/g1/g1RemSetSummary.cpp @@ -285,7 +285,8 @@ class HRRSStatsIter: public HeapRegionClosure { rem_set->occupied()); HeapRegionRemSet::print_static_mem_size(out); - G1CardSetFreePool::free_list_pool()->print_on(out); + G1CollectedHeap* g1h = G1CollectedHeap::heap(); + g1h->card_set_freelist_pool()->print_on(out); // Code root statistics HeapRegionRemSet* max_code_root_rem_set = max_code_root_mem_sz_region()->rem_set(); diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp index 0e5a800e6a5..a4d7aea17ca 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.cpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.cpp @@ -59,7 +59,7 @@ HeapRegionRemSet::HeapRegionRemSet(HeapRegion* hr, G1CardSetConfiguration* config) : _m(Mutex::service - 1, FormatBuffer<128>("HeapRegionRemSet#%u_lock", hr->hrm_index())), _code_roots(), - _card_set_mm(config, G1MonotonicArenaFreePool::free_list_pool()), + _card_set_mm(config, G1CollectedHeap::heap()->card_set_freelist_pool()), _card_set(config, &_card_set_mm), _hr(hr), _state(Untracked) { } diff --git a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp index 67c6d421d86..f4a1fb3a87f 100644 --- a/src/hotspot/share/gc/g1/heapRegionRemSet.hpp +++ b/src/hotspot/share/gc/g1/heapRegionRemSet.hpp @@ -141,7 +141,7 @@ class HeapRegionRemSet : public CHeapObj { // Returns the memory occupancy of all static data structures associated // with remembered sets. static size_t static_mem_size() { - return G1CardSet::static_mem_size() + G1CodeRootSet::static_mem_size() + sizeof(G1CardSetFreePool); + return G1CardSet::static_mem_size() + G1CodeRootSet::static_mem_size(); } static void print_static_mem_size(outputStream* out); From 82561de722b9ca580c0c1a53050c711b64611352 Mon Sep 17 00:00:00 2001 From: sendaoYan Date: Mon, 5 Dec 2022 07:41:42 +0000 Subject: [PATCH 033/494] 8296384: [TESTBUG] sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java intermittently timeout Reviewed-by: weijun, wetmore --- test/jdk/java/security/SecureRandom/NoSync.java | 4 ++-- .../security/provider/SecureRandom/AbstractDrbg/SpecTest.java | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/security/SecureRandom/NoSync.java b/test/jdk/java/security/SecureRandom/NoSync.java index 032833c4a7f..3e8485313f3 100644 --- a/test/jdk/java/security/SecureRandom/NoSync.java +++ b/test/jdk/java/security/SecureRandom/NoSync.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,7 +30,7 @@ /* * @test * @bug 7004967 - * @run main/othervm NoSync + * @run main/othervm -Djava.security.egd=file:/dev/urandom NoSync * @summary SecureRandom should be more explicit about threading */ public class NoSync { diff --git a/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java b/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java index 9ff9a1b9d51..c01aaf8b00e 100644 --- a/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java +++ b/test/jdk/sun/security/provider/SecureRandom/AbstractDrbg/SpecTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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 @@ * @bug 8051408 8157308 8130181 * @modules java.base/sun.security.provider * @build java.base/sun.security.provider.S - * @run main SpecTest + * @run main/othervm -Djava.security.egd=file:/dev/urandom SpecTest * @summary check the AbstractDrbg API etc */ From 619b68c5d1908de335cefd536963cadd57472925 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 5 Dec 2022 08:30:31 +0000 Subject: [PATCH 034/494] 8294540: Remove Opaque2Node: it is broken and triggers assert Reviewed-by: chagedorn, kvn --- src/hotspot/share/opto/classes.hpp | 1 - src/hotspot/share/opto/compile.cpp | 1 - src/hotspot/share/opto/loopTransform.cpp | 31 +------- src/hotspot/share/opto/loopnode.hpp | 6 -- src/hotspot/share/opto/loopopts.cpp | 97 +----------------------- src/hotspot/share/opto/macro.cpp | 3 +- src/hotspot/share/opto/opaquenode.cpp | 20 +---- src/hotspot/share/opto/opaquenode.hpp | 33 +++----- src/hotspot/share/opto/phaseX.cpp | 1 - src/hotspot/share/opto/subnode.cpp | 9 --- src/hotspot/share/runtime/vmStructs.cpp | 1 - 11 files changed, 16 insertions(+), 187 deletions(-) diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 36f230be9f9..ba50d559d99 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -268,7 +268,6 @@ macro(OnSpinWait) macro(Opaque1) macro(OpaqueLoopInit) macro(OpaqueLoopStride) -macro(Opaque2) macro(Opaque3) macro(Opaque4) macro(ProfileBoolean) diff --git a/src/hotspot/share/opto/compile.cpp b/src/hotspot/share/opto/compile.cpp index 442fee99619..2ac3b12a9f1 100644 --- a/src/hotspot/share/opto/compile.cpp +++ b/src/hotspot/share/opto/compile.cpp @@ -3161,7 +3161,6 @@ void Compile::final_graph_reshaping_main_switch(Node* n, Final_Reshape_Counts& f frc.inc_double_count(); break; case Op_Opaque1: // Remove Opaque Nodes before matching - case Op_Opaque2: // Remove Opaque Nodes before matching case Op_Opaque3: n->subsume_by(n->in(1), this); break; diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index b4ba8decbda..e636440d8cb 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -2287,18 +2287,7 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj set_ctrl(new_limit, C->root()); } else { // Limit is not constant. - if (loop_head->unrolled_count() == 1) { // only for first unroll - // Separate limit by Opaque node in case it is an incremented - // variable from previous loop to avoid using pre-incremented - // value which could increase register pressure. - // Otherwise reorg_offsets() optimization will create a separate - // Opaque node for each use of trip-counter and as result - // zero trip guard limit will be different from loop limit. - assert(has_ctrl(opaq), "should have it"); - Node* opaq_ctrl = get_ctrl(opaq); - limit = new Opaque2Node(C, limit); - register_new_node(limit, opaq_ctrl); - } + assert(loop_head->unrolled_count() != 1 || has_ctrl(opaq), "should have opaque for first unroll"); if ((stride_con > 0 && (java_subtract(limit_type->_lo, stride_con) < limit_type->_lo)) || (stride_con < 0 && (java_subtract(limit_type->_hi, stride_con) > limit_type->_hi))) { // No underflow. @@ -2346,20 +2335,6 @@ void PhaseIdealLoop::do_unroll(IdealLoopTree *loop, Node_List &old_new, bool adj new_limit = new CMoveINode(adj_bool, adj_limit, adj_max, TypeInt::INT); } register_new_node(new_limit, ctrl); - if (loop_head->unrolled_count() == 1) { - // The Opaque2 node created above (in the case of the first unrolling) hides the type of the loop limit. - // As a result, if the iv Phi constant folds (because it captured the iteration range), the exit test won't - // constant fold and the graph contains a broken counted loop. - const Type* new_limit_t; - if (stride_con > 0) { - new_limit_t = TypeInt::make(min_jint, limit_type->_hi, limit_type->_widen); - } else { - assert(stride_con < 0, "stride can't be 0"); - new_limit_t = TypeInt::make(limit_type->_lo, max_jint, limit_type->_widen); - } - new_limit = new CastIINode(new_limit, new_limit_t); - register_new_node(new_limit, ctrl); - } } assert(new_limit != NULL, ""); @@ -3940,10 +3915,6 @@ bool IdealLoopTree::iteration_split(PhaseIdealLoop* phase, Node_List &old_new) { } } - // Minor offset re-organization to remove loop-fallout uses of - // trip counter when there was no major reshaping. - phase->reorg_offsets(this); - if (_next && !_next->iteration_split(phase, old_new)) { return false; } diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index df1fd8ec702..b5b01a9fcd7 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1522,12 +1522,6 @@ class PhaseIdealLoop : public PhaseTransform { // Attempt to use a conditional move instead of a phi/branch Node *conditional_move( Node *n ); - // Reorganize offset computations to lower register pressure. - // Mostly prevent loop-fallout uses of the pre-incremented trip counter - // (which are then alive with the post-incremented trip counter - // forcing an extra register move) - void reorg_offsets( IdealLoopTree *loop ); - // Check for aggressive application of 'split-if' optimization, // using basic block level info. void split_if_with_blocks ( VectorSet &visited, Node_Stack &nstack); diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 22e1a741981..5dea9537497 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1023,8 +1023,7 @@ Node *PhaseIdealLoop::split_if_with_blocks_pre( Node *n ) { if (n->is_CFG() || n->is_LoadStore()) { return n; } - if (n->is_Opaque1() || // Opaque nodes cannot be mod'd - n_op == Op_Opaque2) { + if (n->is_Opaque1()) { // Opaque nodes cannot be mod'd if (!C->major_progress()) { // If chance of no more loop opts... _igvn._worklist.push(n); // maybe we'll remove them } @@ -1426,14 +1425,6 @@ void PhaseIdealLoop::split_if_with_blocks_post(Node *n) { try_sink_out_of_loop(n); try_move_store_after_loop(n); - - // Check for Opaque2's who's loop has disappeared - who's input is in the - // same loop nest as their output. Remove 'em, they are no longer useful. - if( n_op == Op_Opaque2 && - n->in(1) != NULL && - get_loop(get_ctrl(n)) == get_loop(get_ctrl(n->in(1))) ) { - _igvn.replace_node( n, n->in(1) ); - } } // Transform: @@ -4106,89 +4097,3 @@ bool PhaseIdealLoop::duplicate_loop_backedge(IdealLoopTree *loop, Node_List &old return true; } - -//------------------------------reorg_offsets---------------------------------- -// Reorganize offset computations to lower register pressure. Mostly -// prevent loop-fallout uses of the pre-incremented trip counter (which are -// then alive with the post-incremented trip counter forcing an extra -// register move): -// -// iv Phi iv Phi -// | | -// | AddI (+stride) -// | | -// | Opaque2 # Blocks IGVN from folding these nodes until loop opts are over. -// | ====> | -// | AddI (-stride) -// | | -// | CastII # Preserve type of iv Phi -// | | -// Outside Use Outside Use -// -void PhaseIdealLoop::reorg_offsets(IdealLoopTree *loop) { - // Perform it only for canonical counted loops. - // Loop's shape could be messed up by iteration_split_impl. - if (!loop->_head->is_CountedLoop()) - return; - if (!loop->_head->as_Loop()->is_valid_counted_loop(T_INT)) - return; - - CountedLoopNode *cl = loop->_head->as_CountedLoop(); - CountedLoopEndNode *cle = cl->loopexit(); - Node *exit = cle->proj_out(false); - Node *phi = cl->phi(); - - // Check for the special case when using the pre-incremented trip-counter on - // the fall-out path (forces the pre-incremented and post-incremented trip - // counter to be live at the same time). Fix this by adjusting to use the - // post-increment trip counter. - - bool progress = true; - while (progress) { - progress = false; - for (DUIterator_Fast imax, i = phi->fast_outs(imax); i < imax; i++) { - Node* use = phi->fast_out(i); // User of trip-counter - if (!has_ctrl(use)) continue; - Node *u_ctrl = get_ctrl(use); - if (use->is_Phi()) { - u_ctrl = NULL; - for (uint j = 1; j < use->req(); j++) - if (use->in(j) == phi) - u_ctrl = dom_lca(u_ctrl, use->in(0)->in(j)); - } - IdealLoopTree *u_loop = get_loop(u_ctrl); - // Look for loop-invariant use - if (u_loop == loop) continue; - if (loop->is_member(u_loop)) continue; - // Check that use is live out the bottom. Assuming the trip-counter - // update is right at the bottom, uses of of the loop middle are ok. - if (dom_lca(exit, u_ctrl) != exit) continue; - // Hit! Refactor use to use the post-incremented tripcounter. - // Compute a post-increment tripcounter. - Node* c = exit; - if (cl->is_strip_mined()) { - IdealLoopTree* outer_loop = get_loop(cl->outer_loop()); - if (!outer_loop->is_member(u_loop)) { - c = cl->outer_loop_exit(); - } - } - Node *opaq = new Opaque2Node(C, cle->incr()); - register_new_node(opaq, c); - Node *neg_stride = _igvn.intcon(-cle->stride_con()); - set_ctrl(neg_stride, C->root()); - Node *post = new AddINode(opaq, neg_stride); - register_new_node(post, c); - post = new CastIINode(post, phi->bottom_type()); // preserve the iv phi's type - register_new_node(post, c); - _igvn.rehash_node_delayed(use); - for (uint j = 1; j < use->req(); j++) { - if (use->in(j) == phi) - use->set_req(j, post); - } - // Since DU info changed, rerun loop - progress = true; - break; - } - } - -} diff --git a/src/hotspot/share/opto/macro.cpp b/src/hotspot/share/opto/macro.cpp index 1dea2f15b13..62b41d720b1 100644 --- a/src/hotspot/share/opto/macro.cpp +++ b/src/hotspot/share/opto/macro.cpp @@ -2371,7 +2371,6 @@ void PhaseMacroExpand::eliminate_macro_nodes() { break; default: assert(n->Opcode() == Op_LoopLimit || - n->Opcode() == Op_Opaque2 || n->Opcode() == Op_Opaque3 || n->Opcode() == Op_Opaque4 || BarrierSet::barrier_set()->barrier_set_c2()->is_gc_barrier_node(n), @@ -2414,7 +2413,7 @@ bool PhaseMacroExpand::expand_macro_nodes() { C->remove_macro_node(n); _igvn._worklist.push(n); success = true; - } else if (n->is_Opaque1() || n->Opcode() == Op_Opaque2) { + } else if (n->is_Opaque1()) { _igvn.replace_node(n, n->in(1)); success = true; #if INCLUDE_RTM_OPT diff --git a/src/hotspot/share/opto/opaquenode.cpp b/src/hotspot/share/opto/opaquenode.cpp index 3f796e163e9..42e59cacd49 100644 --- a/src/hotspot/share/opto/opaquenode.cpp +++ b/src/hotspot/share/opto/opaquenode.cpp @@ -44,20 +44,8 @@ Node* Opaque1Node::Identity(PhaseGVN* phase) { return this; } -//============================================================================= -// A node to prevent unwanted optimizations. Allows constant folding. Stops -// value-numbering, most Ideal calls or Identity functions. This Node is -// specifically designed to prevent the pre-increment value of a loop trip -// counter from being live out of the bottom of the loop (hence causing the -// pre- and post-increment values both being live and thus requiring an extra -// temp register and an extra move). If we "accidentally" optimize through -// this kind of a Node, we'll get slightly pessimal, but correct, code. Thus -// it's OK to be slightly sloppy on optimizations here. - -// Do NOT remove the opaque node until no more loop opts can happen. Opaque1 -// and Opaque2 nodes are removed together in order to optimize loops away -// before macro expansion. -Node* Opaque2Node::Identity(PhaseGVN* phase) { +// Do NOT remove the opaque node until no more loop opts can happen. +Node* Opaque3Node::Identity(PhaseGVN* phase) { if (phase->C->post_loop_opts_phase()) { return in(1); } else { @@ -67,8 +55,8 @@ Node* Opaque2Node::Identity(PhaseGVN* phase) { } // Do not allow value-numbering -uint Opaque2Node::hash() const { return NO_HASH; } -bool Opaque2Node::cmp( const Node &n ) const { +uint Opaque3Node::hash() const { return NO_HASH; } +bool Opaque3Node::cmp(const Node &n) const { return (&n == this); // Always fail except on self } diff --git a/src/hotspot/share/opto/opaquenode.hpp b/src/hotspot/share/opto/opaquenode.hpp index 1dedd032041..11a79f8a478 100644 --- a/src/hotspot/share/opto/opaquenode.hpp +++ b/src/hotspot/share/opto/opaquenode.hpp @@ -70,20 +70,16 @@ class OpaqueLoopStrideNode : public Opaque1Node { virtual int Opcode() const; }; -//------------------------------Opaque2Node------------------------------------ -// A node to prevent unwanted optimizations. Allows constant folding. Stops -// value-numbering, most Ideal calls or Identity functions. This Node is -// specifically designed to prevent the pre-increment value of a loop trip -// counter from being live out of the bottom of the loop (hence causing the -// pre- and post-increment values both being live and thus requiring an extra -// temp register and an extra move). If we "accidentally" optimize through -// this kind of a Node, we'll get slightly pessimal, but correct, code. Thus -// it's OK to be slightly sloppy on optimizations here. -class Opaque2Node : public Node { - virtual uint hash() const ; // { return NO_HASH; } - virtual bool cmp( const Node &n ) const; +//------------------------------Opaque3Node------------------------------------ +// A node to prevent unwanted optimizations. Will be optimized only during +// macro nodes expansion. +class Opaque3Node : public Node { + int _opt; // what optimization it was used for + virtual uint hash() const; + virtual bool cmp(const Node &n) const; public: - Opaque2Node( Compile* C, Node *n ) : Node(0,n) { + enum { RTM_OPT }; + Opaque3Node(Compile* C, Node* n, int opt) : Node(0, n), _opt(opt) { // Put it on the Macro nodes list to removed during macro nodes expansion. init_flags(Flag_is_macro); C->add_macro_node(this); @@ -91,17 +87,6 @@ class Opaque2Node : public Node { virtual int Opcode() const; virtual const Type* bottom_type() const { return TypeInt::INT; } virtual Node* Identity(PhaseGVN* phase); -}; - -//------------------------------Opaque3Node------------------------------------ -// A node to prevent unwanted optimizations. Will be optimized only during -// macro nodes expansion. -class Opaque3Node : public Opaque2Node { - int _opt; // what optimization it was used for - public: - enum { RTM_OPT }; - Opaque3Node(Compile* C, Node *n, int opt) : Opaque2Node(C, n), _opt(opt) {} - virtual int Opcode() const; bool rtm_opt() const { return (_opt == RTM_OPT); } }; diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index a22a20d1371..beafcb3beb9 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -2116,7 +2116,6 @@ Node *PhaseCCP::transform_once( Node *n ) { case Op_CountedLoop: case Op_Conv2B: case Op_Opaque1: - case Op_Opaque2: _worklist.push(n); break; default: diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 570f5828f23..2d01e1ea32c 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -69,15 +69,6 @@ Node* SubNode::Identity(PhaseGVN* phase) { if (in(1)->in(1) == in(2)) { return in(1)->in(2); } - - // Also catch: "(X + Opaque2(Y)) - Y". In this case, 'Y' is a loop-varying - // trip counter and X is likely to be loop-invariant (that's how O2 Nodes - // are originally used, although the optimizer sometimes jiggers things). - // This folding through an O2 removes a loop-exit use of a loop-varying - // value and generally lowers register pressure in and around the loop. - if (in(1)->in(2)->Opcode() == Op_Opaque2 && in(1)->in(2)->in(1) == in(2)) { - return in(1)->in(1); - } } return ( phase->type( in(2) )->higher_equal( zero ) ) ? in(1) : this; diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 2ee5a251a65..4407b065309 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1570,7 +1570,6 @@ declare_c2_type(InitializeNode, MemBarNode) \ declare_c2_type(ThreadLocalNode, Node) \ declare_c2_type(Opaque1Node, Node) \ - declare_c2_type(Opaque2Node, Node) \ declare_c2_type(PartialSubtypeCheckNode, Node) \ declare_c2_type(MoveI2FNode, Node) \ declare_c2_type(MoveL2DNode, Node) \ From 17666fbcae795a01ee462651c7694b5e4af30e32 Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Mon, 5 Dec 2022 09:27:14 +0000 Subject: [PATCH 035/494] 8297794: Deprecate JMX Management Applets for Removal Reviewed-by: dfuchs, mullan, rriggs, alanb --- .../share/classes/javax/management/loading/MLet.java | 6 ++++++ .../classes/javax/management/loading/MLetContent.java | 6 +++++- .../classes/javax/management/loading/MLetMBean.java | 8 ++++++-- .../javax/management/loading/MLetObjectInputStream.java | 5 ++++- .../classes/javax/management/loading/MLetParser.java | 4 +++- .../classes/javax/management/loading/PrivateMLet.java | 9 +++++++-- .../jdk/javax/management/Introspector/ClassLeakTest.java | 3 ++- .../javax/management/MBeanServer/PostExceptionTest.java | 3 ++- test/jdk/javax/management/loading/DocumentRootTest.java | 3 ++- .../javax/management/loading/GetMBeansFromURLTest.java | 3 ++- .../javax/management/loading/MLetCLR/MLetCommand.java | 3 ++- test/jdk/javax/management/loading/MLetContentTest.java | 3 ++- test/jdk/javax/management/loading/MLetInternalsTest.java | 3 ++- .../javax/management/loading/MletParserLocaleTest.java | 1 + .../javax/management/loading/ParserInfiniteLoopTest.java | 3 ++- test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java | 4 +++- test/jdk/javax/management/relation/NonArrayListTest.java | 4 +++- .../remote/mandatory/loading/TargetMBeanTest.java | 3 ++- .../remote/mandatory/notif/NotificationBufferTest.java | 3 ++- 19 files changed, 58 insertions(+), 19 deletions(-) diff --git a/src/java.management/share/classes/javax/management/loading/MLet.java b/src/java.management/share/classes/javax/management/loading/MLet.java index 250e5945645..aacf73e4821 100644 --- a/src/java.management/share/classes/javax/management/loading/MLet.java +++ b/src/java.management/share/classes/javax/management/loading/MLet.java @@ -162,8 +162,14 @@ *

Note - The MLet class loader uses the {@link javax.management.MBeanServerFactory#getClassLoaderRepository(javax.management.MBeanServer)} * to load classes that could not be found in the loaded jar files. * + * @deprecated This API is part of Management Applets (m-lets), which is a legacy feature that allows loading + * of remote MBeans. This feature is not usable without a Security Manager, which is deprecated and subject to + * removal in a future release. Consequently, this API is also deprecated and subject to removal. There is no replacement. + * * @since 1.5 */ +@Deprecated(since="20", forRemoval=true) +@SuppressWarnings("removal") public class MLet extends java.net.URLClassLoader implements MLetMBean, MBeanRegistration, Externalizable { diff --git a/src/java.management/share/classes/javax/management/loading/MLetContent.java b/src/java.management/share/classes/javax/management/loading/MLetContent.java index 32b099a3615..638f7b38c21 100644 --- a/src/java.management/share/classes/javax/management/loading/MLetContent.java +++ b/src/java.management/share/classes/javax/management/loading/MLetContent.java @@ -39,11 +39,15 @@ * It can be consulted by a subclass of {@link MLet} that overrides * the {@link MLet#check MLet.check} method. * + * @deprecated This API is part of Management Applets (m-lets), which is a legacy feature that allows loading + * of remote MBeans. This feature is not usable without a Security Manager, which is deprecated and subject to + * removal in a future release. Consequently, this API is also deprecated and subject to removal. There is no replacement. + * * @since 1.6 */ +@Deprecated(since="20", forRemoval=true) public class MLetContent { - /** * A map of the attributes of the MLET tag * and their values. diff --git a/src/java.management/share/classes/javax/management/loading/MLetMBean.java b/src/java.management/share/classes/javax/management/loading/MLetMBean.java index a18b08d70fe..1e57cef9be7 100644 --- a/src/java.management/share/classes/javax/management/loading/MLetMBean.java +++ b/src/java.management/share/classes/javax/management/loading/MLetMBean.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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,11 +39,15 @@ * Exposes the remote management interface of the MLet * MBean. * + * @deprecated This API is part of Management Applets (m-lets), which is a legacy feature that allows loading + * of remote MBeans. This feature is not usable without a Security Manager, which is deprecated and subject to + * removal in a future release. Consequently, this API is also deprecated and subject to removal. There is no replacement. + * * @since 1.5 */ +@Deprecated(since="20", forRemoval=true) public interface MLetMBean { - /** * Loads a text file containing MLET tags that define the MBeans * to be added to the MBean server. The location of the text file is diff --git a/src/java.management/share/classes/javax/management/loading/MLetObjectInputStream.java b/src/java.management/share/classes/javax/management/loading/MLetObjectInputStream.java index e0938316a1b..159fa85b22e 100644 --- a/src/java.management/share/classes/javax/management/loading/MLetObjectInputStream.java +++ b/src/java.management/share/classes/javax/management/loading/MLetObjectInputStream.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1999, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1999, 2022, 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,13 +38,16 @@ * * @since 1.5 */ +@Deprecated(since="20", forRemoval=true) class MLetObjectInputStream extends ObjectInputStream { + @SuppressWarnings("removal") private MLet loader; /** * Loader must be non-null; */ + @SuppressWarnings("removal") public MLetObjectInputStream(InputStream in, MLet loader) throws IOException, StreamCorruptedException { diff --git a/src/java.management/share/classes/javax/management/loading/MLetParser.java b/src/java.management/share/classes/javax/management/loading/MLetParser.java index 0e53b1ddcc6..41bb9d35878 100644 --- a/src/java.management/share/classes/javax/management/loading/MLetParser.java +++ b/src/java.management/share/classes/javax/management/loading/MLetParser.java @@ -47,6 +47,7 @@ * * @since 1.5 */ +@Deprecated(since="20", forRemoval=true) class MLetParser { /* @@ -153,6 +154,7 @@ public Map scanTag(Reader in) throws IOException { /** * Scan an html file for {@literal } tags. */ + @SuppressWarnings("removal") public List parse(URL url) throws IOException { // Warning Messages String requiresTypeWarning = " tag requires type parameter."; @@ -249,7 +251,7 @@ public List parse(URL url) throws IOException { /** * Parse the document pointed by the URL urlname */ - @SuppressWarnings("deprecation") + @SuppressWarnings("removal") public List parseURL(String urlname) throws IOException { // Parse the document // diff --git a/src/java.management/share/classes/javax/management/loading/PrivateMLet.java b/src/java.management/share/classes/javax/management/loading/PrivateMLet.java index f9b0d0ebd77..372db255b72 100644 --- a/src/java.management/share/classes/javax/management/loading/PrivateMLet.java +++ b/src/java.management/share/classes/javax/management/loading/PrivateMLet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,9 +36,14 @@ * ClassLoaderRepository}. This is true because this class implements * the interface {@link PrivateClassLoader}. * + * @deprecated This API is part of Management Applets (m-lets), which is a legacy feature that allows loading + * of remote MBeans. This feature is not usable without a Security Manager, which is deprecated and subject to + * removal in a future release. Consequently, this API is also deprecated and subject to removal. There is no replacement. + * * @since 1.5 */ -@SuppressWarnings("serial") // Externalizable class w/o no-arg c'tor +@Deprecated(since="20", forRemoval=true) +@SuppressWarnings({"serial", "removal"}) // Externalizable class w/o no-arg c'tor public class PrivateMLet extends MLet implements PrivateClassLoader { private static final long serialVersionUID = 2503458973393711979L; diff --git a/test/jdk/javax/management/Introspector/ClassLeakTest.java b/test/jdk/javax/management/Introspector/ClassLeakTest.java index 9a08c04b0c2..f6316f7e2c3 100644 --- a/test/jdk/javax/management/Introspector/ClassLeakTest.java +++ b/test/jdk/javax/management/Introspector/ClassLeakTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,6 +56,7 @@ public static void main(String[] args) throws Exception { urls[i] = Paths.get(cpaths[i]).toUri().toURL(); } + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMBean.class.getName()); if (shadowClass == TestMBean.class) { diff --git a/test/jdk/javax/management/MBeanServer/PostExceptionTest.java b/test/jdk/javax/management/MBeanServer/PostExceptionTest.java index 3e3c802fc88..a004acceee5 100644 --- a/test/jdk/javax/management/MBeanServer/PostExceptionTest.java +++ b/test/jdk/javax/management/MBeanServer/PostExceptionTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -432,6 +432,7 @@ public ObjectName registerMLet(MBeanServer server) throws Exception { if (server.isRegistered(name)) { return name; } + @SuppressWarnings("removal") final MLet mlet = new MLet(new URL[0], ClassLoader.getSystemClassLoader()); return server.registerMBean(mlet, name).getObjectName(); diff --git a/test/jdk/javax/management/loading/DocumentRootTest.java b/test/jdk/javax/management/loading/DocumentRootTest.java index ae598ddd99e..73b1654d135 100644 --- a/test/jdk/javax/management/loading/DocumentRootTest.java +++ b/test/jdk/javax/management/loading/DocumentRootTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2022, 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,6 +38,7 @@ import java.util.HashMap; import javax.management.loading.MLetContent; +@SuppressWarnings("removal") public class DocumentRootTest { public static int test(URL documentBase, URL codeBase) { int error = 0; diff --git a/test/jdk/javax/management/loading/GetMBeansFromURLTest.java b/test/jdk/javax/management/loading/GetMBeansFromURLTest.java index 5f4d889c91b..31b86c72e8d 100644 --- a/test/jdk/javax/management/loading/GetMBeansFromURLTest.java +++ b/test/jdk/javax/management/loading/GetMBeansFromURLTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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,7 @@ import javax.management.ServiceNotFoundException; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class GetMBeansFromURLTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java b/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java index 2519f4329b2..2973b15c2cb 100644 --- a/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java +++ b/test/jdk/javax/management/loading/MLetCLR/MLetCommand.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 javax.management.ObjectName; import java.io.File; +@SuppressWarnings("removal") public class MLetCommand { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/MLetContentTest.java b/test/jdk/javax/management/loading/MLetContentTest.java index 0fa9ce939f7..455a20533be 100644 --- a/test/jdk/javax/management/loading/MLetContentTest.java +++ b/test/jdk/javax/management/loading/MLetContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -37,6 +37,7 @@ import javax.management.loading.*; +@SuppressWarnings("removal") public class MLetContentTest { public static void main(String[] args) throws Exception { System.out.println(">>> General test for the public class MLetContent."); diff --git a/test/jdk/javax/management/loading/MLetInternalsTest.java b/test/jdk/javax/management/loading/MLetInternalsTest.java index 4d312728dcf..2007e68fddc 100644 --- a/test/jdk/javax/management/loading/MLetInternalsTest.java +++ b/test/jdk/javax/management/loading/MLetInternalsTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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 @@ * @modules java.management/javax.management.loading:open * @run testng MLetInternalsTest */ +@SuppressWarnings("removal") public class MLetInternalsTest { private final static String CONSTRUCT_PARAMETER = "constructParameter"; diff --git a/test/jdk/javax/management/loading/MletParserLocaleTest.java b/test/jdk/javax/management/loading/MletParserLocaleTest.java index 065fd45d854..4242caad0a2 100644 --- a/test/jdk/javax/management/loading/MletParserLocaleTest.java +++ b/test/jdk/javax/management/loading/MletParserLocaleTest.java @@ -39,6 +39,7 @@ import javax.management.ObjectName; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class MletParserLocaleTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java b/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java index f02455826b4..4881d75556c 100644 --- a/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java +++ b/test/jdk/javax/management/loading/ParserInfiniteLoopTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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,6 +45,7 @@ import javax.management.ServiceNotFoundException; import javax.management.loading.MLet; +@SuppressWarnings("removal") public class ParserInfiniteLoopTest { public static void main(String[] args) throws Exception { diff --git a/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java b/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java index 3a02ea262b5..a677133ea50 100644 --- a/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java +++ b/test/jdk/javax/management/mxbean/MXBeanLoadingTest1.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 @@ -81,6 +81,7 @@ public void run(Map args) { + ".class", ""); URL[] urls = new URL[]{new URL(clsLoadPath)}; + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(TestMXBean.class.getName()); @@ -266,6 +267,7 @@ public void run(Map args) { mbs.unregisterMBean(testName); mbs.unregisterMBean(mletName); + @SuppressWarnings("removal") WeakReference mletRef = new WeakReference(mlet); mlet = null; diff --git a/test/jdk/javax/management/relation/NonArrayListTest.java b/test/jdk/javax/management/relation/NonArrayListTest.java index 0304c198333..0bb75f7ca8a 100644 --- a/test/jdk/javax/management/relation/NonArrayListTest.java +++ b/test/jdk/javax/management/relation/NonArrayListTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,6 +38,8 @@ import javax.management.loading.MLet; public class NonArrayListTest { + + @SuppressWarnings("removal") // use of MLet public static void main(String[] args) throws Exception { MBeanServer mbs = MBeanServerFactory.createMBeanServer(); RelationService rs = new RelationService(true); diff --git a/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java b/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java index 9d949995351..1908a31e2de 100644 --- a/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java +++ b/test/jdk/javax/management/remote/mandatory/loading/TargetMBeanTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -101,6 +101,7 @@ public static void main(String[] args) throws Exception { URLClassLoader jrcl = (URLClassLoader) jmxRemoteClassLoader; URL[] urls = jrcl.getURLs(); + @SuppressWarnings("removal") PrivateMLet mlet = new PrivateMLet(urls, null, false); Class shadowClass = mlet.loadClass(JMXServiceURL.class.getName()); if (shadowClass == JMXServiceURL.class) { diff --git a/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java b/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java index bf8c1639486..6d21127bf25 100644 --- a/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java +++ b/test/jdk/javax/management/remote/mandatory/notif/NotificationBufferTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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,6 +80,7 @@ public static void main(String[] args) { } } + @SuppressWarnings("removal") // use of MLet private static boolean test() throws Exception { MBeanServer mbs = MBeanServerFactory.createMBeanServer(); From 777fb52ef5b0d95b756ce4fa71a7ddf2d7d2a8f1 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 5 Dec 2022 09:33:42 +0000 Subject: [PATCH 036/494] 8297974: ClassCastException in com.sun.tools.javac.comp.AttrRecover.doRecovery Reviewed-by: vromero --- .../com/sun/tools/javac/comp/AttrRecover.java | 2 +- .../tools/javac/recovery/LambdaRecovery.java | 104 ++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/recovery/LambdaRecovery.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java index f95be28973f..98bc9eb4ac3 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/AttrRecover.java @@ -156,7 +156,7 @@ public void visitClassDef(JCClassDecl tree) { //do not touch nested classes } }.translate(lambda.body); - if (!voidCompatible) { + if (!voidCompatible && lambda.body.hasTag(Tag.BLOCK)) { JCReturn ret = make.Return(make.Erroneous().setType(syms.errType)); ((JCBlock) lambda.body).stats = ((JCBlock) lambda.body).stats.append(ret); rollback.append(() -> { diff --git a/test/langtools/tools/javac/recovery/LambdaRecovery.java b/test/langtools/tools/javac/recovery/LambdaRecovery.java new file mode 100644 index 00000000000..74d796d0b02 --- /dev/null +++ b/test/langtools/tools/javac/recovery/LambdaRecovery.java @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2022, 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 8297974 + * @summary Verify error recovery w.r.t. lambdas + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.jdeps/com.sun.tools.classfile + * @build toolbox.ToolBox toolbox.JavacTask + * @run main LambdaRecovery + */ + +import java.nio.file.Path; +import java.util.List; +import java.util.Objects; + +import toolbox.JavacTask; +import toolbox.Task.Expect; +import toolbox.Task.OutputKind; +import toolbox.TestRunner; +import toolbox.ToolBox; + +public class LambdaRecovery extends TestRunner { + + ToolBox tb; + + public LambdaRecovery() { + super(System.err); + tb = new ToolBox(); + } + + public static void main(String[] args) throws Exception { + LambdaRecovery t = new LambdaRecovery(); + t.runTests(); + } + + @Test + public void testRecoveryExpressionLambda() throws Exception { + String code = """ + class Test { + interface I { + int convert(int i); + } + interface O { + Object convert(Object o); + } + void t1(I f, String e) { + t1(param -> param); + t1(param -> voidMethod(param)); + } + void t2(O f, String e) { + t2(param -> param); + t2(param -> voidMethod(param)); + } + void voidMethod(Object o) {} + } + """; + Path curPath = Path.of("."); + List actual = new JavacTask(tb) + .options("-XDrawDiagnostics", "-XDdev") + .sources(code) + .outdir(curPath) + .run(Expect.FAIL) + .getOutputLines(OutputKind.DIRECT); + + List expected = List.of( + "Test.java:9:9: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:10:9: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:10:11: compiler.err.cant.apply.symbol: kindname.method, t1, Test.I,java.lang.String, @12,, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: void, int)))", + "Test.java:13:9: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:14:9: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12, kindname.class, Test, (compiler.misc.arg.length.mismatch)", + "Test.java:14:11: compiler.err.cant.apply.symbol: kindname.method, t2, Test.O,java.lang.String, @12,, kindname.class, Test, (compiler.misc.no.conforming.assignment.exists: (compiler.misc.incompatible.ret.type.in.lambda: (compiler.misc.inconvertible.types: void, java.lang.Object)))", + "6 errors" + ); + + if (!Objects.equals(actual, expected)) { + error("Expected: " + expected + ", but got: " + actual); + } + + } +} From d523d9d081a3bc698abcf493e038779a29eb47ea Mon Sep 17 00:00:00 2001 From: Robbin Ehn Date: Mon, 5 Dec 2022 10:31:35 +0000 Subject: [PATCH 037/494] 8297864: Dead code elimination Reviewed-by: coleenp, pchilanomate --- .../continuationFreezeThaw_aarch64.inline.hpp | 5 - .../stackChunkFrameStream_aarch64.inline.hpp | 6 -- .../arm/continuationFreezeThaw_arm.inline.hpp | 4 - .../arm/stackChunkFrameStream_arm.inline.hpp | 6 -- .../ppc/stackChunkFrameStream_ppc.inline.hpp | 6 -- .../continuationFreezeThaw_riscv.inline.hpp | 5 - .../stackChunkFrameStream_riscv.inline.hpp | 6 -- .../continuationFreezeThaw_s390.inline.hpp | 4 - .../stackChunkFrameStream_s390.inline.hpp | 6 -- .../x86/continuationFreezeThaw_x86.inline.hpp | 5 - .../x86/stackChunkFrameStream_x86.inline.hpp | 6 -- .../continuationFreezeThaw_zero.inline.hpp | 4 - .../stackChunkFrameStream_zero.inline.hpp | 6 -- src/hotspot/cpu/zero/stubGenerator_zero.cpp | 3 - src/hotspot/share/prims/forte.cpp | 4 - .../share/runtime/abstract_vm_version.cpp | 11 --- .../share/runtime/abstract_vm_version.hpp | 8 -- src/hotspot/share/runtime/arguments.cpp | 32 ------- src/hotspot/share/runtime/arguments.hpp | 6 -- .../share/runtime/continuationEntry.hpp | 2 - .../share/runtime/continuationFreezeThaw.cpp | 5 - .../share/runtime/continuationHelper.hpp | 8 -- .../runtime/continuationHelper.inline.hpp | 29 ------ .../share/runtime/continuationJavaClasses.hpp | 18 ++-- .../continuationJavaClasses.inline.hpp | 16 ---- .../runtime/continuationWrapper.inline.hpp | 10 -- src/hotspot/share/runtime/deoptimization.cpp | 15 --- src/hotspot/share/runtime/deoptimization.hpp | 16 ---- src/hotspot/share/runtime/escapeBarrier.hpp | 2 - src/hotspot/share/runtime/fieldDescriptor.cpp | 5 - src/hotspot/share/runtime/fieldDescriptor.hpp | 5 - src/hotspot/share/runtime/frame.cpp | 2 - src/hotspot/share/runtime/frame.hpp | 19 ---- src/hotspot/share/runtime/frame.inline.hpp | 7 -- src/hotspot/share/runtime/handles.hpp | 3 - src/hotspot/share/runtime/java.hpp | 9 -- src/hotspot/share/runtime/javaCalls.hpp | 2 - src/hotspot/share/runtime/javaThread.cpp | 34 ------- src/hotspot/share/runtime/javaThread.hpp | 26 +----- src/hotspot/share/runtime/jniHandles.cpp | 24 ----- src/hotspot/share/runtime/jniHandles.hpp | 4 - .../share/runtime/jniPeriodicChecker.cpp | 22 ----- .../share/runtime/jniPeriodicChecker.hpp | 7 -- .../share/runtime/keepStackGCProcessed.cpp | 16 ---- .../share/runtime/keepStackGCProcessed.hpp | 2 - src/hotspot/share/runtime/monitorChunk.hpp | 3 - .../share/runtime/monitorDeflationThread.hpp | 1 - src/hotspot/share/runtime/mutex.hpp | 1 - src/hotspot/share/runtime/mutexLocker.cpp | 5 - src/hotspot/share/runtime/mutexLocker.hpp | 4 - src/hotspot/share/runtime/objectMonitor.hpp | 10 -- .../share/runtime/objectMonitor.inline.hpp | 17 ---- src/hotspot/share/runtime/os.hpp | 3 - src/hotspot/share/runtime/os_perf.hpp | 31 ------- src/hotspot/share/runtime/perfData.cpp | 72 --------------- src/hotspot/share/runtime/perfData.hpp | 62 ------------- src/hotspot/share/runtime/perfData.inline.hpp | 8 -- src/hotspot/share/runtime/reflectionUtils.hpp | 1 - src/hotspot/share/runtime/registerMap.hpp | 10 -- src/hotspot/share/runtime/relocator.cpp | 6 -- src/hotspot/share/runtime/relocator.hpp | 1 - src/hotspot/share/runtime/rtmLocking.hpp | 2 - src/hotspot/share/runtime/safepoint.hpp | 3 - .../share/runtime/safepointMechanism.hpp | 1 - .../runtime/safepointMechanism.inline.hpp | 6 -- src/hotspot/share/runtime/sharedRuntime.cpp | 29 +----- src/hotspot/share/runtime/sharedRuntime.hpp | 8 -- src/hotspot/share/runtime/signature.cpp | 17 ---- src/hotspot/share/runtime/signature.hpp | 19 ---- .../share/runtime/stackChunkFrameStream.hpp | 12 --- .../runtime/stackChunkFrameStream.inline.hpp | 19 ---- src/hotspot/share/runtime/stackOverflow.cpp | 14 --- src/hotspot/share/runtime/stackOverflow.hpp | 1 - .../share/runtime/stackValueCollection.hpp | 1 - src/hotspot/share/runtime/stackWatermark.hpp | 1 - .../share/runtime/stubCodeGenerator.cpp | 6 -- .../share/runtime/stubCodeGenerator.hpp | 1 - src/hotspot/share/runtime/stubRoutines.cpp | 4 - src/hotspot/share/runtime/stubRoutines.hpp | 8 -- .../share/runtime/suspendedThreadTask.hpp | 1 - src/hotspot/share/runtime/synchronizer.cpp | 10 -- src/hotspot/share/runtime/synchronizer.hpp | 11 --- src/hotspot/share/runtime/thread.cpp | 8 -- src/hotspot/share/runtime/thread.hpp | 6 -- .../share/runtime/threadHeapSampler.hpp | 1 - src/hotspot/share/runtime/threadSMR.hpp | 23 ----- .../share/runtime/threadStatisticalInfo.hpp | 1 - src/hotspot/share/runtime/threads.cpp | 6 -- src/hotspot/share/runtime/threads.hpp | 1 - src/hotspot/share/runtime/timer.hpp | 1 - src/hotspot/share/runtime/timerTrace.hpp | 8 -- src/hotspot/share/runtime/vframe.cpp | 92 ------------------- src/hotspot/share/runtime/vframe.hpp | 36 -------- src/hotspot/share/runtime/vframe.inline.hpp | 2 - src/hotspot/share/runtime/vframeArray.cpp | 5 +- src/hotspot/share/runtime/vframeArray.hpp | 15 --- src/hotspot/share/runtime/vframe_hp.cpp | 7 -- src/hotspot/share/runtime/vframe_hp.hpp | 5 - src/hotspot/share/runtime/vmOperations.cpp | 1 - src/hotspot/share/runtime/vmStructs.cpp | 1 - 100 files changed, 11 insertions(+), 1058 deletions(-) diff --git a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp index 79976b84d0a..6075c09f8d2 100644 --- a/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/continuationFreezeThaw_aarch64.inline.hpp @@ -196,11 +196,6 @@ inline void ThawBase::prefetch_chunk_pd(void* start, int size) { Prefetch::read(start, size - 64); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - frame::sender_sp_offset) = fp; -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { // Fast path depends on !PreserveFramePointer. See can_thaw_fast(). diff --git a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp index 58200559181..598104264d8 100644 --- a/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp +++ b/src/hotspot/cpu/aarch64/stackChunkFrameStream_aarch64.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp b/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp index c166ca72254..f79a22751c1 100644 --- a/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp +++ b/src/hotspot/cpu/arm/continuationFreezeThaw_arm.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp b/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp index b3c2714037c..218f5841181 100644 --- a/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp +++ b/src/hotspot/cpu/arm/stackChunkFrameStream_arm.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp b/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp index 06b0f045f1c..e4489660f46 100644 --- a/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/stackChunkFrameStream_ppc.inline.hpp @@ -80,12 +80,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(ijava_idx(esp)) + 1 - frame::metadata_words; // On PPC esp points to the next free slot } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp index 9f69f681ba3..7863cbe6415 100644 --- a/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/continuationFreezeThaw_riscv.inline.hpp @@ -199,11 +199,6 @@ inline void ThawBase::prefetch_chunk_pd(void* start, int size) { Prefetch::read(start, size - 64); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - 2) = fp; -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { // Fast path depends on !PreserveFramePointer. See can_thaw_fast(). diff --git a/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp b/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp index 9fb17e6e4e2..38ee1de6470 100644 --- a/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp +++ b/src/hotspot/cpu/riscv/stackChunkFrameStream_riscv.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp b/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp index a97e700ee3a..5b9c5d9a8bd 100644 --- a/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp +++ b/src/hotspot/cpu/s390/continuationFreezeThaw_s390.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp b/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp index 2df1e38a9de..4f372c982d5 100644 --- a/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp +++ b/src/hotspot/cpu/s390/stackChunkFrameStream_s390.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp index 0b2b51f6e45..fc804b3795a 100644 --- a/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp +++ b/src/hotspot/cpu/x86/continuationFreezeThaw_x86.inline.hpp @@ -199,11 +199,6 @@ inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { assert(!PreserveFramePointer, "Frame pointers need to be fixed"); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - intptr_t* fp = _cont.entryFP(); - *(intptr_t**)(sp - frame::sender_sp_offset) = fp; -} - // Slow path inline frame ThawBase::new_entry_frame() { diff --git a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp index 70f10dc646d..6240de27b6b 100644 --- a/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp +++ b/src/hotspot/cpu/x86/stackChunkFrameStream_x86.inline.hpp @@ -76,12 +76,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return derelativize(frame::interpreter_frame_last_sp_offset); } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - assert_is_interpreted_and_frame_type_mixed(); - return (derelativize(frame::interpreter_frame_locals_offset) + 1 >= _end) ? _end : fp() + frame::sender_sp_offset; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { assert_is_interpreted_and_frame_type_mixed(); diff --git a/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp b/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp index 69d77500fa7..7de24a461c9 100644 --- a/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp +++ b/src/hotspot/cpu/zero/continuationFreezeThaw_zero.inline.hpp @@ -87,10 +87,6 @@ inline void ThawBase::patch_pd(frame& f, const frame& caller) { Unimplemented(); } -void ThawBase::patch_chunk_pd(intptr_t* sp) { - Unimplemented(); -} - template inline void Thaw::patch_caller_links(intptr_t* sp, intptr_t* bottom) { Unimplemented(); diff --git a/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp b/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp index 64eb4e00ced..d9f16caca1e 100644 --- a/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp +++ b/src/hotspot/cpu/zero/stackChunkFrameStream_zero.inline.hpp @@ -67,12 +67,6 @@ inline intptr_t* StackChunkFrameStream::unextended_sp_for_interprete return NULL; } -template -intptr_t* StackChunkFrameStream::next_sp_for_interpreter_frame() const { - Unimplemented(); - return NULL; -} - template inline void StackChunkFrameStream::next_for_interpreter_frame() { Unimplemented(); diff --git a/src/hotspot/cpu/zero/stubGenerator_zero.cpp b/src/hotspot/cpu/zero/stubGenerator_zero.cpp index 80e55d9c8e4..4fe19588133 100644 --- a/src/hotspot/cpu/zero/stubGenerator_zero.cpp +++ b/src/hotspot/cpu/zero/stubGenerator_zero.cpp @@ -191,12 +191,9 @@ class StubGenerator: public StubCodeGenerator { // atomic calls StubRoutines::_atomic_xchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_xchg_long_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_cmpxchg_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_cmpxchg_byte_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_cmpxchg_long_entry = ShouldNotCallThisStub(); StubRoutines::_atomic_add_entry = ShouldNotCallThisStub(); - StubRoutines::_atomic_add_long_entry = ShouldNotCallThisStub(); StubRoutines::_fence_entry = ShouldNotCallThisStub(); } diff --git a/src/hotspot/share/prims/forte.cpp b/src/hotspot/share/prims/forte.cpp index eddf7697256..cd417acab98 100644 --- a/src/hotspot/share/prims/forte.cpp +++ b/src/hotspot/share/prims/forte.cpp @@ -606,9 +606,6 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { return; } - // !important! make sure all to call thread->set_in_asgct(false) before every return - thread->set_in_asgct(true); - switch (thread->thread_state()) { case _thread_new: case _thread_uninitialized: @@ -666,7 +663,6 @@ void AsyncGetCallTrace(ASGCT_CallTrace *trace, jint depth, void* ucontext) { trace->num_frames = ticks_unknown_state; // -7 break; } - thread->set_in_asgct(false); } diff --git a/src/hotspot/share/runtime/abstract_vm_version.cpp b/src/hotspot/share/runtime/abstract_vm_version.cpp index 72045d2bde5..1124507f46d 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.cpp +++ b/src/hotspot/share/runtime/abstract_vm_version.cpp @@ -161,13 +161,6 @@ const char* Abstract_VM_Version::vm_release() { return VM_RELEASE; } -// NOTE: do *not* use stringStream. this function is called by -// fatal error handlers. if the crash is in native thread, -// stringStream cannot get resource allocated and will SEGV. -const char* Abstract_VM_Version::jre_release_version() { - return VERSION_STRING; -} - #define OS LINUX_ONLY("linux") \ WINDOWS_ONLY("windows") \ AIX_ONLY("aix") \ @@ -281,10 +274,6 @@ const char* Abstract_VM_Version::internal_vm_info_string() { : VMNAME " (" DEBUG_LEVEL " " INTERNAL_VERSION_SUFFIX; } -const char *Abstract_VM_Version::vm_build_user() { - return HOTSPOT_BUILD_USER; -} - const char *Abstract_VM_Version::jdk_debug_level() { return DEBUG_LEVEL; } diff --git a/src/hotspot/share/runtime/abstract_vm_version.hpp b/src/hotspot/share/runtime/abstract_vm_version.hpp index a1dd51dad2c..4dfc40f4f18 100644 --- a/src/hotspot/share/runtime/abstract_vm_version.hpp +++ b/src/hotspot/share/runtime/abstract_vm_version.hpp @@ -102,7 +102,6 @@ class Abstract_VM_Version: AllStatic { static const char* vm_info_string(); static const char* vm_release(); static const char* vm_platform_string(); - static const char* vm_build_user(); static int vm_major_version() { return _vm_major_version; } static int vm_minor_version() { return _vm_minor_version; } @@ -115,7 +114,6 @@ class Abstract_VM_Version: AllStatic { // Internal version providing additional build information static const char* internal_vm_info_string(); - static const char* jre_release_version(); static const char* jdk_debug_level(); static const char* printable_jdk_debug_level(); @@ -166,12 +164,6 @@ class Abstract_VM_Version: AllStatic { return _data_cache_line_flush_size != 0; } - // Number of page sizes efficiently supported by the hardware. Most chips now - // support two sizes, thus this default implementation. Processor-specific - // subclasses should define new versions to hide this one as needed. Note - // that the O/S may support more sizes, but at most this many are used. - static uint page_size_count() { return 2; } - // Denominator for computing default ParallelGCThreads for machines with // a large number of cores. static uint parallel_worker_threads_denominator() { return 8; } diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index bd6dad0d0e2..405fb123e8d 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -4163,38 +4163,6 @@ const char* Arguments::PropertyList_get_readable_value(SystemProperty *pl, const return NULL; } -const char* Arguments::PropertyList_get_key_at(SystemProperty *pl, int index) { - int count = 0; - const char* ret_val = NULL; - - while(pl != NULL) { - if(count >= index) { - ret_val = pl->key(); - break; - } - count++; - pl = pl->next(); - } - - return ret_val; -} - -char* Arguments::PropertyList_get_value_at(SystemProperty* pl, int index) { - int count = 0; - char* ret_val = NULL; - - while(pl != NULL) { - if(count >= index) { - ret_val = pl->value(); - break; - } - count++; - pl = pl->next(); - } - - return ret_val; -} - void Arguments::PropertyList_add(SystemProperty** plist, SystemProperty *new_p) { SystemProperty* p = *plist; if (p == NULL) { diff --git a/src/hotspot/share/runtime/arguments.hpp b/src/hotspot/share/runtime/arguments.hpp index a1c42a4318c..cbf9dc33745 100644 --- a/src/hotspot/share/runtime/arguments.hpp +++ b/src/hotspot/share/runtime/arguments.hpp @@ -86,7 +86,6 @@ class ModulePatchPath : public CHeapObj { ModulePatchPath(const char* module_name, const char* path); ~ModulePatchPath(); - inline void set_path(const char* path) { _path->set_value(path); } inline const char* module_name() const { return _module_name; } inline char* path_string() const { return _path->value(); } }; @@ -174,7 +173,6 @@ class AgentLibrary : public CHeapObj { void set_static_lib(bool is_static_lib) { _is_static_lib = is_static_lib; } bool valid() { return (_state == agent_valid); } void set_valid() { _state = agent_valid; } - void set_invalid() { _state = agent_invalid; } // Constructor AgentLibrary(const char* name, const char* options, bool is_absolute_path, @@ -592,8 +590,6 @@ class Arguments : AllStatic { static const char* PropertyList_get_readable_value(SystemProperty* plist, const char* key); static int PropertyList_count(SystemProperty* pl); static int PropertyList_readable_count(SystemProperty* pl); - static const char* PropertyList_get_key_at(SystemProperty* pl,int index); - static char* PropertyList_get_value_at(SystemProperty* pl,int index); static bool is_internal_module_property(const char* option); @@ -618,12 +614,10 @@ class Arguments : AllStatic { static GrowableArray* get_patch_mod_prefix() { return _patch_mod_prefix; } static char* get_boot_class_path() { return _boot_class_path->value(); } - static char* get_jdk_boot_class_path_append() { return _jdk_boot_class_path_append->value(); } static bool has_jimage() { return _has_jimage; } static char* get_java_home() { return _java_home->value(); } static char* get_dll_dir() { return _sun_boot_library_path->value(); } - static char* get_ext_dirs() { return _ext_dirs; } static char* get_appclasspath() { return _java_class_path->value(); } static void fix_appclasspath(); diff --git a/src/hotspot/share/runtime/continuationEntry.hpp b/src/hotspot/share/runtime/continuationEntry.hpp index 0d578827309..d2d5a5ab366 100644 --- a/src/hotspot/share/runtime/continuationEntry.hpp +++ b/src/hotspot/share/runtime/continuationEntry.hpp @@ -103,8 +103,6 @@ class ContinuationEntry { static address compiled_entry(); static address interpreted_entry(); - static CompiledMethod* enter_special() { return _enter_special; } - int argsize() const { return _argsize; } void set_argsize(int value) { _argsize = value; } diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index c56178e6008..645b6619cc8 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -388,7 +388,6 @@ class FreezeBase : public StackObj { protected: inline void init_rest(); - void freeze_fast_init_cont_data(intptr_t* frame_sp); void throw_stack_overflow_on_humongous_chunk(); // fast path @@ -1721,7 +1720,6 @@ class ThawBase : public StackObj { // fast path inline void prefetch_chunk_pd(void* start, int size_words); void patch_return(intptr_t* sp, bool is_last); - void patch_chunk_pd(intptr_t* sp); // TODO remove // slow path NOINLINE intptr_t* thaw_slow(stackChunkOop chunk, bool return_barrier); @@ -1803,8 +1801,6 @@ class ReconstructedStack : public StackObj { assert(_base - 1 <= top() + total_size() + frame::metadata_words_at_bottom, "missed entry frame"); } - int thaw_size() const { return _thaw_size; } - int argsize() const { return _argsize; } int entry_frame_extension() const { return _argsize + (_argsize > 0 ? frame::metadata_words_at_top : 0); } // top and bottom stack pointers @@ -1865,7 +1861,6 @@ void ThawBase::patch_return(intptr_t* sp, bool is_last) { address pc = !is_last ? StubRoutines::cont_returnBarrier() : _cont.entryPC(); *(address*)(sp - frame::sender_sp_ret_address_offset()) = pc; - // patch_chunk_pd(sp); -- TODO: If not needed - remove method; it's not used elsewhere } template diff --git a/src/hotspot/share/runtime/continuationHelper.hpp b/src/hotspot/share/runtime/continuationHelper.hpp index 1ab101709aa..e3958632975 100644 --- a/src/hotspot/share/runtime/continuationHelper.hpp +++ b/src/hotspot/share/runtime/continuationHelper.hpp @@ -75,10 +75,6 @@ class ContinuationHelper::Frame : public AllStatic { static inline intptr_t* frame_top(const frame &f); static inline bool is_deopt_return(address pc, const frame& sender); static bool assert_frame_laid_out(frame f); - - static char* method_name(Method* m) { return m != nullptr ? m->name_and_sig_as_C_string() : nullptr; } - static Method* top_java_frame_method(const frame& f); - static Method* bottom_java_frame_method(const frame& f) { return frame_method(f); } #endif }; @@ -97,7 +93,6 @@ class ContinuationHelper::InterpretedFrame : public ContinuationHelper::Frame { static address return_pc(const frame& f); static void patch_sender_sp(frame& f, const frame& caller); - static int size(const frame& f, InterpreterOopMap* mask); static int size(const frame& f); static inline int expression_stack_size(const frame &f, InterpreterOopMap* mask); @@ -118,7 +113,6 @@ class ContinuationHelper::NonInterpretedFrame : public ContinuationHelper::Frame static inline int size(const frame& f); static inline int stack_argsize(const frame& f); - static inline int num_oops(const frame& f); }; class ContinuationHelper::NonInterpretedUnknownFrame : public ContinuationHelper::NonInterpretedFrame { @@ -128,8 +122,6 @@ class ContinuationHelper::NonInterpretedUnknownFrame : public ContinuationHelper class ContinuationHelper::CompiledFrame : public ContinuationHelper::NonInterpretedFrame { public: - static inline int num_oops(const frame& f); - static bool is_instance(const frame& f); #ifdef ASSERT diff --git a/src/hotspot/share/runtime/continuationHelper.inline.hpp b/src/hotspot/share/runtime/continuationHelper.inline.hpp index 07ba6618861..4e74a7871b9 100644 --- a/src/hotspot/share/runtime/continuationHelper.inline.hpp +++ b/src/hotspot/share/runtime/continuationHelper.inline.hpp @@ -61,21 +61,6 @@ inline intptr_t* ContinuationHelper::Frame::frame_top(const frame &f) { } } -inline Method* ContinuationHelper::Frame::top_java_frame_method(const frame& f) { - Method* m = nullptr; - if (f.is_interpreted_frame()) { - m = f.interpreter_frame_method(); - } else if (f.is_compiled_frame()) { - CompiledMethod* cm = f.cb()->as_compiled_method(); - ScopeDesc* scope = cm->scope_desc_at(f.pc()); - m = scope->method(); - } else if (f.is_native_frame()) { - m = f.cb()->as_nmethod()->method(); - } - - return m; -} - inline bool ContinuationHelper::Frame::is_deopt_return(address pc, const frame& sender) { if (sender.is_interpreted_frame()) return false; @@ -131,10 +116,6 @@ inline intptr_t* ContinuationHelper::InterpretedFrame::frame_top(const frame& f) return f.unextended_sp(); } -inline int ContinuationHelper::InterpretedFrame::size(const frame&f, InterpreterOopMap* mask) { - return InterpretedFrame::frame_bottom(f) - InterpretedFrame::frame_top(f, mask); -} - inline intptr_t* ContinuationHelper::NonInterpretedFrame::frame_top(const frame& f, int callee_argsize, bool callee_interpreted) { return f.unextended_sp() + (callee_interpreted ? 0 : callee_argsize); } @@ -156,20 +137,10 @@ inline int ContinuationHelper::NonInterpretedFrame::stack_argsize(const frame& f return f.compiled_frame_stack_argsize(); } -inline int ContinuationHelper::NonInterpretedFrame::num_oops(const frame& f) { - assert(!f.is_interpreted_frame(), ""); - return f.num_oops(); -} - inline bool ContinuationHelper::CompiledFrame::is_instance(const frame& f) { return f.is_compiled_frame(); } -inline int ContinuationHelper::CompiledFrame::num_oops(const frame& f) { - assert(CompiledFrame::is_instance(f), "Not a compiled frame"); - return f.num_oops() + 1; -} - #ifdef ASSERT template bool ContinuationHelper::CompiledFrame::is_owning_locks(JavaThread* thread, RegisterMapT* map, const frame& f) { diff --git a/src/hotspot/share/runtime/continuationJavaClasses.hpp b/src/hotspot/share/runtime/continuationJavaClasses.hpp index 99c5d4ef887..2186dbe3535 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.hpp @@ -41,8 +41,6 @@ class jdk_internal_vm_ContinuationScope: AllStatic { static void compute_offsets(); public: static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; - - static inline oop name(oop ref); }; // Interface to jdk.internal.vm.Continuation objects @@ -63,13 +61,9 @@ class jdk_internal_vm_Continuation: AllStatic { static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; // Accessors static inline oop scope(oop continuation); - static inline oop target(oop continuation); static inline oop parent(oop continuation); - static inline oop yieldInfo(oop continuation); - static inline void set_yieldInfo(oop continuation, oop value); static inline stackChunkOop tail(oop continuation); static inline void set_tail(oop continuation, stackChunkOop value); - static inline bool on_local_stack(oop continuation, address adr); static inline bool done(oop continuation); static inline bool is_preempted(oop continuation); static inline void set_preempted(oop continuation, bool value); @@ -130,12 +124,12 @@ class jdk_internal_vm_StackChunk: AllStatic { static inline void set_maxThawingSize(oop chunk, int value); // cont oop's processing is essential for the chunk's GC protocol - static inline oop cont(oop chunk); - static inline void set_cont(oop chunk, oop value); - template - static inline void set_cont_raw(oop chunk, oop value); - template - static inline void set_cont_access(oop chunk, oop value); + static inline oop cont(oop chunk); + static inline void set_cont(oop chunk, oop value); + template + static inline void set_cont_raw(oop chunk, oop value); + template + static inline void set_cont_access(oop chunk, oop value); }; #endif // SHARE_RUNTIME_CONTINUATIONJAVACLASSES_HPP diff --git a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp index 6262eea8427..1d0ff75225a 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp @@ -33,30 +33,14 @@ #include "oops/stackChunkOop.inline.hpp" #include "runtime/atomic.hpp" -inline oop jdk_internal_vm_ContinuationScope::name(oop ref) { - return ref->obj_field(_name_offset); -} - inline oop jdk_internal_vm_Continuation::scope(oop continuation) { return continuation->obj_field(_scope_offset); } -inline oop jdk_internal_vm_Continuation::target(oop continuation) { - return continuation->obj_field(_target_offset); -} - inline oop jdk_internal_vm_Continuation::parent(oop continuation) { return continuation->obj_field(_parent_offset); } -inline oop jdk_internal_vm_Continuation::yieldInfo(oop continuation) { - return continuation->obj_field(_yieldInfo_offset); -} - -inline void jdk_internal_vm_Continuation::set_yieldInfo(oop continuation, oop value) { - continuation->obj_field_put(_yieldInfo_offset, value); -} - inline stackChunkOop jdk_internal_vm_Continuation::tail(oop continuation) { return stackChunkOopDesc::cast(continuation->obj_field(_tail_offset)); } diff --git a/src/hotspot/share/runtime/continuationWrapper.inline.hpp b/src/hotspot/share/runtime/continuationWrapper.inline.hpp index ce5217c7fba..fc89d98be64 100644 --- a/src/hotspot/share/runtime/continuationWrapper.inline.hpp +++ b/src/hotspot/share/runtime/continuationWrapper.inline.hpp @@ -111,9 +111,7 @@ class ContinuationWrapper : public StackObj { stackChunkOop tail() const { return _tail; } void set_tail(stackChunkOop chunk) { _tail = chunk; } - inline oop parent(); inline bool is_preempted(); - inline void set_preempted(bool value); inline void read(); inline void write(); @@ -162,18 +160,10 @@ inline ContinuationWrapper::ContinuationWrapper(oop continuation) read(); } -inline oop ContinuationWrapper::parent() { - return jdk_internal_vm_Continuation::parent(_continuation); -} - inline bool ContinuationWrapper::is_preempted() { return jdk_internal_vm_Continuation::is_preempted(_continuation); } -inline void ContinuationWrapper::set_preempted(bool value) { - jdk_internal_vm_Continuation::set_preempted(_continuation, value); -} - inline void ContinuationWrapper::read() { _tail = jdk_internal_vm_Continuation::tail(_continuation); } diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index c86f3b96475..b63038b2b5d 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -98,8 +98,6 @@ #include "jfr/metadata/jfrSerializer.hpp" #endif -bool DeoptimizationMarker::_is_active = false; - Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame, int caller_adjustment, int caller_actual_parameters, @@ -126,21 +124,12 @@ Deoptimization::UnrollBlock::UnrollBlock(int size_of_deoptimized_frame, assert(exec_mode >= 0 && exec_mode < Unpack_LIMIT, "Unexpected exec_mode"); } - Deoptimization::UnrollBlock::~UnrollBlock() { FREE_C_HEAP_ARRAY(intptr_t, _frame_sizes); FREE_C_HEAP_ARRAY(intptr_t, _frame_pcs); FREE_C_HEAP_ARRAY(intptr_t, _register_block); } - -intptr_t* Deoptimization::UnrollBlock::value_addr_at(int register_number) const { - assert(register_number < RegisterMap::reg_count, "checking register number"); - return &_register_block[register_number * 2]; -} - - - int Deoptimization::UnrollBlock::size_of_frames() const { // Account first for the adjustment of the initial frame int result = _caller_adjustment; @@ -150,7 +139,6 @@ int Deoptimization::UnrollBlock::size_of_frames() const { return result; } - void Deoptimization::UnrollBlock::print() { ResourceMark rm; stringStream st; @@ -164,7 +152,6 @@ void Deoptimization::UnrollBlock::print() { tty->print_raw(st.freeze()); } - // In order to make fetch_unroll_info work properly with escape // analysis, the method was changed from JRT_LEAF to JRT_BLOCK_ENTRY. // The actual reallocation of previously eliminated objects occurs in realloc_objects, @@ -933,7 +920,6 @@ class DeoptimizeMarkedClosure : public HandshakeClosure { void Deoptimization::deoptimize_all_marked(nmethod* nmethod_only) { ResourceMark rm; - DeoptimizationMarker dm; // Make the dependent methods not entrant if (nmethod_only != NULL) { @@ -1655,7 +1641,6 @@ void Deoptimization::deoptimize(JavaThread* thread, frame fr, DeoptReason reason return; } ResourceMark rm; - DeoptimizationMarker dm; deoptimize_single_frame(thread, fr, reason); } diff --git a/src/hotspot/share/runtime/deoptimization.hpp b/src/hotspot/share/runtime/deoptimization.hpp index 65e86ce285b..19d05bb0aa7 100644 --- a/src/hotspot/share/runtime/deoptimization.hpp +++ b/src/hotspot/share/runtime/deoptimization.hpp @@ -227,14 +227,9 @@ class Deoptimization : AllStatic { int unpack_kind); ~UnrollBlock(); - // Returns where a register is located. - intptr_t* value_addr_at(int register_number) const; - // Accessors intptr_t* frame_sizes() const { return _frame_sizes; } int number_of_frames() const { return _number_of_frames; } - address* frame_pcs() const { return _frame_pcs ; } - int unpack_kind() const { return _unpack_kind; } // Returns the total size of frames int size_of_frames() const; @@ -250,8 +245,6 @@ class Deoptimization : AllStatic { static int frame_sizes_offset_in_bytes() { return offset_of(UnrollBlock, _frame_sizes); } static int total_frame_sizes_offset_in_bytes() { return offset_of(UnrollBlock, _total_frame_sizes); } static int frame_pcs_offset_in_bytes() { return offset_of(UnrollBlock, _frame_pcs); } - static int register_block_offset_in_bytes() { return offset_of(UnrollBlock, _register_block); } - static int return_type_offset_in_bytes() { return offset_of(UnrollBlock, _return_type); } static int counter_temp_offset_in_bytes() { return offset_of(UnrollBlock, _counter_temp); } static int initial_info_offset_in_bytes() { return offset_of(UnrollBlock, _initial_info); } static int unpack_kind_offset_in_bytes() { return offset_of(UnrollBlock, _unpack_kind); } @@ -473,13 +466,4 @@ class Deoptimization : AllStatic { static void update_method_data_from_interpreter(MethodData* trap_mdo, int trap_bci, int reason); }; - -class DeoptimizationMarker : StackObj { // for profiling - static bool _is_active; -public: - DeoptimizationMarker() { _is_active = true; } - ~DeoptimizationMarker() { _is_active = false; } - static bool is_active() { return _is_active; } -}; - #endif // SHARE_RUNTIME_DEOPTIMIZATION_HPP diff --git a/src/hotspot/share/runtime/escapeBarrier.hpp b/src/hotspot/share/runtime/escapeBarrier.hpp index 61a81628321..67b6be39683 100644 --- a/src/hotspot/share/runtime/escapeBarrier.hpp +++ b/src/hotspot/share/runtime/escapeBarrier.hpp @@ -120,8 +120,6 @@ class EscapeBarrier : StackObj { // Returns true iff objects were reallocated and relocked because of access through JVMTI. static bool objs_are_deoptimized(JavaThread* thread, intptr_t* fr_id); - static bool deoptimizing_objects_for_all_threads() { return _deoptimizing_objects_for_all_threads; } - ~EscapeBarrier() { if (!barrier_active()) return; if (all_threads()) { diff --git a/src/hotspot/share/runtime/fieldDescriptor.cpp b/src/hotspot/share/runtime/fieldDescriptor.cpp index 5047aa2c10c..c90ad16651d 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.cpp +++ b/src/hotspot/share/runtime/fieldDescriptor.cpp @@ -35,11 +35,6 @@ #include "runtime/handles.inline.hpp" #include "runtime/signature.hpp" - -oop fieldDescriptor::loader() const { - return _cp->pool_holder()->class_loader(); -} - Symbol* fieldDescriptor::generic_signature() const { if (!has_generic_signature()) { return NULL; diff --git a/src/hotspot/share/runtime/fieldDescriptor.hpp b/src/hotspot/share/runtime/fieldDescriptor.hpp index cbb13ba292b..6bdbec2dd3e 100644 --- a/src/hotspot/share/runtime/fieldDescriptor.hpp +++ b/src/hotspot/share/runtime/fieldDescriptor.hpp @@ -61,7 +61,6 @@ class fieldDescriptor { inline ConstantPool* constants() const; AccessFlags access_flags() const { return _access_flags; } - oop loader() const; // Offset (in bytes) of field from start of instanceOop / Klass* inline int offset() const; Symbol* generic_signature() const; @@ -83,16 +82,12 @@ class fieldDescriptor { inline BasicType field_type() const; // Access flags - bool is_public() const { return access_flags().is_public(); } bool is_private() const { return access_flags().is_private(); } bool is_protected() const { return access_flags().is_protected(); } - bool is_package_private() const { return !is_public() && !is_private() && !is_protected(); } bool is_static() const { return access_flags().is_static(); } bool is_final() const { return access_flags().is_final(); } bool is_stable() const { return access_flags().is_stable(); } - bool is_volatile() const { return access_flags().is_volatile(); } - bool is_transient() const { return access_flags().is_transient(); } bool is_synthetic() const { return access_flags().is_synthetic(); } diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index e3c935de17f..7b002d7e771 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -773,8 +773,6 @@ class InterpreterFrameClosure : public OffsetClosure { } } } - - int max_locals() { return _max_locals; } }; diff --git a/src/hotspot/share/runtime/frame.hpp b/src/hotspot/share/runtime/frame.hpp index d067f97f82e..d93f84f0020 100644 --- a/src/hotspot/share/runtime/frame.hpp +++ b/src/hotspot/share/runtime/frame.hpp @@ -210,9 +210,6 @@ class frame { // the frame size in machine words inline int frame_size() const; - // the number of oops in the frame for non-interpreted frames - inline int num_oops() const; - // the size, in words, of stack-passed arguments inline int compiled_frame_stack_argsize() const; @@ -235,7 +232,6 @@ class frame { inline frame sender_for_compiled_frame(RegisterMap* map) const; frame sender_for_entry_frame(RegisterMap* map) const; frame sender_for_interpreter_frame(RegisterMap* map) const; - frame sender_for_native_frame(RegisterMap* map) const; frame sender_for_upcall_stub_frame(RegisterMap* map) const; bool is_entry_frame_valid(JavaThread* thread) const; @@ -255,20 +251,6 @@ class frame { return _on_heap ? at_relative(index) : at_absolute(index); } - // accessors for locals - oop obj_at(int offset) const { return *obj_at_addr(offset); } - void obj_at_put(int offset, oop value) { *obj_at_addr(offset) = value; } - - jint int_at(int offset) const { return *int_at_addr(offset); } - void int_at_put(int offset, jint value) { *int_at_addr(offset) = value; } - - oop* obj_at_addr(int offset) const { return (oop*) addr_at(offset); } - - oop* adjusted_obj_at_addr(Method* method, int index) { return obj_at_addr(adjust_offset(method, index)); } - - private: - jint* int_at_addr(int offset) const { return (jint*) addr_at(offset); } - public: // Link (i.e., the pointer to the previous frame) // might crash if the frame has no parent @@ -465,7 +447,6 @@ class frame { void oops_code_blob_do(OopClosure* f, CodeBlobClosure* cf, DerivedOopClosure* df, DerivedPointerIterationMode derived_mode, const RegisterMap* map) const; - int adjust_offset(Method* method, int index); // helper for above fn public: // Memory management void oops_do(OopClosure* f, CodeBlobClosure* cf, const RegisterMap* map) { diff --git a/src/hotspot/share/runtime/frame.inline.hpp b/src/hotspot/share/runtime/frame.inline.hpp index 926f7d6b38d..8fb0e6ccf56 100644 --- a/src/hotspot/share/runtime/frame.inline.hpp +++ b/src/hotspot/share/runtime/frame.inline.hpp @@ -104,11 +104,4 @@ inline CodeBlob* frame::get_cb() const { return _cb; } -inline int frame::num_oops() const { - assert(!is_interpreted_frame(), "interpreted"); - assert(oop_map() != NULL, ""); - return oop_map()->num_oops() ; -} - - #endif // SHARE_RUNTIME_FRAME_INLINE_HPP diff --git a/src/hotspot/share/runtime/handles.hpp b/src/hotspot/share/runtime/handles.hpp index a4f245a55c5..dd7a4d48d83 100644 --- a/src/hotspot/share/runtime/handles.hpp +++ b/src/hotspot/share/runtime/handles.hpp @@ -213,9 +213,6 @@ class HandleArea: public Arena { // Garbage collection support void oops_do(OopClosure* f); - // Number of handles in use - size_t used() const { return Arena::used() / oopSize; } - debug_only(bool no_handle_mark_active() { return _no_handle_mark_nesting > 0; }) }; diff --git a/src/hotspot/share/runtime/java.hpp b/src/hotspot/share/runtime/java.hpp index ad179662f7b..93978411bfc 100644 --- a/src/hotspot/share/runtime/java.hpp +++ b/src/hotspot/share/runtime/java.hpp @@ -126,15 +126,6 @@ class JDK_Version { // Performs a full ordering comparison using all fields (patch, build, etc.) int compare(const JDK_Version& other) const; - /** - * Performs comparison using only the major version, returning negative - * if the major version of 'this' is less than the parameter, 0 if it is - * equal, and a positive value if it is greater. - */ - int compare_major(int version) const { - return major_version() - version; - } - void to_string(char* buffer, size_t buflen) const; static const char* java_version() { diff --git a/src/hotspot/share/runtime/javaCalls.hpp b/src/hotspot/share/runtime/javaCalls.hpp index 672f8df8c7e..ba7a76fe89f 100644 --- a/src/hotspot/share/runtime/javaCalls.hpp +++ b/src/hotspot/share/runtime/javaCalls.hpp @@ -57,7 +57,6 @@ class JavaCallWrapper: StackObj { ~JavaCallWrapper(); // Accessors - JavaThread* thread() const { return _thread; } JNIHandleBlock* handles() const { return _handles; } JavaFrameAnchor* anchor(void) { return &_anchor; } @@ -65,7 +64,6 @@ class JavaCallWrapper: StackObj { JavaValue* result() const { return _result; } // GC support Method* callee_method() { return _callee_method; } - oop receiver() { return _receiver; } void oops_do(OopClosure* f); bool is_first_frame() const { return _anchor.last_Java_sp() == NULL; } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 067f1bff7d6..19bd3e657af 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -383,7 +383,6 @@ void JavaThread::check_for_valid_safepoint_state() { JavaThread::JavaThread() : // Initialize fields - _in_asgct(false), _on_thread_list(false), DEBUG_ONLY(_java_call_counter(0) COMMA) _entry_point(nullptr), @@ -981,30 +980,6 @@ bool JavaThread::is_lock_owned(address adr) const { return false; } -bool JavaThread::is_lock_owned_current(address adr) const { - address stack_end = _stack_base - _stack_size; - const ContinuationEntry* ce = vthread_continuation(); - address stack_base = ce != nullptr ? (address)ce->entry_sp() : _stack_base; - if (stack_base > adr && adr >= stack_end) { - return true; - } - - for (MonitorChunk* chunk = monitor_chunks(); chunk != NULL; chunk = chunk->next()) { - if (chunk->contains(adr)) { - return true; - } - } - - return false; -} - -bool JavaThread::is_lock_owned_carrier(address adr) const { - assert(is_vthread_mounted(), ""); - address stack_end = _stack_base - _stack_size; - address stack_base = (address)vthread_continuation()->entry_sp(); - return stack_base > adr && adr >= stack_end; -} - oop JavaThread::exception_oop() const { return Atomic::load(&_exception_oop); } @@ -1471,10 +1446,6 @@ void JavaThread::print_thread_state_on(outputStream *st) const { st->print_cr(" JavaThread state: %s", _get_thread_state_name(_thread_state)); } -const char* JavaThread::thread_state_name() const { - return _get_thread_state_name(_thread_state); -} - // Called by Threads::print() for VM_PrintThreads operation void JavaThread::print_on(outputStream *st, bool print_extended_info) const { st->print_raw("\""); @@ -1909,11 +1880,6 @@ javaVFrame* JavaThread::last_java_vframe(const frame f, RegisterMap *reg_map) { return NULL; } -oop JavaThread::get_continuation() const { - assert(threadObj() != nullptr, "must be set"); - return java_lang_Thread::continuation(threadObj()); -} - Klass* JavaThread::security_get_caller_class(int depth) { ResetNoHandleMark rnhm; HandleMark hm(Thread::current()); diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index acd6b759cec..02e646c8d77 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -84,7 +84,6 @@ class JavaThread: public Thread { friend class Threads; friend class ServiceThread; // for deferred OopHandle release access private: - bool _in_asgct; // Is set when this JavaThread is handling ASGCT call bool _on_thread_list; // Is set when this JavaThread is added to the Threads list // All references to Java objects managed via OopHandles. These @@ -469,11 +468,6 @@ class JavaThread: public Thread { public: inline StackWatermarks* stack_watermarks() { return &_stack_watermarks; } - public: - jlong _extentLocal_hash_table_shift; - - void allocate_extentLocal_hash_table(int count); - public: // Constructor JavaThread(); // delegating constructor @@ -595,7 +589,6 @@ class JavaThread: public Thread { void set_requires_cross_modify_fence(bool val) PRODUCT_RETURN NOT_PRODUCT({ _requires_cross_modify_fence = val; }) // Continuation support - oop get_continuation() const; ContinuationEntry* last_continuation() const { return _cont_entry; } void set_cont_fastpath(intptr_t* x) { _cont_fastpath = x; } void push_cont_fastpath(intptr_t* sp) { if (sp > _cont_fastpath) _cont_fastpath = sp; } @@ -670,8 +663,6 @@ class JavaThread: public Thread { // Fast-locking support bool is_lock_owned(address adr) const; - bool is_lock_owned_current(address adr) const; // virtual if mounted, otherwise whole thread - bool is_lock_owned_carrier(address adr) const; // Accessors for vframe array top // The linked list of vframe arrays are sorted on sp. This means when we @@ -697,22 +688,19 @@ class JavaThread: public Thread { CompiledMethod* deopt_compiled_method() { return _deopt_nmethod; } Method* callee_target() const { return _callee_target; } - void set_callee_target (Method* x) { _callee_target = x; } + void set_callee_target (Method* x) { _callee_target = x; } // Oop results of vm runtime calls oop vm_result() const { return _vm_result; } void set_vm_result (oop x) { _vm_result = x; } - Metadata* vm_result_2() const { return _vm_result_2; } - void set_vm_result_2 (Metadata* x) { _vm_result_2 = x; } + void set_vm_result_2 (Metadata* x) { _vm_result_2 = x; } MemRegion deferred_card_mark() const { return _deferred_card_mark; } void set_deferred_card_mark(MemRegion mr) { _deferred_card_mark = mr; } #if INCLUDE_JVMCI - int pending_deoptimization() const { return _pending_deoptimization; } jlong pending_failed_speculation() const { return _pending_failed_speculation; } - bool has_pending_monitorenter() const { return _pending_monitorenter; } void set_pending_monitorenter(bool b) { _pending_monitorenter = b; } void set_pending_deoptimization(int reason) { _pending_deoptimization = reason; } void set_pending_failed_speculation(jlong failed_speculation) { _pending_failed_speculation = failed_speculation; } @@ -733,8 +721,6 @@ class JavaThread: public Thread { // Exception handling for compiled methods oop exception_oop() const; address exception_pc() const { return _exception_pc; } - address exception_handler_pc() const { return _exception_handler_pc; } - bool is_method_handle_return() const { return _is_method_handle_return == 1; } void set_exception_oop(oop o); void set_exception_pc(address a) { _exception_pc = a; } @@ -787,7 +773,6 @@ class JavaThread: public Thread { #if INCLUDE_JVMCI static ByteSize pending_deoptimization_offset() { return byte_offset_of(JavaThread, _pending_deoptimization); } static ByteSize pending_monitorenter_offset() { return byte_offset_of(JavaThread, _pending_monitorenter); } - static ByteSize pending_failed_speculation_offset() { return byte_offset_of(JavaThread, _pending_failed_speculation); } static ByteSize jvmci_alternate_call_target_offset() { return byte_offset_of(JavaThread, _jvmci._alternate_call_target); } static ByteSize jvmci_implicit_exception_pc_offset() { return byte_offset_of(JavaThread, _jvmci._implicit_exception_pc); } static ByteSize jvmci_counters_offset() { return byte_offset_of(JavaThread, _jvmci_counters); } @@ -923,7 +908,6 @@ class JavaThread: public Thread { void print_on(outputStream* st) const { print_on(st, false); } void print() const; void print_thread_state_on(outputStream*) const; - const char* thread_state_name() const; void print_on_error(outputStream* st, char* buf, int buflen) const; void print_name_on_error(outputStream* st, char* buf, int buflen) const; void verify(); @@ -1044,7 +1028,6 @@ class JavaThread: public Thread { static ByteSize popframe_condition_offset() { return byte_offset_of(JavaThread, _popframe_condition); } bool has_pending_popframe() { return (popframe_condition() & popframe_pending_bit) != 0; } bool popframe_forcing_deopt_reexecution() { return (popframe_condition() & popframe_force_deopt_reexecution_bit) != 0; } - void clear_popframe_forcing_deopt_reexecution() { _popframe_condition &= ~popframe_force_deopt_reexecution_bit; } bool pop_frame_in_process(void) { return ((_popframe_condition & popframe_processing_bit) != 0); } void set_pop_frame_in_process(void) { _popframe_condition |= popframe_processing_bit; } @@ -1096,7 +1079,6 @@ class JavaThread: public Thread { int _should_post_on_exceptions_flag; public: - int should_post_on_exceptions_flag() { return _should_post_on_exceptions_flag; } void set_should_post_on_exceptions_flag(int val) { _should_post_on_exceptions_flag = val; } private: @@ -1171,10 +1153,6 @@ class JavaThread: public Thread { // resource allocation failure. static void vm_exit_on_osthread_failure(JavaThread* thread); - // AsyncGetCallTrace support - inline bool in_asgct(void) {return _in_asgct;} - inline void set_in_asgct(bool value) {_in_asgct = value;} - // Deferred OopHandle release support private: // List of OopHandles to be released - guarded by the Service_lock. diff --git a/src/hotspot/share/runtime/jniHandles.cpp b/src/hotspot/share/runtime/jniHandles.cpp index 60f216ee0e2..9c5e675db5f 100644 --- a/src/hotspot/share/runtime/jniHandles.cpp +++ b/src/hotspot/share/runtime/jniHandles.cpp @@ -252,15 +252,6 @@ bool JNIHandles::is_weak_global_handle(jobject handle) { return is_jweak(handle) && is_storage_handle(weak_global_handles(), jweak_ptr(handle)); } -size_t JNIHandles::global_handle_memory_usage() { - return global_handles()->total_memory_usage(); -} - -size_t JNIHandles::weak_global_handle_memory_usage() { - return weak_global_handles()->total_memory_usage(); -} - - // We assume this is called at a safepoint: no lock is needed. void JNIHandles::print_on(outputStream* st) { assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint"); @@ -539,18 +530,3 @@ bool JNIHandleBlock::chain_contains(jobject handle) const { } return false; } - - -size_t JNIHandleBlock::length() const { - size_t result = 1; - for (JNIHandleBlock* current = _next; current != NULL; current = current->_next) { - result++; - } - return result; -} - -// This method is not thread-safe, i.e., must be called while holding a lock on the -// structure. -size_t JNIHandleBlock::memory_usage() const { - return length() * sizeof(JNIHandleBlock); -} diff --git a/src/hotspot/share/runtime/jniHandles.hpp b/src/hotspot/share/runtime/jniHandles.hpp index 03926d5f9ee..9d5d4627960 100644 --- a/src/hotspot/share/runtime/jniHandles.hpp +++ b/src/hotspot/share/runtime/jniHandles.hpp @@ -108,8 +108,6 @@ class JNIHandles : AllStatic { static bool is_frame_handle(JavaThread* thread, jobject handle); static bool is_global_handle(jobject handle); static bool is_weak_global_handle(jobject handle); - static size_t global_handle_memory_usage(); - static size_t weak_global_handle_memory_usage(); // precondition: handle != NULL. static jobjectRefType handle_type(JavaThread* thread, jobject handle); @@ -180,8 +178,6 @@ class JNIHandleBlock : public CHeapObj { // Debugging bool chain_contains(jobject handle) const; // Does this block or following blocks contain handle bool contains(jobject handle) const; // Does this block contain handle - size_t length() const; // Length of chain starting with this block - size_t memory_usage() const; }; #endif // SHARE_RUNTIME_JNIHANDLES_HPP diff --git a/src/hotspot/share/runtime/jniPeriodicChecker.cpp b/src/hotspot/share/runtime/jniPeriodicChecker.cpp index a2874f5ff8c..96d16834608 100644 --- a/src/hotspot/share/runtime/jniPeriodicChecker.cpp +++ b/src/hotspot/share/runtime/jniPeriodicChecker.cpp @@ -34,11 +34,8 @@ class JniPeriodicCheckerTask : public PeriodicTask { public: JniPeriodicCheckerTask(int interval_time) : PeriodicTask(interval_time) {} void task() { os::run_periodic_checks(tty); } - static void engage(); - static void disengage(); }; - //---------------------------------------------------------- // Implementation of JniPeriodicChecker @@ -56,22 +53,3 @@ void JniPeriodicChecker::engage() { _task->enroll(); } } - - -/* - * the disengage() method is responsible for deactivating the periodic - * task. This method is called from before_exit() in java.cpp and is only called - * after the WatcherThread has been stopped. - */ -void JniPeriodicChecker::disengage() { - if (CheckJNICalls && is_active()) { - // remove JniPeriodicChecker - _task->disenroll(); - delete _task; - _task = NULL; - } -} - -void jniPeriodicChecker_exit() { - if (!CheckJNICalls) return; -} diff --git a/src/hotspot/share/runtime/jniPeriodicChecker.hpp b/src/hotspot/share/runtime/jniPeriodicChecker.hpp index f9fad332261..4d6489117b2 100644 --- a/src/hotspot/share/runtime/jniPeriodicChecker.hpp +++ b/src/hotspot/share/runtime/jniPeriodicChecker.hpp @@ -44,14 +44,7 @@ class JniPeriodicChecker : AllStatic { public: // Start/stop task static void engage(); - static void disengage(); - static bool is_active() { return _task != NULL; } - - static void initialize(); - static void destroy(); }; -void jniPeriodicChecker_exit(); - #endif // SHARE_RUNTIME_JNIPERIODICCHECKER_HPP diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.cpp b/src/hotspot/share/runtime/keepStackGCProcessed.cpp index 12bc3299f97..df851b9f1cc 100644 --- a/src/hotspot/share/runtime/keepStackGCProcessed.cpp +++ b/src/hotspot/share/runtime/keepStackGCProcessed.cpp @@ -58,19 +58,3 @@ KeepStackGCProcessedMark::~KeepStackGCProcessedMark() { void KeepStackGCProcessedMark::finish_processing() { StackWatermarkSet::finish_processing(_jt, NULL /* context */, StackWatermarkKind::gc); } - -#ifdef ASSERT -bool KeepStackGCProcessedMark::stack_is_kept_gc_processed(JavaThread* jt) { - if (!Thread::current()->is_Java_thread()) { - assert(SafepointSynchronize::is_at_safepoint() && Thread::current()->is_VM_thread(), - "must be either Java thread or VM thread in a safepoint"); - return true; - } - StackWatermark* our_watermark = StackWatermarkSet::get(JavaThread::current(), StackWatermarkKind::gc); - if (our_watermark == nullptr) { - return true; - } - StackWatermark* their_watermark = StackWatermarkSet::get(jt, StackWatermarkKind::gc); - return our_watermark->linked_watermark() == their_watermark; -} -#endif // ASSERT diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.hpp b/src/hotspot/share/runtime/keepStackGCProcessed.hpp index 9ac12520ba1..2c36991fe28 100644 --- a/src/hotspot/share/runtime/keepStackGCProcessed.hpp +++ b/src/hotspot/share/runtime/keepStackGCProcessed.hpp @@ -43,8 +43,6 @@ class KeepStackGCProcessedMark : public StackObj { public: KeepStackGCProcessedMark(JavaThread* jt); ~KeepStackGCProcessedMark(); - - static bool stack_is_kept_gc_processed(JavaThread* jt) NOT_DEBUG({ return true; }) ; }; diff --git a/src/hotspot/share/runtime/monitorChunk.hpp b/src/hotspot/share/runtime/monitorChunk.hpp index 09b609b8e35..f16aa46fa64 100644 --- a/src/hotspot/share/runtime/monitorChunk.hpp +++ b/src/hotspot/share/runtime/monitorChunk.hpp @@ -48,9 +48,6 @@ class MonitorChunk: public CHeapObj { MonitorChunk* next() const { return _next; } void set_next(MonitorChunk* next) { _next = next; } - // Tells whether the monitor chunk is linked into the JavaThread - bool is_linked() const { return next() != NULL; } - // Returns the number of monitors int number_of_monitors() const { return _number_of_monitors; } diff --git a/src/hotspot/share/runtime/monitorDeflationThread.hpp b/src/hotspot/share/runtime/monitorDeflationThread.hpp index 8bf4b546f81..4946ec5891f 100644 --- a/src/hotspot/share/runtime/monitorDeflationThread.hpp +++ b/src/hotspot/share/runtime/monitorDeflationThread.hpp @@ -41,7 +41,6 @@ class MonitorDeflationThread : public JavaThread { // Hide this thread from external view. bool is_hidden_from_external_view() const { return true; } - bool is_monitor_deflation_thread() const { return true; } }; #endif // SHARE_RUNTIME_MONITORDEFLATIONTHREAD_HPP diff --git a/src/hotspot/share/runtime/mutex.hpp b/src/hotspot/share/runtime/mutex.hpp index b719036670b..129f3e0c847 100644 --- a/src/hotspot/share/runtime/mutex.hpp +++ b/src/hotspot/share/runtime/mutex.hpp @@ -119,7 +119,6 @@ class Mutex : public CHeapObj { Rank rank() const { return _rank; } const char* rank_name() const; Mutex* next() const { return _next; } - void set_next(Mutex *next) { _next = next; } #endif // ASSERT protected: diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index 384268ac613..d71f57695e0 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -193,11 +193,6 @@ void assert_lock_strong(const Mutex* lock) { if (lock->owned_by_self()) return; fatal("must own lock %s", lock->name()); } - -void assert_locked_or_safepoint_or_handshake(const Mutex* lock, const JavaThread* thread) { - if (thread->is_handshake_safe_for(Thread::current())) return; - assert_locked_or_safepoint(lock); -} #endif static void add_mutex(Mutex* var) { diff --git a/src/hotspot/share/runtime/mutexLocker.hpp b/src/hotspot/share/runtime/mutexLocker.hpp index e32ca553f3e..6498867a3fd 100644 --- a/src/hotspot/share/runtime/mutexLocker.hpp +++ b/src/hotspot/share/runtime/mutexLocker.hpp @@ -176,19 +176,15 @@ extern Mutex* tty_lock; // lock to synchronize output. void print_owned_locks_on_error(outputStream* st); void print_lock_ranks(outputStream* st); -char *lock_name(Mutex *mutex); - // for debugging: check that we're already owning this lock (or are at a safepoint / handshake) #ifdef ASSERT void assert_locked_or_safepoint(const Mutex* lock); void assert_locked_or_safepoint_weak(const Mutex* lock); void assert_lock_strong(const Mutex* lock); -void assert_locked_or_safepoint_or_handshake(const Mutex* lock, const JavaThread* thread); #else #define assert_locked_or_safepoint(lock) #define assert_locked_or_safepoint_weak(lock) #define assert_lock_strong(lock) -#define assert_locked_or_safepoint_or_handshake(lock, thread) #endif class MutexLocker: public StackObj { diff --git a/src/hotspot/share/runtime/objectMonitor.hpp b/src/hotspot/share/runtime/objectMonitor.hpp index 57da85dddc5..3a6106d09a1 100644 --- a/src/hotspot/share/runtime/objectMonitor.hpp +++ b/src/hotspot/share/runtime/objectMonitor.hpp @@ -204,8 +204,6 @@ class ObjectMonitor : public CHeapObj { // TODO-FIXME: the "offset" routines should return a type of off_t instead of int ... // ByteSize would also be an appropriate type. - static int header_offset_in_bytes() { return offset_of(ObjectMonitor, _header); } - static int object_offset_in_bytes() { return offset_of(ObjectMonitor, _object); } static int owner_offset_in_bytes() { return offset_of(ObjectMonitor, _owner); } static int recursions_offset_in_bytes() { return offset_of(ObjectMonitor, _recursions); } static int cxq_offset_in_bytes() { return offset_of(ObjectMonitor, _cxq); } @@ -267,16 +265,8 @@ class ObjectMonitor : public CHeapObj { // Simply get _next_om field. ObjectMonitor* next_om() const; - // Get _next_om field with acquire semantics. - ObjectMonitor* next_om_acquire() const; // Simply set _next_om field to new_value. void set_next_om(ObjectMonitor* new_value); - // Set _next_om field to new_value with release semantics. - void release_set_next_om(ObjectMonitor* new_value); - // Try to set _next_om field to new_value if the current value matches - // old_value, using Atomic::cmpxchg(). Otherwise, does not change the - // _next_om field. Returns the prior value of the _next_om field. - ObjectMonitor* try_set_next_om(ObjectMonitor* old_value, ObjectMonitor* new_value); int waiters() const; diff --git a/src/hotspot/share/runtime/objectMonitor.inline.hpp b/src/hotspot/share/runtime/objectMonitor.inline.hpp index 0bace2468f6..1944141f065 100644 --- a/src/hotspot/share/runtime/objectMonitor.inline.hpp +++ b/src/hotspot/share/runtime/objectMonitor.inline.hpp @@ -160,26 +160,9 @@ inline ObjectMonitor* ObjectMonitor::next_om() const { return Atomic::load(&_next_om); } -// Get _next_om field with acquire semantics. -inline ObjectMonitor* ObjectMonitor::next_om_acquire() const { - return Atomic::load_acquire(&_next_om); -} - // Simply set _next_om field to new_value. inline void ObjectMonitor::set_next_om(ObjectMonitor* new_value) { Atomic::store(&_next_om, new_value); } -// Set _next_om field to new_value with release semantics. -inline void ObjectMonitor::release_set_next_om(ObjectMonitor* new_value) { - Atomic::release_store(&_next_om, new_value); -} - -// Try to set _next_om field to new_value if the current value matches -// old_value. Otherwise, does not change the _next_om field. Returns -// the prior value of the _next_om field. -inline ObjectMonitor* ObjectMonitor::try_set_next_om(ObjectMonitor* old_value, ObjectMonitor* new_value) { - return Atomic::cmpxchg(&_next_om, old_value, new_value); -} - #endif // SHARE_RUNTIME_OBJECTMONITOR_INLINE_HPP diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 971d78950b3..7ccc9cf4c58 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -584,8 +584,6 @@ class os: AllStatic { static OSReturn set_priority(Thread* thread, ThreadPriority priority); static OSReturn get_priority(const Thread* const thread, ThreadPriority& priority); - static int pd_self_suspend_thread(Thread* thread); - static address fetch_frame_from_context(const void* ucVoid, intptr_t** sp, intptr_t** fp); static frame fetch_frame_from_context(const void* ucVoid); static frame fetch_compiled_frame_from_context(const void* ucVoid); @@ -1003,7 +1001,6 @@ class os: AllStatic { static bool find(address pc, outputStream* st = tty); // OS specific function to make sense out of an address static bool dont_yield(); // when true, JVM_Yield() is nop - static void print_statistics(); // Thread priority helpers (implemented in OS-specific part) static OSReturn set_native_priority(Thread* thread, int native_prio); diff --git a/src/hotspot/share/runtime/os_perf.hpp b/src/hotspot/share/runtime/os_perf.hpp index 43c410f0aed..303f463d7b3 100644 --- a/src/hotspot/share/runtime/os_perf.hpp +++ b/src/hotspot/share/runtime/os_perf.hpp @@ -31,29 +31,6 @@ #define FUNCTIONALITY_NOT_IMPLEMENTED -8 -class EnvironmentVariable : public CHeapObj { - public: - char* _key; - char* _value; - - EnvironmentVariable() { - _key = NULL; - _value = NULL; - } - - ~EnvironmentVariable() { - FREE_C_HEAP_ARRAY(char, _key); - FREE_C_HEAP_ARRAY(char, _value); - } - - EnvironmentVariable(char* key, char* value) { - _key = key; - _value = value; - } - -}; - - class CPUInformation : public CHeapObj { private: int _no_of_sockets; @@ -129,14 +106,6 @@ class SystemProcess : public CHeapObj { _next = NULL; } - SystemProcess(int pid, char* name, char* path, char* command_line, SystemProcess* next) { - _pid = pid; - _name = name; - _path = path; - _command_line = command_line; - _next = next; - } - void set_next(SystemProcess* sys_process) { _next = sys_process; } diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index c1ab45fc40f..bc919d32e14 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -190,10 +190,6 @@ PerfLong::PerfLong(CounterNS ns, const char* namep, Units u, Variability v) create_entry(T_LONG, sizeof(jlong)); } -int PerfLong::format(char* buffer, int length) { - return jio_snprintf(buffer, length, JLONG_FORMAT, *(jlong*)_valuep); -} - PerfLongVariant::PerfLongVariant(CounterNS ns, const char* namep, Units u, Variability v, jlong* sampled) : PerfLong(ns, namep, u, v), @@ -233,10 +229,6 @@ void PerfString::set_string(const char* s2) { ((char*)_valuep)[_length-1] = '\0'; } -int PerfString::format(char* buffer, int length) { - return jio_snprintf(buffer, length, "%s", (char*)_valuep); -} - PerfStringConstant::PerfStringConstant(CounterNS ns, const char* namep, const char* initial_value) : PerfString(ns, namep, V_Constant, @@ -325,17 +317,6 @@ void PerfDataManager::add_item(PerfData* p, bool sampled) { } } -PerfDataList* PerfDataManager::all() { - - MutexLocker ml(PerfDataManager_lock); - - if (_all == NULL) - return NULL; - - PerfDataList* clone = _all->clone(); - return clone; -} - PerfDataList* PerfDataManager::sampled() { MutexLocker ml(PerfDataManager_lock); @@ -347,17 +328,6 @@ PerfDataList* PerfDataManager::sampled() { return clone; } -PerfDataList* PerfDataManager::constants() { - - MutexLocker ml(PerfDataManager_lock); - - if (_constants == NULL) - return NULL; - - PerfDataList* clone = _constants->clone(); - return clone; -} - char* PerfDataManager::counter_name(const char* ns, const char* name) { assert(ns != NULL, "ns string required"); assert(name != NULL, "name string required"); @@ -458,27 +428,6 @@ PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, return p; } -PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, - const char* name, - PerfData::Units u, - jlong* sp, TRAPS) { - - // Sampled counters not supported if UsePerfData is false - if (!UsePerfData) return NULL; - - PerfLongVariable* p = new PerfLongVariable(ns, name, u, sp); - - if (!p->is_valid()) { - // allocation of native resources failed. - delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } - - add_item(p, true); - - return p; -} - PerfLongVariable* PerfDataManager::create_long_variable(CounterNS ns, const char* name, PerfData::Units u, @@ -519,27 +468,6 @@ PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, return p; } -PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, - const char* name, - PerfData::Units u, - jlong* sp, TRAPS) { - - // Sampled counters not supported if UsePerfData is false - if (!UsePerfData) return NULL; - - PerfLongCounter* p = new PerfLongCounter(ns, name, u, sp); - - if (!p->is_valid()) { - // allocation of native resources failed. - delete p; - THROW_0(vmSymbols::java_lang_OutOfMemoryError()); - } - - add_item(p, true); - - return p; -} - PerfLongCounter* PerfDataManager::create_long_counter(CounterNS ns, const char* name, PerfData::Units u, diff --git a/src/hotspot/share/runtime/perfData.hpp b/src/hotspot/share/runtime/perfData.hpp index f7680a99578..2cefc277e4a 100644 --- a/src/hotspot/share/runtime/perfData.hpp +++ b/src/hotspot/share/runtime/perfData.hpp @@ -333,10 +333,6 @@ class PerfData : public CHeapObj { // returns the address of the data portion of the item in the // PerfData memory region. inline void* get_address() { return _valuep; } - - // returns the value of the data portion of the item in the - // PerfData memory region formatted as a string. - virtual int format(char* cp, int length) = 0; }; /* @@ -362,8 +358,6 @@ class PerfLong : public PerfData { PerfLong(CounterNS ns, const char* namep, Units u, Variability v); public: - int format(char* buffer, int length); - // returns the value of the data portion of the item in the // PerfData memory region. inline jlong get_value() { return *(jlong*)_valuep; } @@ -423,7 +417,6 @@ class PerfLongVariant : public PerfLong { inline void inc() { (*(jlong*)_valuep)++; } inline void inc(jlong val) { (*(jlong*)_valuep) += val; } inline void dec(jlong val) { inc(-val); } - inline void add(jlong val) { (*(jlong*)_valuep) += val; } }; /* @@ -510,9 +503,6 @@ class PerfString : public PerfByteArray { if (is_valid()) set_string(initial_value); } - public: - - int format(char* buffer, int length); }; /* @@ -627,14 +617,6 @@ class PerfDataList : public CHeapObj { // add a PerfData item to this list inline void append(PerfData *p); - // remove the given PerfData item from this list. When called - // while iterating over the list, this method will result in a - // change in the length of the container. The at(int index) - // method is also impacted by this method as elements with an - // index greater than the index of the element removed by this - // method will be shifted down by one. - inline void remove(PerfData *p); - // create a new PerfDataList from this list. The new list is // a shallow copy of the original list and care should be taken // with respect to delete operations on the elements of the list @@ -668,18 +650,11 @@ class PerfDataManager : AllStatic { static void add_item(PerfData* p, bool sampled); protected: - // return the list of all known PerfData items - static PerfDataList* all(); - static inline int count(); // return the list of all known PerfData items that are to be // sampled by the StatSampler. static PerfDataList* sampled(); - // return the list of all known PerfData items that have a - // variability classification of type Constant - static PerfDataList* constants(); - public: // method to check for the existence of a PerfData item with @@ -754,12 +729,6 @@ class PerfDataManager : AllStatic { int max_length, const char *s, TRAPS); - static PerfStringVariable* create_string_variable(CounterNS ns, - const char* name, - const char *s, TRAPS) { - return create_string_variable(ns, name, 0, s, THREAD); - }; - static PerfLongVariable* create_long_variable(CounterNS ns, const char* name, PerfData::Units u, @@ -771,10 +740,6 @@ class PerfDataManager : AllStatic { return create_long_variable(ns, name, u, (jlong)0, THREAD); }; - static PerfLongVariable* create_long_variable(CounterNS, const char* name, - PerfData::Units u, - jlong* sp, TRAPS); - static PerfLongVariable* create_long_variable(CounterNS ns, const char* name, PerfData::Units u, @@ -787,15 +752,6 @@ class PerfDataManager : AllStatic { PerfData::Units u, jlong ival, TRAPS); - static PerfLongCounter* create_long_counter(CounterNS ns, const char* name, - PerfData::Units u, TRAPS) { - return create_long_counter(ns, name, u, (jlong)0, THREAD); - }; - - static PerfLongCounter* create_long_counter(CounterNS ns, const char* name, - PerfData::Units u, jlong* sp, - TRAPS); - static PerfLongCounter* create_long_counter(CounterNS ns, const char* name, PerfData::Units u, PerfLongSampleHelper* sh, @@ -820,32 +776,17 @@ class PerfDataManager : AllStatic { return create_long_variable(ns, name, u, (jlong)0, THREAD); } - static PerfVariable* create_variable(CounterNS ns, const char* name, - PerfData::Units u, jlong* sp, TRAPS) { - return create_long_variable(ns, name, u, sp, THREAD); - } - static PerfVariable* create_variable(CounterNS ns, const char* name, PerfData::Units u, PerfSampleHelper* sh, TRAPS) { return create_long_variable(ns, name, u, sh, THREAD); } - static PerfCounter* create_counter(CounterNS ns, const char* name, - PerfData::Units u, jlong ival, TRAPS) { - return create_long_counter(ns, name, u, ival, THREAD); - } - static PerfCounter* create_counter(CounterNS ns, const char* name, PerfData::Units u, TRAPS) { return create_long_counter(ns, name, u, (jlong)0, THREAD); } - static PerfCounter* create_counter(CounterNS ns, const char* name, - PerfData::Units u, jlong* sp, TRAPS) { - return create_long_counter(ns, name, u, sp, THREAD); - } - static PerfCounter* create_counter(CounterNS ns, const char* name, PerfData::Units u, PerfSampleHelper* sh, TRAPS) { @@ -900,9 +841,6 @@ class PerfTraceTime : public StackObj { _t.start(); } - inline void suspend() { if (!UsePerfData) return; _t.stop(); } - inline void resume() { if (!UsePerfData) return; _t.start(); } - ~PerfTraceTime(); }; diff --git a/src/hotspot/share/runtime/perfData.inline.hpp b/src/hotspot/share/runtime/perfData.inline.hpp index 5e868816757..c802aa2f6d9 100644 --- a/src/hotspot/share/runtime/perfData.inline.hpp +++ b/src/hotspot/share/runtime/perfData.inline.hpp @@ -38,18 +38,10 @@ inline void PerfDataList::append(PerfData *p) { _set->append(p); } -inline void PerfDataList::remove(PerfData *p) { - _set->remove(p); -} - inline PerfData* PerfDataList::at(int index) { return _set->at(index); } -inline int PerfDataManager::count() { - return _all->length(); -} - inline bool PerfDataManager::exists(const char* name) { if (_all != NULL) { return _all->contains(name); diff --git a/src/hotspot/share/runtime/reflectionUtils.hpp b/src/hotspot/share/runtime/reflectionUtils.hpp index ef9f8bbd62e..c534e361ddf 100644 --- a/src/hotspot/share/runtime/reflectionUtils.hpp +++ b/src/hotspot/share/runtime/reflectionUtils.hpp @@ -70,7 +70,6 @@ class KlassStream { virtual void next() = 0; // accessors - InstanceKlass* klass() const { return _klass; } int index() const { return _index; } bool base_class_search_defaults() const { return _base_class_search_defaults; } void base_class_search_defaults(bool b) { _base_class_search_defaults = b; } diff --git a/src/hotspot/share/runtime/registerMap.hpp b/src/hotspot/share/runtime/registerMap.hpp index c13750cb7e4..c532a5062ec 100644 --- a/src/hotspot/share/runtime/registerMap.hpp +++ b/src/hotspot/share/runtime/registerMap.hpp @@ -120,16 +120,6 @@ class RegisterMap : public StackObj { } } - address trusted_location(VMReg reg) const { - return (address) _location[reg->value()]; - } - - void verify(RegisterMap& other) { - for (int i = 0; i < reg_count; ++i) { - assert(_location[i] == other._location[i], ""); - } - } - void set_location(VMReg reg, address loc) { int index = reg->value() / location_valid_type_size; assert(0 <= reg->value() && reg->value() < reg_count, "range check"); diff --git a/src/hotspot/share/runtime/relocator.cpp b/src/hotspot/share/runtime/relocator.cpp index a55dc644577..a8b239d6db2 100644 --- a/src/hotspot/share/runtime/relocator.cpp +++ b/src/hotspot/share/runtime/relocator.cpp @@ -47,8 +47,6 @@ class ChangeItem : public ResourceObj { virtual bool handle_code_change(Relocator *r) = 0; // type info - virtual bool is_widen() { return false; } - virtual bool is_jump_widen() { return false; } virtual bool is_switch_pad() { return false; } // accessors @@ -73,8 +71,6 @@ class ChangeWiden : public ChangeItem { // Callback to do instruction bool handle_code_change(Relocator *r) { return r->handle_widen(bci(), _new_ilen, _inst_buffer); }; - bool is_widen() { return true; } - void print() { tty->print_cr("ChangeWiden. bci: %d New_ilen: %d", bci(), _new_ilen); } }; @@ -86,8 +82,6 @@ class ChangeJumpWiden : public ChangeItem { // Callback to do instruction bool handle_code_change(Relocator *r) { return r->handle_jump_widen(bci(), _delta); }; - bool is_jump_widen() { return true; } - // If the bci matches, adjust the delta in the change jump request. bool adjust(int jump_bci, int delta) { if (bci() == jump_bci) { diff --git a/src/hotspot/share/runtime/relocator.hpp b/src/hotspot/share/runtime/relocator.hpp index ab6f6e0fa0e..c0c42fdfda1 100644 --- a/src/hotspot/share/runtime/relocator.hpp +++ b/src/hotspot/share/runtime/relocator.hpp @@ -37,7 +37,6 @@ class ChangeItem; // Callback object for code relocations class RelocatorListener : public StackObj { public: - RelocatorListener() {}; virtual void relocated(int bci, int delta, int new_method_size) = 0; }; diff --git a/src/hotspot/share/runtime/rtmLocking.hpp b/src/hotspot/share/runtime/rtmLocking.hpp index dbc54b97d08..db9678b17b1 100644 --- a/src/hotspot/share/runtime/rtmLocking.hpp +++ b/src/hotspot/share/runtime/rtmLocking.hpp @@ -97,8 +97,6 @@ class RTMLockingCounters { } uintx* total_count_addr() { return &_total_count; } - uintx* abort_count_addr() { return &_abort_count; } - uintx* abortX_count_addr() { return &_abortX_count[0]; } static int total_count_offset() { return (int)offset_of(RTMLockingCounters, _total_count); } static int abort_count_offset() { return (int)offset_of(RTMLockingCounters, _abort_count); } diff --git a/src/hotspot/share/runtime/safepoint.hpp b/src/hotspot/share/runtime/safepoint.hpp index eed4ab8bc94..1f78a1b8e5a 100644 --- a/src/hotspot/share/runtime/safepoint.hpp +++ b/src/hotspot/share/runtime/safepoint.hpp @@ -165,9 +165,6 @@ class SafepointSynchronize : AllStatic { static void set_is_at_safepoint() { _state = _synchronized; } static void set_is_not_at_safepoint() { _state = _not_synchronized; } - // Assembly support - static address address_of_state() { return (address)&_state; } - // Only used for making sure that no safepoint has happened in // JNI_FastGetField. Therefore only the low 32-bits are needed // even if this is a 64-bit counter. diff --git a/src/hotspot/share/runtime/safepointMechanism.hpp b/src/hotspot/share/runtime/safepointMechanism.hpp index 913999b8f39..331f5177e60 100644 --- a/src/hotspot/share/runtime/safepointMechanism.hpp +++ b/src/hotspot/share/runtime/safepointMechanism.hpp @@ -73,7 +73,6 @@ class SafepointMechanism : public AllStatic { inline uintptr_t get_polling_word(); inline void set_polling_page(uintptr_t poll_value); - inline uintptr_t get_polling_page(); }; // Call this method to see if this thread should block for a safepoint or process handshake. diff --git a/src/hotspot/share/runtime/safepointMechanism.inline.hpp b/src/hotspot/share/runtime/safepointMechanism.inline.hpp index c8a4811e44f..d0fb3a8fa2d 100644 --- a/src/hotspot/share/runtime/safepointMechanism.inline.hpp +++ b/src/hotspot/share/runtime/safepointMechanism.inline.hpp @@ -37,12 +37,6 @@ inline void SafepointMechanism::ThreadData::set_polling_page(uintptr_t poll_valu Atomic::store(&_polling_page, poll_value); } -// The acquire makes sure reading of polling page is done before -// the reading the handshake operation or the global state -inline uintptr_t SafepointMechanism::ThreadData::get_polling_page() { - return Atomic::load_acquire(&_polling_page); -} - // Caller is responsible for using a memory barrier if needed. inline void SafepointMechanism::ThreadData::set_polling_word(uintptr_t poll_value) { Atomic::store(&_polling_word, poll_value); diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 095ea6c8139..db2acd25772 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -143,15 +143,12 @@ int SharedRuntime::_implicit_null_throws = 0; int SharedRuntime::_implicit_div0_throws = 0; int64_t SharedRuntime::_nof_normal_calls = 0; -int64_t SharedRuntime::_nof_optimized_calls = 0; int64_t SharedRuntime::_nof_inlined_calls = 0; int64_t SharedRuntime::_nof_megamorphic_calls = 0; int64_t SharedRuntime::_nof_static_calls = 0; int64_t SharedRuntime::_nof_inlined_static_calls = 0; int64_t SharedRuntime::_nof_interface_calls = 0; -int64_t SharedRuntime::_nof_optimized_interface_calls = 0; int64_t SharedRuntime::_nof_inlined_interface_calls = 0; -int64_t SharedRuntime::_nof_megamorphic_interface_calls = 0; int SharedRuntime::_new_instance_ctr=0; int SharedRuntime::_new_array_ctr=0; @@ -680,17 +677,6 @@ address SharedRuntime::get_poll_stub(address pc) { return stub; } - -oop SharedRuntime::retrieve_receiver( Symbol* sig, frame caller ) { - assert(caller.is_interpreted_frame(), ""); - int args_size = ArgumentSizeComputer(sig).size() + 1; - assert(args_size <= caller.interpreter_frame_expression_stack_size(), "receiver must be on interpreter stack"); - oop result = cast_to_oop(*caller.interpreter_frame_tos_at(args_size - 1)); - assert(Universe::heap()->is_in(result) && oopDesc::is_oop(result), "receiver must be an oop"); - return result; -} - - void SharedRuntime::throw_and_post_jvmti_exception(JavaThread* current, Handle h_exception) { if (JvmtiExport::can_post_on_exceptions()) { vframeStream vfst(current, true); @@ -2379,10 +2365,6 @@ void SharedRuntime::print_statistics() { if (xtty != NULL) xtty->tail("statistics"); } -inline double percent(int x, int y) { - return 100.0 * x / MAX2(y, 1); -} - inline double percent(int64_t x, int64_t y) { return 100.0 * x / MAX2(y, (int64_t)1); } @@ -2470,19 +2452,16 @@ int MethodArityHistogram::_max_size; void SharedRuntime::print_call_statistics(uint64_t comp_total) { tty->print_cr("Calls from compiled code:"); int64_t total = _nof_normal_calls + _nof_interface_calls + _nof_static_calls; - int64_t mono_c = _nof_normal_calls - _nof_optimized_calls - _nof_megamorphic_calls; - int64_t mono_i = _nof_interface_calls - _nof_optimized_interface_calls - _nof_megamorphic_interface_calls; + int64_t mono_c = _nof_normal_calls - _nof_megamorphic_calls; + int64_t mono_i = _nof_interface_calls; tty->print_cr("\t" INT64_FORMAT_W(12) " (100%%) total non-inlined ", total); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- virtual calls ", _nof_normal_calls, percent(_nof_normal_calls, total)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_calls, percent(_nof_inlined_calls, _nof_normal_calls)); - tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- optimized ", _nof_optimized_calls, percent(_nof_optimized_calls, _nof_normal_calls)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- monomorphic ", mono_c, percent(mono_c, _nof_normal_calls)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- megamorphic ", _nof_megamorphic_calls, percent(_nof_megamorphic_calls, _nof_normal_calls)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- interface calls ", _nof_interface_calls, percent(_nof_interface_calls, total)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_interface_calls, percent(_nof_inlined_interface_calls, _nof_interface_calls)); - tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- optimized ", _nof_optimized_interface_calls, percent(_nof_optimized_interface_calls, _nof_interface_calls)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- monomorphic ", mono_i, percent(mono_i, _nof_interface_calls)); - tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- megamorphic ", _nof_megamorphic_interface_calls, percent(_nof_megamorphic_interface_calls, _nof_interface_calls)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.1f%%) |- static/special calls", _nof_static_calls, percent(_nof_static_calls, total)); tty->print_cr("\t" INT64_FORMAT_W(12) " (%4.0f%%) | |- inlined ", _nof_inlined_static_calls, percent(_nof_inlined_static_calls, _nof_static_calls)); tty->cr(); @@ -2750,10 +2729,6 @@ BufferBlob* AdapterHandlerLibrary::buffer_blob() { return _buffer; } -extern "C" void unexpected_adapter_call() { - ShouldNotCallThis(); -} - static void post_adapter_creation(const AdapterBlob* new_adapter, const AdapterHandlerEntry* entry) { if (Forte::is_enabled() || JvmtiExport::should_post_dynamic_code_generated()) { diff --git a/src/hotspot/share/runtime/sharedRuntime.hpp b/src/hotspot/share/runtime/sharedRuntime.hpp index b0019da99a9..7aedab8da0b 100644 --- a/src/hotspot/share/runtime/sharedRuntime.hpp +++ b/src/hotspot/share/runtime/sharedRuntime.hpp @@ -272,8 +272,6 @@ class SharedRuntime: AllStatic { // To be used as the entry point for unresolved native methods. static address native_method_throw_unsatisfied_link_error_entry(); - static oop retrieve_receiver(Symbol* sig, frame caller); - static void register_finalizer(JavaThread* thread, oopDesc* obj); // dtrace notifications @@ -556,26 +554,20 @@ class SharedRuntime: AllStatic { // Statistics code // stats for "normal" compiled calls (non-interface) static int64_t _nof_normal_calls; // total # of calls - static int64_t _nof_optimized_calls; // total # of statically-bound calls static int64_t _nof_inlined_calls; // total # of inlined normal calls static int64_t _nof_static_calls; // total # of calls to static methods or super methods (invokespecial) static int64_t _nof_inlined_static_calls; // total # of inlined static calls // stats for compiled interface calls static int64_t _nof_interface_calls; // total # of compiled calls - static int64_t _nof_optimized_interface_calls; // total # of statically-bound interface calls static int64_t _nof_inlined_interface_calls; // total # of inlined interface calls - static int64_t _nof_megamorphic_interface_calls;// total # of megamorphic interface calls public: // for compiler static address nof_normal_calls_addr() { return (address)&_nof_normal_calls; } - static address nof_optimized_calls_addr() { return (address)&_nof_optimized_calls; } static address nof_inlined_calls_addr() { return (address)&_nof_inlined_calls; } static address nof_static_calls_addr() { return (address)&_nof_static_calls; } static address nof_inlined_static_calls_addr() { return (address)&_nof_inlined_static_calls; } static address nof_interface_calls_addr() { return (address)&_nof_interface_calls; } - static address nof_optimized_interface_calls_addr() { return (address)&_nof_optimized_interface_calls; } static address nof_inlined_interface_calls_addr() { return (address)&_nof_inlined_interface_calls; } - static address nof_megamorphic_interface_calls_addr() { return (address)&_nof_megamorphic_interface_calls; } static void print_call_statistics(uint64_t comp_total); static void print_statistics(); static void print_ic_miss_histogram(); diff --git a/src/hotspot/share/runtime/signature.cpp b/src/hotspot/share/runtime/signature.cpp index 9600b50a9b0..6beac4b366b 100644 --- a/src/hotspot/share/runtime/signature.cpp +++ b/src/hotspot/share/runtime/signature.cpp @@ -569,12 +569,6 @@ ResolvingSignatureStream::ResolvingSignatureStream(const Method* method) initialize_load_origin(method->method_holder()); } -ResolvingSignatureStream::ResolvingSignatureStream(fieldDescriptor& field) - : SignatureStream(field.signature(), false) -{ - initialize_load_origin(field.field_holder()); -} - void ResolvingSignatureStream::cache_handles() { assert(_load_origin != NULL, ""); JavaThread* current = JavaThread::current(); @@ -582,17 +576,6 @@ void ResolvingSignatureStream::cache_handles() { _protection_domain = Handle(current, _load_origin->protection_domain()); } -Klass* ResolvingSignatureStream::as_klass_if_loaded(TRAPS) { - Klass* klass = as_klass(CachedOrNull, THREAD); - // SD::find does not trigger loading, so there should be no throws - // Still, bad things can happen, so we CHECK_NULL and ask callers - // to do likewise. - if (HAS_PENDING_EXCEPTION) { - CLEAR_PENDING_EXCEPTION; - } - return klass; -} - #ifdef ASSERT extern bool signature_constants_sane(); // called from basic_types_init() diff --git a/src/hotspot/share/runtime/signature.hpp b/src/hotspot/share/runtime/signature.hpp index a74f4149206..f56bfd977be 100644 --- a/src/hotspot/share/runtime/signature.hpp +++ b/src/hotspot/share/runtime/signature.hpp @@ -97,14 +97,6 @@ class Signature : AllStatic { // Returns T_ILLEGAL for an illegal signature char. static BasicType basic_type(int ch); - // Assuming it is either a class name or signature, - // determine if it in fact cannot be a class name. - // This means it either starts with '[' or ends with ';' - static bool not_class_name(const Symbol* signature) { - return (signature->starts_with(JVM_SIGNATURE_ARRAY) || - signature->ends_with(JVM_SIGNATURE_ENDCLASS)); - } - // Assuming it is either a class name or signature, // determine if it in fact is an array descriptor. static bool is_array(const Symbol* signature) { @@ -230,10 +222,6 @@ class SignatureIterator: public ResourceObj { template inline void do_parameters_on(T* callback); // iterates over parameters only BasicType return_type(); // computes the value on the fly if necessary - static bool fp_is_static(fingerprint_t fingerprint) { - assert(fp_is_valid(fingerprint), "invalid fingerprint"); - return fingerprint & fp_is_static_bit; - } static BasicType fp_return_type(fingerprint_t fingerprint) { assert(fp_is_valid(fingerprint), "invalid fingerprint"); return (BasicType) ((fingerprint >> fp_static_feature_size) & fp_result_feature_mask); @@ -509,7 +497,6 @@ class SignatureStream : public StackObj { bool is_reference() const { return is_reference_type(_type); } bool is_array() const { return _type == T_ARRAY; } - bool is_primitive() const { return is_java_primitive(_type); } BasicType type() const { return _type; } const u1* raw_bytes() const { return _signature->bytes() + _begin; } @@ -602,13 +589,7 @@ class ResolvingSignatureStream : public SignatureStream { ResolvingSignatureStream(Symbol* signature, Klass* load_origin, bool is_method = true); ResolvingSignatureStream(Symbol* signature, Handle class_loader, Handle protection_domain, bool is_method = true); ResolvingSignatureStream(const Method* method); - ResolvingSignatureStream(fieldDescriptor& field); - - Klass* load_origin() { return _load_origin; } - Handle class_loader() { need_handles(); return _class_loader; } - Handle protection_domain() { need_handles(); return _protection_domain; } - Klass* as_klass_if_loaded(TRAPS); Klass* as_klass(FailureMode failure_mode, TRAPS) { need_handles(); return SignatureStream::as_klass(_class_loader, _protection_domain, diff --git a/src/hotspot/share/runtime/stackChunkFrameStream.hpp b/src/hotspot/share/runtime/stackChunkFrameStream.hpp index a2ea09e38b3..e6f2bef50b4 100644 --- a/src/hotspot/share/runtime/stackChunkFrameStream.hpp +++ b/src/hotspot/share/runtime/stackChunkFrameStream.hpp @@ -63,19 +63,12 @@ class StackChunkFrameStream : public StackObj { inline StackChunkFrameStream(stackChunkOop chunk, const frame& f); bool is_done() const { return _sp >= _end; } - bool is_last() const { return next_sp() >= _end; } - - intptr_t* end() { return _end; } - void set_end(intptr_t* end) { _end = end; } // Query - intptr_t* end() const { return _end; } - intptr_t* sp() const { return _sp; } inline address pc() const { return get_pc(); } inline intptr_t* fp() const; inline intptr_t* unextended_sp() const { return frame_kind == ChunkFrames::Mixed ? _unextended_sp : _sp; } - NOT_PRODUCT(int index() { return _index; }) inline address orig_pc() const; inline bool is_interpreted() const; @@ -94,13 +87,10 @@ class StackChunkFrameStream : public StackObj { void handle_deopted() const; - inline int to_offset(stackChunkOop chunk) const; - inline frame to_frame() const; #ifdef ASSERT bool is_in_frame(void* p) const; - bool is_deoptimized() const; template bool is_in_oops(void* p, const RegisterMapT* map) const; #endif @@ -110,12 +100,10 @@ class StackChunkFrameStream : public StackObj { inline address get_pc() const; inline void get_cb(); - inline intptr_t* next_sp() const; inline int interpreter_frame_size() const; inline int interpreter_frame_num_oops() const; inline int interpreter_frame_stack_argsize() const; inline void next_for_interpreter_frame(); - inline intptr_t* next_sp_for_interpreter_frame() const; inline intptr_t* unextended_sp_for_interpreter_frame() const; inline intptr_t* derelativize(int offset) const; inline void get_oopmap() const; diff --git a/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp b/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp index 1c24a9ed28c..e5d300b0016 100644 --- a/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp +++ b/src/hotspot/share/runtime/stackChunkFrameStream.inline.hpp @@ -236,11 +236,6 @@ inline void StackChunkFrameStream::next(RegisterMapT* map, bool stop } } -template -inline intptr_t* StackChunkFrameStream::next_sp() const { - return is_interpreted() ? next_sp_for_interpreter_frame() : unextended_sp() + cb()->frame_size(); -} - template inline void StackChunkFrameStream::get_cb() { _oopmap = nullptr; @@ -334,20 +329,6 @@ inline address StackChunkFrameStream::orig_pc() const { return pc1; } -template -inline int StackChunkFrameStream::to_offset(stackChunkOop chunk) const { - assert(!is_done(), ""); - return _sp - chunk->start_address(); -} - -#ifdef ASSERT -template -bool StackChunkFrameStream::is_deoptimized() const { - address pc1 = pc(); - return is_compiled() && CodeCache::find_oopmap_slot_fast(pc1) < 0 && cb()->as_compiled_method()->is_deopt_pc(pc1); -} -#endif - template void StackChunkFrameStream::handle_deopted() const { assert(!is_done(), ""); diff --git a/src/hotspot/share/runtime/stackOverflow.cpp b/src/hotspot/share/runtime/stackOverflow.cpp index 05c491469af..532e91f527f 100644 --- a/src/hotspot/share/runtime/stackOverflow.cpp +++ b/src/hotspot/share/runtime/stackOverflow.cpp @@ -214,20 +214,6 @@ void StackOverflow::disable_stack_yellow_reserved_zone() { } } -void StackOverflow::enable_stack_red_zone() { - // The base notation is from the stacks point of view, growing downward. - // We need to adjust it to work correctly with guard_memory() - assert(_stack_guard_state != stack_guard_unused, "must be using guard pages."); - address base = stack_red_zone_base() - stack_red_zone_size(); - - guarantee(base < stack_base(), "Error calculating stack red zone"); - guarantee(base < os::current_stack_pointer(), "Error calculating stack red zone"); - - if (!os::guard_memory((char *) base, stack_red_zone_size())) { - warning("Attempt to guard stack red zone failed."); - } -} - void StackOverflow::disable_stack_red_zone() { // The base notation is from the stacks point of view, growing downward. // We need to adjust it to work correctly with guard_memory() diff --git a/src/hotspot/share/runtime/stackOverflow.hpp b/src/hotspot/share/runtime/stackOverflow.hpp index db4bf03892f..b897c86d249 100644 --- a/src/hotspot/share/runtime/stackOverflow.hpp +++ b/src/hotspot/share/runtime/stackOverflow.hpp @@ -300,7 +300,6 @@ class StackOverflow { void disable_stack_reserved_zone(); void enable_stack_yellow_reserved_zone(); void disable_stack_yellow_reserved_zone(); - void enable_stack_red_zone(); void disable_stack_red_zone(); bool stack_guard_zone_unused() const { return _stack_guard_state == stack_guard_unused; } diff --git a/src/hotspot/share/runtime/stackValueCollection.hpp b/src/hotspot/share/runtime/stackValueCollection.hpp index b2dc909322a..d167835c5a1 100644 --- a/src/hotspot/share/runtime/stackValueCollection.hpp +++ b/src/hotspot/share/runtime/stackValueCollection.hpp @@ -34,7 +34,6 @@ class StackValueCollection : public ResourceObj { GrowableArray* _values; public: - StackValueCollection() { _values = new GrowableArray(); } StackValueCollection(int length) { _values = new GrowableArray(length); } void add(StackValue *val) const { _values->push(val); } diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index 6210a0bc2bf..98a056eae41 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -130,7 +130,6 @@ class StackWatermark : public CHeapObj { void set_next(StackWatermark* n) { _next = n; } void link_watermark(StackWatermark* watermark); - DEBUG_ONLY(StackWatermark* linked_watermark() const { return _linked_watermark; }) uintptr_t watermark(); uintptr_t last_processed(); diff --git a/src/hotspot/share/runtime/stubCodeGenerator.cpp b/src/hotspot/share/runtime/stubCodeGenerator.cpp index 8134258cafa..6ec4ee31e95 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.cpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.cpp @@ -46,12 +46,6 @@ StubCodeDesc* StubCodeDesc::desc_for(address pc) { return p; } -const char* StubCodeDesc::name_for(address pc) { - StubCodeDesc* p = desc_for(pc); - return p == NULL ? NULL : p->name(); -} - - void StubCodeDesc::freeze() { assert(!_frozen, "repeated freeze operation"); _frozen = true; diff --git a/src/hotspot/share/runtime/stubCodeGenerator.hpp b/src/hotspot/share/runtime/stubCodeGenerator.hpp index 061e2d0b71d..7bc454ab190 100644 --- a/src/hotspot/share/runtime/stubCodeGenerator.hpp +++ b/src/hotspot/share/runtime/stubCodeGenerator.hpp @@ -69,7 +69,6 @@ class StubCodeDesc: public CHeapObj { static StubCodeDesc* next(StubCodeDesc* desc) { return desc->_next; } static StubCodeDesc* desc_for(address pc); // returns the code descriptor for the code containing pc or NULL - static const char* name_for(address pc); // returns the name of the code containing pc or NULL StubCodeDesc(const char* group, const char* name, address begin, address end = NULL) { assert(!_frozen, "no modifications allowed"); diff --git a/src/hotspot/share/runtime/stubRoutines.cpp b/src/hotspot/share/runtime/stubRoutines.cpp index 091ff90e470..872cf358879 100644 --- a/src/hotspot/share/runtime/stubRoutines.cpp +++ b/src/hotspot/share/runtime/stubRoutines.cpp @@ -67,13 +67,9 @@ address StubRoutines::_throw_delayed_StackOverflowError_entry = NULL; jint StubRoutines::_verify_oop_count = 0; address StubRoutines::_verify_oop_subroutine_entry = NULL; address StubRoutines::_atomic_xchg_entry = NULL; -address StubRoutines::_atomic_xchg_long_entry = NULL; -address StubRoutines::_atomic_store_entry = NULL; address StubRoutines::_atomic_cmpxchg_entry = NULL; -address StubRoutines::_atomic_cmpxchg_byte_entry = NULL; address StubRoutines::_atomic_cmpxchg_long_entry = NULL; address StubRoutines::_atomic_add_entry = NULL; -address StubRoutines::_atomic_add_long_entry = NULL; address StubRoutines::_fence_entry = NULL; // Compiled code entry points default values diff --git a/src/hotspot/share/runtime/stubRoutines.hpp b/src/hotspot/share/runtime/stubRoutines.hpp index 767a2a098c0..80e77beb8aa 100644 --- a/src/hotspot/share/runtime/stubRoutines.hpp +++ b/src/hotspot/share/runtime/stubRoutines.hpp @@ -143,13 +143,9 @@ class StubRoutines: AllStatic { static address _throw_delayed_StackOverflowError_entry; static address _atomic_xchg_entry; - static address _atomic_xchg_long_entry; - static address _atomic_store_entry; static address _atomic_cmpxchg_entry; - static address _atomic_cmpxchg_byte_entry; static address _atomic_cmpxchg_long_entry; static address _atomic_add_entry; - static address _atomic_add_long_entry; static address _fence_entry; static BufferBlob* _code1; // code buffer for initial routines @@ -314,13 +310,9 @@ class StubRoutines: AllStatic { static address throw_delayed_StackOverflowError_entry() { return _throw_delayed_StackOverflowError_entry; } static address atomic_xchg_entry() { return _atomic_xchg_entry; } - static address atomic_xchg_long_entry() { return _atomic_xchg_long_entry; } - static address atomic_store_entry() { return _atomic_store_entry; } static address atomic_cmpxchg_entry() { return _atomic_cmpxchg_entry; } - static address atomic_cmpxchg_byte_entry() { return _atomic_cmpxchg_byte_entry; } static address atomic_cmpxchg_long_entry() { return _atomic_cmpxchg_long_entry; } static address atomic_add_entry() { return _atomic_add_entry; } - static address atomic_add_long_entry() { return _atomic_add_long_entry; } static address fence_entry() { return _fence_entry; } static address select_arraycopy_function(BasicType t, bool aligned, bool disjoint, const char* &name, bool dest_uninitialized); diff --git a/src/hotspot/share/runtime/suspendedThreadTask.hpp b/src/hotspot/share/runtime/suspendedThreadTask.hpp index c4145772c51..d6f93fab43c 100644 --- a/src/hotspot/share/runtime/suspendedThreadTask.hpp +++ b/src/hotspot/share/runtime/suspendedThreadTask.hpp @@ -41,7 +41,6 @@ class SuspendedThreadTask { public: SuspendedThreadTask(Thread* thread) : _thread(thread), _done(false) {} void run(); - bool is_done() { return _done; } virtual void do_task(const SuspendedThreadTaskContext& context) = 0; protected: ~SuspendedThreadTask() {} diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 225ae9cc083..9e190e876c2 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -694,16 +694,6 @@ int ObjectSynchronizer::wait(Handle obj, jlong millis, TRAPS) { return ret_code; } -// No exception are possible in this case as we only use this internally when locking is -// correct and we have to wait until notified - so no interrupts or timeouts. -void ObjectSynchronizer::wait_uninterruptibly(Handle obj, JavaThread* current) { - // The ObjectMonitor* can't be async deflated because the _waiters - // field is incremented before ownership is dropped and decremented - // after ownership is regained. - ObjectMonitor* monitor = inflate(current, obj(), inflate_cause_wait); - monitor->wait(0 /* wait-forever */, false /* not interruptible */, current); -} - void ObjectSynchronizer::notify(Handle obj, TRAPS) { JavaThread* current = THREAD; diff --git a/src/hotspot/share/runtime/synchronizer.hpp b/src/hotspot/share/runtime/synchronizer.hpp index f90be2be94c..9592d1a43f7 100644 --- a/src/hotspot/share/runtime/synchronizer.hpp +++ b/src/hotspot/share/runtime/synchronizer.hpp @@ -79,11 +79,6 @@ class ObjectMonitorsHashtable { return (listpp == nullptr) ? nullptr : *listpp; } - bool has_entry(void* key) { - PtrList** listpp = _ptrs->get(key); - return listpp != nullptr && *listpp != nullptr; - } - bool has_entry(void* key, ObjectMonitor* om); size_t key_count() { return _key_count; } @@ -159,11 +154,6 @@ class ObjectSynchronizer : AllStatic { static bool quick_notify(oopDesc* obj, JavaThread* current, bool All); static bool quick_enter(oop obj, JavaThread* current, BasicLock* Lock); - // Special internal-use-only method for use by JVM infrastructure - // that needs to wait() on a java-level object but must not respond - // to interrupt requests and doesn't timeout. - static void wait_uninterruptibly(Handle obj, JavaThread* current); - // used by classloading to free classloader object lock, // wait on an internal lock, and reclaim original lock // with original recursion count @@ -266,7 +256,6 @@ class ObjectLocker : public StackObj { // Monitor behavior void wait(TRAPS) { ObjectSynchronizer::wait(_obj, 0, CHECK); } // wait forever void notify_all(TRAPS) { ObjectSynchronizer::notifyall(_obj, CHECK); } - void wait_uninterruptibly(JavaThread* current) { ObjectSynchronizer::wait_uninterruptibly(_obj, current); } }; #endif // SHARE_RUNTIME_SYNCHRONIZER_HPP diff --git a/src/hotspot/share/runtime/thread.cpp b/src/hotspot/share/runtime/thread.cpp index 6da24fad44c..18ae0114442 100644 --- a/src/hotspot/share/runtime/thread.cpp +++ b/src/hotspot/share/runtime/thread.cpp @@ -368,14 +368,6 @@ bool Thread::is_JavaThread_protected_by_TLH(const JavaThread* target) { return false; } -ThreadPriority Thread::get_priority(const Thread* const thread) { - ThreadPriority priority; - // Can return an error! - (void)os::get_priority(thread, priority); - assert(MinPriority <= priority && priority <= MaxPriority, "non-Java priority found"); - return priority; -} - void Thread::set_priority(Thread* thread, ThreadPriority priority) { debug_only(check_for_dangling_thread_pointer(thread);) // Can return an error! diff --git a/src/hotspot/share/runtime/thread.hpp b/src/hotspot/share/runtime/thread.hpp index 6edb46ad2b7..2e1e5cc89d7 100644 --- a/src/hotspot/share/runtime/thread.hpp +++ b/src/hotspot/share/runtime/thread.hpp @@ -119,10 +119,6 @@ class Thread: public ThreadShadow { uint64_t _nmethod_disarm_value; public: - int nmethod_disarm_value() { - return (int)(uint32_t)_nmethod_disarm_value; - } - void set_nmethod_disarm_value(int value) { _nmethod_disarm_value = (uint64_t)(uint32_t)value; } @@ -324,7 +320,6 @@ class Thread: public ThreadShadow { virtual bool is_Java_thread() const { return false; } virtual bool is_Compiler_thread() const { return false; } virtual bool is_service_thread() const { return false; } - virtual bool is_monitor_deflation_thread() const { return false; } virtual bool is_hidden_from_external_view() const { return false; } virtual bool is_jvmti_agent_thread() const { return false; } virtual bool is_Watcher_thread() const { return false; } @@ -363,7 +358,6 @@ class Thread: public ThreadShadow { static void check_for_dangling_thread_pointer(Thread *thread); #endif static void set_priority(Thread* thread, ThreadPriority priority); - static ThreadPriority get_priority(const Thread* const thread); static void start(Thread* thread); void set_native_thread_name(const char *name) { diff --git a/src/hotspot/share/runtime/threadHeapSampler.hpp b/src/hotspot/share/runtime/threadHeapSampler.hpp index 220998c26f7..6f77547fc83 100644 --- a/src/hotspot/share/runtime/threadHeapSampler.hpp +++ b/src/hotspot/share/runtime/threadHeapSampler.hpp @@ -54,7 +54,6 @@ class ThreadHeapSampler { } size_t bytes_until_sample() { return _bytes_until_sample; } - void set_bytes_until_sample(size_t bytes) { _bytes_until_sample = bytes; } void check_for_sampling(oop obj, size_t size_in_bytes, size_t bytes_allocated_before); diff --git a/src/hotspot/share/runtime/threadSMR.hpp b/src/hotspot/share/runtime/threadSMR.hpp index 4fa72abc8d7..7760aeff169 100644 --- a/src/hotspot/share/runtime/threadSMR.hpp +++ b/src/hotspot/share/runtime/threadSMR.hpp @@ -122,8 +122,6 @@ class ThreadsSMRSupport : AllStatic { static uint _to_delete_list_cnt; static uint _to_delete_list_max; - static ThreadsList *acquire_stable_list_fast_path(Thread *self); - static ThreadsList *acquire_stable_list_nested_path(Thread *self); static void add_deleted_thread_times(uint add_value); static void add_tlh_times(uint add_value); static void clear_delete_notify(); @@ -139,7 +137,6 @@ class ThreadsSMRSupport : AllStatic { static void update_deleted_thread_time_max(uint new_value); static void update_java_thread_list_max(uint new_value); static void update_tlh_time_max(uint new_value); - static void verify_hazard_ptr_scanned(Thread *self, ThreadsList *threads); static ThreadsList* xchg_java_thread_list(ThreadsList* new_list); public: @@ -274,17 +271,6 @@ class SafeThreadsListPtr { } } - // Constructor that transfers ownership of the pointer. - SafeThreadsListPtr(SafeThreadsListPtr& other) : - _previous(other._previous), - _thread(other._thread), - _list(other._list), - _has_ref_count(other._has_ref_count), - _needs_release(other._needs_release) - { - other._needs_release = false; - } - ~SafeThreadsListPtr() { if (_needs_release) { release_stable_list(); @@ -332,11 +318,6 @@ class ThreadsListHandle : public StackObj { inline Iterator begin(); inline Iterator end(); - template - void threads_do(T *cl) const { - return list()->threads_do(cl); - } - bool cv_internal_thread_to_JavaThread(jobject jthread, JavaThread ** jt_pp, oop * thread_oop_p); bool includes(JavaThread* p) { @@ -378,10 +359,6 @@ class JavaThreadIterator : public StackObj { return _list->length(); } - ThreadsList *list() const { - return _list; - } - JavaThread *next() { if (++_index >= length()) { return NULL; diff --git a/src/hotspot/share/runtime/threadStatisticalInfo.hpp b/src/hotspot/share/runtime/threadStatisticalInfo.hpp index f0353a0f8f6..ef3d585debb 100644 --- a/src/hotspot/share/runtime/threadStatisticalInfo.hpp +++ b/src/hotspot/share/runtime/threadStatisticalInfo.hpp @@ -39,7 +39,6 @@ class ThreadStatisticalInfo { public: ThreadStatisticalInfo() : _start_time_stamp(os::javaTimeNanos()), _define_class_count(0) {} uint64_t getDefineClassCount() const { return _define_class_count; } - void setDefineClassCount(uint64_t defineClassCount) { _define_class_count = defineClassCount; } void incr_define_class_count() { _define_class_count += 1; } uint64_t getElapsedTime() const { return nanos_to_millis(os::javaTimeNanos() - _start_time_stamp); } }; diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index 7bf508075ce..6e312501c4a 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -246,12 +246,6 @@ void Threads::java_threads_do(ThreadClosure* tc) { } } -void Threads::java_threads_and_vm_thread_do(ThreadClosure* tc) { - assert_locked_or_safepoint(Threads_lock); - java_threads_do(tc); - tc->do_thread(VMThread::vm_thread()); -} - // All JavaThreads + all non-JavaThreads (i.e., every thread in the system). void Threads::threads_do(ThreadClosure* tc) { assert_locked_or_safepoint(Threads_lock); diff --git a/src/hotspot/share/runtime/threads.hpp b/src/hotspot/share/runtime/threads.hpp index 3b8d5e72a4c..cb09a8d5f9a 100644 --- a/src/hotspot/share/runtime/threads.hpp +++ b/src/hotspot/share/runtime/threads.hpp @@ -66,7 +66,6 @@ class Threads: AllStatic { static void remove(JavaThread* p, bool is_daemon); static void non_java_threads_do(ThreadClosure* tc); static void java_threads_do(ThreadClosure* tc); - static void java_threads_and_vm_thread_do(ThreadClosure* tc); static void threads_do(ThreadClosure* tc); static void possibly_parallel_threads_do(bool is_par, ThreadClosure* tc); diff --git a/src/hotspot/share/runtime/timer.hpp b/src/hotspot/share/runtime/timer.hpp index a3d3237aeac..f539ea32859 100644 --- a/src/hotspot/share/runtime/timer.hpp +++ b/src/hotspot/share/runtime/timer.hpp @@ -55,7 +55,6 @@ class TimeStamp { jlong _counter; public: TimeStamp() { _counter = 0; } - void clear() { _counter = 0; } // has the timestamp been updated since being created or cleared? bool is_updated() const { return _counter != 0; } // update to current elapsed time diff --git a/src/hotspot/share/runtime/timerTrace.hpp b/src/hotspot/share/runtime/timerTrace.hpp index 237afc9cd52..0c03b107269 100644 --- a/src/hotspot/share/runtime/timerTrace.hpp +++ b/src/hotspot/share/runtime/timerTrace.hpp @@ -67,14 +67,6 @@ class TraceTime: public StackObj { TraceTimerLogPrintFunc ttlpf); ~TraceTime(); - - // Accessors - void set_verbose(bool verbose) { _verbose = verbose; } - bool verbose() const { return _verbose; } - - // Activation - void suspend() { if (_active) _t.stop(); } - void resume() { if (_active) _t.start(); } }; diff --git a/src/hotspot/share/runtime/vframe.cpp b/src/hotspot/share/runtime/vframe.cpp index 7244e1bd90d..3d4ef87da73 100644 --- a/src/hotspot/share/runtime/vframe.cpp +++ b/src/hotspot/share/runtime/vframe.cpp @@ -62,25 +62,6 @@ vframe::vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) _fr = *fr; } -vframe::vframe(const frame* fr, JavaThread* thread) -: _reg_map(thread, - RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::include, - RegisterMap::WalkContinuation::skip), - _thread(thread), _chunk() { - assert(fr != NULL, "must have frame"); - _fr = *fr; - assert(!_reg_map.in_cont(), ""); -} - -vframe* vframe::new_vframe(StackFrameStream& fst, JavaThread* thread) { - if (fst.current()->is_runtime_frame()) { - fst.next(); - } - guarantee(!fst.is_done(), "missing caller"); - return new_vframe(fst.current(), fst.register_map(), thread); -} - vframe* vframe::new_vframe(const frame* f, const RegisterMap* reg_map, JavaThread* thread) { // Interpreter frame if (f->is_interpreted_frame()) { @@ -126,13 +107,6 @@ bool vframe::is_vthread_entry() const { return _fr.is_first_vthread_frame(register_map()->thread()); } -vframe* vframe::top() const { - vframe* vf = (vframe*) this; - while (!vf->is_top()) vf = vf->sender(); - return vf; -} - - javaVFrame* vframe::java_sender() const { vframe* f = sender(); while (f != NULL) { @@ -295,18 +269,12 @@ u_char* interpretedVFrame::bcp() const { return stack_chunk() == NULL ? fr().interpreter_frame_bcp() : stack_chunk()->interpreter_frame_bcp(fr()); } -void interpretedVFrame::set_bcp(u_char* bcp) { - assert(stack_chunk() == NULL, "Not supported for heap frames"); // unsupported for now because seems to be unused - fr().interpreter_frame_set_bcp(bcp); -} - intptr_t* interpretedVFrame::locals_addr_at(int offset) const { assert(stack_chunk() == NULL, "Not supported for heap frames"); // unsupported for now because seems to be unused assert(fr().is_interpreted_frame(), "frame should be an interpreted frame"); return fr().interpreter_frame_local_at(offset); } - GrowableArray* interpretedVFrame::monitors() const { GrowableArray* result = new GrowableArray(5); if (stack_chunk() == NULL) { // no monitors in continuations @@ -520,22 +488,6 @@ void vframeStreamCommon::found_bad_method_frame() const { } #endif -// top-frame will be skipped -vframeStream::vframeStream(JavaThread* thread, frame top_frame, - bool stop_at_java_call_stub) : - vframeStreamCommon(RegisterMap(thread, - RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::include, - RegisterMap::WalkContinuation::include)) { - _stop_at_java_call_stub = stop_at_java_call_stub; - - // skip top frame, as it may not be at safepoint - _frame = top_frame.sender(&_reg_map); - while (!fill_from_frame()) { - _frame = _frame.sender(&_reg_map); - } -} - vframeStream::vframeStream(JavaThread* thread, Handle continuation_scope, bool stop_at_java_call_stub) : vframeStreamCommon(RegisterMap(thread, RegisterMap::UpdateMap::include, @@ -767,40 +719,6 @@ void javaVFrame::print_value() const { } } - -bool javaVFrame::structural_compare(javaVFrame* other) { - // Check static part - if (method() != other->method()) return false; - if (bci() != other->bci()) return false; - - // Check locals - StackValueCollection *locs = locals(); - StackValueCollection *other_locs = other->locals(); - assert(locs->size() == other_locs->size(), "sanity check"); - int i; - for(i = 0; i < locs->size(); i++) { - // it might happen the compiler reports a conflict and - // the interpreter reports a bogus int. - if ( is_compiled_frame() && locs->at(i)->type() == T_CONFLICT) continue; - if (other->is_compiled_frame() && other_locs->at(i)->type() == T_CONFLICT) continue; - - if (!locs->at(i)->equal(other_locs->at(i))) - return false; - } - - // Check expressions - StackValueCollection* exprs = expressions(); - StackValueCollection* other_exprs = other->expressions(); - assert(exprs->size() == other_exprs->size(), "sanity check"); - for(i = 0; i < exprs->size(); i++) { - if (!exprs->at(i)->equal(other_exprs->at(i))) - return false; - } - - return true; -} - - void javaVFrame::print_activation(int index) const { // frame number and method tty->print("%2d - ", index); @@ -813,22 +731,12 @@ void javaVFrame::print_activation(int index) const { } } - -void javaVFrame::verify() const { -} - - -void interpretedVFrame::verify() const { -} - - // ------------- externalVFrame -------------- void externalVFrame::print() { _fr.print_value_on(tty,NULL); } - void externalVFrame::print_value() const { ((vframe*)this)->print(); } diff --git a/src/hotspot/share/runtime/vframe.hpp b/src/hotspot/share/runtime/vframe.hpp index e383099eeee..988f62693a8 100644 --- a/src/hotspot/share/runtime/vframe.hpp +++ b/src/hotspot/share/runtime/vframe.hpp @@ -63,20 +63,14 @@ class vframe: public ResourceObj { stackChunkHandle _chunk; vframe(const frame* fr, const RegisterMap* reg_map, JavaThread* thread); - vframe(const frame* fr, JavaThread* thread); public: // Factory methods for creating vframes static vframe* new_vframe(const frame* f, const RegisterMap *reg_map, JavaThread* thread); - static vframe* new_vframe(StackFrameStream& fst, JavaThread* thread); // Accessors frame fr() const { return _fr; } CodeBlob* cb() const { return _fr.cb(); } - CompiledMethod* nm() const { - assert( cb() != NULL && cb()->is_compiled(), "usage"); - return (CompiledMethod*) cb(); - } // ???? Does this need to be a copy? frame* frame_pointer() { return &_fr; } @@ -97,9 +91,6 @@ class vframe: public ResourceObj { // is in the caller frame virtual bool is_top() const { return true; } - // Returns top vframe within same frame (see is_top()) - virtual vframe* top() const; - // Type testing operations virtual bool is_entry_frame() const { return false; } virtual bool is_java_frame() const { return false; } @@ -135,7 +126,6 @@ class javaVFrame: public vframe { protected: javaVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread) : vframe(fr, reg_map, thread) {} - javaVFrame(const frame* fr, JavaThread* thread) : vframe(fr, thread) {} public: // casting @@ -158,12 +148,6 @@ class javaVFrame: public vframe { void print(); void print_value() const; void print_activation(int index) const; - - // verify operations - virtual void verify() const; - - // Structural compare - bool structural_compare(javaVFrame* other); #endif friend class vframe; }; @@ -188,7 +172,6 @@ class interpretedVFrame: public javaVFrame { public: // Accessors for Byte Code Pointer u_char* bcp() const; - void set_bcp(u_char* bcp); // casting static interpretedVFrame* cast(vframe* vf) { @@ -200,14 +183,7 @@ class interpretedVFrame: public javaVFrame { static const int bcp_offset; intptr_t* locals_addr_at(int offset) const; StackValueCollection* stack_data(bool expressions) const; - // returns where the parameters starts relative to the frame pointer - int start_of_parameters() const; -#ifndef PRODUCT - public: - // verify operations - void verify() const; -#endif friend class vframe; }; @@ -232,13 +208,6 @@ class entryVFrame: public externalVFrame { protected: entryVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread); - public: - // casting - static entryVFrame* cast(vframe* vf) { - assert(vf == NULL || vf->is_entry_frame(), "must be entry frame"); - return (entryVFrame*) vf; - } - #ifndef PRODUCT public: // printing @@ -330,13 +299,11 @@ class vframeStreamCommon : StackObj { } const RegisterMap* reg_map() { return &_reg_map; } - void dont_walk_cont() { _reg_map.set_walk_cont(false); } javaVFrame* asJavaVFrame(); // Frame type inline bool is_interpreted_frame() const; - inline bool is_entry_frame() const; // Iteration inline void next(); @@ -356,9 +323,6 @@ class vframeStream : public vframeStreamCommon { vframeStream(JavaThread* thread, Handle continuation_scope, bool stop_at_java_call_stub = false); - // top_frame may not be at safepoint, start with sender - vframeStream(JavaThread* thread, frame top_frame, bool stop_at_java_call_stub = false); - vframeStream(oop continuation, Handle continuation_scope = Handle()); }; diff --git a/src/hotspot/share/runtime/vframe.inline.hpp b/src/hotspot/share/runtime/vframe.inline.hpp index 2df24c2d770..c6c12976268 100644 --- a/src/hotspot/share/runtime/vframe.inline.hpp +++ b/src/hotspot/share/runtime/vframe.inline.hpp @@ -70,8 +70,6 @@ inline int vframeStreamCommon::decode_offset() const { inline bool vframeStreamCommon::is_interpreted_frame() const { return _frame.is_interpreted_frame(); } -inline bool vframeStreamCommon::is_entry_frame() const { return _frame.is_entry_frame(); } - inline void vframeStreamCommon::next() { // handle frames with inlining if (_mode == compiled_mode && fill_in_compiled_inlined_sender()) return; diff --git a/src/hotspot/share/runtime/vframeArray.cpp b/src/hotspot/share/runtime/vframeArray.cpp index 717f8851bff..5521b7a1552 100644 --- a/src/hotspot/share/runtime/vframeArray.cpp +++ b/src/hotspot/share/runtime/vframeArray.cpp @@ -547,10 +547,7 @@ void vframeArray::fill_in(JavaThread* thread, jint* src = (jint*) reg_map->location(VMRegImpl::as_VMReg(i), _caller.sp()); _callee_registers[i] = src != NULL ? *src : NULL_WORD; #endif - if (src == NULL) { - set_location_valid(i, false); - } else { - set_location_valid(i, true); + if (src != NULL) { jint* dst = (jint*) register_location(i); *dst = *src; } diff --git a/src/hotspot/share/runtime/vframeArray.hpp b/src/hotspot/share/runtime/vframeArray.hpp index fa2ab054186..734703a94ae 100644 --- a/src/hotspot/share/runtime/vframeArray.hpp +++ b/src/hotspot/share/runtime/vframeArray.hpp @@ -141,7 +141,6 @@ class vframeArray: public CHeapObj { */ JavaThread* _owner_thread; - vframeArray* _next; frame _original; // the original frame of the deoptee frame _caller; // caller of root frame in vframeArray frame _sender; @@ -152,15 +151,9 @@ class vframeArray: public CHeapObj { int _frames; // number of javavframes in the array (does not count any adapter) intptr_t _callee_registers[RegisterMap::reg_count]; - unsigned char _valid[RegisterMap::reg_count]; vframeArrayElement _elements[1]; // First variable section. - void fill_in_element(int index, compiledVFrame* vf); - - bool is_location_valid(int i) const { return _valid[i] != 0; } - void set_location_valid(int i, bool valid) { _valid[i] = valid; } - public: @@ -183,21 +176,13 @@ class vframeArray: public CHeapObj { // Returns the owner of this vframeArray JavaThread* owner_thread() const { return _owner_thread; } - // Accessors for next - vframeArray* next() const { return _next; } - void set_next(vframeArray* value) { _next = value; } - // Accessors for sp intptr_t* sp() const { return _original.sp(); } intptr_t* unextended_sp() const; - address original_pc() const { return _original.pc(); } - frame original() const { return _original; } - frame caller() const { return _caller; } - frame sender() const { return _sender; } // Accessors for unroll block diff --git a/src/hotspot/share/runtime/vframe_hp.cpp b/src/hotspot/share/runtime/vframe_hp.cpp index 115bc2f78ce..d5458d3bea2 100644 --- a/src/hotspot/share/runtime/vframe_hp.cpp +++ b/src/hotspot/share/runtime/vframe_hp.cpp @@ -535,10 +535,3 @@ jvmtiDeferredLocalVariable::jvmtiDeferredLocalVariable(int index, BasicType type _type = type; _value = value; } - - -#ifndef PRODUCT -void compiledVFrame::verify() const { - Unimplemented(); -} -#endif // PRODUCT diff --git a/src/hotspot/share/runtime/vframe_hp.hpp b/src/hotspot/share/runtime/vframe_hp.hpp index 2c410fb28d0..3bee308b1ed 100644 --- a/src/hotspot/share/runtime/vframe_hp.hpp +++ b/src/hotspot/share/runtime/vframe_hp.hpp @@ -98,11 +98,6 @@ class compiledVFrame: public javaVFrame { private: compiledVFrame(const frame* fr, const RegisterMap* reg_map, JavaThread* thread, ScopeDesc* scope, int vframe_id); - -#ifndef PRODUCT - public: - void verify() const; -#endif }; #endif // SHARE_RUNTIME_VFRAME_HP_HPP diff --git a/src/hotspot/share/runtime/vmOperations.cpp b/src/hotspot/share/runtime/vmOperations.cpp index c49cadd0e76..6e2e70b825d 100644 --- a/src/hotspot/share/runtime/vmOperations.cpp +++ b/src/hotspot/share/runtime/vmOperations.cpp @@ -117,7 +117,6 @@ void VM_DeoptimizeFrame::doit() { #ifndef PRODUCT void VM_DeoptimizeAll::doit() { - DeoptimizationMarker dm; JavaThreadIteratorWithHandle jtiwh; // deoptimize all java threads in the system if (DeoptimizeALot) { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4407b065309..4271f6a3e23 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1071,7 +1071,6 @@ nonstatic_field(CompileTask, _next, CompileTask*) \ nonstatic_field(CompileTask, _prev, CompileTask*) \ \ - nonstatic_field(vframeArray, _next, vframeArray*) \ nonstatic_field(vframeArray, _original, frame) \ nonstatic_field(vframeArray, _caller, frame) \ nonstatic_field(vframeArray, _frames, int) \ From dea2161f069a88553bc514c7210dc1d31febd90a Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Mon, 5 Dec 2022 11:31:31 +0000 Subject: [PATCH 038/494] 8297959: Provide better descriptions for some Operating System JFR events Reviewed-by: stuefe --- src/hotspot/share/jfr/metadata/metadata.xml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index b145d3d080c..8ae6f289481 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -732,11 +732,15 @@ - + - + @@ -745,7 +749,9 @@ - + From eab0ada3a16a432fdfd1f0b8fceca149c725451b Mon Sep 17 00:00:00 2001 From: Aleksey Shipilev Date: Mon, 5 Dec 2022 12:00:30 +0000 Subject: [PATCH 039/494] 8296545: C2 Blackholes should allow load optimizations Reviewed-by: kvn, vlivanov --- src/hotspot/share/opto/cfgnode.cpp | 23 ++++ src/hotspot/share/opto/cfgnode.hpp | 25 ++++ src/hotspot/share/opto/library_call.cpp | 9 +- src/hotspot/share/opto/memnode.cpp | 21 ---- src/hotspot/share/opto/memnode.hpp | 20 ---- src/hotspot/share/runtime/vmStructs.cpp | 2 +- .../blackhole/BlackholeLoadOptoTest.java | 111 ++++++++++++++++++ 7 files changed, 168 insertions(+), 43 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/irTests/blackhole/BlackholeLoadOptoTest.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 62e111e4632..fdee440cf47 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -39,6 +39,7 @@ #include "opto/narrowptrnode.hpp" #include "opto/mulnode.hpp" #include "opto/phaseX.hpp" +#include "opto/regalloc.hpp" #include "opto/regmask.hpp" #include "opto/runtime.hpp" #include "opto/subnode.hpp" @@ -2814,3 +2815,25 @@ void NeverBranchNode::format( PhaseRegAlloc *ra_, outputStream *st) const { st->print("%s", Name()); } #endif + +#ifndef PRODUCT +void BlackholeNode::format(PhaseRegAlloc* ra, outputStream* st) const { + st->print("blackhole "); + bool first = true; + for (uint i = 0; i < req(); i++) { + Node* n = in(i); + if (n != NULL && OptoReg::is_valid(ra->get_reg_first(n))) { + if (first) { + first = false; + } else { + st->print(", "); + } + char buf[128]; + ra->dump_register(n, buf); + st->print("%s", buf); + } + } + st->cr(); +} +#endif + diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index 4147f0db021..ea6ec6aff43 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -47,6 +47,7 @@ class PCTableNode; class JumpNode; class CatchNode; class NeverBranchNode; +class BlackholeNode; class ProjNode; class CProjNode; class IfTrueNode; @@ -604,4 +605,28 @@ class NeverBranchNode : public MultiBranchNode { #endif }; +//------------------------------BlackholeNode---------------------------- +// Blackhole all arguments. This node would survive through the compiler +// the effects on its arguments, and would be finally matched to nothing. +class BlackholeNode : public MultiNode { +public: + BlackholeNode(Node* ctrl) : MultiNode(1) { + init_req(TypeFunc::Control, ctrl); + } + virtual int Opcode() const; + virtual uint ideal_reg() const { return 0; } // not matched in the AD file + virtual const Type* bottom_type() const { return TypeTuple::MEMBAR; } + + const RegMask &in_RegMask(uint idx) const { + // Fake the incoming arguments mask for blackholes: accept all registers + // and all stack slots. This would avoid any redundant register moves + // for blackhole inputs. + return RegMask::All; + } +#ifndef PRODUCT + virtual void format(PhaseRegAlloc* ra, outputStream* st) const; +#endif +}; + + #endif // SHARE_OPTO_CFGNODE_HPP diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 05eaccfd38e..365a2065c85 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -7841,8 +7841,15 @@ bool LibraryCallKit::inline_blackhole() { assert(callee()->is_empty(), "Should have been checked before: only empty methods here"); assert(callee()->holder()->is_loaded(), "Should have been checked before: only methods for loaded classes here"); + // Blackhole node pinches only the control, not memory. This allows + // the blackhole to be pinned in the loop that computes blackholed + // values, but have no other side effects, like breaking the optimizations + // across the blackhole. + + Node* bh = _gvn.transform(new BlackholeNode(control())); + set_control(_gvn.transform(new ProjNode(bh, TypeFunc::Control))); + // Bind call arguments as blackhole arguments to keep them alive - Node* bh = insert_mem_bar(Op_Blackhole); uint nargs = callee()->arg_size(); for (uint i = 0; i < nargs; i++) { bh->add_req(argument(i)); diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 5e041b5b783..6cb8b742dfb 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -3261,7 +3261,6 @@ MemBarNode* MemBarNode::make(Compile* C, int opcode, int atp, Node* pn) { case Op_MemBarCPUOrder: return new MemBarCPUOrderNode(C, atp, pn); case Op_OnSpinWait: return new OnSpinWaitNode(C, atp, pn); case Op_Initialize: return new InitializeNode(C, atp, pn); - case Op_Blackhole: return new BlackholeNode(C, atp, pn); default: ShouldNotReachHere(); return NULL; } } @@ -3501,26 +3500,6 @@ MemBarNode* MemBarNode::leading_membar() const { return mb; } -#ifndef PRODUCT -void BlackholeNode::format(PhaseRegAlloc* ra, outputStream* st) const { - st->print("blackhole "); - bool first = true; - for (uint i = 0; i < req(); i++) { - Node* n = in(i); - if (n != NULL && OptoReg::is_valid(ra->get_reg_first(n))) { - if (first) { - first = false; - } else { - st->print(", "); - } - char buf[128]; - ra->dump_register(n, buf); - st->print("%s", buf); - } - } - st->cr(); -} -#endif //===========================InitializeNode==================================== // SUMMARY: diff --git a/src/hotspot/share/opto/memnode.hpp b/src/hotspot/share/opto/memnode.hpp index 53384bb8a6b..92040e81c4b 100644 --- a/src/hotspot/share/opto/memnode.hpp +++ b/src/hotspot/share/opto/memnode.hpp @@ -1296,26 +1296,6 @@ class OnSpinWaitNode: public MemBarNode { virtual int Opcode() const; }; -//------------------------------BlackholeNode---------------------------- -// Blackhole all arguments. This node would survive through the compiler -// the effects on its arguments, and would be finally matched to nothing. -class BlackholeNode : public MemBarNode { -public: - BlackholeNode(Compile* C, int alias_idx, Node* precedent) - : MemBarNode(C, alias_idx, precedent) {} - virtual int Opcode() const; - virtual uint ideal_reg() const { return 0; } // not matched in the AD file - const RegMask &in_RegMask(uint idx) const { - // Fake the incoming arguments mask for blackholes: accept all registers - // and all stack slots. This would avoid any redundant register moves - // for blackhole inputs. - return RegMask::All; - } -#ifndef PRODUCT - virtual void format(PhaseRegAlloc* ra, outputStream* st) const; -#endif -}; - // Isolation of object setup after an AllocateNode and before next safepoint. // (See comment in memnode.cpp near InitializeNode::InitializeNode for semantics.) class InitializeNode: public MemBarNode { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 4271f6a3e23..06d420e47f6 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1565,7 +1565,7 @@ declare_c2_type(MemBarVolatileNode, MemBarNode) \ declare_c2_type(MemBarCPUOrderNode, MemBarNode) \ declare_c2_type(OnSpinWaitNode, MemBarNode) \ - declare_c2_type(BlackholeNode, MemBarNode) \ + declare_c2_type(BlackholeNode, MultiNode) \ declare_c2_type(InitializeNode, MemBarNode) \ declare_c2_type(ThreadLocalNode, Node) \ declare_c2_type(Opaque1Node, Node) \ diff --git a/test/hotspot/jtreg/compiler/c2/irTests/blackhole/BlackholeLoadOptoTest.java b/test/hotspot/jtreg/compiler/c2/irTests/blackhole/BlackholeLoadOptoTest.java new file mode 100644 index 00000000000..e7db84d75c6 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/irTests/blackhole/BlackholeLoadOptoTest.java @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2022, 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 8296545 + * @requires vm.compiler2.enabled + * @summary Blackholes should allow load optimizations + * @library /test/lib / + * @run driver compiler.c2.irTests.blackhole.BlackholeLoadOptoTest + */ + +package compiler.c2.irTests.blackhole; + +import compiler.lib.ir_framework.*; +import jdk.test.lib.Asserts; + +public class BlackholeLoadOptoTest { + + public static void main(String[] args) { + TestFramework.runWithFlags( + "-XX:+UnlockExperimentalVMOptions", + "-XX:CompileThreshold=100", + "-XX:-TieredCompilation", + "-XX:CompileCommand=blackhole,compiler.c2.irTests.blackhole.BlackholeLoadOptoTest::blackhole", + "-XX:CompileCommand=dontinline,compiler.c2.irTests.blackhole.BlackholeLoadOptoTest::dontinline" + ); + } + + static int x, y; + + + /* + * Negative test: check that dangling expressions are eliminated + */ + + @Test + @IR(failOn = {IRNode.LOAD_I, IRNode.MUL_I}) + static void testNothing() { + int r1 = x * y; + int r2 = x * y; + } + + @Run(test = "testNothing") + static void runNothing() { + testNothing(); + } + + /* + * Auxiliary test: check that dontinline method does break optimizations + */ + + @Test + @IR(counts = {IRNode.LOAD_I, "4"}) + @IR(counts = {IRNode.MUL_I, "2"}) + static void testDontline() { + int r1 = x * y; + dontinline(r1); + int r2 = x * y; + dontinline(r2); + } + + static void dontinline(int x) {} + + @Run(test = "testDontline") + static void runDontinline() { + testDontline(); + } + + /* + * Positive test: check that blackhole does not break optimizations + */ + + @Test + @IR(counts = {IRNode.LOAD_I, "2"}) + @IR(counts = {IRNode.MUL_I, "1"}) + static void testBlackholed() { + int r1 = x * y; + blackhole(r1); + int r2 = x * y; + blackhole(r2); + } + + static void blackhole(int x) {} + + @Run(test = "testBlackholed") + static void runBlackholed() { + testBlackholed(); + } + +} From 2300ed458dcda568afad818d2d3133e545a58ad5 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Mon, 5 Dec 2022 12:04:23 +0000 Subject: [PATCH 040/494] 8291769: Translation of switch with record patterns could be improved Reviewed-by: vromero --- .../sun/tools/javac/comp/TransPatterns.java | 580 ++++++++++++++---- .../com/sun/tools/javac/comp/TreeDiffer.java | 15 + .../classes/com/sun/tools/javac/jvm/Gen.java | 69 ++- .../sun/tools/javac/main/JavaCompiler.java | 46 +- .../com/sun/tools/javac/tree/JCTree.java | 11 + .../com/sun/tools/javac/tree/TreeInfo.java | 9 + .../typeAnnotations/classfile/Patterns.java | 32 +- .../patterns/DeconstructionDesugaring.java | 124 ++++ .../tools/javac/patterns/Guards.java | 4 + .../javac/patterns/PatternDesugaring.java | 201 ++++++ .../tools/javac/patterns/Switches.java | 33 + .../tools/javac/patterns/TranslationTest.java | 331 ++++++++++ .../TypedDeconstructionPatternExc.java | 82 +++ 13 files changed, 1373 insertions(+), 164 deletions(-) create mode 100644 test/langtools/tools/javac/patterns/DeconstructionDesugaring.java create mode 100644 test/langtools/tools/javac/patterns/PatternDesugaring.java create mode 100644 test/langtools/tools/javac/patterns/TranslationTest.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java index 9ac54e14cc4..450f1d067f1 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TransPatterns.java @@ -26,7 +26,7 @@ package com.sun.tools.javac.comp; import com.sun.source.tree.CaseTree; -import com.sun.source.tree.EnhancedForLoopTree; +import com.sun.source.tree.CaseTree.CaseKind; import com.sun.tools.javac.code.BoundKind; import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Kinds; @@ -50,7 +50,6 @@ import com.sun.tools.javac.tree.JCTree.JCIdent; import com.sun.tools.javac.tree.JCTree.JCIf; import com.sun.tools.javac.tree.JCTree.JCInstanceOf; -import com.sun.tools.javac.tree.JCTree.JCLabeledStatement; import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCSwitch; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; @@ -64,12 +63,14 @@ import com.sun.tools.javac.util.ListBuffer; import com.sun.tools.javac.util.Name; import com.sun.tools.javac.util.Names; -import com.sun.tools.javac.util.Options; -import java.util.HashMap; +import java.util.Collections; import java.util.Map; import java.util.Map.Entry; +import java.util.HashMap; +import java.util.IdentityHashMap; import java.util.LinkedHashMap; +import java.util.Set; import com.sun.tools.javac.code.Symbol.MethodSymbol; import com.sun.tools.javac.code.Symbol.RecordComponent; @@ -79,13 +80,16 @@ import com.sun.tools.javac.jvm.Target; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCBlock; +import com.sun.tools.javac.tree.JCTree.JCBlock.PatternMatchingCatch; import com.sun.tools.javac.tree.JCTree.JCBreak; import com.sun.tools.javac.tree.JCTree.JCCase; import com.sun.tools.javac.tree.JCTree.JCCaseLabel; +import com.sun.tools.javac.tree.JCTree.JCCatch; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCContinue; import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; import com.sun.tools.javac.tree.JCTree.JCConstantCaseLabel; +import com.sun.tools.javac.tree.JCTree.JCExpressionStatement; import com.sun.tools.javac.tree.JCTree.JCFieldAccess; import com.sun.tools.javac.tree.JCTree.JCLambda; import com.sun.tools.javac.tree.JCTree.JCMethodInvocation; @@ -96,10 +100,11 @@ import com.sun.tools.javac.tree.JCTree.JCRecordPattern; import com.sun.tools.javac.tree.JCTree.JCStatement; import com.sun.tools.javac.tree.JCTree.JCSwitchExpression; +import com.sun.tools.javac.tree.JCTree.JCTry; import com.sun.tools.javac.tree.JCTree.LetExpr; import com.sun.tools.javac.tree.TreeInfo; +import com.sun.tools.javac.tree.TreeScanner; import com.sun.tools.javac.util.Assert; -import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; import com.sun.tools.javac.util.List; /** @@ -165,16 +170,14 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { } }; - JCLabeledStatement pendingMatchLabel = null; - - boolean debugTransPatterns; - private ClassSymbol currentClass = null; private JCClassDecl currentClassTree = null; private ListBuffer pendingMethods = null; private MethodSymbol currentMethodSym = null; private VarSymbol currentValue = null; private Map component2Proxy = null; + private Set deconstructorCalls; + private int variableIndex = 0; protected TransPatterns(Context context) { context.put(transPatternsKey, this); @@ -187,16 +190,27 @@ protected TransPatterns(Context context) { names = Names.instance(context); target = Target.instance(context); preview = Preview.instance(context); - debugTransPatterns = Options.instance(context).isSet("debug.patterns"); } @Override public void visitTypeTest(JCInstanceOf tree) { - if (tree.pattern instanceof JCPattern) { - //E instanceof $pattern + if (tree.pattern instanceof JCPattern pattern) { + //first, resolve any parenthesized and record patterns: + pattern = TreeInfo.skipParens(pattern); + JCExpression extraConditions = null; + if (pattern instanceof JCRecordPattern recordPattern) { + UnrolledRecordPattern unrolledRecordPattern = unrollRecordPattern(recordPattern); + pattern = unrolledRecordPattern.primaryPattern(); + extraConditions = unrolledRecordPattern.newGuard(); + } + //$pattern is now always a binding pattern, $extraConditions are possibly additional tests + //implementing to the record pattern + // + //E instanceof $patternType $patternName && $extraConditions //=> - //(let T' N$temp = E; N$temp instanceof typeof($pattern) && ) - //note the pattern desugaring performs binding variable assignments + //(let $patternType N$temp = E; N$temp instanceof $patternType && + // (let $patternName = ($patternType) N$temp; true) && + // $extraConditions) Type tempType = tree.expr.type.hasTag(BOT) ? syms.objectType : tree.expr.type; @@ -212,16 +226,23 @@ public void visitTypeTest(JCInstanceOf tree) { currentValue = (VarSymbol) exprSym; } else { currentValue = new VarSymbol(Flags.FINAL | Flags.SYNTHETIC, - names.fromString("patt" + tree.pos + target.syntheticNameChar() + "temp"), + names.fromString("patt" + variableIndex++ + target.syntheticNameChar() + "temp"), tempType, currentMethodSym); } - Type principalType = principalType((JCPattern) tree.pattern); - JCExpression resultExpression= - makeBinary(Tag.AND, - makeTypeTest(make.Ident(currentValue), make.Type(principalType)), - (JCExpression) this.translate(tree.pattern)); + Type principalType = types.erasure(TreeInfo.primaryPatternType((pattern))); + JCExpression resultExpression= (JCExpression) this.translate(pattern); + if (!tree.allowNull || !types.isSubtype(currentValue.type, principalType)) { + resultExpression = + makeBinary(Tag.AND, + makeTypeTest(make.Ident(currentValue), make.Type(principalType)), + resultExpression); + } + if (extraConditions != null) { + extraConditions = translate(extraConditions); + resultExpression = makeBinary(Tag.AND, resultExpression, extraConditions); + } if (currentValue != exprSym) { resultExpression = make.at(tree.pos).LetExpr(make.VarDef(currentValue, translatedExpr), @@ -242,7 +263,7 @@ public void visitTypeTest(JCInstanceOf tree) { public void visitBindingPattern(JCBindingPattern tree) { //it is assumed the primary type has already been checked: BindingSymbol binding = (BindingSymbol) tree.var.sym; - Type castTargetType = principalType(tree); + Type castTargetType = types.erasure(TreeInfo.primaryPatternType(tree)); VarSymbol bindingVar = bindingContext.bindingDeclared(binding); if (bindingVar != null) { @@ -265,60 +286,68 @@ public void visitParenthesizedPattern(JCParenthesizedPattern tree) { @Override public void visitRecordPattern(JCRecordPattern tree) { - //type test already done, finish handling of deconstruction patterns ("T(PATT1, PATT2, ...)") + //record patterns should be resolved by the constructs that use them. + Assert.error(); + } + + private UnrolledRecordPattern unrollRecordPattern(JCRecordPattern recordPattern) { + //Convert a record pattern in the basic binding pattern and additional conditions + //implementing the record pattern: + //$record($nestedPattern1, $nestedPattern2, ...) $r //=> - // && && ... - List components = tree.record.getRecordComponents(); - List nestedFullComponentTypes = tree.fullComponentTypes; - List nestedPatterns = tree.nested; - JCExpression test = null; - while (components.nonEmpty() && nestedFullComponentTypes.nonEmpty() && nestedPatterns.nonEmpty()) { - //PATTn for record component COMPn of type Tn; - //PATTn is a type test pattern or a deconstruction pattern: - //=> - //(let Tn $c$COMPn = ((T) N$temp).COMPn(); ) - //or - //(let Tn $c$COMPn = ((T) N$temp).COMPn(); $c$COMPn != null && ) - //or - //(let Tn $c$COMPn = ((T) N$temp).COMPn(); $c$COMPn instanceof T' && ) + //$record $r; type-test-of($nestedPattern1) && type-test-of($nestedPattern2) && ... && + // nested-conditions-of($nestedPattern1) && nested-conditions-of($nestedPattern2) + Type recordType = recordPattern.record.erasure(types); + BindingSymbol tempBind = new BindingSymbol(Flags.SYNTHETIC, + names.fromString(target.syntheticNameChar() + "b" + target.syntheticNameChar() + variableIndex++), recordType, + currentMethodSym); + JCVariableDecl recordBindingVar = make.VarDef(tempBind, null); + + VarSymbol recordBinding = recordBindingVar.sym; + List components = recordPattern.record.getRecordComponents(); + List nestedFullComponentTypes = recordPattern.fullComponentTypes; + List nestedPatterns = recordPattern.nested; + JCExpression firstLevelChecks = null; + JCExpression secondLevelChecks = null; + + while (components.nonEmpty()) { RecordComponent component = components.head; - JCPattern nested = nestedPatterns.head; - VarSymbol nestedTemp = new VarSymbol(Flags.SYNTHETIC, - names.fromString(target.syntheticNameChar() + "c" + target.syntheticNameChar() + component.name), - component.erasure(types), - currentMethodSym); - Symbol accessor = getAccessor(tree.pos(), component); - JCVariableDecl nestedTempVar = - make.VarDef(nestedTemp, - make.App(make.QualIdent(accessor), - List.of(convert(make.Ident(currentValue), tree.type)))); - JCExpression extracted; - VarSymbol prevCurrentValue = currentValue; - try { - currentValue = nestedTemp; - extracted = (JCExpression) this.translate(nested); - } finally { - currentValue = prevCurrentValue; - } - JCExpression extraTest = null; - if (!types.isAssignable(nestedTemp.type, nested.type)) { - if (!types.isAssignable(nestedFullComponentTypes.head, nested.type)) { - extraTest = makeTypeTest(make.Ident(nestedTemp), - make.Type(nested.type)); + Type componentType = types.erasure(nestedFullComponentTypes.head); + JCPattern nestedPattern = TreeInfo.skipParens(nestedPatterns.head); + JCBindingPattern nestedBinding; + boolean allowNull; + if (nestedPattern instanceof JCRecordPattern nestedRecordPattern) { + UnrolledRecordPattern nestedDesugared = unrollRecordPattern(nestedRecordPattern); + JCExpression newGuard = nestedDesugared.newGuard(); + if (newGuard != null) { + if (secondLevelChecks == null) { + secondLevelChecks = newGuard; + } else { + secondLevelChecks = mergeConditions(secondLevelChecks, newGuard); + } } - } else if (nested.type.isReference() && nested.hasTag(Tag.RECORDPATTERN)) { - extraTest = makeBinary(Tag.NE, make.Ident(nestedTemp), makeNull()); + nestedBinding = nestedDesugared.primaryPattern(); + allowNull = false; + } else { + nestedBinding = (JCBindingPattern) nestedPattern; + allowNull = true; } - if (extraTest != null) { - extracted = makeBinary(Tag.AND, extraTest, extracted); + JCMethodInvocation componentAccessor = + make.App(make.Select(convert(make.Ident(recordBinding), recordBinding.type), //TODO - cast needed???? + component.accessor)); + if (deconstructorCalls == null) { + deconstructorCalls = Collections.newSetFromMap(new IdentityHashMap<>()); } - LetExpr getAndRun = make.LetExpr(nestedTempVar, extracted); - getAndRun.needsCond = true; - getAndRun.setType(syms.booleanType); - if (test == null) { - test = getAndRun; + deconstructorCalls.add(componentAccessor); + JCExpression accessedComponentValue = + convert(componentAccessor, componentType); + JCInstanceOf firstLevelCheck = (JCInstanceOf) make.TypeTest(accessedComponentValue, nestedBinding).setType(syms.booleanType); + //TODO: verify deep/complex nesting with nulls + firstLevelCheck.allowNull = allowNull; + if (firstLevelChecks == null) { + firstLevelChecks = firstLevelCheck; } else { - test = makeBinary(Tag.AND, test, getAndRun); + firstLevelChecks = mergeConditions(firstLevelChecks, firstLevelCheck); } components = components.tail; nestedFullComponentTypes = nestedFullComponentTypes.tail; @@ -326,46 +355,17 @@ public void visitRecordPattern(JCRecordPattern tree) { } Assert.check(components.isEmpty() == nestedPatterns.isEmpty()); - Assert.check(components.isEmpty() == nestedFullComponentTypes.isEmpty()); - result = test != null ? test : makeLit(syms.booleanType, 1); + JCExpression guard = null; + if (firstLevelChecks != null) { + guard = firstLevelChecks; + if (secondLevelChecks != null) { + guard = mergeConditions(guard, secondLevelChecks); + } + } + return new UnrolledRecordPattern((JCBindingPattern) make.BindingPattern(recordBindingVar).setType(recordBinding.type), guard); } - private MethodSymbol getAccessor(DiagnosticPosition pos, RecordComponent component) { - return component2Proxy.computeIfAbsent(component, c -> { - MethodType type = new MethodType(List.of(component.owner.erasure(types)), - types.erasure(component.type), - List.nil(), - syms.methodClass); - MethodSymbol proxy = new MethodSymbol(Flags.PRIVATE | Flags.STATIC | Flags.SYNTHETIC, - names.fromString("$proxy$" + component.name), - type, - currentClass); - JCStatement accessorStatement = - make.Return(make.App(make.Select(make.Ident(proxy.params().head), c.accessor))); - VarSymbol ctch = new VarSymbol(Flags.SYNTHETIC, - names.fromString("catch" + currentClassTree.pos + target.syntheticNameChar()), - syms.throwableType, - currentMethodSym); - JCNewClass newException = makeNewClass(syms.matchExceptionType, - List.of(makeApply(make.Ident(ctch), - names.toString, - List.nil()), - make.Ident(ctch))); - JCTree.JCCatch catchClause = make.Catch(make.VarDef(ctch, null), - make.Block(0, List.of(make.Throw(newException)))); - JCStatement tryCatchAll = make.Try(make.Block(0, List.of(accessorStatement)), - List.of(catchClause), - null); - JCMethodDecl md = make.MethodDef(proxy, - proxy.externalType(types), - make.Block(0, List.of(tryCatchAll))); - - pendingMethods.append(md); - currentClass.members().enter(proxy); - - return proxy; - }); - } + record UnrolledRecordPattern(JCBindingPattern primaryPattern, JCExpression newGuard) {} @Override public void visitSwitch(JCSwitch tree) { @@ -391,27 +391,33 @@ private void handleSwitch(JCTree tree, Assert.check(preview.isEnabled()); Assert.check(preview.usesPreview(env.toplevel.sourcefile)); - //rewrite pattern matching switches: + //rewrite pattern matching switches, performed in several steps: + //1. record patterns are unrolled into a binding pattern and guards using unrollRecordPattern + // (guards implement the nested pattern checks) + // the switch only has constants and binding patterns as the + //2. the cases are processed through processCases, that will group cases with the same + // binding pattern and similar guards, and will factor out the common binding pattern, + // creating nested switches. + //3. the simplified binding-only switch with guards is then converted to an ordinary switch: //switch ($obj) { - // case $constant: $stats$ - // case $pattern1: $stats$ - // case $pattern2, null: $stats$ - // case $pattern3: $stats$ + // case $constant: $stats1$ + // case $pattern2 when $guard2: $stats2$ + // case $pattern3, null: $stats3$ + // case $pattern4: $stats4$ //} //=> //int $idx = 0; //$RESTART: switch (invokeDynamic typeSwitch($constant, typeof($pattern1), typeof($pattern2), typeof($pattern3))($obj, $idx)) { // case 0: - // if (!()) { $idx = 1; continue $RESTART; } - // $stats$ + // $stats1$ // case 1: - // if (!()) { $idx = 2; continue $RESTART; } + // if (!( && $guard2)) { $idx = 2; continue $RESTART; } // $stats$ // case 2, -1: - // if (!()) { $idx = 3; continue $RESTART; } + // if (!()) { $idx = 3; continue $RESTART; } // $stats$ // case 3: - // if (!()) { $idx = 4; continue $RESTART; } + // if (!()) { $idx = 4; continue $RESTART; } // $stats$ //} //notes: @@ -426,9 +432,28 @@ private void handleSwitch(JCTree tree, // return -1 when the input is null // //note the selector is evaluated only once and stored in a temporary variable + ListBuffer newCases = new ListBuffer<>(); + for (List c = cases; c.nonEmpty(); c = c.tail) { + c.head.labels = c.head.labels.map(l -> { + if (l instanceof JCPatternCaseLabel patternLabel) { + JCPattern pattern = TreeInfo.skipParens(patternLabel.pat); + if (pattern instanceof JCRecordPattern recordPattern) { + UnrolledRecordPattern deconstructed = unrollRecordPattern(recordPattern); + JCExpression guard = deconstructed.newGuard(); + if (patternLabel.guard != null) { + guard = mergeConditions(guard, patternLabel.guard); + } + return make.PatternCaseLabel(deconstructed.primaryPattern(), guard); + } + } + return l; + }); + newCases.add(c.head); + } + cases = processCases(tree, newCases.toList()); ListBuffer statements = new ListBuffer<>(); VarSymbol temp = new VarSymbol(Flags.SYNTHETIC, - names.fromString("selector" + tree.pos + target.syntheticNameChar() + "temp"), + names.fromString("selector" + variableIndex++ + target.syntheticNameChar() + "temp"), seltype, currentMethodSym); boolean hasNullCase = cases.stream() @@ -442,7 +467,7 @@ private void handleSwitch(JCTree tree, statements.append(make.at(tree.pos).VarDef(temp, needsNullCheck ? attr.makeNullCheck(selector) : selector)); VarSymbol index = new VarSymbol(Flags.SYNTHETIC, - names.fromString(tree.pos + target.syntheticNameChar() + "index"), + names.fromString("index" + target.syntheticNameChar() + variableIndex++), syms.intType, currentMethodSym); statements.append(make.at(tree.pos).VarDef(index, makeLit(syms.intType, 0))); @@ -540,6 +565,9 @@ private void handleSwitch(JCTree tree, } else { c.stats = translate(c.stats); } + + fixupContinue(tree, c, index, i); + ListBuffer translatedLabels = new ListBuffer<>(); for (var p : c.labels) { if (p.hasTag(Tag.DEFAULTCASELABEL)) { @@ -596,6 +624,23 @@ private void handleSwitch(JCTree tree, super.visitSwitchExpression((JCSwitchExpression) tree); } } + //where: + private void fixupContinue(JCTree switchTree, JCCase c, VarSymbol indexVariable, int currentCaseIndex) { + //inject 'index = currentCaseIndex + 1;` before continue which has the current switch as the target + new TreeScanner() { + @Override + public void visitCase(JCCase c) { + if (c.stats.size() == 1 && c.stats.head instanceof JCContinue cont && + cont.target == switchTree) { + JCExpressionStatement setIndex = + make.Exec(make.Assign(make.Ident(indexVariable), + makeLit(syms.intType, currentCaseIndex + 1)) + .setType(syms.intType)); + c.stats = c.stats.prepend(setIndex); + } + } + }.scan(c.stats); + } JCMethodInvocation makeApply(JCExpression selector, Name name, List args) { MethodSymbol method = rs.resolveInternalMethod( @@ -616,6 +661,165 @@ JCNewClass makeNewClass(Type ctype, List args) { return tree; } + /** + * Considering a list of cases, find consecutive cases with the same binding pattern as their label, + * and type tests with binding patterns as the first element in the guard. These cases are then + * merged into a single case, and a nested switch is generated from the first element of the guard. + * + * For example: + * + * OUTER: + * switch (selector) { + * case Box b when b.o() instanceof String s -> {} + * case Box b when b.o() instanceof Integer i-> {} + * case Box b when b.o() instanceof Number n -> {} + * ... + * } + * => + * OUTER: + * switch (selector) { + * case Box b -> + * switch (b.o()) { + * case String s -> {} + * case Integer i -> {} + * case Number n -> {} + * default -> continue OUTER; //continue matching on next case of the outer switch + * } + * ... + * } + */ + private List processCases(JCTree currentSwitch, List inputCases) { + interface AccummulatorResolver { + public void resolve(VarSymbol commonBinding, + JCExpression commonNestedExpression, + VarSymbol commonNestedBinding); + } + ListBuffer accummulator = new ListBuffer<>(); + ListBuffer result = new ListBuffer<>(); + AccummulatorResolver resolveAccummulator = (commonBinding, commonNestedExpression, commonNestedBinding) -> { + boolean hasUnconditional = false; + if (accummulator.size() > 1) { + Assert.check(commonBinding != null && + commonNestedExpression != null && + commonNestedBinding != null, + () -> "commonBinding: " + commonBinding + + "commonNestedExpression: " + commonNestedExpression + + "commonNestedBinding: " + commonNestedBinding); + ListBuffer nestedCases = new ListBuffer<>(); + + for(List accList = accummulator.toList(); accList.nonEmpty(); accList = accList.tail) { + var accummulated = accList.head; + JCPatternCaseLabel accummulatedFirstLabel = + (JCPatternCaseLabel) accummulated.labels.head; + JCBindingPattern accummulatedPattern = + (JCBindingPattern) accummulatedFirstLabel.pat; + VarSymbol accummulatedBinding = accummulatedPattern.var.sym; + TreeScanner replaceNested = + new ReplaceVar(Map.of(accummulatedBinding, commonBinding)); + + replaceNested.scan(accummulated); + JCExpression newGuard; + JCInstanceOf instanceofCheck; + if (accummulatedFirstLabel.guard instanceof JCBinary binOp) { + newGuard = binOp.rhs; + instanceofCheck = (JCInstanceOf) binOp.lhs; + } else { + newGuard = null; + instanceofCheck = (JCInstanceOf) accummulatedFirstLabel.guard; + } + JCBindingPattern binding = (JCBindingPattern) instanceofCheck.pattern; + hasUnconditional = + instanceofCheck.allowNull && + types.isSubtype(commonNestedExpression.type, + types.boxedTypeOrType(types.erasure(binding.type))) && + accList.tail.isEmpty(); + List newLabel; + if (hasUnconditional) { + newLabel = List.of(make.ConstantCaseLabel(makeNull()), + make.DefaultCaseLabel()); + } else { + newLabel = List.of(make.PatternCaseLabel(binding, newGuard)); + } + nestedCases.add(make.Case(CaseKind.STATEMENT, newLabel, accummulated.stats, null)); + } + if (!hasUnconditional) { + JCContinue continueSwitch = make.Continue(null); + continueSwitch.target = currentSwitch; + nestedCases.add(make.Case(CaseKind.STATEMENT, + List.of(make.ConstantCaseLabel(makeNull()), + make.DefaultCaseLabel()), + List.of(continueSwitch), + null)); + } + JCSwitch newSwitch = make.Switch(commonNestedExpression, nestedCases.toList()); + newSwitch.patternSwitch = true; + JCPatternCaseLabel leadingTest = + (JCPatternCaseLabel) accummulator.first().labels.head; + leadingTest.guard = null; + result.add(make.Case(CaseKind.STATEMENT, + List.of(leadingTest), + List.of(newSwitch), + null)); + } else { + result.addAll(accummulator); + } + accummulator.clear(); + }; + + VarSymbol commonBinding = null; + JCExpression commonNestedExpression = null; + VarSymbol commonNestedBinding = null; + + for (List c = inputCases; c.nonEmpty(); c = c.tail) { + VarSymbol currentBinding = null; + JCExpression currentNestedExpression = null; + VarSymbol currentNestedBinding = null; + + if (c.head.labels.size() == 1 && + c.head.labels.head instanceof JCPatternCaseLabel patternLabel) { + if (patternLabel.guard instanceof JCBinary binOp && + binOp.lhs instanceof JCInstanceOf instanceofCheck && + instanceofCheck.pattern instanceof JCBindingPattern binding) { + currentBinding = ((JCBindingPattern) patternLabel.pat).var.sym; + currentNestedExpression = instanceofCheck.expr; + currentNestedBinding = binding.var.sym; + } else if (patternLabel.guard instanceof JCInstanceOf instanceofCheck && + instanceofCheck.pattern instanceof JCBindingPattern binding) { + currentBinding = ((JCBindingPattern) patternLabel.pat).var.sym; + currentNestedExpression = instanceofCheck.expr; + currentNestedBinding = binding.var.sym; + } + } + if (commonBinding == null) { + if (currentBinding != null) { + commonBinding = currentBinding; + commonNestedExpression = currentNestedExpression; + commonNestedBinding = currentNestedBinding; + accummulator.add(c.head); + } else { + result.add(c.head); + } + } else if (currentBinding != null && + commonBinding.type.tsym == currentBinding.type.tsym && + new TreeDiffer(List.of(commonBinding), List.of(currentBinding)) + .scan(commonNestedExpression, currentNestedExpression)) { + accummulator.add(c.head); + } else { + resolveAccummulator.resolve(commonBinding, commonNestedExpression, commonNestedBinding); + if (currentBinding != null) { + accummulator.add(c.head); + } else { + result.add(c.head); + } + commonBinding = currentBinding; + commonNestedExpression = currentNestedExpression; + commonNestedBinding = currentNestedBinding; + } + } + resolveAccummulator.resolve(commonBinding, commonNestedExpression, commonNestedBinding); + return result.toList(); + } + private Type principalType(JCTree p) { return types.boxedTypeOrType(types.erasure(TreeInfo.primaryPatternType(p))); } @@ -787,11 +991,18 @@ public void visitDoLoop(JCDoWhileLoop tree) { @Override public void visitMethodDef(JCMethodDecl tree) { MethodSymbol prevMethodSym = currentMethodSym; + int prevVariableIndex = variableIndex; + Set prevDeconstructorCalls = deconstructorCalls; try { currentMethodSym = tree.sym; + variableIndex = 0; + deconstructorCalls = null; super.visitMethodDef(tree); + preparePatternMatchingCatchIfNeeded(tree.body); } finally { + variableIndex = prevVariableIndex; currentMethodSym = prevMethodSym; + deconstructorCalls = prevDeconstructorCalls; } } @@ -833,21 +1044,38 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { } }; MethodSymbol oldMethodSym = currentMethodSym; + int prevVariableIndex = variableIndex; try { - if (currentMethodSym == null) { - // Block is a static or instance initializer. - currentMethodSym = - new MethodSymbol(tree.flags | Flags.BLOCK, - names.empty, null, - currentClass); - } - for (List l = tree.stats; l.nonEmpty(); l = l.tail) { - statements.append(translate(l.head)); + boolean isInit = currentMethodSym == null; + Set prevDeconstructorCalls = deconstructorCalls; + try { + if (isInit) { + // Block is a static or instance initializer. + currentMethodSym = + new MethodSymbol(tree.flags | Flags.BLOCK, + names.empty, null, + currentClass); + variableIndex = 0; + deconstructorCalls = null; + } + + for (List l = tree.stats; l.nonEmpty(); l = l.tail) { + statements.append(translate(l.head)); + } + + if (isInit) { + preparePatternMatchingCatchIfNeeded(tree); + } + } finally { + if (isInit) { + deconstructorCalls = prevDeconstructorCalls; + } } tree.stats = statements.toList(); result = tree; } finally { + variableIndex = prevVariableIndex; currentMethodSym = oldMethodSym; bindingContext.pop(); } @@ -856,10 +1084,31 @@ boolean tryPrepend(BindingSymbol binding, JCVariableDecl var) { @Override public void visitLambda(JCLambda tree) { BindingContext prevContent = bindingContext; + int prevVariableIndex = variableIndex; try { bindingContext = new BindingDeclarationFenceBindingContext(); - super.visitLambda(tree); + variableIndex = 0; + tree.params = translate(tree.params); + Set prevDeconstructorCalls = deconstructorCalls; + try { + deconstructorCalls = null; + tree.body = translate(tree.body); + if (deconstructorCalls != null) { + if (tree.body instanceof JCExpression value) { + tree.body = make.Block(0, List.of(make.Return(value))); + } + if (tree.body instanceof JCBlock block) { + preparePatternMatchingCatchIfNeeded(block); + } else { + throw Assert.error("Unexpected lambda body type: " + tree.body.getKind()); + } + } + } finally { + deconstructorCalls = prevDeconstructorCalls; + } + result = tree; } finally { + variableIndex = prevVariableIndex; bindingContext = prevContent; } } @@ -890,6 +1139,7 @@ public void visitClassDef(JCClassDecl tree) { public void visitVarDef(JCVariableDecl tree) { MethodSymbol prevMethodSym = currentMethodSym; + int prevVariableIndex = variableIndex; try { tree.mods = translate(tree.mods); tree.vartype = translate(tree.vartype); @@ -899,14 +1149,53 @@ public void visitVarDef(JCVariableDecl tree) { new MethodSymbol((tree.mods.flags&Flags.STATIC) | Flags.BLOCK, names.empty, null, currentClass); + variableIndex = 0; } if (tree.init != null) tree.init = translate(tree.init); result = tree; } finally { + variableIndex = prevVariableIndex; currentMethodSym = prevMethodSym; } } + @Override + public void visitTry(JCTry tree) { + tree.resources = translate(tree.resources); + Set prevDeconstructorCalls = deconstructorCalls; + try { + deconstructorCalls = null; + tree.body = translate(tree.body); + preparePatternMatchingCatchIfNeeded(tree.body); + } finally { + deconstructorCalls = prevDeconstructorCalls; + } + tree.catchers = translateCatchers(tree.catchers); + tree.finalizer = translate(tree.finalizer); + result = tree; + } + + private void preparePatternMatchingCatchIfNeeded(JCBlock tree) { + if (deconstructorCalls != null) { + VarSymbol ctch = new VarSymbol(Flags.SYNTHETIC, + names.fromString("catch" + variableIndex++ + target.syntheticNameChar()), + syms.throwableType, + currentMethodSym); + + JCCatch patternMatchingCatch = + make.Catch(make.VarDef(ctch, null), + make.Block(0, + List.of(make.Throw(makeNewClass(syms.matchExceptionType, + List.of(makeApply(make.Ident(ctch), + names.toString, + List.nil()), + make.Ident(ctch))))))); + tree.patternMatchingCatch = + new PatternMatchingCatch(patternMatchingCatch, deconstructorCalls); + deconstructorCalls = null; + } + } + public JCTree translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { try { this.make = make; @@ -956,11 +1245,27 @@ JCTree.JCUnary makeUnary(JCTree.Tag optag, JCExpression arg) { } JCExpression convert(JCExpression expr, Type target) { + if (types.isSubtype(expr.type, target)) { + //cast not needed + return expr; + } JCExpression result = make.at(expr.pos()).TypeCast(make.Type(target), expr); result.type = target; return result; } + JCExpression mergeConditions(JCExpression left, JCExpression right) { + if (left instanceof JCBinary lastBinary) { + while (lastBinary.rhs instanceof JCBinary nextBinary) { + lastBinary = nextBinary; + } + lastBinary.rhs = makeBinary(Tag.AND, lastBinary.rhs, right); + return left; + } else { + return makeBinary(Tag.AND, left, right); + } + } + abstract class BindingContext { abstract VarSymbol bindingDeclared(BindingSymbol varSymbol); abstract VarSymbol getBindingFor(BindingSymbol varSymbol); @@ -984,7 +1289,7 @@ public BasicBindingContext() { VarSymbol bindingDeclared(BindingSymbol varSymbol) { VarSymbol res = parent.bindingDeclared(varSymbol); if (res == null) { - res = new VarSymbol(varSymbol.flags(), varSymbol.name, varSymbol.type, currentMethodSym); + res = new VarSymbol(varSymbol.flags() & ~Flags.MATCH_BINDING, varSymbol.name, varSymbol.type, currentMethodSym); res.setTypeAttributes(varSymbol.getRawTypeAttributes()); hoistedVarMap.put(varSymbol, res); } @@ -1086,4 +1391,19 @@ JCExpression makeLit(Type type, Object value) { JCExpression makeNull() { return makeLit(syms.botType, null); } + + private class ReplaceVar extends TreeScanner { + + private final Map fromTo; + + public ReplaceVar(Map fromTo) { + this.fromTo = fromTo; + } + + @Override + public void visitIdent(JCIdent tree) { + tree.sym = fromTo.getOrDefault(tree.sym, tree.sym); + super.visitIdent(tree); + } + } } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java index f8d61fce126..36222b88766 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TreeDiffer.java @@ -26,6 +26,7 @@ package com.sun.tools.javac.comp; +import com.sun.tools.javac.code.Flags; import com.sun.tools.javac.code.Symbol; import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotatedType; @@ -44,6 +45,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCCompilationUnit; import com.sun.tools.javac.tree.JCTree.JCConditional; +import com.sun.tools.javac.tree.JCTree.JCConstantCaseLabel; import com.sun.tools.javac.tree.JCTree.JCContinue; import com.sun.tools.javac.tree.JCTree.JCDefaultCaseLabel; import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop; @@ -69,6 +71,7 @@ import com.sun.tools.javac.tree.JCTree.JCNewClass; import com.sun.tools.javac.tree.JCTree.JCOpens; import com.sun.tools.javac.tree.JCTree.JCPackageDecl; +import com.sun.tools.javac.tree.JCTree.JCPatternCaseLabel; import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree; import com.sun.tools.javac.tree.JCTree.JCProvides; import com.sun.tools.javac.tree.JCTree.JCRecordPattern; @@ -297,6 +300,18 @@ public void visitCase(JCCase tree) { result = scan(tree.labels, that.labels) && scan(tree.stats, that.stats); } + @Override + public void visitConstantCaseLabel(JCConstantCaseLabel tree) { + JCConstantCaseLabel that = (JCConstantCaseLabel) parameter; + result = scan(tree.expr, that.expr); + } + + @Override + public void visitPatternCaseLabel(JCPatternCaseLabel tree) { + JCPatternCaseLabel that = (JCPatternCaseLabel) parameter; + result = scan(tree.pat, that.pat) && scan(tree.guard, that.guard); + } + @Override public void visitDefaultCaseLabel(JCDefaultCaseLabel tree) { result = true; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java index e3095a0275a..ee2974d9478 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Gen.java @@ -27,6 +27,7 @@ import java.util.HashMap; import java.util.Map; +import java.util.Set; import com.sun.tools.javac.jvm.PoolConstant.LoadableConstant; import com.sun.tools.javac.tree.TreeInfo.PosKind; @@ -170,6 +171,8 @@ protected Gen(Context context) { Chain switchExpressionFalseChain; List stackBeforeSwitchExpression; LocalItem switchResult; + Set invocationsWithPatternMatchingCatch = Set.of(); + ListBuffer patternMatchingInvocationRanges; /** Generate code to load an integer constant. * @param n The integer to be loaded. @@ -1049,6 +1052,29 @@ public void visitSkip(JCSkip tree) { } public void visitBlock(JCBlock tree) { + if (tree.patternMatchingCatch != null) { + Set prevInvocationsWithPatternMatchingCatch = invocationsWithPatternMatchingCatch; + ListBuffer prevRanges = patternMatchingInvocationRanges; + State startState = code.state.dup(); + try { + invocationsWithPatternMatchingCatch = tree.patternMatchingCatch.calls2Handle(); + patternMatchingInvocationRanges = new ListBuffer<>(); + doVisitBlock(tree); + } finally { + Chain skipCatch = code.branch(goto_); + JCCatch handler = tree.patternMatchingCatch.handler(); + code.entryPoint(startState, handler.param.sym.type); + genPatternMatchingCatch(handler, env, patternMatchingInvocationRanges.toList()); + code.resolve(skipCatch); + invocationsWithPatternMatchingCatch = prevInvocationsWithPatternMatchingCatch; + patternMatchingInvocationRanges = prevRanges; + } + } else { + doVisitBlock(tree); + } + } + + private void doVisitBlock(JCBlock tree) { int limit = code.nextreg; Env localEnv = env.dup(tree, new GenContext()); genStats(tree.stats, localEnv); @@ -1611,18 +1637,33 @@ void genCatch(JCCatch tree, } } } - VarSymbol exparam = tree.param.sym; - code.statBegin(tree.pos); - code.markStatBegin(); - int limit = code.nextreg; - code.newLocal(exparam); - items.makeLocalItem(exparam).store(); - code.statBegin(TreeInfo.firstStatPos(tree.body)); - genStat(tree.body, env, CRT_BLOCK); - code.endScopes(limit); - code.statBegin(TreeInfo.endPos(tree.body)); + genCatchBlock(tree, env); } } + void genPatternMatchingCatch(JCCatch tree, + Env env, + List ranges) { + for (int[] range : ranges) { + JCExpression subCatch = tree.param.vartype; + int catchType = makeRef(tree.pos(), subCatch.type); + registerCatch(tree.pos(), + range[0], range[1], code.curCP(), + catchType); + } + genCatchBlock(tree, env); + } + void genCatchBlock(JCCatch tree, Env env) { + VarSymbol exparam = tree.param.sym; + code.statBegin(tree.pos); + code.markStatBegin(); + int limit = code.nextreg; + code.newLocal(exparam); + items.makeLocalItem(exparam).store(); + code.statBegin(TreeInfo.firstStatPos(tree.body)); + genStat(tree.body, env, CRT_BLOCK); + code.endScopes(limit); + code.statBegin(TreeInfo.endPos(tree.body)); + } // where List, JCExpression>> catchTypesWithAnnotations(JCCatch tree) { return TreeInfo.isMultiCatch(tree) ? @@ -1839,7 +1880,13 @@ public void visitApply(JCMethodInvocation tree) { if (!msym.isDynamic()) { code.statBegin(tree.pos); } - result = m.invoke(); + if (invocationsWithPatternMatchingCatch.contains(tree)) { + int start = code.curCP(); + result = m.invoke(); + patternMatchingInvocationRanges.add(new int[] {start, code.curCP()}); + } else { + result = m.invoke(); + } } public void visitConditional(JCConditional tree) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index d126e9108b9..8f1cb2df1b5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -89,11 +89,15 @@ import static com.sun.tools.javac.code.TypeTag.CLASS; import static com.sun.tools.javac.main.Option.*; +import com.sun.tools.javac.tree.JCTree.JCBindingPattern; import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*; import static javax.tools.StandardLocation.CLASS_OUTPUT; import com.sun.tools.javac.tree.JCTree.JCModuleDecl; +import com.sun.tools.javac.tree.JCTree.JCRecordPattern; +import com.sun.tools.javac.tree.JCTree.JCSwitch; +import com.sun.tools.javac.tree.JCTree.JCSwitchExpression; /** This class could be the main entry point for GJC when GJC is used as a * component in a larger software system. It provides operations to @@ -1465,6 +1469,7 @@ protected void desugar(final Env env, Queue, class ScanNested extends TreeScanner { Set> dependencies = new LinkedHashSet<>(); protected boolean hasLambdas; + protected boolean hasPatterns; @Override public void visitClassDef(JCClassDecl node) { Type st = types.supertype(node.sym.type); @@ -1475,16 +1480,19 @@ public void visitClassDef(JCClassDecl node) { if (stEnv != null && env != stEnv) { if (dependencies.add(stEnv)) { boolean prevHasLambdas = hasLambdas; + boolean prevHasPatterns = hasPatterns; try { scan(stEnv.tree); } finally { /* - * ignore any updates to hasLambdas made during - * the nested scan, this ensures an initialized - * LambdaToMethod is available only to those - * classes that contain lambdas + * ignore any updates to hasLambdas and hasPatterns + * made during the nested scan, this ensures an + * initialized LambdaToMethod or TransPatterns is + * available only to those classes that contain + * lambdas or patterns, respectivelly */ hasLambdas = prevHasLambdas; + hasPatterns = prevHasPatterns; } } envForSuperTypeFound = true; @@ -1503,6 +1511,31 @@ public void visitReference(JCMemberReference tree) { hasLambdas = true; super.visitReference(tree); } + @Override + public void visitBindingPattern(JCBindingPattern tree) { + hasPatterns = true; + super.visitBindingPattern(tree); + } + @Override + public void visitRecordPattern(JCRecordPattern that) { + hasPatterns = true; + super.visitRecordPattern(that); + } + @Override + public void visitParenthesizedPattern(JCTree.JCParenthesizedPattern tree) { + hasPatterns = true; + super.visitParenthesizedPattern(tree); + } + @Override + public void visitSwitch(JCSwitch tree) { + hasPatterns |= tree.patternSwitch; + super.visitSwitch(tree); + } + @Override + public void visitSwitchExpression(JCSwitchExpression tree) { + hasPatterns |= tree.patternSwitch; + super.visitSwitchExpression(tree); + } } ScanNested scanner = new ScanNested(); scanner.scan(env.tree); @@ -1551,7 +1584,10 @@ public void visitReference(JCMemberReference tree) { if (shouldStop(CompileState.TRANSPATTERNS)) return; - env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake); + if (scanner.hasPatterns) { + env.tree = TransPatterns.instance(context).translateTopLevelClass(env, env.tree, localMake); + } + compileStates.put(env, CompileState.TRANSPATTERNS); if (scanner.hasLambdas) { diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java index ccb414fdb3c..d45858eb2e8 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/JCTree.java @@ -1074,6 +1074,12 @@ public static class JCBlock extends JCStatement implements BlockTree { public List stats; /** Position of closing brace, optional. */ public int endpos = Position.NOPOS; + /** If this block contains record pattern, it is necessary to catch + * exceptions from the deconstructors and wrap them. + * The {@code patternMatchingCatch} keeps the list of the deconstructor + * invocations, and the additional catch block that wraps the exceptions. + */ + public PatternMatchingCatch patternMatchingCatch; protected JCBlock(long flags, List stats) { this.stats = stats; this.flags = flags; @@ -1098,6 +1104,8 @@ public R accept(TreeVisitor v, D d) { public Tag getTag() { return BLOCK; } + + public record PatternMatchingCatch(JCCatch handler, Set calls2Handle) {} } /** @@ -2218,6 +2226,9 @@ public Tag getTag() { public static class JCInstanceOf extends JCExpression implements InstanceOfTree { public JCExpression expr; public JCTree pattern; + /**{@code true} if this instanceof test should have + * value {@code true} when the {@code expr} is {@code null}.*/ + public boolean allowNull; protected JCInstanceOf(JCExpression expr, JCTree pattern) { this.expr = expr; this.pattern = pattern; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index a0fd4f3a3b7..901724ddcab 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -838,6 +838,15 @@ public static JCTree skipParens(JCTree tree) { return tree; } + /** Skip parens and return the enclosed expression + */ + public static JCPattern skipParens(JCPattern tree) { + while (tree.hasTag(PARENTHESIZEDPATTERN)) { + tree = ((JCParenthesizedPattern) tree).pattern; + } + return tree; + } + /** Return the types of a list of trees. */ public static List types(List trees) { diff --git a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java index 207fdc8f913..b9b1e88d746 100644 --- a/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java +++ b/test/langtools/tools/javac/annotations/typeAnnotations/classfile/Patterns.java @@ -209,27 +209,27 @@ public void runDeconstruction() throws Exception { descriptor: ()V flags: (0x0001) ACC_PUBLIC RuntimeInvisibleTypeAnnotations: - 0: #_A_(): LOCAL_VARIABLE, {start_pc=251, length=11, index=2} + 0: #_A_(): LOCAL_VARIABLE, {start_pc=316, length=11, index=2} Patterns$DeconstructionPattern$A - 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=290, length=11, index=3} + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=359, length=11, index=3} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) - 2: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=1} + 2: #_A_(): LOCAL_VARIABLE, {start_pc=30, length=11, index=1} Patterns$DeconstructionPattern$A - 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=63, length=11, index=1} + 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=1} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) - 4: #_A_(): LOCAL_VARIABLE, {start_pc=101, length=11, index=2} + 4: #_A_(): LOCAL_VARIABLE, {start_pc=114, length=11, index=2} Patterns$DeconstructionPattern$A - 5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=140, length=11, index=3} + 5: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=157, length=11, index=3} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) - 6: #_A_(): LOCAL_VARIABLE, {start_pc=176, length=11, index=2} + 6: #_A_(): LOCAL_VARIABLE, {start_pc=215, length=11, index=2} Patterns$DeconstructionPattern$A - 7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=215, length=11, index=3} + 7: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=258, length=11, index=3} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) @@ -238,30 +238,26 @@ public void runDeconstruction() throws Exception { descriptor: ()V flags: (0x0000) RuntimeInvisibleTypeAnnotations: - 0: #_A_(): LOCAL_VARIABLE, {start_pc=23, length=11, index=2} + 0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=2} Patterns$DeconstructionPattern$A - 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=3} + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=71, length=11, index=3} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) - private static java.lang.String $proxy$s(Patterns$DeconstructionPattern$R); - descriptor: (LPatterns$DeconstructionPattern$R;)Ljava/lang/String; - flags: (0x100a) ACC_PRIVATE, ACC_STATIC, ACC_SYNTHETIC - static {}; descriptor: ()V flags: (0x0008) ACC_STATIC RuntimeInvisibleTypeAnnotations: - 0: #_A_(): LOCAL_VARIABLE, {start_pc=26, length=11, index=0} + 0: #_A_(): LOCAL_VARIABLE, {start_pc=28, length=11, index=0} Patterns$DeconstructionPattern$A - 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=62, length=11, index=0} + 1: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=66, length=11, index=0} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) - 2: #_A_(): LOCAL_VARIABLE, {start_pc=98, length=11, index=1} + 2: #_A_(): LOCAL_VARIABLE, {start_pc=106, length=11, index=1} Patterns$DeconstructionPattern$A - 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=134, length=11, index=2} + 3: #_CA_(#_value_=[@#_A_(),@#_A_()]): LOCAL_VARIABLE, {start_pc=147, length=11, index=2} Patterns$DeconstructionPattern$CA( value=[@Patterns$DeconstructionPattern$A,@Patterns$DeconstructionPattern$A] ) diff --git a/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java b/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java new file mode 100644 index 00000000000..47b988b6284 --- /dev/null +++ b/test/langtools/tools/javac/patterns/DeconstructionDesugaring.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, 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 8291769 + * @summary Verify more complex switches work properly + * @compile --enable-preview -source ${jdk.version} DeconstructionDesugaring.java + * @run main/othervm --enable-preview DeconstructionDesugaring + */ + +import java.util.function.ToIntFunction; +public class DeconstructionDesugaring { + + public static void main(String... args) throws Throwable { + new DeconstructionDesugaring().test(); + } + + private void test() { + test(this::runCheckStatement); + test(this::runCheckExpression); + assertEquals(runCheckExpressionWithUnconditional(new R5(new R4(new Sub3()))), 3); + assertEquals(runCheckExpressionWithUnconditional(new R5(new R4(null))), 3); + assertEquals(runCheckExpressionWithUnconditional1(new R5(new R4(null))), 2); + assertEquals(runCheckExpressionWithUnconditional1(new R5(null)), 3); + } + + private void test(ToIntFunction task) { + assertEquals(1, task.applyAsInt(new R1(new R2("")))); + assertEquals(2, task.applyAsInt(new R1(new R2(1)))); + assertEquals(3, task.applyAsInt(new R1(new R2(1.0)))); + assertEquals(-1, task.applyAsInt(new R1(new R2(null)))); + assertEquals(4, task.applyAsInt(new R1(new R2(new StringBuilder())))); + assertEquals(5, task.applyAsInt(new R1(new R3("")))); + assertEquals(6, task.applyAsInt(new R1(new R3(1)))); + assertEquals(7, task.applyAsInt(new R1(new R3(1.0)))); + assertEquals(8, task.applyAsInt(new R1(new R3(new StringBuilder())))); + assertEquals(-1, task.applyAsInt(new R1(1.0f))); + assertEquals(-1, task.applyAsInt("foo")); + } + + private int runCheckStatement(Object o) { + switch (o) { + case (((R1((((R2((((String s))))))))))) -> { return 1; } + case R1(R2(Integer i)) -> { return 2; } + case R1(R2(Double d)) -> { return 3; } + case R1(R2(CharSequence cs)) -> { return 4; } + case R1(R3(String s)) -> { return 5; } + case R1(R3(Integer i)) -> { return 6; } + case R1(R3(Double f)) -> { return 7; } + case R1(R3(CharSequence cs)) -> { return 8; } + default -> { return -1; } + } + } + + private int runCheckExpression(Object o) { + return switch (o) { + case (((R1((((R2((((String s))))))))))) -> 1; + case R1(R2(Integer i)) -> 2; + case R1(R2(Double d)) -> 3; + case R1(R2(CharSequence cs)) -> 4; + case R1(R3(String s)) -> 5; + case R1(R3(Integer i)) -> 6; + case R1(R3(Double f)) -> 7; + case R1(R3(CharSequence cs)) -> 8; + default -> -1; + }; + } + + private int runCheckExpressionWithUnconditional(R5 o) { + return switch (o) { + case R5(R4(Sub1 s)) -> 1; + case R5(R4(Sub2 s)) -> 2; + case R5(R4(Super s)) -> 3; + }; + } + + private int runCheckExpressionWithUnconditional1(R5 o) { + return switch (o) { + case R5(R4(Sub1 s)) -> 1; + case R5(R4(Super s)) -> 2; + case R5(Object obj) -> 3; + }; + } + + private void assertEquals(int expected, int actual) { + if (expected != actual) { + throw new AssertionError("expected: " + expected + ", " + + "actual: " + actual); + } + } + + record R1(Object o) {} + record R2(Object o) {} + record R3(Object o) {} + + sealed class Super permits Sub1, Sub2, Sub3 {} + final class Sub1 extends Super {} + final class Sub2 extends Super {} + final class Sub3 extends Super {} + + record R4(Super o) {} + record R5(R4 o) {} +} diff --git a/test/langtools/tools/javac/patterns/Guards.java b/test/langtools/tools/javac/patterns/Guards.java index f8cffd41655..3292bdc9fb0 100644 --- a/test/langtools/tools/javac/patterns/Guards.java +++ b/test/langtools/tools/javac/patterns/Guards.java @@ -55,6 +55,7 @@ void run(Function convert) { assertEquals("one", convert.apply(1)); assertEquals("other", convert.apply(-1)); assertEquals("box with empty", convert.apply(new Box(""))); + assertEquals("box with non-empty", convert.apply(new Box("a"))); assertEquals("any", convert.apply("")); } @@ -70,6 +71,7 @@ String typeTestPatternSwitchTest(Object o) { case Integer i when i == 1: return "one"; case Integer i: return "other"; case Box(String s) when s.isEmpty(): return "box with empty"; + case Box(String s) : return "box with non-empty"; case Object x: return "any"; } } @@ -80,6 +82,7 @@ String typeTestPatternSwitchExpressionTest(Object o) { case Integer i when i == 1 -> { yield "one"; } case Integer i -> "other"; case Box(String s) when s.isEmpty() -> "box with empty"; + case Box(String s) -> "box with non-empty"; case Object x -> "any"; }; } @@ -91,6 +94,7 @@ String testBooleanSwitchExpression(Object o) { case Integer i when i == 1 -> { x = "one"; yield true; } case Integer i -> { x = "other"; yield true; } case Box(String s) when s.isEmpty() -> {x = "box with empty"; yield true; } + case Box(String s) -> {x = "box with non-empty"; yield true; } case Object other -> (x = "any") != null; }) { return x; diff --git a/test/langtools/tools/javac/patterns/PatternDesugaring.java b/test/langtools/tools/javac/patterns/PatternDesugaring.java new file mode 100644 index 00000000000..67c19b2441b --- /dev/null +++ b/test/langtools/tools/javac/patterns/PatternDesugaring.java @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2022, 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 8291769 + * @summary Verify the compiled code does not have unwanted constructs. + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.util + * jdk.jdeps/com.sun.tools.javap + * @build toolbox.ToolBox toolbox.JavacTask + * @run main PatternDesugaring +*/ + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.function.Consumer; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.JavapTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class PatternDesugaring extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new PatternDesugaring().runTests(); + } + + PatternDesugaring() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testPrimitiveNoBoxUnbox(Path base) throws Exception { + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return switch (obj) { + case R(int i) -> i; + default -> -1; + }; + } + record R(int i) {} + } + """, + decompiled -> { + if (decompiled.contains("intValue") || decompiled.contains("valueOf")) { + throw new AssertionError("Has boxing/unboxing."); + } + }); + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return obj instanceof R(int i) ? i : -1; + } + record R(int i) {} + } + """, + decompiled -> { + if (decompiled.contains("intValue") || decompiled.contains("valueOf")) { + throw new AssertionError("Has boxing/unboxing."); + } + }); + } + + @Test + public void testCacheRecordsForRecordPatterns(Path base) throws Exception { + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return switch (obj) { + case R(Integer i, Integer j, Integer k) -> i + j + k; + default -> -1; + }; + } + record R(Integer i, Integer j, Integer k) {} + } + """, + decompiled -> { + if (decompiled.split("checkcast").length != 2) { + throw new AssertionError("Unexpected number of checkcasts."); + } + }); + doTest(base, + new String[0], + """ + package test; + public class Test { + public int test(Object obj) { + return obj instanceof R(Integer i, Integer j, Integer k) ? i + j + k: -1; + } + record R(Integer i, Integer j, Integer k) {} + } + """, + decompiled -> { + if (decompiled.split("checkcast").length != 2) { + throw new AssertionError("Unexpected number of checkcasts."); + } + }); + } + + private void doTest(Path base, String[] libraryCode, String testCode, Consumer validate) throws IOException { + Path current = base.resolve("."); + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + if (libraryCode.length != 0) { + Path libSrc = current.resolve("lib-src"); + + for (String code : libraryCode) { + tb.writeJavaFiles(libSrc, code); + } + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + } + + Path src = current.resolve("src"); + tb.writeJavaFiles(src, testCode); + + Path classes = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + var log = + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-XDrawDiagnostics", + "-Xlint:-preview", + "--class-path", libClasses.toString(), + "-XDshould-stop.at=FLOW") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .run(Task.Expect.SUCCESS) + .writeAll(); + var decompiled = + new JavapTask(tb) + .classpath(classes.toString()) + .classes("test.Test") + .options("-s", "-verbose") + .run() + .writeAll() + .getOutput(Task.OutputKind.DIRECT); + + System.err.println("decompiled: " + decompiled); + + validate.accept(decompiled); + } + +} diff --git a/test/langtools/tools/javac/patterns/Switches.java b/test/langtools/tools/javac/patterns/Switches.java index 48eda83e8cb..1c7ae41274e 100644 --- a/test/langtools/tools/javac/patterns/Switches.java +++ b/test/langtools/tools/javac/patterns/Switches.java @@ -92,6 +92,10 @@ void run() { assertEquals("a", deconstructExpression(new R("a"))); assertEquals("1", deconstructExpression(new R(1))); assertEquals("other", deconstructExpression("")); + assertEquals("a", translationTest("a")); + assertEquals("Rb", translationTest(new R("b"))); + assertEquals("R2c", translationTest(new R2("c"))); + assertEquals("other", translationTest(0)); assertEquals("OK", totalPatternAndNull(Integer.valueOf(42))); assertEquals("OK", totalPatternAndNull(null)); assertEquals("1", nullAfterTotal(Integer.valueOf(42))); @@ -99,6 +103,8 @@ void run() { emptyFallThrough(1); emptyFallThrough(""); emptyFallThrough(1.0); + testSimpleSwitch(); + testSimpleSwitchExpression(); } void run(Function mapper) { @@ -636,6 +642,15 @@ String deconstructExpression(Object o) { }; } + String translationTest(Object o) { + return switch (o) { + case R(String s) -> "R" + s; + case String s -> s; + case R2(String s) -> "R2" + s; + default -> "other"; + }; + } + String totalPatternAndNull(Integer in) { return switch (in) { case -1: { yield "";} @@ -659,6 +674,23 @@ void emptyFallThrough(Object o) { } } + void testSimpleSwitch() { + Object o = ""; + int res; + switch (o) { + default -> res = 1; + }; + assertEquals(1, res); + } + + void testSimpleSwitchExpression() { + Object o = ""; + int res = switch (o) { + default -> 1; + }; + assertEquals(1, res); + } + //verify that for cases like: //case ConstantClassClash -> //ConstantClassClash is interpreted as a field, not as a class @@ -700,4 +732,5 @@ public enum E implements Runnable { } record R(Object o) {} + record R2(Object o) {} } diff --git a/test/langtools/tools/javac/patterns/TranslationTest.java b/test/langtools/tools/javac/patterns/TranslationTest.java new file mode 100644 index 00000000000..f77b04fc9a3 --- /dev/null +++ b/test/langtools/tools/javac/patterns/TranslationTest.java @@ -0,0 +1,331 @@ +/* + * Copyright (c) 2022, 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 8291769 + * @summary Check expected translation of various pattern related constructs + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.comp + * jdk.compiler/com.sun.tools.javac.main + * jdk.compiler/com.sun.tools.javac.tree + * jdk.compiler/com.sun.tools.javac.util + * @build toolbox.ToolBox toolbox.JavacTask + * @run main TranslationTest +*/ + +import com.sun.tools.javac.api.JavacTaskImpl; +import com.sun.tools.javac.comp.AttrContext; +import com.sun.tools.javac.comp.Env; +import com.sun.tools.javac.comp.TransPatterns; +import com.sun.tools.javac.tree.JCTree; +import com.sun.tools.javac.tree.JCTree.JCCase; +import com.sun.tools.javac.tree.JCTree.JCSwitch; +import com.sun.tools.javac.tree.JCTree.JCSwitchExpression; +import com.sun.tools.javac.tree.JCTree.Tag; +import com.sun.tools.javac.tree.TreeMaker; +import com.sun.tools.javac.tree.TreeScanner; +import com.sun.tools.javac.util.Context; +import com.sun.tools.javac.util.Context.Factory; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.List; + +import toolbox.TestRunner; +import toolbox.JavacTask; +import toolbox.Task; +import toolbox.ToolBox; + +public class TranslationTest extends TestRunner { + + private static final String JAVA_VERSION = System.getProperty("java.specification.version"); + + ToolBox tb; + + public static void main(String... args) throws Exception { + new TranslationTest().runTests(); + } + + TranslationTest() { + super(System.err); + tb = new ToolBox(); + } + + public void runTests() throws Exception { + runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + @Test + public void testSimple(Path base) throws Exception { + doTest(base, + new String[]{""" + package lib; + public record Box(Object o) {} + """}, + """ + package test; + import lib.*; + public class Test { + private int test(Object obj) { + return switch (obj) { + case Box(String s) -> 0; + case Box(Integer i) -> 0; + case Box(Number n) -> 0; + case Box(CharSequence cs) -> 0; + + default -> -1; + }; + } + } + """, + toplevel -> printSwitchStructure(toplevel), + """ + switch + case + switch + case + case + case + case + case ..., default + default + """); + } + + @Test + public void testMultiComponent(Path base) throws Exception { + doTest(base, + new String[]{""" + package lib; + public record Pair(Object o1, Object o2) {} + """, + """ + package lib; + public record Triplet(Object o1, Object o2, Object o3) {} + """}, + """ + package test; + import lib.*; + public class Test { + private int test(Object obj) { + return switch (obj) { + case Pair(String c1, Pair(String o2, String s2)) -> 0; + case Pair(String c1, Pair(String o2, Integer s2)) -> 0; + case Pair(String c1, Pair(Integer o2, String s2)) -> 0; + case Pair(String c1, Pair(Integer o2, Integer s2)) -> 0; + + case Pair(Integer c1, Pair(String o2, String s2)) -> 0; + case Pair(Integer c1, Pair(String o2, Integer s2)) -> 0; + case Pair(Integer c1, Pair(Integer o2, String s2)) -> 0; + case Pair(Integer c1, Pair(Integer o2, Integer s2)) -> 0; + + default -> -1; + }; + } + } + """, + toplevel -> printSwitchStructure(toplevel), + """ + switch + case + switch + case + switch + case + switch + case + switch + case + case + case ..., default + case + switch + case + case + case ..., default + case ..., default + case ..., default + case + switch + case + switch + case + switch + case + case + case ..., default + case + switch + case + case + case ..., default + case ..., default + case ..., default + case ..., default + default + """); + } + + private void doTest(Path base, String[] libraryCode, String testCode, + Callback callback, String expectedOutput) throws IOException { + Path current = base.resolve("."); + Path libClasses = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + if (libraryCode.length != 0) { + Path libSrc = current.resolve("lib-src"); + + for (String code : libraryCode) { + tb.writeJavaFiles(libSrc, code); + } + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION) + .outdir(libClasses) + .files(tb.findJavaFiles(libSrc)) + .run(); + } + + Path src = current.resolve("src"); + tb.writeJavaFiles(src, testCode); + + Path classes = current.resolve("libClasses"); + + Files.createDirectories(libClasses); + + List output = new ArrayList<>(); + + new JavacTask(tb) + .options("--enable-preview", + "-source", JAVA_VERSION, + "-Xlint:-preview", + "--class-path", libClasses.toString(), + "-XDshould-stop.at=FLOW") + .outdir(classes) + .files(tb.findJavaFiles(src)) + .callback(task -> { + Context ctx = ((JavacTaskImpl) task).getContext(); + + TestTransPatterns.preRegister(ctx, callback, output); + }) + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + if (output.size() != 1 || !expectedOutput.equals(output.get(0))) { + throw new AssertionError("Unexpected output:\n" + output); + } + } + + private String printSwitchStructure(JCTree topLevel) { + StringBuilder structure = new StringBuilder(); + + new TreeScanner() { + private static final int INDENT = 4; + private int indent = 0; + @Override + public void visitSwitch(JCSwitch node) { + int prevIndent = indent; + appendLine("switch"); + try { + indent += INDENT; + super.visitSwitch(node); + } finally { + indent = prevIndent; + } + } + + @Override + public void visitSwitchExpression(JCSwitchExpression node) { + int prevIndent = indent; + appendLine("switch"); + try { + indent += INDENT; + super.visitSwitchExpression(node); + } finally { + indent = prevIndent; + } + } + @Override + public void visitCase(JCCase node) { + int prevIndent = indent; + if (node.labels.size() == 1 && node.labels.head.hasTag(Tag.DEFAULTCASELABEL)) { + appendLine("default"); + } else if (node.labels.stream().anyMatch(l -> l.hasTag(Tag.DEFAULTCASELABEL))) { + appendLine("case ..., default"); + } else { + appendLine("case"); + } + try { + indent += INDENT; + super.visitCase(node); + } finally { + indent = prevIndent; + } + } + private void appendLine(String what) { + for (int i = 0; i < indent; i++) { + structure.append(' '); + } + structure.append(what); + structure.append('\n'); + } + }.scan(topLevel); + + return structure.toString(); + } + + public interface Callback { + public String patternsTranslated(JCTree topLevel); + } + + private static final class TestTransPatterns extends TransPatterns { + + public static void preRegister(Context ctx, Callback validator, List output) { + ctx.put(transPatternsKey, (Factory) c -> new TestTransPatterns(c, validator, output)); + } + + private final Callback callback; + private final List output; + + public TestTransPatterns(Context context, Callback callback, List output) { + super(context); + this.callback = callback; + this.output = output; + } + + @Override + public JCTree translateTopLevelClass(Env env, JCTree cdef, TreeMaker make) { + JCTree result = super.translateTopLevelClass(env, cdef, make); + output.add(callback.patternsTranslated(cdef)); + return result; + } + + } +} diff --git a/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java b/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java index a93cfa61071..8dcae4e6f89 100644 --- a/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java +++ b/test/langtools/tools/javac/patterns/TypedDeconstructionPatternExc.java @@ -28,6 +28,7 @@ import java.util.Objects; import java.util.function.Function; +import java.util.function.ToIntFunction; public class TypedDeconstructionPatternExc { @@ -38,6 +39,9 @@ public static void main(String... args) throws Throwable { void run() { run(this::testExpr); run(this::testExprCond); + testTryExpr(); + run(this::testLambda); + runBoxed(); } void run(Function, Integer> tested) { @@ -82,6 +86,82 @@ int testExprCond(Pair p) { } } + void testTryExpr() { + TEST: { + try { + var v = switch ((Pair) (Object) new Pair(1, 1)) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } catch (ClassCastException ex) { + //OK + break TEST; + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected Throwable!"); + } + fail("ClassCastException not thrown!"); + } + TEST: { + try { + var v = switch (new Pair("fail", 1)) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } catch (MatchException ex) { + //OK + break TEST; + } catch (Throwable t) { + t.printStackTrace(); + fail("Unexpected Throwable!"); + } + fail("MatchException not thrown!"); + } + } + + int testLambda(Pair p) { + var r = prepareLambda(); + return r.applyAsInt(p); + } + + ToIntFunction> prepareLambda() { + return p -> switch (p) { + case Pair(String s, Integer i) -> s.length() + i; + case Object o -> -1; + }; + } + + void runBoxed() { + assertEquals(2, testBoxed(new Box(new Pair<>("1", 1)))); + try { + testBoxed(new Box((Pair) (Object) new Pair(1, 1))); + fail("Expected an exception, but none happened!"); + } catch (ClassCastException ex) { + System.err.println("expected exception:"); + ex.printStackTrace(); + } + try { + testBoxed(new Box(new Pair("fail", 1))); + fail("Expected an exception, but none happened!"); + } catch (MatchException ex) { + assertEquals(TestPatternFailed.class.getName() + ": " + EXCEPTION_MESSAGE, + ex.getMessage()); + if (ex.getCause() instanceof TestPatternFailed ex2) { + System.err.println("expected exception:"); + ex2.printStackTrace(); + } else { + fail("Not the correct exception."); + } + } + } + + int testBoxed(Object p) { + return switch (p) { + case Box(Pair(String s, Integer i)) -> s.length() + i; + case Object o -> -1; + }; + } + static final String EXCEPTION_MESSAGE = "exception-message"; record Pair(L l, R r) { @@ -96,6 +176,8 @@ public R r() { } } + record Box(Pair boxed) {} + void assertEquals(Object expected, Object actual) { if (!Objects.equals(expected, actual)) { throw new AssertionError("Expected: " + expected + "," + From f9e0f1d5b3663db5de0532e9d9ce41312bf35ed3 Mon Sep 17 00:00:00 2001 From: Xiaolin Zheng Date: Mon, 5 Dec 2022 12:43:57 +0000 Subject: [PATCH 041/494] 8297763: Fix missing stub code expansion before align() in shared trampolines Reviewed-by: fyang, luhenry --- src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp | 9 ++++++++- src/hotspot/cpu/riscv/codeBuffer_riscv.cpp | 9 ++++++++- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 3 +++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp index a4213707afb..3bc12a1f651 100644 --- a/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/codeBuffer_aarch64.cpp @@ -52,7 +52,14 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline bool p_succeeded = true; auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) { masm.set_code_section(cb->stubs()); - masm.align(wordSize); + if (!is_aligned(masm.offset(), wordSize)) { + if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + p_succeeded = false; + return p_succeeded; + } + masm.align(wordSize); + } LinkedListIterator it(offsets.head()); int offset = *it.next(); diff --git a/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp b/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp index b4746649f19..eedaff87b2c 100644 --- a/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp +++ b/src/hotspot/cpu/riscv/codeBuffer_riscv.cpp @@ -53,7 +53,14 @@ static bool emit_shared_trampolines(CodeBuffer* cb, CodeBuffer::SharedTrampoline bool p_succeeded = true; auto emit = [&](address dest, const CodeBuffer::Offsets &offsets) { masm.set_code_section(cb->stubs()); - masm.align(wordSize, NativeCallTrampolineStub::data_offset); + if (!is_aligned(masm.offset() + NativeCallTrampolineStub::data_offset, wordSize)) { + if (cb->stubs()->maybe_expand_to_ensure_remaining(NativeInstruction::instruction_size) && cb->blob() == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + p_succeeded = false; + return p_succeeded; + } + masm.align(wordSize, NativeCallTrampolineStub::data_offset); + } LinkedListIterator it(offsets.head()); int offset = *it.next(); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 779e7912b43..3c613d8c09b 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -3128,6 +3128,9 @@ address MacroAssembler::emit_trampoline_stub(int insts_call_instruction_offset, return NULL; // CodeBuffer::expand failed } + // We are always 4-byte aligned here. + assert_alignment(pc()); + // Create a trampoline stub relocation which relates this trampoline stub // with the call instruction at insts_call_instruction_offset in the // instructions code-section. From e7e03548feabb3f200b4f6f5d04c392343adb131 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Mon, 5 Dec 2022 13:18:44 +0000 Subject: [PATCH 042/494] 8297767: Assert JNICritical_lock/safepoint-1 and AdapterHandlerLibrary_lock/safepoint-1 Reviewed-by: pchilanomate, rehn --- src/hotspot/share/runtime/mutexLocker.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/mutexLocker.cpp b/src/hotspot/share/runtime/mutexLocker.cpp index d71f57695e0..fca953f4570 100644 --- a/src/hotspot/share/runtime/mutexLocker.cpp +++ b/src/hotspot/share/runtime/mutexLocker.cpp @@ -369,7 +369,7 @@ void mutex_init() { defl(OopMapCacheAlloc_lock , PaddedMutex , Threads_lock, true); defl(Module_lock , PaddedMutex , ClassLoaderDataGraph_lock); defl(SystemDictionary_lock , PaddedMonitor, Module_lock); - defl(JNICritical_lock , PaddedMonitor, MultiArray_lock); // used for JNI critical regions + defl(JNICritical_lock , PaddedMonitor, AdapterHandlerLibrary_lock); // used for JNI critical regions #if INCLUDE_JVMCI // JVMCIRuntime_lock must be acquired before JVMCI_lock to avoid deadlock defl(JVMCI_lock , PaddedMonitor, JVMCIRuntime_lock); From b9eec96889abf7df6d2b479e294c7823fb3d5850 Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Mon, 5 Dec 2022 13:30:15 +0000 Subject: [PATCH 043/494] 8281214: Unsafe use of long in VMThread::setup_periodic_safepoint_if_needed Reviewed-by: eastigeevich, shade --- src/hotspot/share/runtime/vmThread.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/vmThread.cpp b/src/hotspot/share/runtime/vmThread.cpp index d70455a570e..c1f226702cd 100644 --- a/src/hotspot/share/runtime/vmThread.cpp +++ b/src/hotspot/share/runtime/vmThread.cpp @@ -323,7 +323,7 @@ void VMThread::setup_periodic_safepoint_if_needed() { assert(_cur_vm_operation == NULL, "Already have an op"); assert(_next_vm_operation == NULL, "Already have an op"); // Check for a cleanup before SafepointALot to keep stats correct. - long interval_ms = SafepointTracing::time_since_last_safepoint_ms(); + jlong interval_ms = SafepointTracing::time_since_last_safepoint_ms(); bool max_time_exceeded = GuaranteedSafepointInterval != 0 && (interval_ms >= GuaranteedSafepointInterval); if (!max_time_exceeded) { From bd381886e0f39d0e48b555b5e3167565d6a6b40d Mon Sep 17 00:00:00 2001 From: Afshin Zafari Date: Mon, 5 Dec 2022 13:31:15 +0000 Subject: [PATCH 044/494] 8297766: Remove UseMallocOnly development option Reviewed-by: coleenp, stuefe, dholmes --- src/hotspot/share/memory/arena.cpp | 83 ------------------- src/hotspot/share/memory/arena.hpp | 3 - src/hotspot/share/memory/resourceArea.hpp | 4 - .../share/memory/resourceArea.inline.hpp | 5 -- src/hotspot/share/runtime/globals.hpp | 4 - src/hotspot/share/runtime/handles.hpp | 1 - test/hotspot/gtest/memory/test_arena.cpp | 61 +++++--------- test/hotspot/jtreg/gtest/ArenaGtests.java | 40 --------- .../runtime/8007475/StackMapFrameTest.java | 41 --------- 9 files changed, 23 insertions(+), 219 deletions(-) delete mode 100644 test/hotspot/jtreg/gtest/ArenaGtests.java delete mode 100644 test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index b925daecd3c..050d129351f 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -273,10 +273,6 @@ Arena::~Arena() { // Destroy this arenas contents and reset to empty void Arena::destruct_contents() { - if (UseMallocOnly && _first != NULL) { - char* end = _first->next() ? _first->top() : _hwm; - free_malloced_objects(_first, _first->bottom(), end, _hwm); - } // reset size before chop to avoid a rare racing condition // that can have total arena memory exceed total chunk memory set_size_in_bytes(0); @@ -342,19 +338,6 @@ void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFail assert(old_size == 0, "sanity"); return Amalloc(new_size, alloc_failmode); // as with realloc(3), a NULL old ptr is equivalent to malloc(3) } -#ifdef ASSERT - if (UseMallocOnly) { - // always allocate a new object (otherwise we'll free this one twice) - char* copy = (char*)Amalloc(new_size, alloc_failmode); - if (copy == NULL) { - return NULL; - } - size_t n = MIN2(old_size, new_size); - if (n > 0) memcpy(copy, old_ptr, n); - Afree(old_ptr,old_size); // Mostly done to keep stats accurate - return copy; - } -#endif char *c_old = (char*)old_ptr; // Handy name // Stupid fast special case if( new_size <= old_size ) { // Shrink in-place @@ -386,24 +369,6 @@ void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFail // Determine if pointer belongs to this Arena or not. bool Arena::contains( const void *ptr ) const { -#ifdef ASSERT - if (UseMallocOnly) { - // really slow, but not easy to make fast - if (_chunk == NULL) return false; - char** bottom = (char**)_chunk->bottom(); - for (char** p = (char**)_hwm - 1; p >= bottom; p--) { - if (*p == ptr) return true; - } - for (Chunk *c = _first; c != NULL; c = c->next()) { - if (c == _chunk) continue; // current chunk has been processed - char** bottom = (char**)c->bottom(); - for (char** p = (char**)c->top() - 1; p >= bottom; p--) { - if (*p == ptr) return true; - } - } - return false; - } -#endif if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm ) return true; // Check for in this chunk for (Chunk *c = _first; c; c = c->next()) { @@ -414,51 +379,3 @@ bool Arena::contains( const void *ptr ) const { } return false; // Not in any Chunk, so not in Arena } - - -#ifdef ASSERT -void* Arena::malloc(size_t size) { - assert(UseMallocOnly, "shouldn't call"); - // use malloc, but save pointer in res. area for later freeing - char** save = (char**)internal_amalloc(sizeof(char*)); - return (*save = (char*)os::malloc(size, mtChunk)); -} -#endif - - -//-------------------------------------------------------------------------------------- -// Non-product code - -#ifndef PRODUCT - -// debugging code -inline void Arena::free_all(char** start, char** end) { - for (char** p = start; p < end; p++) if (*p) os::free(*p); -} - -void Arena::free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) { - assert(UseMallocOnly, "should not call"); - // free all objects malloced since resource mark was created; resource area - // contains their addresses - if (chunk->next()) { - // this chunk is full, and some others too - for (Chunk* c = chunk->next(); c != NULL; c = c->next()) { - char* top = c->top(); - if (c->next() == NULL) { - top = hwm2; // last junk is only used up to hwm2 - assert(c->contains(hwm2), "bad hwm2"); - } - free_all((char**)c->bottom(), (char**)top); - } - assert(chunk->contains(hwm), "bad hwm"); - assert(chunk->contains(max), "bad max"); - free_all((char**)hwm, (char**)max); - } else { - // this chunk was partially used - assert(chunk->contains(hwm), "bad hwm"); - assert(chunk->contains(hwm2), "bad hwm2"); - free_all((char**)hwm, (char**)hwm2); - } -} - -#endif // Non-product diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index bdddf5a3feb..35a47f953ac 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -125,7 +125,6 @@ class Arena : public CHeapObjBase { // on both 32 and 64 bit platforms. Required for atomic jlong operations on 32 bits. void* Amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { x = ARENA_ALIGN(x); // note for 32 bits this should align _hwm as well. - debug_only(if (UseMallocOnly) return malloc(x);) // Amalloc guarantees 64-bit alignment and we need to ensure that in case the preceding // allocation was AmallocWords. Only needed on 32-bit - on 64-bit Amalloc and AmallocWords are // identical. @@ -138,7 +137,6 @@ class Arena : public CHeapObjBase { // is 4 bytes on 32 bits, hence the name. void* AmallocWords(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { assert(is_aligned(x, BytesPerWord), "misaligned size"); - debug_only(if (UseMallocOnly) return malloc(x);) return internal_amalloc(x, alloc_failmode); } @@ -149,7 +147,6 @@ class Arena : public CHeapObjBase { } #ifdef ASSERT if (ZapResourceArea) memset(ptr, badResourceValue, size); // zap freed memory - if (UseMallocOnly) return true; #endif if (((char*)ptr) + size == _hwm) { _hwm = (char*)ptr; diff --git a/src/hotspot/share/memory/resourceArea.hpp b/src/hotspot/share/memory/resourceArea.hpp index 85c030db648..a10e3105c6b 100644 --- a/src/hotspot/share/memory/resourceArea.hpp +++ b/src/hotspot/share/memory/resourceArea.hpp @@ -105,10 +105,6 @@ class ResourceArea: public Arena { assert(_nesting > state._nesting, "rollback to inactive mark"); assert((_nesting - state._nesting) == 1, "rollback across another mark"); - if (UseMallocOnly) { - free_malloced_objects(state._chunk, state._hwm, state._max, _hwm); - } - if (state._chunk->next() != nullptr) { // Delete later chunks. // Reset size before deleting chunks. Otherwise, the total // size could exceed the total chunk size. diff --git a/src/hotspot/share/memory/resourceArea.inline.hpp b/src/hotspot/share/memory/resourceArea.inline.hpp index 5ec7ae8ecda..0cd7b8a28b9 100644 --- a/src/hotspot/share/memory/resourceArea.inline.hpp +++ b/src/hotspot/share/memory/resourceArea.inline.hpp @@ -32,11 +32,6 @@ inline char* ResourceArea::allocate_bytes(size_t size, AllocFailType alloc_failmode) { #ifdef ASSERT verify_has_resource_mark(); - if (UseMallocOnly) { - // use malloc, but save pointer in res. area for later freeing - char** save = (char**)internal_amalloc(sizeof(char*)); - return (*save = (char*)os::malloc(size, mtThread, CURRENT_PC)); - } #endif // ASSERT return (char*)Amalloc(size, alloc_failmode); } diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index ab64c9bc6a1..c728915d34b 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -455,10 +455,6 @@ const int ObjectAlignmentInBytes = 8; notproduct(bool, VerifyCodeCache, false, \ "Verify code cache on memory allocation/deallocation") \ \ - develop(bool, UseMallocOnly, false, \ - "Use only malloc/free for allocation (no resource area/arena). " \ - "Used to help diagnose memory stomping bugs.") \ - \ develop(bool, ZapResourceArea, trueInDebug, \ "Zap freed resource/arena space") \ \ diff --git a/src/hotspot/share/runtime/handles.hpp b/src/hotspot/share/runtime/handles.hpp index dd7a4d48d83..fa3f5cca589 100644 --- a/src/hotspot/share/runtime/handles.hpp +++ b/src/hotspot/share/runtime/handles.hpp @@ -196,7 +196,6 @@ class HandleArea: public Arena { // Handle allocation private: oop* real_allocate_handle(oop obj) { - // Ignore UseMallocOnly by allocating only in arena. oop* handle = (oop*)internal_amalloc(oopSize); *handle = obj; return handle; diff --git a/test/hotspot/gtest/memory/test_arena.cpp b/test/hotspot/gtest/memory/test_arena.cpp index 363ee984503..35a85508d68 100644 --- a/test/hotspot/gtest/memory/test_arena.cpp +++ b/test/hotspot/gtest/memory/test_arena.cpp @@ -57,17 +57,13 @@ TEST_VM(Arena, alloc_size_0) { void* p = ar.Amalloc(0); ASSERT_NOT_NULL(p); ASSERT_ALIGN_AMALLOC(p); - if (!UseMallocOnly) { - // contains works differently for malloced mode (and there its broken anyway) - ASSERT_FALSE(ar.contains(p)); - } + + ASSERT_FALSE(ar.contains(p)); // Allocate again. The new allocations should have the same position as the 0-sized // first one. - if (!UseMallocOnly) { - void* p2 = ar.Amalloc(1); - ASSERT_AMALLOC(ar, p2); - ASSERT_EQ(p2, p); - } + void* p2 = ar.Amalloc(1); + ASSERT_AMALLOC(ar, p2); + ASSERT_EQ(p2, p); } // Test behavior for Arealloc(p, 0) @@ -81,10 +77,8 @@ TEST_VM(Arena, realloc_size_0) { ASSERT_NULL(p2); // a subsequent allocation should get the same pointer - if (!UseMallocOnly) { - void* p3 = ar.Amalloc(0x20); - ASSERT_EQ(p3, p1); - } + void* p3 = ar.Amalloc(0x20); + ASSERT_EQ(p3, p1); } // Realloc equal sizes is a noop @@ -96,9 +90,7 @@ TEST_VM(Arena, realloc_same_size) { void* p2 = ar.Arealloc(p1, 0x200, 0x200); - if (!UseMallocOnly) { - ASSERT_EQ(p2, p1); - } + ASSERT_EQ(p2, p1); ASSERT_RANGE_IS_MARKED(p2, 0x200); } @@ -157,29 +149,26 @@ TEST_VM(Arena, free_top) { DEBUG_ONLY(ASSERT_RANGE_IS_MARKED_WITH(p, 0x10, badResourceValue);) // a subsequent allocation should get the same pointer - if (!UseMallocOnly) { - void* p2 = ar.Amalloc(0x20); - ASSERT_EQ(p2, p); - } + void* p2 = ar.Amalloc(0x20); + ASSERT_EQ(p2, p); } + // In-place shrinking. TEST_VM(Arena, realloc_top_shrink) { - if (!UseMallocOnly) { - Arena ar(mtTest); + Arena ar(mtTest); - void* p1 = ar.Amalloc(0x200); - ASSERT_AMALLOC(ar, p1); - GtestUtils::mark_range(p1, 0x200); + void* p1 = ar.Amalloc(0x200); + ASSERT_AMALLOC(ar, p1); + GtestUtils::mark_range(p1, 0x200); - void* p2 = ar.Arealloc(p1, 0x200, 0x100); - ASSERT_EQ(p1, p2); - ASSERT_RANGE_IS_MARKED(p2, 0x100); // realloc should preserve old content + void* p2 = ar.Arealloc(p1, 0x200, 0x100); + ASSERT_EQ(p1, p2); + ASSERT_RANGE_IS_MARKED(p2, 0x100); // realloc should preserve old content - // A subsequent allocation should be placed right after the end of the first, shrunk, allocation - void* p3 = ar.Amalloc(1); - ASSERT_EQ(p3, ((char*)p1) + 0x100); - } + // A subsequent allocation should be placed right after the end of the first, shrunk, allocation + void* p3 = ar.Amalloc(1); + ASSERT_EQ(p3, ((char*)p1) + 0x100); } // not-in-place shrinking. @@ -193,9 +182,7 @@ TEST_VM(Arena, realloc_nontop_shrink) { void* p_other = ar.Amalloc(20); // new top, p1 not top anymore void* p2 = ar.Arealloc(p1, 200, 100); - if (!UseMallocOnly) { - ASSERT_EQ(p1, p2); // should still shrink in place - } + ASSERT_EQ(p1, p2); // should still shrink in place ASSERT_RANGE_IS_MARKED(p2, 100); // realloc should preserve old content } @@ -208,9 +195,7 @@ TEST_VM(Arena, realloc_top_grow) { GtestUtils::mark_range(p1, 0x10); void* p2 = ar.Arealloc(p1, 0x10, 0x20); - if (!UseMallocOnly) { - ASSERT_EQ(p1, p2); - } + ASSERT_EQ(p1, p2); ASSERT_RANGE_IS_MARKED(p2, 0x10); // realloc should preserve old content } diff --git a/test/hotspot/jtreg/gtest/ArenaGtests.java b/test/hotspot/jtreg/gtest/ArenaGtests.java deleted file mode 100644 index ee8ec94e456..00000000000 --- a/test/hotspot/jtreg/gtest/ArenaGtests.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2020 SAP SE. All rights reserved. - * 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. - * - */ - -/* - * Note: This runs the Arena portion of the gtests with UseMallocOnly - * (restricted to debug since UseMallocOnly is debug-only) - */ - -/* @test - * @bug 8271242 - * @summary Run arena tests with UseMallocOnly - * @requires vm.debug - * @library /test/lib - * @modules java.base/jdk.internal.misc - * java.xml - * @requires vm.flagless - * @run main/native GTestWrapper --gtest_filter=Arena* -XX:+UseMallocOnly - */ diff --git a/test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java b/test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java deleted file mode 100644 index b927ae76db6..00000000000 --- a/test/hotspot/jtreg/runtime/8007475/StackMapFrameTest.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2013, 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 8007475 - * @summary Test memory stomp in stack map test - * @run main/othervm -XX:+IgnoreUnrecognizedVMOptions -XX:+UseMallocOnly StackMapFrameTest - */ -public class StackMapFrameTest { - - public static void foo() { - Object o = new Object(); - } - - public static void main(String args[]) { - for (int i = 0; i < 25000; i++) { - foo(); - } - } -} From 73baadceb60029f6340c1327118aeb59971c2434 Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Mon, 5 Dec 2022 13:49:53 +0000 Subject: [PATCH 045/494] 8295044: Implementation of Foreign Function and Memory API (Second Preview) Co-authored-by: Jorn Vernee Co-authored-by: Per Minborg Co-authored-by: Maurizio Cimadamore Reviewed-by: jvernee, pminborg, psandoz, alanb, sundar --- .../cpu/aarch64/downcallLinker_aarch64.cpp | 18 +- src/hotspot/cpu/x86/downcallLinker_x86_64.cpp | 19 +- src/hotspot/share/ci/ciField.cpp | 2 +- .../share/classes/java/lang/Module.java | 72 +- .../share/classes/java/lang/ModuleLayer.java | 37 +- .../share/classes/java/lang/System.java | 8 +- .../classes/java/lang/foreign/Arena.java | 166 ++ .../java/lang/foreign/FunctionDescriptor.java | 202 +- .../java/lang/foreign/GroupLayout.java | 132 +- .../classes/java/lang/foreign/Linker.java | 171 +- .../java/lang/foreign/MemoryAddress.java | 854 -------- .../java/lang/foreign/MemoryLayout.java | 142 +- .../java/lang/foreign/MemorySegment.java | 1853 ++++++++++------- .../java/lang/foreign/MemorySession.java | 285 --- .../java/lang/foreign/PaddingLayout.java | 64 +- .../java/lang/foreign/SegmentAllocator.java | 168 +- .../java/lang/foreign/SegmentScope.java | 132 ++ .../java/lang/foreign/SequenceLayout.java | 136 +- .../java/lang/foreign/StructLayout.java | 47 + .../java/lang/foreign/SymbolLookup.java | 104 +- .../java/lang/foreign/UnionLayout.java | 53 + .../classes/java/lang/foreign/VaList.java | 203 +- .../java/lang/foreign/ValueLayout.java | 684 +++--- .../java/lang/foreign/package-info.java | 183 +- .../java/lang/invoke/MethodHandles.java | 12 +- .../java/lang/invoke/NativeMethodHandle.java | 24 +- .../X-VarHandleByteArrayView.java.template | 1 - .../java/nio/Direct-X-Buffer.java.template | 1 - .../java/nio/channels/FileChannel.java | 11 +- .../jdk/internal/access/JavaLangAccess.java | 7 +- .../foreign/AbstractMemorySegmentImpl.java | 268 ++- .../jdk/internal/foreign/ArenaAllocator.java | 95 - .../classes/jdk/internal/foreign/CABI.java | 16 +- .../jdk/internal/foreign/ConfinedSession.java | 10 +- .../foreign/FunctionDescriptorImpl.java | 186 ++ .../jdk/internal/foreign/GlobalSession.java | 70 + .../foreign/HeapMemorySegmentImpl.java | 80 +- .../jdk/internal/foreign/ImplicitSession.java | 67 + .../jdk/internal/foreign/LayoutPath.java | 13 +- .../foreign/MappedMemorySegmentImpl.java | 14 +- .../internal/foreign/MemoryAddressImpl.java | 389 ---- .../internal/foreign/MemorySessionImpl.java | 269 +-- .../foreign/NativeMemorySegmentImpl.java | 100 +- .../jdk/internal/foreign/PlatformLayouts.java | 13 +- .../jdk/internal/foreign/SharedSession.java | 6 +- .../internal/foreign/SlicingAllocator.java} | 48 +- .../jdk/internal/foreign/SystemLookup.java | 37 +- .../classes/jdk/internal/foreign/Utils.java | 83 +- .../internal/foreign/abi/AbstractLinker.java | 57 +- .../jdk/internal/foreign/abi/Binding.java | 537 ++--- .../foreign/abi/BindingSpecializer.java | 185 +- .../foreign/abi/CallingSequenceBuilder.java | 18 +- .../internal/foreign/abi/DowncallLinker.java | 9 +- .../internal/foreign/abi/LinkerOptions.java | 80 + .../jdk/internal/foreign/abi/SharedUtils.java | 213 +- .../foreign/abi/SoftReferenceCache.java | 2 +- .../internal/foreign/abi/UpcallLinker.java | 6 +- .../jdk/internal/foreign/abi/UpcallStubs.java | 14 +- .../foreign/abi/aarch64/CallArranger.java | 77 +- .../foreign/abi/aarch64/TypeClass.java | 13 +- .../abi/aarch64/linux/LinuxAArch64Linker.java | 28 +- .../abi/aarch64/linux/LinuxAArch64VaList.java | 120 +- .../abi/aarch64/macos/MacOsAArch64Linker.java | 28 +- .../abi/aarch64/macos/MacOsAArch64VaList.java | 71 +- .../foreign/abi/x64/sysv/CallArranger.java | 83 +- .../foreign/abi/x64/sysv/SysVVaList.java | 88 +- .../foreign/abi/x64/sysv/SysVx64Linker.java | 25 +- .../foreign/abi/x64/sysv/TypeClass.java | 38 +- .../foreign/abi/x64/windows/CallArranger.java | 66 +- .../foreign/abi/x64/windows/TypeClass.java | 8 +- .../foreign/abi/x64/windows/WinVaList.java | 69 +- .../abi/x64/windows/Windowsx64Linker.java | 28 +- .../foreign/layout/AbstractGroupLayout.java | 151 ++ .../foreign/layout}/AbstractLayout.java | 129 +- .../foreign/layout/MemoryLayoutUtil.java | 43 + .../foreign/layout/PaddingLayoutImpl.java | 80 + .../foreign/layout/SequenceLayoutImpl.java | 216 ++ .../foreign/layout/StructLayoutImpl.java | 52 + .../foreign/layout/UnionLayoutImpl.java | 52 + .../internal/foreign/layout/ValueLayouts.java | 457 ++++ .../jdk/internal/javac/PreviewFeature.java | 2 +- .../jdk/internal/module/ModuleBootstrap.java | 2 +- .../jdk/internal/reflect/Reflection.java | 28 +- .../classes/sun/nio/ch/FileChannelImpl.java | 6 +- .../compiler/TestLinkToNativeRBP.java | 2 +- .../ClassFile/ClassFileVersionTest.java | 2 +- test/jdk/com/sun/jdi/JdbLastErrorTest.java | 4 +- .../jdk/java/foreign/CallGeneratorHelper.java | 30 +- test/jdk/java/foreign/LibraryLookupTest.java | 48 +- .../MemoryLayoutPrincipalTotalityTest.java | 120 ++ .../MemoryLayoutTypeRetentionTest.java | 174 ++ test/jdk/java/foreign/NativeTestHelper.java | 40 +- .../java/foreign/SafeFunctionAccessTest.java | 90 +- test/jdk/java/foreign/StdLibTest.java | 120 +- .../jdk/java/foreign/TestAdaptVarHandles.java | 27 +- test/jdk/java/foreign/TestArrays.java | 17 +- test/jdk/java/foreign/TestByteBuffer.java | 163 +- .../foreign/TestClassLoaderFindNative.java | 10 +- test/jdk/java/foreign/TestDowncallBase.java | 4 +- test/jdk/java/foreign/TestDowncallScope.java | 11 +- test/jdk/java/foreign/TestDowncallStack.java | 11 +- test/jdk/java/foreign/TestFallbackLookup.java | 2 +- test/jdk/java/foreign/TestFree.java | 16 +- .../java/foreign/TestFunctionDescriptor.java | 25 +- test/jdk/java/foreign/TestHandshake.java | 22 +- test/jdk/java/foreign/TestHeapAlignment.java | 7 +- test/jdk/java/foreign/TestIllegalLink.java | 54 +- test/jdk/java/foreign/TestIntrinsics.java | 23 +- .../java/foreign/TestLargeSegmentCopy.java | 57 + test/jdk/java/foreign/TestLayoutEquality.java | 41 +- test/jdk/java/foreign/TestLayoutPaths.java | 12 +- test/jdk/java/foreign/TestLayouts.java | 13 +- test/jdk/java/foreign/TestLinker.java | 50 + test/jdk/java/foreign/TestMemoryAccess.java | 19 +- .../foreign/TestMemoryAccessInstance.java | 136 +- .../jdk/java/foreign/TestMemoryAlignment.java | 18 +- .../java/foreign/TestMemoryDereference.java | 26 +- test/jdk/java/foreign/TestMemorySession.java | 204 +- test/jdk/java/foreign/TestMismatch.java | 152 +- test/jdk/java/foreign/TestNULLAddress.java | 33 +- test/jdk/java/foreign/TestNative.java | 42 +- test/jdk/java/foreign/TestNulls.java | 19 +- test/jdk/java/foreign/TestOfBufferIssue.java | 53 + .../java/foreign/TestScopedOperations.java | 49 +- .../java/foreign/TestSegmentAllocators.java | 129 +- test/jdk/java/foreign/TestSegmentCopy.java | 4 +- test/jdk/java/foreign/TestSegmentOffset.java | 6 +- test/jdk/java/foreign/TestSegmentOverlap.java | 19 +- test/jdk/java/foreign/TestSegments.java | 169 +- test/jdk/java/foreign/TestSharedAccess.java | 15 +- test/jdk/java/foreign/TestSlices.java | 10 +- test/jdk/java/foreign/TestSpliterator.java | 45 +- test/jdk/java/foreign/TestStringEncoding.java | 9 +- test/jdk/java/foreign/TestTypeAccess.java | 26 +- .../java/foreign/TestUnsupportedLinker.java | 7 +- test/jdk/java/foreign/TestUpcallAsync.java | 26 +- test/jdk/java/foreign/TestUpcallBase.java | 41 +- .../jdk/java/foreign/TestUpcallException.java | 73 +- .../jdk/java/foreign/TestUpcallHighArity.java | 33 +- test/jdk/java/foreign/TestUpcallScope.java | 15 +- test/jdk/java/foreign/TestUpcallStack.java | 18 +- .../java/foreign/TestUpcallStructScope.java | 12 +- test/jdk/java/foreign/TestValueLayouts.java | 148 ++ test/jdk/java/foreign/TestVarArgs.java | 39 +- .../foreign/TestVarHandleCombinators.java | 9 +- test/jdk/java/foreign/ThrowingUpcall.java | 12 +- test/jdk/java/foreign/UpcallTestHelper.java | 87 + .../callarranger/TestAarch64CallArranger.java | 125 +- .../callarranger/TestSysVCallArranger.java | 143 +- .../callarranger/TestWindowsCallArranger.java | 127 +- .../channels/AbstractChannelsTest.java | 81 +- .../channels/TestAsyncSocketChannels.java | 68 +- .../foreign/channels/TestSocketChannels.java | 67 +- .../foreign/dontrelease/TestDontRelease.java | 79 + .../java/foreign/dontrelease/libDontRelease.c | 30 + .../NativeAccessDynamicMain.java | 85 + .../TestEnableNativeAccessDynamic.java | 196 ++ .../openjdk/foreigntest/PanamaMainDirect.java | 3 +- .../openjdk/foreigntest/PanamaMainInvoke.java | 5 +- .../foreigntest/PanamaMainReflection.java | 5 +- .../handle/invoker/MethodHandleInvoker.java | 9 +- .../handle/lookup/MethodHandleLookup.java | 119 +- test/jdk/java/foreign/libNull.c | 32 + .../loaderLookup/TestLoaderLookup.java | 4 +- .../loaderLookup/TestLoaderLookupJNI.java | 4 +- .../foreign/loaderLookup/invoker/Invoker.java | 2 +- .../foreign/loaderLookup/lookup/Lookup.java | 6 +- .../java/foreign/normalize/TestNormalize.java | 207 ++ .../jdk/java/foreign/normalize/libNormalize.c | 39 + .../passheapsegment/TestPassHeapSegment.java | 86 + .../passheapsegment/libPassHeapSegment.c | 34 + .../foreign/stackwalk/TestAsyncStackWalk.java | 14 +- .../java/foreign/stackwalk/TestStackWalk.java | 16 +- .../foreign/upcalldeopt/TestUpcallDeopt.java | 12 +- test/jdk/java/foreign/valist/VaListTest.java | 156 +- .../foreign/virtual/TestVirtualCalls.java | 10 +- .../AttachCurrentThread/ImplicitAttach.java | 4 +- .../invoke/VarHandles/VarHandleTestExact.java | 6 +- .../channels/FileChannel/LargeMapTest.java | 4 +- .../FileChannel/MapToMemorySegmentTest.java | 19 +- .../java/util/stream/SpliteratorTest.java | 6 +- .../vector/AbstractVectorLoadStoreTest.java | 31 +- .../vector/Byte128VectorLoadStoreTests.java | 18 +- .../vector/Byte256VectorLoadStoreTests.java | 18 +- .../vector/Byte512VectorLoadStoreTests.java | 18 +- .../vector/Byte64VectorLoadStoreTests.java | 18 +- .../vector/ByteMaxVectorLoadStoreTests.java | 18 +- .../vector/Double128VectorLoadStoreTests.java | 18 +- .../vector/Double256VectorLoadStoreTests.java | 18 +- .../vector/Double512VectorLoadStoreTests.java | 18 +- .../vector/Double64VectorLoadStoreTests.java | 18 +- .../vector/DoubleMaxVectorLoadStoreTests.java | 18 +- .../vector/Float128VectorLoadStoreTests.java | 18 +- .../vector/Float256VectorLoadStoreTests.java | 18 +- .../vector/Float512VectorLoadStoreTests.java | 18 +- .../vector/Float64VectorLoadStoreTests.java | 18 +- .../vector/FloatMaxVectorLoadStoreTests.java | 18 +- .../vector/Int128VectorLoadStoreTests.java | 18 +- .../vector/Int256VectorLoadStoreTests.java | 18 +- .../vector/Int512VectorLoadStoreTests.java | 18 +- .../vector/Int64VectorLoadStoreTests.java | 18 +- .../vector/IntMaxVectorLoadStoreTests.java | 18 +- .../vector/Long128VectorLoadStoreTests.java | 18 +- .../vector/Long256VectorLoadStoreTests.java | 18 +- .../vector/Long512VectorLoadStoreTests.java | 18 +- .../vector/Long64VectorLoadStoreTests.java | 18 +- .../vector/LongMaxVectorLoadStoreTests.java | 18 +- .../vector/Short128VectorLoadStoreTests.java | 18 +- .../vector/Short256VectorLoadStoreTests.java | 18 +- .../vector/Short512VectorLoadStoreTests.java | 18 +- .../vector/Short64VectorLoadStoreTests.java | 18 +- .../vector/ShortMaxVectorLoadStoreTests.java | 18 +- test/jdk/jdk/incubator/vector/gen-template.sh | 1 + .../templates/X-LoadStoreTest.java.template | 18 +- .../lang/foreign/BulkMismatchAcquire.java | 37 +- .../bench/java/lang/foreign/BulkOps.java | 25 +- .../bench/java/lang/foreign/CLayouts.java | 15 +- .../lang/foreign/CallOverheadConstant.java | 45 +- .../java/lang/foreign/CallOverheadHelper.java | 62 +- .../lang/foreign/CallOverheadVirtual.java | 42 +- .../bench/java/lang/foreign/JavaLayouts.java | 16 +- .../bench/java/lang/foreign/LinkUpcall.java | 4 +- .../java/lang/foreign/LoopOverConstant.java | 6 +- .../bench/java/lang/foreign/LoopOverNew.java | 22 +- .../java/lang/foreign/LoopOverNewHeap.java | 2 +- .../lang/foreign/LoopOverNonConstant.java | 30 +- .../lang/foreign/LoopOverNonConstantFP.java | 13 +- .../lang/foreign/LoopOverNonConstantHeap.java | 10 +- .../foreign/LoopOverNonConstantMapped.java | 22 +- .../foreign/LoopOverNonConstantShared.java | 9 +- .../java/lang/foreign/LoopOverOfAddress.java | 77 + .../foreign/LoopOverPollutedSegments.java | 16 +- .../java/lang/foreign/LoopOverSlice.java | 10 +- .../java/lang/foreign/MemorySessionClose.java | 18 +- .../bench/java/lang/foreign/ParallelSum.java | 9 +- .../java/lang/foreign/PointerInvoke.java | 29 +- .../bench/java/lang/foreign/QSort.java | 31 +- .../bench/java/lang/foreign/StrLenTest.java | 66 +- .../java/lang/foreign/TestLoadBytes.java | 5 +- .../java/lang/foreign/UnrolledAccess.java | 12 +- .../bench/java/lang/foreign/Upcalls.java | 27 +- .../bench/java/lang/foreign/VaList.java | 17 +- .../java/lang/foreign/VarHandleExact.java | 9 +- .../lang/foreign/pointers/NativeType.java | 82 + .../java/lang/foreign/pointers/Point.java | 63 + .../java/lang/foreign/pointers/Pointer.java | 88 + .../lang/foreign/pointers/PointerBench.java | 145 ++ .../java/lang/foreign/pointers/Struct.java | 18 +- .../foreign/points/support/PanamaPoint.java | 16 +- .../vector/MemorySegmentVectorAccess.java | 6 +- .../incubator/vector/TestLoadStoreBytes.java | 28 +- .../incubator/vector/TestLoadStoreShorts.java | 27 +- 252 files changed, 9209 insertions(+), 7877 deletions(-) create mode 100644 src/java.base/share/classes/java/lang/foreign/Arena.java delete mode 100644 src/java.base/share/classes/java/lang/foreign/MemoryAddress.java delete mode 100644 src/java.base/share/classes/java/lang/foreign/MemorySession.java create mode 100644 src/java.base/share/classes/java/lang/foreign/SegmentScope.java create mode 100644 src/java.base/share/classes/java/lang/foreign/StructLayout.java create mode 100644 src/java.base/share/classes/java/lang/foreign/UnionLayout.java delete mode 100644 src/java.base/share/classes/jdk/internal/foreign/ArenaAllocator.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/FunctionDescriptorImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java delete mode 100644 src/java.base/share/classes/jdk/internal/foreign/MemoryAddressImpl.java rename src/java.base/share/classes/{java/lang/foreign/Addressable.java => jdk/internal/foreign/SlicingAllocator.java} (51%) create mode 100644 src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java rename src/java.base/share/classes/{java/lang/foreign => jdk/internal/foreign/layout}/AbstractLayout.java (67%) create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/PaddingLayoutImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/SequenceLayoutImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/StructLayoutImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/UnionLayoutImpl.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java create mode 100644 test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java create mode 100644 test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java create mode 100644 test/jdk/java/foreign/TestLargeSegmentCopy.java create mode 100644 test/jdk/java/foreign/TestLinker.java create mode 100644 test/jdk/java/foreign/TestOfBufferIssue.java create mode 100644 test/jdk/java/foreign/TestValueLayouts.java create mode 100644 test/jdk/java/foreign/UpcallTestHelper.java create mode 100644 test/jdk/java/foreign/dontrelease/TestDontRelease.java create mode 100644 test/jdk/java/foreign/dontrelease/libDontRelease.c create mode 100644 test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java create mode 100644 test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java create mode 100644 test/jdk/java/foreign/libNull.c create mode 100644 test/jdk/java/foreign/normalize/TestNormalize.java create mode 100644 test/jdk/java/foreign/normalize/libNormalize.c create mode 100644 test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java create mode 100644 test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java create mode 100644 test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java rename src/java.base/share/classes/jdk/internal/foreign/Scoped.java => test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java (67%) diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index a46a8be39d1..7a940a4b25a 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -210,23 +210,7 @@ void DowncallStubGenerator::generate() { __ blr(_abi._target_addr_reg); // this call is assumed not to have killed rthread - if (!_needs_return_buffer) { - // Unpack native results. - switch (_ret_bt) { - case T_BOOLEAN: __ c2bool(r0); break; - case T_CHAR : __ ubfx(r0, r0, 0, 16); break; - case T_BYTE : __ sbfx(r0, r0, 0, 8); break; - case T_SHORT : __ sbfx(r0, r0, 0, 16); break; - case T_INT : __ sbfx(r0, r0, 0, 32); break; - case T_DOUBLE : - case T_FLOAT : - // Result is in v0 we'll save as needed - break; - case T_VOID: break; - case T_LONG: break; - default : ShouldNotReachHere(); - } - } else { + if (_needs_return_buffer) { assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill"); __ ldr(tmp1, Address(sp, ret_buf_addr_sp_offset)); int offset = 0; diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index 06bf0099a91..b7da306ad75 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -211,24 +211,7 @@ void DowncallStubGenerator::generate() { __ call(_abi._target_addr_reg); // this call is assumed not to have killed r15_thread - if (!_needs_return_buffer) { - // FIXME: this assumes we return in rax/xmm0, which might not be the case - // Unpack native results. - switch (_ret_bt) { - case T_BOOLEAN: __ c2bool(rax); break; - case T_CHAR : __ movzwl(rax, rax); break; - case T_BYTE : __ sign_extend_byte (rax); break; - case T_SHORT : __ sign_extend_short(rax); break; - case T_INT : /* nothing to do */ break; - case T_DOUBLE : - case T_FLOAT : - // Result is in xmm0 we'll save as needed - break; - case T_VOID: break; - case T_LONG: break; - default : ShouldNotReachHere(); - } - } else { + if (_needs_return_buffer) { assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill"); __ movptr(rscratch1, Address(rsp, ret_buf_addr_rsp_offset)); int offset = 0; diff --git a/src/hotspot/share/ci/ciField.cpp b/src/hotspot/share/ci/ciField.cpp index 485db1b2748..24bf59dcb91 100644 --- a/src/hotspot/share/ci/ciField.cpp +++ b/src/hotspot/share/ci/ciField.cpp @@ -225,7 +225,7 @@ static bool trust_final_non_static_fields(ciInstanceKlass* holder) { // Even if general trusting is disabled, trust system-built closures in these packages. if (holder->is_in_package("java/lang/invoke") || holder->is_in_package("sun/invoke") || holder->is_in_package("java/lang/reflect") || holder->is_in_package("jdk/internal/reflect") || - holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("java/lang/foreign") || + holder->is_in_package("jdk/internal/foreign/layout") || holder->is_in_package("jdk/internal/foreign") || holder->is_in_package("jdk/internal/vm/vector") || holder->is_in_package("jdk/incubator/vector") || holder->is_in_package("java/lang")) return true; diff --git a/src/java.base/share/classes/java/lang/Module.java b/src/java.base/share/classes/java/lang/Module.java index 2f315b42cfc..9ca560cfcba 100644 --- a/src/java.base/share/classes/java/lang/Module.java +++ b/src/java.base/share/classes/java/lang/Module.java @@ -52,10 +52,12 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.javac.PreviewFeature; import jdk.internal.loader.BuiltinClassLoader; import jdk.internal.loader.BootLoader; import jdk.internal.loader.ClassLoaders; import jdk.internal.misc.CDS; +import jdk.internal.module.ModuleBootstrap; import jdk.internal.module.ModuleLoaderMap; import jdk.internal.module.ServicesCatalog; import jdk.internal.module.Resources; @@ -256,25 +258,77 @@ public ModuleLayer getLayer() { /** * Update this module to allow access to restricted methods. */ - Module implAddEnableNativeAccess() { + synchronized Module implAddEnableNativeAccess() { enableNativeAccess = true; return this; } /** - * Update all unnamed modules to allow access to restricted methods. + * Returns {@code true} if this module can access + * restricted methods. + * + * @since 20 + * + * @return {@code true} if this module can access restricted methods. */ - static void implAddEnableNativeAccessAllUnnamed() { - ALL_UNNAMED_MODULE.enableNativeAccess = true; + @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) + public boolean isNativeAccessEnabled() { + Module target = moduleForNativeAccess(); + synchronized(target) { + return target.enableNativeAccess; + } } + // Returns the Module object that holds the enableNativeAccess + // flag for this module. + private Module moduleForNativeAccess() { + return isNamed() ? this : ALL_UNNAMED_MODULE; + } + + // This is invoked from Reflection.ensureNativeAccess + void ensureNativeAccess(Class owner, String methodName) { + // The target module whose enableNativeAccess flag is ensured + Module target = moduleForNativeAccess(); + // racy read of the enable native access flag + boolean isNativeAccessEnabled = target.enableNativeAccess; + if (!isNativeAccessEnabled) { + synchronized (target) { + // safe read of the enableNativeAccess of the target module + isNativeAccessEnabled = target.enableNativeAccess; + + // check again with the safely read flag + if (isNativeAccessEnabled) { + // another thread beat us to it - nothing to do + return; + } else if (ModuleBootstrap.hasEnableNativeAccessFlag()) { + throw new IllegalCallerException("Illegal native access from: " + this); + } else { + // warn and set flag, so that only one warning is reported per module + String cls = owner.getName(); + String mtd = cls + "::" + methodName; + String mod = isNamed() ? "module " + getName() : "the unnamed module"; + String modflag = isNamed() ? getName() : "ALL-UNNAMED"; + System.err.printf(""" + WARNING: A restricted method in %s has been called + WARNING: %s has been called by %s + WARNING: Use --enable-native-access=%s to avoid a warning for this module + %n""", cls, mtd, mod, modflag); + + // set the flag + target.enableNativeAccess = true; + } + } + } + } + + /** - * Returns true if module m can access restricted methods. + * Update all unnamed modules to allow access to restricted methods. */ - boolean implIsEnableNativeAccess() { - return isNamed() ? - enableNativeAccess : - ALL_UNNAMED_MODULE.enableNativeAccess; + static void implAddEnableNativeAccessToAllUnnamed() { + synchronized (ALL_UNNAMED_MODULE) { + ALL_UNNAMED_MODULE.enableNativeAccess = true; + } } // -- diff --git a/src/java.base/share/classes/java/lang/ModuleLayer.java b/src/java.base/share/classes/java/lang/ModuleLayer.java index 91e4dd873be..444f8cdeb82 100644 --- a/src/java.base/share/classes/java/lang/ModuleLayer.java +++ b/src/java.base/share/classes/java/lang/ModuleLayer.java @@ -44,15 +44,17 @@ import java.util.stream.Collectors; import java.util.stream.Stream; +import jdk.internal.javac.PreviewFeature; import jdk.internal.loader.ClassLoaderValue; import jdk.internal.loader.Loader; import jdk.internal.loader.LoaderPool; 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.Stable; import sun.security.util.SecurityConstants; - /** * A layer of modules in the Java virtual machine. * @@ -297,6 +299,39 @@ public Controller addOpens(Module source, String pn, Module target) { source.implAddOpens(pn, target); return this; } + + /** + * Enables native access for a module in the layer if the caller's module + * has native access. + * + *

This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain + * from depending on restricted methods, and use safe and supported functionalities, + * where possible. + * + * @param target + * The module to update + * + * @return This controller + * + * @throws IllegalArgumentException + * If {@code target} is not in the module layer + * + * @throws IllegalCallerException + * If the caller is in a module that does not have native access enabled + * + * @since 20 + */ + @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) + @CallerSensitive + public Controller enableNativeAccess(Module target) { + ensureInLayer(target); + Reflection.ensureNativeAccess(Reflection.getCallerClass(), Module.class, + "enableNativeAccess"); + target.implAddEnableNativeAccess(); + return this; + } } diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 0cb4624ad8a..f429a041e3d 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -2437,11 +2437,11 @@ public boolean isReflectivelyOpened(Module m, String pn, Module other) { public Module addEnableNativeAccess(Module m) { return m.implAddEnableNativeAccess(); } - public void addEnableNativeAccessAllUnnamed() { - Module.implAddEnableNativeAccessAllUnnamed(); + public void addEnableNativeAccessToAllUnnamed() { + Module.implAddEnableNativeAccessToAllUnnamed(); } - public boolean isEnableNativeAccess(Module m) { - return m.implIsEnableNativeAccess(); + public void ensureNativeAccess(Module m, Class owner, String methodName) { + m.ensureNativeAccess(owner, methodName); } public ServicesCatalog getServicesCatalog(ModuleLayer layer) { return layer.getServicesCatalog(); diff --git a/src/java.base/share/classes/java/lang/foreign/Arena.java b/src/java.base/share/classes/java/lang/foreign/Arena.java new file mode 100644 index 00000000000..2fff341e658 --- /dev/null +++ b/src/java.base/share/classes/java/lang/foreign/Arena.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022, 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. + */ + +package java.lang.foreign; + +import jdk.internal.foreign.MemorySessionImpl; +import jdk.internal.javac.PreviewFeature; + +/** + * An arena controls the lifecycle of memory segments, providing both flexible allocation and timely deallocation. + *

+ * An arena has a {@linkplain #scope() scope}, called the arena scope. When the arena is {@linkplain #close() closed}, + * the arena scope is no longer {@linkplain SegmentScope#isAlive() alive}. As a result, all the + * segments associated with the arena scope are invalidated, safely and atomically, their backing memory regions are + * deallocated (where applicable) and can no longer be accessed after the arena is closed: + * + * {@snippet lang = java: + * try (Arena arena = Arena.openConfined()) { + * MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); + * ... + * } // memory released here + *} + * + * Furthermore, an arena is a {@link SegmentAllocator}. All the segments {@linkplain #allocate(long, long) allocated} by the + * arena are associated with the arena scope. This makes arenas extremely useful when interacting with foreign code, as shown below: + * + * {@snippet lang = java: + * try (Arena arena = Arena.openConfined()) { + * MemorySegment nativeArray = arena.allocateArray(ValueLayout.JAVA_INT, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9); + * MemorySegment nativeString = arena.allocateUtf8String("Hello!"); + * MemorySegment upcallStub = linker.upcallStub(handle, desc, arena.scope()); + * ... + * } // memory released here + *} + * + *

Safety and thread-confinement

+ * + * Arenas provide strong temporal safety guarantees: a memory segment allocated by an arena cannot be accessed + * after the arena has been closed. The cost of providing this guarantee varies based on the + * number of threads that have access to the memory segments allocated by the arena. For instance, if an arena + * is always created and closed by one thread, and the memory segments associated with the arena's scope are always + * accessed by that same thread, then ensuring correctness is trivial. + *

+ * Conversely, if an arena allocates segments that can be accessed by multiple threads, or if the arena can be closed + * by a thread other than the accessing thread, then ensuring correctness is much more complex. For example, a segment + * allocated with the arena might be accessed while another thread attempts, concurrently, to close the arena. + * To provide the strong temporal safety guarantee without forcing every client, even simple ones, to incur a performance + * impact, arenas are divided into thread-confined arenas, and shared arenas. + *

+ * Confined arenas, support strong thread-confinement guarantees. Upon creation, they are assigned an + * {@linkplain #isCloseableBy(Thread) owner thread}, typically the thread which initiated the creation operation. + * The segments created by a confined arena can only be {@linkplain SegmentScope#isAccessibleBy(Thread) accessed} + * by the owner thread. Moreover, any attempt to close the confined arena from a thread other than the owner thread will + * fail with {@link WrongThreadException}. + *

+ * Shared arenas, on the other hand, have no owner thread. The segments created by a shared arena + * can be {@linkplain SegmentScope#isAccessibleBy(Thread) accessed} by any thread. This might be useful when + * multiple threads need to access the same memory segment concurrently (e.g. in the case of parallel processing). + * Moreover, a shared arena {@linkplain #isCloseableBy(Thread) can be closed} by any thread. + * + * @since 20 + */ +@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) +public interface Arena extends SegmentAllocator, AutoCloseable { + + /** + * Returns a native memory segment with the given size (in bytes) and alignment constraint (in bytes). + * The returned segment is associated with the arena scope. + * The segment's {@link MemorySegment#address() address} is the starting address of the + * allocated off-heap memory region backing the segment, and the address is + * aligned according the provided alignment constraint. + * + * @implSpec + * The default implementation of this method is equivalent to the following code: + * {@snippet lang = java: + * MemorySegment.allocateNative(bytesSize, byteAlignment, scope()); + *} + * More generally implementations of this method must return a native segment featuring the requested size, + * and that is compatible with the provided alignment constraint. Furthermore, for any two segments + * {@code S1, S2} returned by this method, the following invariant must hold: + * + * {@snippet lang = java: + * S1.overlappingSlice(S2).isEmpty() == true + *} + * + * @param byteSize the size (in bytes) of the off-heap memory block backing the native memory segment. + * @param byteAlignment the alignment constraint (in bytes) of the off-heap region of memory backing the native memory segment. + * @return a new native memory segment. + * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes <= 0}, or if {@code alignmentBytes} + * is not a power of 2. + * @throws IllegalStateException if the arena has already been {@linkplain #close() closed}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @see MemorySegment#allocateNative(long, long, SegmentScope) + */ + @Override + default MemorySegment allocate(long byteSize, long byteAlignment) { + return MemorySegment.allocateNative(byteSize, byteAlignment, scope()); + } + + /** + * {@return the arena scope} + */ + SegmentScope scope(); + + /** + * Closes this arena. If this method completes normally, the arena scope is no longer {@linkplain SegmentScope#isAlive() alive}, + * and all the memory segments associated with it can no longer be accessed. Furthermore, any off-heap region of memory backing the + * segments associated with that scope are also released. + * + * @apiNote This operation is not idempotent; that is, closing an already closed arena always results in an + * exception being thrown. This reflects a deliberate design choice: failure to close an arena might reveal a bug + * in the underlying application logic. + * + * @see SegmentScope#isAlive() + * + * @throws IllegalStateException if the arena has already been closed. + * @throws IllegalStateException if the arena scope is {@linkplain SegmentScope#whileAlive(Runnable) kept alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code isCloseableBy(T) == false}. + */ + @Override + void close(); + + /** + * {@return {@code true} if the provided thread can close this arena} + * @param thread the thread to be tested. + */ + boolean isCloseableBy(Thread thread); + + /** + * {@return a new confined arena, owned by the current thread} + */ + static Arena openConfined() { + return MemorySessionImpl.createConfined(Thread.currentThread()).asArena(); + } + + /** + * {@return a new shared arena} + */ + static Arena openShared() { + return MemorySessionImpl.createShared().asArena(); + } +} diff --git a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java index 3d0a22239c6..3b6627d7f92 100644 --- a/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java +++ b/src/java.base/share/classes/java/lang/foreign/FunctionDescriptor.java @@ -25,101 +25,38 @@ package java.lang.foreign; import java.lang.invoke.MethodHandle; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; +import java.lang.invoke.MethodType; import java.util.Objects; import java.util.Optional; -import java.util.stream.Collectors; -import java.util.stream.IntStream; -import java.util.stream.Stream; +import java.util.List; + +import jdk.internal.foreign.FunctionDescriptorImpl; import jdk.internal.javac.PreviewFeature; /** - * A function descriptor is made up of zero or more argument layouts and zero or one return layout. A function descriptor - * is used to model the signature of foreign functions when creating - * {@linkplain Linker#downcallHandle(Addressable, FunctionDescriptor) downcall method handles} or - * {@linkplain Linker#upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stubs}. + * A function descriptor models the signature of foreign functions. A function descriptor is made up of zero or more + * argument layouts and zero or one return layout. A function descriptor is typically used when creating + * {@linkplain Linker#downcallHandle(MemorySegment, FunctionDescriptor, Linker.Option...) downcall method handles} or + * {@linkplain Linker#upcallStub(MethodHandle, FunctionDescriptor, SegmentScope) upcall stubs}. * * @implSpec - * This class is immutable, thread-safe and value-based. + * Implementing classes are immutable, thread-safe and value-based. * * @see MemoryLayout * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed class FunctionDescriptor permits FunctionDescriptor.VariadicFunction { - - private final MemoryLayout resLayout; - private final List argLayouts; - - private FunctionDescriptor(MemoryLayout resLayout, List argLayouts) { - this.resLayout = resLayout; - this.argLayouts = argLayouts; - } +public sealed interface FunctionDescriptor permits FunctionDescriptorImpl { /** * {@return the return layout (if any) associated with this function descriptor} */ - public Optional returnLayout() { - return Optional.ofNullable(resLayout); - } + Optional returnLayout(); /** * {@return the argument layouts associated with this function descriptor (as an immutable list)}. */ - public List argumentLayouts() { - return Collections.unmodifiableList(argLayouts); - } - - /** - * Creates a function descriptor with the given return and argument layouts. - * @param resLayout the return layout. - * @param argLayouts the argument layouts. - * @return the new function descriptor. - */ - public static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argLayouts) { - Objects.requireNonNull(resLayout); - Objects.requireNonNull(argLayouts); - Arrays.stream(argLayouts).forEach(Objects::requireNonNull); - return new FunctionDescriptor(resLayout, List.of(argLayouts)); - } - - /** - * Creates a function descriptor with the given argument layouts and no return layout. - * @param argLayouts the argument layouts. - * @return the new function descriptor. - */ - public static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) { - Objects.requireNonNull(argLayouts); - Arrays.stream(argLayouts).forEach(Objects::requireNonNull); - return new FunctionDescriptor(null, List.of(argLayouts)); - } - - /** - * Creates a specialized variadic function descriptor, by appending given variadic layouts to this - * function descriptor argument layouts. The resulting function descriptor can report the position - * of the {@linkplain #firstVariadicArgumentIndex() first variadic argument}, and cannot be altered - * in any way: for instance, calling {@link #changeReturnLayout(MemoryLayout)} on the resulting descriptor - * will throw an {@link UnsupportedOperationException}. - * @param variadicLayouts the variadic argument layouts to be appended to this descriptor argument layouts. - * @return a variadic function descriptor, or this descriptor if {@code variadicLayouts.length == 0}. - */ - public FunctionDescriptor asVariadic(MemoryLayout... variadicLayouts) { - Objects.requireNonNull(variadicLayouts); - Arrays.stream(variadicLayouts).forEach(Objects::requireNonNull); - return variadicLayouts.length == 0 ? this : new VariadicFunction(this, variadicLayouts); - } - - /** - * The index of the first variadic argument layout (where defined). - * @return The index of the first variadic argument layout, or {@code -1} if this is not a - * {@linkplain #asVariadic(MemoryLayout...) variadic} layout. - */ - public int firstVariadicArgumentIndex() { - return -1; - } + List argumentLayouts(); /** * Returns a function descriptor with the given argument layouts appended to the argument layout array @@ -127,9 +64,7 @@ public int firstVariadicArgumentIndex() { * @param addedLayouts the argument layouts to append. * @return the new function descriptor. */ - public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) { - return insertArgumentLayouts(argLayouts.size(), addedLayouts); - } + FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts); /** * Returns a function descriptor with the given argument layouts inserted at the given index, into the argument @@ -139,110 +74,57 @@ public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) { * @return the new function descriptor. * @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}. */ - public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) { - if (index < 0 || index > argLayouts.size()) - throw new IllegalArgumentException("Index out of bounds: " + index); - List added = List.of(addedLayouts); // null check on array and its elements - List newLayouts = new ArrayList<>(argLayouts.size() + addedLayouts.length); - newLayouts.addAll(argLayouts.subList(0, index)); - newLayouts.addAll(added); - newLayouts.addAll(argLayouts.subList(index, argLayouts.size())); - return new FunctionDescriptor(resLayout, newLayouts); - } + FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts); /** * Returns a function descriptor with the given memory layout as the new return layout. * @param newReturn the new return layout. * @return the new function descriptor. */ - public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) { - Objects.requireNonNull(newReturn); - return new FunctionDescriptor(newReturn, argLayouts); - } + FunctionDescriptor changeReturnLayout(MemoryLayout newReturn); /** * Returns a function descriptor with the return layout dropped. This is useful to model functions * which return no values. * @return the new function descriptor. */ - public FunctionDescriptor dropReturnLayout() { - return new FunctionDescriptor(null, argLayouts); - } + FunctionDescriptor dropReturnLayout(); /** - * {@return the string representation of this function descriptor} - */ - @Override - public String toString() { - return String.format("(%s)%s", - IntStream.range(0, argLayouts.size()) - .mapToObj(i -> (i == firstVariadicArgumentIndex() ? - "..." : "") + argLayouts.get(i)) - .collect(Collectors.joining()), - returnLayout().map(Object::toString).orElse("v")); - } - - /** - * Compares the specified object with this function descriptor for equality. Returns {@code true} if and only if the specified - * object is also a function descriptor, and all the following conditions are met: + * Returns the method type consisting of the carrier types of the layouts in this function descriptor. + *

+ * The carrier type of a layout is determined as follows: *

    - *
  • the two function descriptors have equals return layouts (see {@link MemoryLayout#equals(Object)}), or both have no return layout;
  • - *
  • the two function descriptors have argument layouts that are pair-wise {@linkplain MemoryLayout#equals(Object) equal}; and
  • - *
  • the two function descriptors have the same leading {@linkplain #firstVariadicArgumentIndex() variadic argument index}
  • + *
  • If the layout is a {@link ValueLayout} the carrier type is determined through {@link ValueLayout#carrier()}.
  • + *
  • If the layout is a {@link GroupLayout} the carrier type is {@link MemorySegment}.
  • + *
  • If the layout is a {@link PaddingLayout}, or {@link SequenceLayout} an {@link IllegalArgumentException} is thrown.
  • *
* - * @param other the object to be compared for equality with this function descriptor. - * @return {@code true} if the specified object is equal to this function descriptor. + * @return the method type consisting of the carrier types of the layouts in this function descriptor + * @throws IllegalArgumentException if one or more layouts in the function descriptor can not be mapped to carrier + * types (e.g. if they are sequence layouts or padding layouts). */ - @Override - public boolean equals(Object other) { - return other instanceof FunctionDescriptor f && - Objects.equals(resLayout, f.resLayout) && - Objects.equals(argLayouts, f.argLayouts) && - firstVariadicArgumentIndex() == f.firstVariadicArgumentIndex(); - } + MethodType toMethodType(); /** - * {@return the hash code value for this function descriptor} + * Creates a function descriptor with the given return and argument layouts. + * @param resLayout the return layout. + * @param argLayouts the argument layouts. + * @return the new function descriptor. */ - @Override - public int hashCode() { - return Objects.hash(argLayouts, resLayout, firstVariadicArgumentIndex()); + static FunctionDescriptor of(MemoryLayout resLayout, MemoryLayout... argLayouts) { + Objects.requireNonNull(resLayout); + // Null checks are implicit in List.of(argLayouts) + return FunctionDescriptorImpl.of(resLayout, List.of(argLayouts)); } - static final class VariadicFunction extends FunctionDescriptor { - - private final int firstVariadicIndex; - - public VariadicFunction(FunctionDescriptor descriptor, MemoryLayout... argLayouts) { - super(descriptor.returnLayout().orElse(null), - Stream.concat(descriptor.argumentLayouts().stream(), Stream.of(argLayouts)).toList()); - this.firstVariadicIndex = descriptor.argumentLayouts().size(); - } - - @Override - public int firstVariadicArgumentIndex() { - return firstVariadicIndex; - } - - @Override - public FunctionDescriptor appendArgumentLayouts(MemoryLayout... addedLayouts) { - throw new UnsupportedOperationException(); - } - - @Override - public FunctionDescriptor insertArgumentLayouts(int index, MemoryLayout... addedLayouts) { - throw new UnsupportedOperationException(); - } - - @Override - public FunctionDescriptor changeReturnLayout(MemoryLayout newReturn) { - throw new UnsupportedOperationException(); - } - - @Override - public FunctionDescriptor dropReturnLayout() { - throw new UnsupportedOperationException(); - } + /** + * Creates a function descriptor with the given argument layouts and no return layout. + * @param argLayouts the argument layouts. + * @return the new function descriptor. + */ + static FunctionDescriptor ofVoid(MemoryLayout... argLayouts) { + // Null checks are implicit in List.of(argLayouts) + return FunctionDescriptorImpl.ofVoid(List.of(argLayouts)); } } diff --git a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java index d012735ba9f..56ace4ee135 100644 --- a/src/java.base/share/classes/java/lang/foreign/GroupLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/GroupLayout.java @@ -25,19 +25,14 @@ */ package java.lang.foreign; -import java.util.Collections; import java.util.List; -import java.util.Objects; -import java.util.Optional; -import java.util.function.LongBinaryOperator; -import java.util.stream.Collectors; import jdk.internal.javac.PreviewFeature; /** * A compound layout that aggregates multiple member layouts. There are two ways in which member layouts - * can be combined: if member layouts are laid out one after the other, the resulting group layout is said to be a struct + * can be combined: if member layouts are laid out one after the other, the resulting group layout is said to be a struct layout * (see {@link MemoryLayout#structLayout(MemoryLayout...)}); conversely, if all member layouts are laid out at the same starting offset, - * the resulting group layout is said to be a union (see {@link MemoryLayout#unionLayout(MemoryLayout...)}). + * the resulting group layout is said to be a union layout (see {@link MemoryLayout#unionLayout(MemoryLayout...)}). * * @implSpec * This class is immutable, thread-safe and value-based. @@ -45,55 +40,7 @@ * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public final class GroupLayout extends AbstractLayout implements MemoryLayout { - - /** - * The group kind. - */ - enum Kind { - /** - * A 'struct' kind. - */ - STRUCT("", Math::addExact), - /** - * A 'union' kind. - */ - UNION("|", Math::max); - - final String delimTag; - final LongBinaryOperator sizeOp; - - Kind(String delimTag, LongBinaryOperator sizeOp) { - this.delimTag = delimTag; - this.sizeOp = sizeOp; - } - - long sizeof(List elems) { - long size = 0; - for (MemoryLayout elem : elems) { - size = sizeOp.applyAsLong(size, elem.bitSize()); - } - return size; - } - - long alignof(List elems) { - return elems.stream().mapToLong(MemoryLayout::bitAlignment).max() // max alignment in case we have member layouts - .orElse(1); // or minimal alignment if no member layout is given - } - } - - private final Kind kind; - private final List elements; - - GroupLayout(Kind kind, List elements) { - this(kind, elements, kind.alignof(elements), Optional.empty()); - } - - GroupLayout(Kind kind, List elements, long alignment, Optional name) { - super(kind.sizeof(elements), alignment, name); - this.kind = kind; - this.elements = elements; - } +public sealed interface GroupLayout extends MemoryLayout permits StructLayout, UnionLayout { /** * Returns the member layouts associated with this group. @@ -104,84 +51,17 @@ long alignof(List elems) { * * @return the member layouts associated with this group. */ - public List memberLayouts() { - return Collections.unmodifiableList(elements); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - return decorateLayoutString(elements.stream() - .map(Object::toString) - .collect(Collectors.joining(kind.delimTag, "[", "]"))); - } - - /** - * {@return {@code true}, if this group layout is a struct layout} - */ - public boolean isStruct() { - return kind == Kind.STRUCT; - } - - /** - * {@return {@code true}, if this group layout is a union layout} - */ - public boolean isUnion() { - return kind == Kind.UNION; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!super.equals(other)) { - return false; - } - return other instanceof GroupLayout otherGroup && - kind == otherGroup.kind && - elements.equals(otherGroup.elements); - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), kind, elements); - } - - @Override - GroupLayout dup(long alignment, Optional name) { - return new GroupLayout(kind, elements, alignment, name); - } - - @Override - boolean hasNaturalAlignment() { - return alignment == kind.alignof(elements); - } - - //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout - //but that causes issues with javadoc, see JDK-8224052 + List memberLayouts(); /** * {@inheritDoc} */ @Override - public GroupLayout withName(String name) { - return (GroupLayout)super.withName(name); - } + GroupLayout withName(String name); /** * {@inheritDoc} */ @Override - public GroupLayout withBitAlignment(long alignmentBits) { - return (GroupLayout)super.withBitAlignment(alignmentBits); - } + GroupLayout withBitAlignment(long bitAlignment); } diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 53196ab2bd0..c8fa1b2320f 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -26,13 +26,13 @@ package java.lang.foreign; import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.javac.PreviewFeature; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; /** * A linker provides access to foreign functions from Java code, and access to Java code from foreign functions. @@ -47,9 +47,9 @@ * in the JVM and foreign functions in the library. In particular: *
    *
  • A linker allows Java code to link against foreign functions, via - * {@linkplain #downcallHandle(Addressable, FunctionDescriptor) downcall method handles}; and
  • + * {@linkplain #downcallHandle(MemorySegment, FunctionDescriptor, Option...) downcall method handles}; and *
  • A linker allows foreign functions to call Java method handles, - * via the generation of {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stubs}.
  • + * via the generation of {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, SegmentScope) upcall stubs}. *
* In addition, a linker provides a way to look up foreign functions in libraries that conform to the ABI. Each linker * chooses a set of libraries that are commonly used on the OS and processor combination associated with the ABI. @@ -62,29 +62,16 @@ * *

Downcall method handles

* - * {@linkplain #downcallHandle(FunctionDescriptor) Linking a foreign function} is a process which requires a function descriptor, + * {@linkplain #downcallHandle(FunctionDescriptor, Option...) Linking a foreign function} is a process which requires a function descriptor, * a set of memory layouts which, together, specify the signature of the foreign function to be linked, and returns, * when complete, a downcall method handle, that is, a method handle that can be used to invoke the target foreign function. *

* The Java {@linkplain java.lang.invoke.MethodType method type} associated with the returned method handle is - * {@linkplain #downcallType(FunctionDescriptor) derived} from the argument and return layouts in the function descriptor. - * More specifically, given each layout {@code L} in the function descriptor, a corresponding carrier {@code C} is inferred, - * as described below: + * {@linkplain FunctionDescriptor#toMethodType() derived} from the argument and return layouts in the function descriptor. + * The downcall method handle type, might then be decorated by additional leading parameters, in the given order if both are present: *

    - *
  • if {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases: - *
      - *
    • if {@code L} occurs in a parameter position and {@code E} is {@code MemoryAddress.class}, - * then {@code C = Addressable.class};
    • - *
    • otherwise, {@code C = E}; - *
  • - *
  • or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}
  • - *
- *

- * The downcall method handle type, derived as above, might be decorated by additional leading parameters, - * in the given order if both are present: - *

    - *
  • If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor) without specifying a target address}, - * the downcall method handle type features a leading parameter of type {@link Addressable}, from which the + *
  • If the downcall method handle is created {@linkplain #downcallHandle(FunctionDescriptor, Option...) without specifying a target address}, + * the downcall method handle type features a leading parameter of type {@link MemorySegment}, from which the * address of the target foreign function can be derived.
  • *
  • If the function descriptor's return layout is a group layout, the resulting downcall method handle accepts * an additional leading parameter of type {@link SegmentAllocator}, which is used by the linker runtime to allocate the @@ -93,26 +80,15 @@ * *

    Upcall stubs

    * - * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, MemorySession) Creating an upcall stub} requires a method + * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, SegmentScope) Creating an upcall stub} requires a method * handle and a function descriptor; in this case, the set of memory layouts in the function descriptor * specify the signature of the function pointer associated with the upcall stub. *

    - * The type of the provided method handle has to {@linkplain #upcallType(FunctionDescriptor) match} the Java - * {@linkplain java.lang.invoke.MethodType method type} associated with the upcall stub, which is derived from the argument - * and return layouts in the function descriptor. More specifically, given each layout {@code L} in the function descriptor, - * a corresponding carrier {@code C} is inferred, as described below: - *

      - *
    • If {@code L} is a {@link ValueLayout} with carrier {@code E} then there are two cases: - *
        - *
      • If {@code L} occurs in a return position and {@code E} is {@code MemoryAddress.class}, - * then {@code C = Addressable.class};
      • - *
      • Otherwise, {@code C = E}; - *
    • - *
    • Or, if {@code L} is a {@link GroupLayout}, then {@code C} is set to {@code MemorySegment.class}
    • - *
    + * The type of the provided method handle's type has to match the method type associated with the upcall stub, + * which is {@linkplain FunctionDescriptor#toMethodType() derived} from the provided function descriptor. + *

    * Upcall stubs are modelled by instances of type {@link MemorySegment}; upcall stubs can be passed by reference to other - * downcall method handles (as {@link MemorySegment} implements the {@link Addressable} interface) and, - * when no longer required, they can be {@linkplain MemorySession#close() released}, via their associated {@linkplain MemorySession session}. + * downcall method handles and, they are released via their associated {@linkplain SegmentScope scope}. * *

    Safety considerations

    * @@ -121,23 +97,34 @@ * the linker runtime cannot validate linkage requests. When a client interacts with a downcall method handle obtained * through an invalid linkage request (e.g. by specifying a function descriptor featuring too many argument layouts), * the result of such interaction is unspecified and can lead to JVM crashes. On downcall handle invocation, - * the linker runtime guarantees the following for any argument that is a memory resource {@code R} (of type {@link MemorySegment} - * or {@link VaList}): + * the linker runtime guarantees the following for any argument {@code A} of type {@link MemorySegment} whose corresponding + * layout is {@link ValueLayout#ADDRESS}: *
      - *
    • The memory session of {@code R} is {@linkplain MemorySession#isAlive() alive}. Otherwise, the invocation throws + *
    • The scope of {@code A} is {@linkplain SegmentScope#isAlive() alive}. Otherwise, the invocation throws * {@link IllegalStateException};
    • - *
    • The invocation occurs in same thread as the one {@linkplain MemorySession#ownerThread() owning} the memory session of {@code R}, - * if said session is confined. Otherwise, the invocation throws {@link WrongThreadException}; and
    • - *
    • The memory session of {@code R} is {@linkplain MemorySession#whileAlive(Runnable) kept alive} (and cannot be closed) during the invocation.
    • + *
    • The invocation occurs in a thread {@code T} such that {@code A.scope().isAccessibleBy(T) == true}. + * Otherwise, the invocation throws {@link WrongThreadException}; and
    • + *
    • The scope of {@code A} is {@linkplain SegmentScope#whileAlive(Runnable) kept alive} during the invocation.
    • *
    + * A downcall method handle created from a function descriptor whose return layout is an + * {@linkplain ValueLayout.OfAddress address layout} returns a native segment associated with + * the {@linkplain SegmentScope#global() global scope}. Under normal conditions, the size of the returned segment is {@code 0}. + * However, if the return layout is an {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout, + * then the size of the returned segment is {@code Long.MAX_VALUE}. *

    * When creating upcall stubs the linker runtime validates the type of the target method handle against the provided * function descriptor and report an error if any mismatch is detected. As for downcalls, JVM crashes might occur, * if the foreign code casts the function pointer associated with an upcall stub to a type * that is incompatible with the provided function descriptor. Moreover, if the target method - * handle associated with an upcall stub returns a {@linkplain MemoryAddress memory address}, clients must ensure + * handle associated with an upcall stub returns a {@linkplain MemorySegment memory segment}, clients must ensure * that this address cannot become invalid after the upcall completes. This can lead to unspecified behavior, * and even JVM crashes, since an upcall is typically executed in the context of a downcall method handle invocation. + *

    + * An upcall stub argument whose corresponding layout is an {@linkplain ValueLayout.OfAddress address layout} + * is a native segment associated with the {@linkplain SegmentScope#global() global scope}. + * Under normal conditions, the size of this segment argument is {@code 0}. However, if the layout associated with + * the upcall stub argument is an {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout, + * then the size of the segment argument is {@code Long.MAX_VALUE}. * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. @@ -159,22 +146,22 @@ public sealed interface Linker permits AbstractLinker { * and its corresponding layout is dependent on the ABI of the returned linker; *

  • Composite types are modelled by a {@linkplain GroupLayout group layout}. Depending on the ABI of the * returned linker, additional {@linkplain MemoryLayout#paddingLayout(long) padding} member layouts might be required to conform - * to the size and alignment constraints of a composite type definition in C (e.g. using {@code struct} or {@code union}); and
  • - *
  • Pointer types are modelled by a {@linkplain ValueLayout value layout} instance with carrier {@link MemoryAddress}. + * to the size and alignment constraint of a composite type definition in C (e.g. using {@code struct} or {@code union}); and
  • + *
  • Pointer types are modelled by a {@linkplain ValueLayout value layout} instance with carrier {@link MemorySegment}. * Examples of pointer types in C are {@code int**} and {@code int(*)(size_t*, size_t*)};
  • *
*

* Any layout not listed above is unsupported; function descriptors containing unsupported layouts * will cause an {@link IllegalArgumentException} to be thrown, when used to create a - * {@link #downcallHandle(Addressable, FunctionDescriptor) downcall method handle} or an - * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stub}. + * {@link #downcallHandle(MemorySegment, FunctionDescriptor, Option...) downcall method handle} or an + * {@linkplain #upcallStub(MethodHandle, FunctionDescriptor, SegmentScope) upcall stub}. *

* Variadic functions (e.g. a C function declared with a trailing ellipses {@code ...} at the end of the formal parameter * list or with an empty formal parameter list) are not supported directly. However, it is possible to link a - * variadic function by using a {@linkplain FunctionDescriptor#asVariadic(MemoryLayout...) variadic} - * function descriptor, in which the specialized signature of a given variable arity callsite is described in full. - * Alternatively, where the foreign library allows it, clients might be able to interact with variadic functions by - * passing a trailing parameter of type {@link VaList} (e.g. as in {@code vsprintf}). + * variadic function by using {@linkplain Linker.Option#firstVariadicArg(int) a linker option} to indicate + * the start of the list of variadic arguments, together with a specialized function descriptor describing a + * given variable arity callsite. Alternatively, where the foreign library allows it, clients might be able to + * interact with variadic functions by passing a trailing parameter of type {@link VaList} (e.g. as in {@code vsprintf}). *

* This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash @@ -199,55 +186,60 @@ static Linker nativeLinker() { } /** - * Creates a method handle which can be used to call a target foreign function with the given signature and address. + * Creates a method handle which can be used to call a foreign function with the given signature and address. *

* If the provided method type's return type is {@code MemorySegment}, then the resulting method handle features - * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker runtime - * to allocate structs returned by-value. + * an additional prefix parameter, of type {@link SegmentAllocator}, which will be used by the linker to allocate + * structs returned by-value. *

* Calling this method is equivalent to the following code: * {@snippet lang=java : * linker.downcallHandle(function).bindTo(symbol); * } * - * @param symbol the address of the target function. + * @param symbol the address of the target function. * @param function the function descriptor of the target function. + * @param options any linker options. * @return a downcall method handle. The method handle type is inferred * @throws IllegalArgumentException if the provided function descriptor is not supported by this linker. - * or if the symbol is {@link MemoryAddress#NULL} + * or if the symbol is {@link MemorySegment#NULL} + * @throws IllegalArgumentException if an invalid combination of linker options is given. */ - default MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor function) { + default MethodHandle downcallHandle(MemorySegment symbol, FunctionDescriptor function, Option... options) { SharedUtils.checkSymbol(symbol); - return downcallHandle(function).bindTo(symbol); + return downcallHandle(function, options).bindTo(symbol); } /** - * Creates a method handle which can be used to call a target foreign function with the given signature. + * Creates a method handle which can be used to call a foreign function with the given signature. * The resulting method handle features a prefix parameter (as the first parameter) corresponding to the foreign function - * entry point, of type {@link Addressable}, which is used to specify the address of the target function + * entry point, of type {@link MemorySegment}, which is used to specify the address of the target function * to be called. *

* If the provided function descriptor's return layout is a {@link GroupLayout}, then the resulting method handle features an * additional prefix parameter (inserted immediately after the address parameter), of type {@link SegmentAllocator}), - * which will be used by the linker runtime to allocate structs returned by-value. + * which will be used by the linker to allocate structs returned by-value. *

- * The returned method handle will throw an {@link IllegalArgumentException} if the {@link Addressable} parameter passed to it is - * associated with the {@link MemoryAddress#NULL} address, or a {@link NullPointerException} if that parameter is {@code null}. + * The returned method handle will throw an {@link IllegalArgumentException} if the {@link MemorySegment} parameter passed to it is + * associated with the {@link MemorySegment#NULL} address, or a {@link NullPointerException} if that parameter is {@code null}. * * @param function the function descriptor of the target function. + * @param options any linker options. * @return a downcall method handle. The method handle type is inferred * from the provided function descriptor. * @throws IllegalArgumentException if the provided function descriptor is not supported by this linker. + * @throws IllegalArgumentException if an invalid combination of linker options is given. */ - MethodHandle downcallHandle(FunctionDescriptor function); + MethodHandle downcallHandle(FunctionDescriptor function, Option... options); /** - * Creates a stub which can be passed to other foreign functions as a function pointer, with the given - * memory session. Calling such a function pointer from foreign code will result in the execution of the provided + * Creates a stub which can be passed to other foreign functions as a function pointer, associated with the given + * scope. Calling such a function pointer from foreign code will result in the execution of the provided * method handle. *

- * The returned memory segment's base address points to the newly allocated upcall stub, and is associated with - * the provided memory session. When such session is closed, the corresponding upcall stub will be deallocated. + * The returned memory segment's address points to the newly allocated upcall stub, and is associated with + * the provided scope. As such, the corresponding upcall stub will be deallocated + * when the scope becomes not {@linkplain SegmentScope#isAlive() alive}. *

* The target method handle should not throw any exceptions. If the target method handle does throw an exception, * the VM will exit with a non-zero exit code. To avoid the VM aborting due to an uncaught exception, clients @@ -257,16 +249,16 @@ default MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor funct * * @param target the target method handle. * @param function the upcall stub function descriptor. - * @param session the upcall stub memory session. - * @return a zero-length segment whose base address is the address of the upcall stub. + * @param scope the scope associated with the returned upcall stub segment. + * @return a zero-length segment whose address is the address of the upcall stub. * @throws IllegalArgumentException if the provided function descriptor is not supported by this linker. * @throws IllegalArgumentException if it is determined that the target method handle can throw an exception, or if the target method handle * has a type that does not match the upcall stub inferred type. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. */ - MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, MemorySession session); + MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, SegmentScope scope); /** * Returns a symbol lookup for symbols in a set of commonly used libraries. @@ -284,22 +276,21 @@ default MethodHandle downcallHandle(Addressable symbol, FunctionDescriptor funct SymbolLookup defaultLookup(); /** - * {@return the downcall method handle {@linkplain MethodType type} associated with the given function descriptor} - * @param functionDescriptor a function descriptor. - * @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported - * (e.g. if they are sequence layouts or padding layouts). + * A linker option is used to indicate additional linking requirements to the linker, + * besides what is described by a function descriptor. + * @since 20 */ - static MethodType downcallType(FunctionDescriptor functionDescriptor) { - return SharedUtils.inferMethodType(functionDescriptor, false); - } + @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) + sealed interface Option + permits LinkerOptions.FirstVariadicArg { - /** - * {@return the method handle {@linkplain MethodType type} associated with an upcall stub with the given function descriptor} - * @param functionDescriptor a function descriptor. - * @throws IllegalArgumentException if one or more layouts in the function descriptor are not supported - * (e.g. if they are sequence layouts or padding layouts). - */ - static MethodType upcallType(FunctionDescriptor functionDescriptor) { - return SharedUtils.inferMethodType(functionDescriptor, true); + /** + * {@return a linker option used to denote the index of the first variadic argument layout in a + * foreign function call} + * @param index the index of the first variadic argument in a downcall handle linkage request. + */ + static Option firstVariadicArg(int index) { + return new LinkerOptions.FirstVariadicArg(index); + } } } diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryAddress.java b/src/java.base/share/classes/java/lang/foreign/MemoryAddress.java deleted file mode 100644 index cc4cd949d64..00000000000 --- a/src/java.base/share/classes/java/lang/foreign/MemoryAddress.java +++ /dev/null @@ -1,854 +0,0 @@ -/* - * Copyright (c) 2019, 2022, 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. - * - */ - -package java.lang.foreign; - -import java.nio.ByteOrder; - -import jdk.internal.foreign.MemoryAddressImpl; -import jdk.internal.javac.PreviewFeature; -import jdk.internal.reflect.CallerSensitive; - -import java.lang.invoke.MethodHandle; - -/** - * A memory address models a reference into a memory location. Memory addresses are typically obtained in one of the following ways: - *

    - *
  • By calling {@link Addressable#address()} on an instance of type {@link Addressable} (e.g. a memory segment);
  • - *
  • By invoking a {@linkplain Linker#downcallHandle(FunctionDescriptor) downcall method handle} which returns a pointer;
  • - *
  • By reading an address from memory, e.g. via {@link MemorySegment#get(ValueLayout.OfAddress, long)}; and
  • - *
  • By the invocation of an {@linkplain Linker#upcallStub(MethodHandle, FunctionDescriptor, MemorySession) upcall stub} which accepts a pointer.
  • - *
- * A memory address is backed by a raw machine pointer, expressed as a {@linkplain #toRawLongValue() long value}. - * - *

Dereferencing memory addresses

- * - * A memory address can be read or written using various methods provided in this class (e.g. {@link #get(ValueLayout.OfInt, long)}). - * Each dereference method takes a {@linkplain ValueLayout value layout}, which specifies the size, - * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. - * For instance, to read an int from a segment, using {@linkplain ByteOrder#nativeOrder() default endianness}, the following code can be used: - * {@snippet lang=java : - * MemoryAddress address = ... - * int value = address.get(ValueLayout.JAVA_INT, 0); - * } - * - * If the value to be read is stored in memory using {@link ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation - * can be expressed as follows: - * {@snippet lang=java : - * MemoryAddress address = ... - * int value = address.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); - * } - * - * All the dereference methods in this class are restricted: since - * a memory address does not feature temporal nor spatial bounds, the runtime has no way to check the correctness - * of the memory dereference operation. - * - * @implSpec - * Implementations of this interface are immutable, thread-safe and value-based. - * - * @since 19 - */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed interface MemoryAddress extends Addressable permits MemoryAddressImpl { - - /** - * {@return the raw long value associated with this memory address} - */ - long toRawLongValue(); - - /** - * Returns a memory address at given offset from this address. - * @param offset specified offset (in bytes), relative to this address, which should be used to create the new address. - * Might be negative. - * @return a memory address with the given offset from current one. - */ - MemoryAddress addOffset(long offset); - - /** - * Reads a UTF-8 encoded, null-terminated string from this address at the given offset. - *

- * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a Java string constructed from the bytes read from the given starting address ({@code toRawLongValue() + offset}) - * up to (but not including) the first {@code '\0'} terminator character (assuming one is found). - * @throws IllegalArgumentException if the size of the UTF-8 string is greater than the largest string supported by the platform. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - String getUtf8String(long offset); - - /** - * Writes the given string to this address at the given offset, converting it to a null-terminated byte sequence using UTF-8 encoding. - *

- * This method always replaces malformed-input and unmappable-character - * sequences with this charset's default replacement string. The {@link - * java.nio.charset.CharsetDecoder} class should be used when more control - * over the decoding process is required. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @param str the Java string to be written at this address. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setUtf8String(long offset, String str); - - /** - * Compares the specified object with this address for equality. Returns {@code true} if and only if the specified - * object is also an address, and it refers to the same memory location as this address. - * - * @param that the object to be compared for equality with this address. - * @return {@code true} if the specified object is equal to this address. - */ - @Override - boolean equals(Object that); - - /** - * {@return the hash code value for this address} - */ - @Override - int hashCode(); - - /** - * The memory address instance modelling the {@code NULL} address. - */ - MemoryAddress NULL = new MemoryAddressImpl(0L); - - /** - * Creates a memory address from the given long value. - * @param value the long value representing a raw address. - * @return a memory address with the given raw long value. - */ - static MemoryAddress ofLong(long value) { - return value == 0 ? - NULL : - new MemoryAddressImpl(value); - } - - /** - * Reads a byte from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a byte value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - byte get(ValueLayout.OfByte layout, long offset); - - /** - * Writes a byte into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the byte value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfByte layout, long offset, byte value); - - /** - * Reads a boolean from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a boolean value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - boolean get(ValueLayout.OfBoolean layout, long offset); - - /** - * Writes a boolean into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the boolean value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfBoolean layout, long offset, boolean value); - - /** - * Reads a char from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a char value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - char get(ValueLayout.OfChar layout, long offset); - - /** - * Writes a char into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the char value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfChar layout, long offset, char value); - - /** - * Reads a short from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a short value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - short get(ValueLayout.OfShort layout, long offset); - - /** - * Writes a short into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the short value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfShort layout, long offset, short value); - - /** - * Reads an int from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return an int value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - int get(ValueLayout.OfInt layout, long offset); - - /** - * Writes an int into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the int value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfInt layout, long offset, int value); - - /** - * Reads a float from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a float value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - float get(ValueLayout.OfFloat layout, long offset); - - /** - * Writes a float into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the float value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfFloat layout, long offset, float value); - - /** - * Reads a long from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a long value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - long get(ValueLayout.OfLong layout, long offset); - - /** - * Writes a long into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the long value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfLong layout, long offset, long value); - - /** - * Reads a double from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return a double value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - double get(ValueLayout.OfDouble layout, long offset); - - /** - * Writes a double into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the double value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfDouble layout, long offset, double value); - - /** - * Reads an address from this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + offset}. - * @return an address value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - MemoryAddress get(ValueLayout.OfAddress layout, long offset); - - /** - * Writes an address into this address at the given offset, with the given layout. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + offset}. - * @param value the address value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void set(ValueLayout.OfAddress layout, long offset, Addressable value); - - /** - * Reads a char from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return a char value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - char getAtIndex(ValueLayout.OfChar layout, long index); - - /** - * Writes a char into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the char value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfChar layout, long index, char value); - - /** - * Reads a short from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return a short value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - short getAtIndex(ValueLayout.OfShort layout, long index); - - /** - * Writes a short into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the short value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfShort layout, long index, short value); - - /** - * Reads an int from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return an int value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - int getAtIndex(ValueLayout.OfInt layout, long index); - - /** - * Writes an int into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the int value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfInt layout, long index, int value); - - /** - * Reads a float from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return a float value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - float getAtIndex(ValueLayout.OfFloat layout, long index); - - /** - * Writes a float into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the float value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfFloat layout, long index, float value); - - /** - * Reads a long from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return a long value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - long getAtIndex(ValueLayout.OfLong layout, long index); - - /** - * Writes a long into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the long value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfLong layout, long index, long value); - - /** - * Reads a double from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return a double value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - double getAtIndex(ValueLayout.OfDouble layout, long index); - - /** - * Writes a double into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the double value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfDouble layout, long index, double value); - - /** - * Reads an address from this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be read. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this read operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @return an address value read from this address. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index); - - /** - * Writes an address into this address at the given index, scaled by the given layout size. - *

- * This method is restricted. - * Restricted methods are unsafe, and, if used incorrectly, their use might crash - * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on - * restricted methods, and use safe and supported functionalities, where possible. - * - * @param layout the layout of the memory region to be written. - * @param index index in bytes (relative to this address). Might be negative. - * The final address of this write operation can be expressed as {@code toRawLongValue() + (index * layout.byteSize())}. - * @param value the address value to be written. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, - * or if the layout alignment is greater than its size. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. - */ - @CallerSensitive - void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value); -} diff --git a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java index fe953d2aa3c..8d56202a04a 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/MemoryLayout.java @@ -35,15 +35,20 @@ import java.util.Set; import java.util.function.Function; import java.util.function.Supplier; -import java.util.stream.Collectors; import java.util.stream.Stream; import jdk.internal.foreign.LayoutPath; import jdk.internal.foreign.LayoutPath.PathElementImpl.PathKind; import jdk.internal.foreign.Utils; +import jdk.internal.foreign.layout.MemoryLayoutUtil; +import jdk.internal.foreign.layout.PaddingLayoutImpl; +import jdk.internal.foreign.layout.SequenceLayoutImpl; +import jdk.internal.foreign.layout.StructLayoutImpl; +import jdk.internal.foreign.layout.UnionLayoutImpl; +import jdk.internal.foreign.layout.ValueLayouts; import jdk.internal.javac.PreviewFeature; /** - * A memory layout can be used to describe the contents of a memory segment. + * A memory layout describes the contents of a memory segment. * There are two leaves in the layout hierarchy, value layouts, which are used to represent values of given size and kind (see * {@link ValueLayout}) and padding layouts which are used, as the name suggests, to represent a portion of a memory * segment whose contents should be ignored, and which are primarily present for alignment reasons (see {@link MemoryLayout#paddingLayout(long)}). @@ -162,10 +167,11 @@ * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. * + * @sealedGraph * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed interface MemoryLayout permits AbstractLayout, SequenceLayout, GroupLayout, PaddingLayout, ValueLayout { +public sealed interface MemoryLayout permits SequenceLayout, GroupLayout, PaddingLayout, ValueLayout { /** * {@return the layout size, in bits} @@ -185,7 +191,7 @@ public sealed interface MemoryLayout permits AbstractLayout, SequenceLayout, Gro Optional name(); /** - * Returns a memory layout with the same size and alignment constraints as this layout, + * Returns a memory layout of the same type with the same size and alignment constraint as this layout, * but with the specified name. * * @param name the layout name. @@ -235,11 +241,11 @@ default long byteAlignment() { } /** - * Returns a memory layout with the same size and name as this layout, - * but with the specified alignment constraints (in bits). + * Returns a memory layout of the same type with the same size and name as this layout, + * but with the specified alignment constraint (in bits). * * @param bitAlignment the layout alignment constraint, expressed in bits. - * @return a memory layout with the given alignment constraints. + * @return a memory layout with the given alignment constraint. * @throws IllegalArgumentException if {@code bitAlignment} is not a power of two, or if it's less than 8. */ MemoryLayout withBitAlignment(long bitAlignment); @@ -307,7 +313,7 @@ default MethodHandle bitOffsetHandle(PathElement... elements) { * in {@code elements} is {@code null}. */ default long byteOffset(PathElement... elements) { - return Utils.bitsToBytesOrThrow(bitOffset(elements), Utils.bitsToBytesThrowOffset); + return Utils.bitsToBytesOrThrow(bitOffset(elements), Utils.BITS_TO_BYTES_THROW_OFFSET); } /** @@ -343,23 +349,24 @@ default long byteOffset(PathElement... elements) { */ default MethodHandle byteOffsetHandle(PathElement... elements) { MethodHandle mh = bitOffsetHandle(elements); - mh = MethodHandles.filterReturnValue(mh, Utils.MH_bitsToBytesOrThrowForOffset); + mh = MethodHandles.filterReturnValue(mh, Utils.MH_BITS_TO_BYTES_OR_THROW_FOR_OFFSET); return mh; } /** - * Creates an access var handle that can be used to dereference memory at the layout selected by the given layout path, + * Creates a var handle that can be used to access a memory segment at the layout selected by the given layout path, * where the path is considered rooted in this layout. *

- * The final memory location accessed by the returned var handle can be computed as follows: + * The final address accessed by the returned var handle can be computed as follows: * *

{@code
-     * address = base + offset
+     * address = base(segment) + offset
      * }
* - * where {@code base} denotes the base address expressed by the {@link MemorySegment} access coordinate - * (see {@link MemorySegment#address()} and {@link MemoryAddress#toRawLongValue()}) and {@code offset} - * can be expressed in the following form: + * Where {@code base(segment)} denotes a function that returns the physical base address of the accessed + * memory segment. For native segments, this function just returns the native segment's + * {@linkplain MemorySegment#address() address}. For heap segments, this function is more complex, as the address + * of heap segments is virtualized. The {@code offset} coordinate can be expressed in the following form: * *
{@code
      * offset = c_1 + c_2 + ... + c_m + (x_1 * s_1) + (x_2 * s_2) + ... + (x_n * s_n)
@@ -378,8 +385,8 @@ default MethodHandle byteOffsetHandle(PathElement... elements) {
      * features certain access mode restrictions, which are common to all memory segment view handles.
      *
      * @param elements the layout path elements.
-     * @return a var handle which can be used to dereference memory at the (possibly nested) layout selected by the layout path in {@code elements}.
-     * @throws UnsupportedOperationException if the layout path has one or more elements with incompatible alignment constraints.
+     * @return a var handle which can be used to access a memory segment at the (possibly nested) layout selected by the layout path in {@code elements}.
+     * @throws UnsupportedOperationException if the layout path has one or more elements with incompatible alignment constraint.
      * @throws IllegalArgumentException if the layout path in {@code elements} does not select a value layout (see {@link ValueLayout}).
      * @see MethodHandles#memorySegmentViewVarHandle(ValueLayout)
      */
@@ -458,11 +465,6 @@ private static  Z computePathOp(LayoutPath path, Function fina
         return finalizer.apply(path);
     }
 
-    /**
-     * {@return true, if this layout is a padding layout}
-     */
-    boolean isPadding();
-
     /**
      * An element in a layout path. There
      * are two kinds of path elements: group path elements and sequence path elements. Group
@@ -581,15 +583,15 @@ static PathElement sequenceElement() {
     /**
      * Compares the specified object with this layout for equality. Returns {@code true} if and only if the specified
      * object is also a layout, and it is equal to this layout. Two layouts are considered equal if they are of
-     * the same kind, have the same size, name and alignment constraints. Furthermore, depending on the layout kind, additional
+     * the same kind, have the same size, name and alignment constraint. Furthermore, depending on the layout kind, additional
      * conditions must be satisfied:
      * 
    *
  • two value layouts are considered equal if they have the same {@linkplain ValueLayout#order() order}, * and {@linkplain ValueLayout#carrier() carrier}
  • *
  • two sequence layouts are considered equal if they have the same element count (see {@link SequenceLayout#elementCount()}), and * if their element layouts (see {@link SequenceLayout#elementLayout()}) are also equal
  • - *
  • two group layouts are considered equal if they are of the same kind (see {@link GroupLayout#isStruct()}, - * {@link GroupLayout#isUnion()}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal
  • + *
  • two group layouts are considered equal if they are of the same type (see {@link StructLayout}, + * {@link UnionLayout}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal
  • *
* * @param other the object to be compared for equality with this layout. @@ -615,9 +617,9 @@ static PathElement sequenceElement() { * @return the new selector layout. * @throws IllegalArgumentException if {@code size <= 0}. */ - static MemoryLayout paddingLayout(long size) { - AbstractLayout.checkSize(size); - return new PaddingLayout(size); + static PaddingLayout paddingLayout(long size) { + MemoryLayoutUtil.checkSize(size); + return PaddingLayoutImpl.of(size); } /** @@ -632,7 +634,7 @@ static MemoryLayout paddingLayout(long size) { *
  • {@link ValueLayout.OfFloat}, for {@code float.class}
  • *
  • {@link ValueLayout.OfLong}, for {@code long.class}
  • *
  • {@link ValueLayout.OfDouble}, for {@code double.class}
  • - *
  • {@link ValueLayout.OfAddress}, for {@code MemoryAddress.class}
  • + *
  • {@link ValueLayout.OfAddress}, for {@code MemorySegment.class}
  • * * @param carrier the value layout carrier. * @param order the value layout's byte order. @@ -643,54 +645,58 @@ static ValueLayout valueLayout(Class carrier, ByteOrder order) { Objects.requireNonNull(carrier); Objects.requireNonNull(order); if (carrier == boolean.class) { - return new ValueLayout.OfBoolean(order); + return ValueLayouts.OfBooleanImpl.of(order); } else if (carrier == char.class) { - return new ValueLayout.OfChar(order); + return ValueLayouts.OfCharImpl.of(order); } else if (carrier == byte.class) { - return new ValueLayout.OfByte(order); + return ValueLayouts.OfByteImpl.of(order); } else if (carrier == short.class) { - return new ValueLayout.OfShort(order); + return ValueLayouts.OfShortImpl.of(order); } else if (carrier == int.class) { - return new ValueLayout.OfInt(order); + return ValueLayouts.OfIntImpl.of(order); } else if (carrier == float.class) { - return new ValueLayout.OfFloat(order); + return ValueLayouts.OfFloatImpl.of(order); } else if (carrier == long.class) { - return new ValueLayout.OfLong(order); + return ValueLayouts.OfLongImpl.of(order); } else if (carrier == double.class) { - return new ValueLayout.OfDouble(order); - } else if (carrier == MemoryAddress.class) { - return new ValueLayout.OfAddress(order); + return ValueLayouts.OfDoubleImpl.of(order); + } else if (carrier == MemorySegment.class) { + return ValueLayouts.OfAddressImpl.of(order); } else { throw new IllegalArgumentException("Unsupported carrier: " + carrier.getName()); } } /** - * Creates a sequence layout with the given element layout and element count. If the element count has the - * special value {@code -1}, the element count is inferred to be the biggest possible count such that - * the sequence layout size does not overflow, using the following formula: - * - *
    {@code
    -     * inferredElementCount = Long.MAX_VALUE / elementLayout.bitSize();
    -     * }
    + * Creates a sequence layout with the given element layout and element count. * - * @param elementCount the sequence element count; if set to {@code -1}, the sequence element count is inferred. + * @param elementCount the sequence element count. * @param elementLayout the sequence element layout. * @return the new sequence layout with the given element layout and size. - * @throws IllegalArgumentException if {@code elementCount < -1}. - * @throws IllegalArgumentException if {@code elementCount != -1} and the computation {@code elementCount * elementLayout.bitSize()} overflows. + * @throws IllegalArgumentException if {@code elementCount } is negative. */ static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayout) { - if (elementCount == -1) { - // inferred element count - long inferredElementCount = Long.MAX_VALUE / elementLayout.bitSize(); - return new SequenceLayout(inferredElementCount, elementLayout); - } else { - // explicit element count - AbstractLayout.checkSize(elementCount, true); - return wrapOverflow(() -> - new SequenceLayout(elementCount, Objects.requireNonNull(elementLayout))); - } + MemoryLayoutUtil.checkSize(elementCount, true); + Objects.requireNonNull(elementLayout); + return wrapOverflow(() -> + SequenceLayoutImpl.of(elementCount, elementLayout)); + } + + /** + * Creates a sequence layout with the given element layout and the maximum element + * count such that it does not overflow a {@code long}. + * + * This is equivalent to the following code: + * {@snippet lang = java: + * sequenceLayout(Long.MAX_VALUE / elementLayout.bitSize(), elementLayout); + * } + * + * @param elementLayout the sequence element layout. + * @return a new sequence layout with the given element layout and maximum element count. + */ + static SequenceLayout sequenceLayout(MemoryLayout elementLayout) { + Objects.requireNonNull(elementLayout); + return sequenceLayout(Long.MAX_VALUE / elementLayout.bitSize(), elementLayout); } /** @@ -701,13 +707,12 @@ static SequenceLayout sequenceLayout(long elementCount, MemoryLayout elementLayo * @throws IllegalArgumentException if the sum of the {@linkplain #bitSize() bit sizes} of the member layouts * overflows. */ - static GroupLayout structLayout(MemoryLayout... elements) { + static StructLayout structLayout(MemoryLayout... elements) { Objects.requireNonNull(elements); return wrapOverflow(() -> - new GroupLayout(GroupLayout.Kind.STRUCT, - Stream.of(elements) - .map(Objects::requireNonNull) - .collect(Collectors.toList()))); + StructLayoutImpl.of(Stream.of(elements) + .map(Objects::requireNonNull) + .toList())); } /** @@ -716,12 +721,11 @@ static GroupLayout structLayout(MemoryLayout... elements) { * @param elements The member layouts of the union layout. * @return a union layout with the given member layouts. */ - static GroupLayout unionLayout(MemoryLayout... elements) { + static UnionLayout unionLayout(MemoryLayout... elements) { Objects.requireNonNull(elements); - return new GroupLayout(GroupLayout.Kind.UNION, - Stream.of(elements) - .map(Objects::requireNonNull) - .collect(Collectors.toList())); + return UnionLayoutImpl.of(Stream.of(elements) + .map(Objects::requireNonNull) + .toList()); } private static L wrapOverflow(Supplier layoutSupplier) { diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 70a52ba37d7..76c2de64242 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -27,13 +27,15 @@ package java.lang.foreign; import java.io.UncheckedIOException; -import java.lang.reflect.Array; import java.lang.invoke.MethodHandles; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import java.nio.CharBuffer; import java.nio.channels.FileChannel; +import java.nio.channels.FileChannel.*; import java.nio.charset.StandardCharsets; +import java.util.Arrays; import java.util.Objects; import java.util.Optional; import java.util.Spliterator; @@ -43,75 +45,91 @@ import jdk.internal.foreign.NativeMemorySegmentImpl; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.SharedUtils; +import jdk.internal.foreign.layout.ValueLayouts; import jdk.internal.javac.PreviewFeature; import jdk.internal.misc.ScopedMemoryAccess; -import jdk.internal.misc.Unsafe; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.vm.annotation.ForceInline; /** - * A memory segment models a contiguous region of memory. A memory segment is associated with both spatial - * and temporal bounds (e.g. a {@link MemorySession}). Spatial bounds ensure that memory access operations on a memory segment cannot affect a memory location - * which falls outside the boundaries of the memory segment being accessed. Temporal bounds ensure that memory access - * operations on a segment cannot occur after the memory session associated with a memory segment has been closed (see {@link MemorySession#close()}). - * - * There are many kinds of memory segments: + * A memory segment provides access to a contiguous region of memory. + *

    + * There are two kinds of memory segments: *

      - *
    • {@linkplain MemorySegment#allocateNative(long, long, MemorySession) native memory segments}, backed by off-heap memory;
    • - *
    • {@linkplain FileChannel#map(FileChannel.MapMode, long, long, MemorySession) mapped memory segments}, obtained by mapping - * a file into main memory ({@code mmap}); the contents of a mapped memory segments can be {@linkplain #force() persisted} and - * {@linkplain #load() loaded} to and from the underlying memory-mapped file;
    • - *
    • {@linkplain MemorySegment#ofArray(int[]) array segments}, wrapping an existing, heap-allocated Java array; and
    • - *
    • {@linkplain MemorySegment#ofBuffer(Buffer) buffer segments}, wrapping an existing {@link Buffer} instance; - * buffer memory segments might be backed by either off-heap memory or on-heap memory, depending on the characteristics of the - * wrapped buffer instance. For instance, a buffer memory segment obtained from a byte buffer created with the - * {@link ByteBuffer#allocateDirect(int)} method will be backed by off-heap memory.
    • + *
    • A heap segment is backed by, and provides access to, a region of memory inside the Java heap (an "on-heap" region).
    • + *
    • A native segment is backed by, and provides access to, a region of memory outside the Java heap (an "off-heap" region).
    • *
    + * Heap segments can be obtained by calling one of the {@link MemorySegment#ofArray(int[])} factory methods. + * These methods return a memory segment backed by the on-heap region that holds the specified Java array. + *

    + * Native segments can be obtained by calling one of the {@link MemorySegment#allocateNative(long, long, SegmentScope)} + * factory methods, which return a memory segment backed by a newly allocated off-heap region with the given size + * and aligned to the given alignment constraint. Alternatively, native segments can be obtained by + * {@link FileChannel#map(MapMode, long, long, SegmentScope) mapping} a file into a new off-heap region + * (in some systems, this operation is sometimes referred to as {@code mmap}). + * Segments obtained in this way are called mapped segments, and their contents can be {@linkplain #force() persisted} and + * {@linkplain #load() loaded} to and from the underlying memory-mapped file. + *

    + * Both kinds of segments are read and written using the same methods, known as access operations. + * An access operation on a memory segment always and only provides access to the region for which the segment was obtained. * - *

    Lifecycle and confinement

    + *

    Characteristics of memory segments

    * - * Memory segments are associated with a {@linkplain MemorySegment#session() memory session}. As for all resources associated - * with a memory session, a segment cannot be accessed after its underlying session has been closed. For instance, - * the following code will result in an exception: - * {@snippet lang=java : - * MemorySegment segment = null; - * try (MemorySession session = MemorySession.openConfined()) { - * segment = MemorySegment.allocateNative(8, session); - * } - * segment.get(ValueLayout.JAVA_LONG, 0); // already closed! - * } - * Additionally, access to a memory segment is subject to the thread-confinement checks enforced by the owning memory - * session; that is, if the segment is associated with a shared session, it can be accessed by multiple threads; - * if it is associated with a confined session, it can only be accessed by the thread which owns the memory session. + * Every memory segment has an {@linkplain #address() address}, expressed as a {@code long} value. + * The nature of a segment's address depends on the kind of the segment: + *
      + *
    • The address of a heap segment is not a physical address, but rather an offset within the region of memory + * which backs the segment. The region is inside the Java heap, so garbage collection might cause the region to be + * relocated in physical memory over time, but this is not exposed to clients of the {@code MemorySegment} API who + * see a stable virtualized address for a heap segment backed by the region. + * A heap segment obtained from one of the {@link #ofArray(int[])} factory methods has an address of zero.
    • + *
    • The address of a native segment (including mapped segments) denotes the physical address of the region of + * memory which backs the segment.
    • + *
    + *

    + * Every memory segment has a {@linkplain #byteSize() size}. The size of a heap segment is derived from the Java array + * from which it is obtained. This size is predictable across Java runtimes. + * The size of a native segment is either passed explicitly + * (as in {@link MemorySegment#allocateNative(long, SegmentScope)}) or derived from a {@link MemoryLayout} + * (as in {@link MemorySegment#allocateNative(MemoryLayout, SegmentScope)}). The size of a memory segment is typically + * a positive number but may be zero, but never negative. + *

    + * The address and size of a memory segment jointly ensure that access operations on the segment cannot fall + * outside the boundaries of the region of memory which backs the segment. + * That is, a memory segment has spatial bounds. + *

    + * Every memory segment is associated with a {@linkplain SegmentScope scope}. This ensures that access operations + * on a memory segment cannot occur when the region of memory which backs the memory segment is no longer available + * (e.g., after the scope associated with the accessed memory segment is no longer {@linkplain SegmentScope#isAlive() alive}). + * That is, a memory segment has temporal bounds. *

    - * Heap segments are always associated with the {@linkplain MemorySession#global() global} memory session. - * This session cannot be closed, and segments associated with it can be considered as always alive. - * Buffer segments are typically associated with the global memory session, with one exception: buffer segments created - * from byte buffer instances obtained calling the {@link #asByteBuffer()} method on a memory segment {@code S} - * are associated with the same memory session as {@code S}. + * Finally, access operations on a memory segment are subject to the thread-confinement checks enforced by the associated + * scope; that is, if the segment is associated with the {@linkplain SegmentScope#global() global scope} or an {@linkplain SegmentScope#auto() automatic scope}, + * it can be accessed by multiple threads. If the segment is associated with an arena scope, then it can only be + * accessed compatibly with the arena confinement characteristics. * - *

    Dereferencing memory segments

    + *

    Accessing memory segments

    * - * A memory segment can be read or written using various methods provided in this class (e.g. {@link #get(ValueLayout.OfInt, long)}). - * Each dereference method takes a {@linkplain ValueLayout value layout}, which specifies the size, - * alignment constraints, byte order as well as the Java type associated with the dereference operation, and an offset. + * A memory segment can be read or written using various access operations provided in this class (e.g. {@link #get(ValueLayout.OfInt, long)}). + * Each access operation takes a {@linkplain ValueLayout value layout}, which specifies the size and shape of the value, + * and an offset, expressed in bytes. * For instance, to read an int from a segment, using {@linkplain ByteOrder#nativeOrder() default endianness}, the following code can be used: * {@snippet lang=java : * MemorySegment segment = ... * int value = segment.get(ValueLayout.JAVA_INT, 0); * } * - * If the value to be read is stored in memory using {@linkplain ByteOrder#BIG_ENDIAN big-endian} encoding, the dereference operation + * If the value to be read is stored in memory using {@linkplain ByteOrder#BIG_ENDIAN big-endian} encoding, the access operation * can be expressed as follows: * {@snippet lang=java : * MemorySegment segment = ... * int value = segment.get(ValueLayout.JAVA_INT.withOrder(BIG_ENDIAN), 0); * } * - * For more complex dereference operations (e.g. structured memory access), clients can obtain a - * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) memory segment view var handle}, - * that is, a var handle that accepts a segment and a {@code long} offset. More complex access var handles + * For more complex access operations (e.g. structured memory access), clients can obtain a + * {@linkplain MethodHandles#memorySegmentViewVarHandle(ValueLayout) var handle} + * that accepts a segment and a {@code long} offset. More complex var handles * can be obtained by adapting a segment var handle view using the var handle combinator functions defined in the * {@link java.lang.invoke.MethodHandles} class: * @@ -126,7 +144,7 @@ * intHandle.get(segment, 3L); // get int element at offset 3 * 4 = 12 * } * - * Alternatively, complex access var handles can can be obtained + * Alternatively, complex var handles can can be obtained * from {@linkplain MemoryLayout#varHandle(MemoryLayout.PathElement...) memory layouts} * by providing a so called layout path: * @@ -138,62 +156,138 @@ * *

    Slicing memory segments

    * - * Memory segments support slicing. A memory segment can be used to {@linkplain MemorySegment#asSlice(long, long) obtain} - * other segments backed by the same underlying memory region, but with stricter spatial bounds than the ones - * of the original segment: + * Memory segments support {@linkplain MemorySegment#asSlice(long, long) slicing}. Slicing a memory segment + * returns a new memory segment that is backed by the same region of memory as the original. The address of the sliced + * segment is derived from the address of the original segment, by adding an offset (expressed in bytes). The size of + * the sliced segment is either derived implicitly (by subtracting the specified offset from the size of the original segment), + * or provided explicitly. In other words, a sliced segment has stricter spatial bounds than those of the original segment: * {@snippet lang=java : - * MemorySession session = ... - * MemorySegment segment = MemorySegment.allocateNative(100, session); + * Arena arena = ... + * MemorySegment segment = arena.allocate(100); * MemorySegment slice = segment.asSlice(50, 10); * slice.get(ValueLayout.JAVA_INT, 20); // Out of bounds! - * session.close(); + * arena.close(); * slice.get(ValueLayout.JAVA_INT, 0); // Already closed! * } * The above code creates a native segment that is 100 bytes long; then, it creates a slice that starts at offset 50 - * of {@code segment}, and is 10 bytes long. As a result, attempting to read an int value at offset 20 of the - * {@code slice} segment will result in an exception. The {@linkplain MemorySession temporal bounds} of the original segment - * are inherited by its slices; that is, when the memory session associated with {@code segment} is closed, {@code slice} - * will also be become inaccessible. + * of {@code segment}, and is 10 bytes long. That is, the address of the {@code slice} is {@code segment.address() + 50}, + * and its size is 10. As a result, attempting to read an int value at offset 20 of the + * {@code slice} segment will result in an exception. The {@linkplain SegmentScope temporal bounds} of the original segment + * is inherited by its slices; that is, when the scope associated with {@code segment} is no longer {@linkplain SegmentScope#isAlive() alive}, + * {@code slice} will also be become inaccessible. *

    * A client might obtain a {@link Stream} from a segment, which can then be used to slice the segment (according to a given * element layout) and even allow multiple threads to work in parallel on disjoint segment slices - * (to do this, the segment has to be associated with a shared memory session). The following code can be used to sum all int - * values in a memory segment in parallel: + * (to do this, the segment has to be associated with a scope that allows {@linkplain SegmentScope#isAccessibleBy(Thread) access} + * from multiple threads). The following code can be used to sum all int values in a memory segment in parallel: * - * {@snippet lang=java : - * try (MemorySession session = MemorySession.openShared()) { + * {@snippet lang = java: + * try (Arena arena = Arena.openShared()) { * SequenceLayout SEQUENCE_LAYOUT = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); - * MemorySegment segment = MemorySegment.allocateNative(SEQUENCE_LAYOUT, session); + * MemorySegment segment = arena.allocate(SEQUENCE_LAYOUT); * int sum = segment.elements(ValueLayout.JAVA_INT).parallel() * .mapToInt(s -> s.get(ValueLayout.JAVA_INT, 0)) * .sum(); * } - * } + *} * *

    Alignment

    * - * When dereferencing a memory segment using a layout, the runtime must check that the segment address being dereferenced - * matches the layout's {@linkplain MemoryLayout#byteAlignment() alignment constraints}. If the segment being - * dereferenced is a native segment, then it has a concrete {@linkplain #address() base address}, which can - * be used to perform the alignment check. The pseudo-function below demonstrates this: + * Access operations on a memory segment are constrained not only by the spatial and temporal bounds of the segment, + * but also by the alignment constraint of the value layout specified to the operation. An access operation can + * access only those offsets in the segment that denote addresses in physical memory which are aligned according + * to the layout. An address in physical memory is aligned according to a layout if the address is an integer + * multiple of the layout's alignment constraint. For example, the address 1000 is aligned according to an 8-byte alignment + * constraint (because 1000 is an integer multiple of 8), and to a 4-byte alignment constraint, and to a 2-byte alignment + * constraint; in contrast, the address 1004 is aligned according to a 4-byte alignment constraint, and to a 2-byte alignment + * constraint, but not to an 8-byte alignment constraint. + * Access operations are required to respect alignment because it can impact the performance of access operations, and + * can also determine which access operations are available at a given physical address. For instance, + * {@linkplain java.lang.invoke.VarHandle#compareAndSet(Object...) atomic access operations} operations using + * {@link java.lang.invoke.VarHandle} are only permitted at aligned addresses. In addition, alignment + * applies to an access operation whether the segment being accessed is a native segment or a heap segment. + *

    + * If the segment being accessed is a native segment, then its {@linkplain #address() address} in physical memory can be + * combined with the offset to obtain the target address in physical memory. The pseudo-function below demonstrates this: * - * {@snippet lang=java : + * {@snippet lang = java: * boolean isAligned(MemorySegment segment, long offset, MemoryLayout layout) { - * return ((segment.address().toRawLongValue() + offset) % layout.byteAlignment()) == 0 + * return ((segment.address() + offset) % layout.byteAlignment()) == 0; * } * } * - * If, however, the segment being dereferenced is a heap segment, the above function will not work: a heap - * segment's base address is virtualized and, as such, cannot be used to construct an alignment check. Instead, - * heap segments are assumed to produce addresses which are never more aligned than the element size of the Java array from which - * they have originated from, as shown in the following table: + * For example: + *

      + *
    • A native segment with address 1000 can be accessed at offsets 0, 8, 16, 24, etc under an 8-byte alignment constraint, + * because the target addresses (1000, 1008, 1016, 1024) are 8-byte aligned. + * Access at offsets 1-7 or 9-15 or 17-23 is disallowed because the target addresses would not be 8-byte aligned.
    • + *
    • A native segment with address 1000 can be accessed at offsets 0, 4, 8, 12, etc under a 4-byte alignment constraint, + * because the target addresses (1000, 1004, 1008, 1012) are 4-byte aligned. + * Access at offsets 1-3 or 5-7 or 9-11 is disallowed because the target addresses would not be 4-byte aligned.
    • + *
    • A native segment with address 1000 can be accessed at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint, + * because the target addresses (1000, 1002, 1004, 1006) are 2-byte aligned. + * Access at offsets 1 or 3 or 5 is disallowed because the target addresses would not be 2-byte aligned.
    • + *
    • A native segment with address 1004 can be accessed at offsets 0, 4, 8, 12, etc under a 4-byte alignment constraint, + * and at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint. + * Under an 8-byte alignment constraint, it can be accessed at offsets 4, 12, 20, 28, etc.
    • + *
    • A native segment with address 1006 can be accessed at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint. + * Under a 4-byte alignment constraint, it can be accessed at offsets 2, 6, 10, 14, etc. + * Under an 8-byte alignment constraint, it can be accessed at offsets 2, 10, 18, 26, etc. + *
    • A native segment with address 1007 can be accessed at offsets 0, 1, 2, 3, etc under a 1-byte alignment constraint. + * Under a 2-byte alignment constraint, it can be accessed at offsets 1, 3, 5, 7, etc. + * Under a 4-byte alignment constraint, it can be accessed at offsets 1, 5, 9, 13, etc. + * Under an 8-byte alignment constraint, it can be accessed at offsets 1, 9, 17, 25, etc.
    • + *
    + *

    + * The alignment constraint used to access a segment is typically dictated by the shape of the data structure stored + * in the segment. For example, if the programmer wishes to store a sequence of 8-byte values in a native segment, then + * the segment should be allocated by specifying a 8-byte alignment constraint, either via {@link #allocateNative(long, long, SegmentScope)} + * or {@link #allocateNative(MemoryLayout, SegmentScope)}. These factories ensure that the off-heap region of memory backing + * the returned segment has a starting address that is 8-byte aligned. Subsequently, the programmer can access the + * segment at the offsets of interest -- 0, 8, 16, 24, etc -- in the knowledge that every such access is aligned. + *

    + * If the segment being accessed is a heap segment, then determining whether access is aligned is more complex. + * The address of the segment in physical memory is not known, and is not even fixed (it may change when the segment + * is relocated during garbage collection). This means that the address cannot be combined with the specified offset to + * determine a target address in physical memory. Since the alignment constraint always refers to alignment of + * addresses in physical memory, it is not possible in principle to determine if any offset in a heap segment is aligned. + * For example, suppose the programmer chooses a 8-byte alignment constraint and tries + * to access offset 16 in a heap segment. If the heap segment's address 0 corresponds to physical address 1000, + * then the target address (1016) would be aligned, but if address 0 corresponds to physical address 1004, + * then the target address (1020) would not be aligned. It is undesirable to allow access to target addresses that are + * aligned according to the programmer's chosen alignment constraint, but might not be predictably aligned in physical memory + * (e.g. because of platform considerations and/or garbage collection behavior). + *

    + * In practice, the Java runtime lays out arrays in memory so that each n-byte element occurs at an n-byte + * aligned physical address. The runtime preserves this invariant even if the array is relocated during garbage + * collection. Access operations rely on this invariant to determine if the specified offset in a heap segment refers + * to an aligned address in physical memory. For example: + *

      + *
    • The starting physical address of a {@code long[]} array will be 8-byte aligned (e.g. 1000), so that successive long elements + * occur at 8-byte aligned addresses (e.g., 1000, 1008, 1016, 1024, etc.) A heap segment backed by a {@code long[]} array + * can be accessed at offsets 0, 8, 16, 24, etc under an 8-byte alignment constraint. In addition, the segment can be + * accessed at offsets 0, 4, 8, 12, etc under a 4-byte alignment constraint, because the target addresses + * (1000, 1004, 1008, 1012) are 4-byte aligned. And, the segment can be accessed at offsets 0, 2, 4, 6, etc under a + * 2-byte alignment constraint, because the target addresses (e.g. 1000, 1002, 1004, 1006) are 2-byte aligned.
    • + *
    • The starting physical address of a {@code short[]} array will be 2-byte aligned (e.g. 1006) so that successive + * short elements occur at 2-byte aligned addresses (e.g. 1006, 1008, 1010, 1012, etc). A heap segment backed by a + * {@code short[]} array can be accessed at offsets 0, 2, 4, 6, etc under a 2-byte alignment constraint. The segment cannot + * be accessed at any offset under a 4-byte alignment constraint, because there is no guarantee that the target + * address would be 4-byte aligned, e.g., offset 0 would correspond to physical address 1006 while offset 1 would correspond + * to physical address 1007. Similarly, the segment cannot be accessed at any offset under an 8-byte alignment constraint, + * because because there is no guarantee that the target address would be 8-byte aligned, e.g., offset 2 would correspond + * to physical address 1008 but offset 4 would correspond to physical address 1010.
    • + *
    + *

    + * In other words, heap segments feature a maximum alignment which is derived from the size of the elements of + * the Java array backing the segment, as shown in the following table: * *

    - * + * * * - * - * + * + * * * * @@ -216,22 +310,86 @@ * *
    Array type of an array backing a segment and its address alignmentMaximum alignment of heap segments
    Array typeAlignmentArray type (of backing region)Maximum supported alignment (in bytes)
    * - * Note that the above definition is conservative: it might be possible, for instance, that a heap segment - * constructed from a {@code byte[]} might have a subset of addresses {@code S} which happen to be 8-byte aligned. But determining - * which segment addresses belong to {@code S} requires reasoning about details which are ultimately implementation-dependent. + * Heap segments can only be accessed using a layout whose alignment is smaller or equal to the + * maximum alignment associated with the heap segment. Attempting to access a heap segment using a layout + * whose alignment is greater than the maximum alignment associated with the heap segment will fail, + * as demonstrated in the following example: + * + * {@snippet lang=java : + * MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]); + * byteSegment.get(ValueLayout.JAVA_INT, 0); // fails: layout alignment is 4, segment max alignment is 1 + * } + * + * In such circumstances, clients have two options. They can use a heap segment backed by a different array + * type (e.g. {@code long[]}), capable of supporting greater maximum alignment: + * + * {@snippet lang=java : + * MemorySegment longSegment = MemorySegment.ofArray(new long[10]); + * longSegment.get(ValueLayout.JAVA_INT, 0); // ok: layout alignment is 4, segment max alignment is 8 + * } + * + * Alternatively, they can invoke the access operation with an unaligned layout. + * All unaligned layout constants (e.g. {@link ValueLayout#JAVA_INT_UNALIGNED}) have their alignment constraint set to 1: + * {@snippet lang=java : + * MemorySegment byteSegment = MemorySegment.ofArray(new byte[10]); + * byteSegment.get(ValueLayout.JAVA_INT_UNALIGNED, 0); // ok: layout alignment is 1, segment max alignment is 1 + * } + * + *

    Zero-length memory segments

    + * + * When interacting with foreign functions, it is common for those functions + * to allocate a region of memory and return a pointer to that region. Modeling the region of memory with a memory segment + * is challenging because the Java runtime has no insight into the size of the region. Only the address of the start of + * the region, stored in the pointer, is available. For example, a C function with return type {@code char*} might return + * a pointer to a region containing a single {@code char} value, or to a region containing an array of {@code char} values, + * where the size of the array might be provided in a separate parameter. The size of the array is not readily apparent + * to the code calling the foreign function and hoping to use its result. + *

    + * The {@link Linker} represents a pointer returned from a foreign function with a zero-length memory segment. + * The address of the segment is the address stored in the pointer. The size of the segment is zero. Similarly, when a + * client reads an address from a memory segment, a zero-length memory segment is returned. + *

    + * Since a zero-length segment features trivial spatial bounds, any attempt to access these segments will fail with + * {@link IndexOutOfBoundsException}. This is a crucial safety feature: as these segments are associated with a region + * of memory whose size is not known, any access operations involving these segments cannot be validated. + * In effect, a zero-length memory segment wraps an address, and it cannot be used without explicit intent. + *

    + * Zero-length memory segments obtained when interacting with foreign functions are associated with the + * {@link SegmentScope#global() global scope}. This is because the Java runtime, in addition to having no insight + * into the size of the region of memory backing a pointer returned from a foreign function, also has no insight + * into the lifetime intended for said region of memory by the foreign function that allocated it. The global scope + * ensures that the obtained segment can be passed, opaquely, to other pointer-accepting foreign functions. + *

    + * To access native zero-length memory segments, clients have two options, both of which are unsafe. Clients + * can {@linkplain java.lang.foreign.MemorySegment#ofAddress(long, long, SegmentScope) obtain} + * a new native segment, with new spatial and temporal bounds, as follows: + * + * {@snippet lang = java: + * SegmentScope scope = ... // obtains a scope + * MemorySegment foreign = someSegment.get(ValueLayout.ADDRESS, 0); // wrap address into segment (size = 0) + * MemorySegment segment = MemorySegment.ofAddress(foreign.address(), 4, scope); // create new segment (size = 4) + * int x = segment.get(ValueLayout.JAVA_INT, 0); //ok + *} + * + * Alternatively, clients can obtain an {@linkplain java.lang.foreign.ValueLayout.OfAddress#asUnbounded() unbounded} + * address value layout. When an access operation, or a function descriptor that is passed to a downcall method handle, + * uses an unbounded address value layouts, the runtime will wrap any corresponding raw addresses with native segments + * with maximal size (i.e. {@linkplain java.lang.Long#MAX_VALUE}). As such, these segments can be accessed directly, as follows: + * + * {@snippet lang = java: + * MemorySegment foreign = someSegment.get(ValueLayout.ADDRESS.asUnbounded(), 0); // wrap address into segment (size = Long.MAX_VALUE) + * int x = foreign.get(ValueLayout.JAVA_INT, 0); //ok + *} * - *

    Restricted memory segments

    - * Sometimes it is necessary to turn a memory address obtained from native code into a memory segment with - * full spatial, temporal and confinement bounds. To do this, clients can {@linkplain #ofAddress(MemoryAddress, long, MemorySession) obtain} - * a native segment unsafely from a give memory address, by providing the segment size, as well as the segment {@linkplain MemorySession session}. - * This is a restricted operation and should be used with - * caution: for instance, an incorrect segment size could result in a VM crash when attempting to dereference - * the memory segment. + * Both {@link #ofAddress(long, long, SegmentScope)} and {@link ValueLayout.OfAddress#asUnbounded()} are + * restricted methods, and should be used with caution: + * for instance, sizing a segment incorrectly could result in a VM crash when attempting to access the memory segment. *

    - * Clients requiring sophisticated, low-level control over mapped memory segments, might consider writing - * custom mapped memory segment factories; using {@link Linker}, e.g. on Linux, it is possible to call {@code mmap} - * with the desired parameters; the returned address can be easily wrapped into a memory segment, using - * {@link MemoryAddress#ofLong(long)} and {@link MemorySegment#ofAddress(MemoryAddress, long, MemorySession)}. + * Which approach is taken largely depends on the information that a client has available when obtaining a memory segment + * wrapping a native pointer. For instance, if such pointer points to a C struct, the client might prefer to resize the + * segment unsafely, to match the size of the struct (so that out-of-bounds access will be detected by the API). + * In other instances, however, there will be no, or little information as to what spatial and/or temporal bounds should + * be associated with a given native pointer. In these cases using an unbounded address layout might be preferable. * * @implSpec * Implementations of this interface are immutable, thread-safe and value-based. @@ -239,18 +397,17 @@ * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed interface MemorySegment extends Addressable permits AbstractMemorySegmentImpl { +public sealed interface MemorySegment permits AbstractMemorySegmentImpl { /** - * {@return the base memory address associated with this native memory segment} - * @throws UnsupportedOperationException if this segment is not a {@linkplain #isNative() native} segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * {@return the address of this memory segment} */ - @Override - MemoryAddress address(); + long address(); + + /** + * {@return the Java array associated with this memory segment, if any} + */ + Optional array(); /** * Returns a spliterator for this memory segment. The returned spliterator reports {@link Spliterator#SIZED}, @@ -261,7 +418,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * if the supplied layout has size N, then calling {@link Spliterator#trySplit()} will result in a spliterator serving * approximately {@code S/N} elements (depending on whether N is even or not), where {@code S} is the size of * this segment. As such, splitting is possible as long as {@code S/N >= 2}. The spliterator returns segments that - * are associated with the same memory session as this segment. + * are associated with the same scope as that associated with this segment. *

    * The returned spliterator effectively allows to slice this segment into disjoint {@linkplain #asSlice(long, long) slices}, * which can then be processed in parallel by multiple threads. @@ -270,7 +427,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return the element spliterator for this segment * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the * {@code elementLayout} size is greater than zero, if this segment is - * incompatible with the alignment constraints in the provided layout, + * incompatible with the alignment constraint in the provided layout, * or if the {@code elementLayout} alignment is greater than its size. */ Spliterator spliterator(MemoryLayout elementLayout); @@ -286,15 +443,15 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * @return a sequential {@code Stream} over disjoint slices in this segment. * @throws IllegalArgumentException if the {@code elementLayout} size is zero, or the segment size modulo the * {@code elementLayout} size is greater than zero, if this segment is - * incompatible with the alignment constraints in the provided layout, + * incompatible with the alignment constraint in the provided layout, * or if the {@code elementLayout} alignment is greater than its size. */ Stream elements(MemoryLayout elementLayout); /** - * {@return the memory session associated with this memory segment} + * {@return the scope associated with this memory segment} */ - MemorySession session(); + SegmentScope scope(); /** * {@return the size (in bytes) of this memory segment} @@ -302,12 +459,12 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory long byteSize(); /** - * Returns a slice of this memory segment, at the given offset. The returned segment's base address is the base address + * Returns a slice of this memory segment, at the given offset. The returned segment's address is the address * of this segment plus the given offset; its size is specified by the given argument. * * @see #asSlice(long) * - * @param offset The new segment base offset (relative to the current segment base address), specified in bytes. + * @param offset The new segment base offset (relative to the address of this segment), specified in bytes. * @param newSize The new segment size, specified in bytes. * @return a slice of this memory segment. * @throws IndexOutOfBoundsException if {@code offset < 0}, {@code offset > byteSize()}, {@code newSize < 0}, or {@code newSize > byteSize() - offset} @@ -315,7 +472,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory MemorySegment asSlice(long offset, long newSize); /** - * Returns a slice of this memory segment, at the given offset. The returned segment's base address is the base address + * Returns a slice of this memory segment, at the given offset. The returned segment's address is the address * of this segment plus the given offset; its size is computed by subtracting the specified offset from this segment size. *

    * Equivalent to the following code: @@ -325,7 +482,7 @@ public sealed interface MemorySegment extends Addressable permits AbstractMemory * * @see #asSlice(long, long) * - * @param offset The new segment base offset (relative to the current segment base address), specified in bytes. + * @param offset The new segment base offset (relative to the address of this segment), specified in bytes. * @return a slice of this memory segment. * @throws IndexOutOfBoundsException if {@code offset < 0}, or {@code offset > byteSize()}. */ @@ -348,18 +505,17 @@ default MemorySegment asSlice(long offset) { MemorySegment asReadOnly(); /** - * Returns {@code true} if this segment is a native segment. A native memory segment is - * created using the {@link #allocateNative(long, MemorySession)} (and related) factory, or a buffer segment - * derived from a {@linkplain ByteBuffer#allocateDirect(int) direct byte buffer} using the {@link #ofBuffer(Buffer)} factory, - * or if this is a {@linkplain #isMapped() mapped} segment. + * Returns {@code true} if this segment is a native segment. A native segment is + * created e.g. using the {@link #allocateNative(long, SegmentScope)} (and related) factory, or by + * {@linkplain #ofBuffer(Buffer) wrapping} a {@linkplain ByteBuffer#allocateDirect(int) direct buffer}. * @return {@code true} if this segment is native segment. */ boolean isNative(); /** - * Returns {@code true} if this segment is a mapped segment. A mapped memory segment is - * created using the {@link FileChannel#map(FileChannel.MapMode, long, long, MemorySession)} factory, or a buffer segment - * derived from a {@link java.nio.MappedByteBuffer} using the {@link #ofBuffer(Buffer)} factory. + * Returns {@code true} if this segment is a mapped segment. A mapped memory segment is created e.g. using the + * {@link FileChannel#map(FileChannel.MapMode, long, long, SegmentScope)} factory, or by + * {@linkplain #ofBuffer(Buffer) wrapping} a {@linkplain java.nio.MappedByteBuffer mapped byte buffer}. * @return {@code true} if this segment is a mapped segment. */ boolean isMapped(); @@ -370,7 +526,7 @@ default MemorySegment asSlice(long offset) { * *

    Two segments {@code S1} and {@code S2} are said to overlap if it is possible to find * at least two slices {@code L1} (from {@code S1}) and {@code L2} (from {@code S2}) that are backed by the - * same memory region. As such, it is not possible for a + * same region of memory. As such, it is not possible for a * {@linkplain #isNative() native} segment to overlap with a heap segment; in * this case, or when no overlap occurs, {@code null} is returned. * @@ -383,19 +539,22 @@ default MemorySegment asSlice(long offset) { * Returns the offset, in bytes, of the provided segment, relative to this * segment. * - *

    The offset is relative to the base address of this segment and can be + *

    The offset is relative to the address of this segment and can be * a negative or positive value. For instance, if both segments are native - * segments, the resulting offset can be computed as follows: + * segments, or heap segments backed by the same array, the resulting offset + * can be computed as follows: * * {@snippet lang=java : - * other.baseAddress().toRawLongValue() - segment.baseAddress().toRawLongValue() + * other.address() - segment.address() * } * - * If the segments share the same base address, {@code 0} is returned. If + * If the segments share the same address, {@code 0} is returned. If * {@code other} is a slice of this segment, the offset is always * {@code 0 <= x < this.byteSize()}. * * @param other the segment to retrieve an offset to. + * @throws UnsupportedOperationException if the two segments cannot be compared, e.g. because they are of + * a different kind, or because they are backed by different Java arrays. * @return the relative offset, in bytes, of the provided segment. */ long segmentOffset(MemorySegment other); @@ -421,10 +580,10 @@ default MemorySegment asSlice(long offset) { * * @param value the value to fill into this segment * @return this memory segment - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}). */ MemorySegment fill(byte value); @@ -440,14 +599,14 @@ default MemorySegment asSlice(long offset) { * } * @param src the source segment. * @throws IndexOutOfBoundsException if {@code src.byteSize() > this.byteSize()}. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code src} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code src}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code src} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code src.scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is read-only (see {@link #isReadOnly()}). * @return this segment. */ @@ -459,7 +618,7 @@ default MemorySegment copyFrom(MemorySegment src) { /** * Finds and returns the offset, in bytes, of the first mismatch between * this segment and the given other segment. The offset is relative to the - * {@linkplain #address() base address} of each segment and will be in the + * {@linkplain #address() address} of each segment and will be in the * range of 0 (inclusive) up to the {@linkplain #byteSize() size} (in bytes) of * the smaller memory segment (exclusive). *

    @@ -474,16 +633,19 @@ default MemorySegment copyFrom(MemorySegment src) { * @param other the segment to be tested for a mismatch with this segment * @return the relative offset, in bytes, of the first mismatch between this * and the given other segment, otherwise -1 if no mismatch - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code other} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code other}. - */ - long mismatch(MemorySegment other); + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code other} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code other.scope().isAccessibleBy(T) == false}. + */ + default long mismatch(MemorySegment other) { + Objects.requireNonNull(other); + return MemorySegment.mismatch(this, 0, byteSize(), other, 0, other.byteSize()); + } /** * Determines whether the contents of this mapped segment is resident in physical @@ -503,10 +665,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @return {@code true} if it is likely that the contents of this segment * is resident in physical memory * - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if * {@code isMapped() == false}. */ @@ -520,10 +682,10 @@ default MemorySegment copyFrom(MemorySegment src) { * method may cause some number of page faults and I/O operations to * occur.

    * - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if * {@code isMapped() == false}. */ @@ -537,10 +699,10 @@ default MemorySegment copyFrom(MemorySegment src) { * after invoking this method may cause some number of page faults and I/O operations to * occur (as this segment's contents might need to be paged back in).

    * - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if * {@code isMapped() == false}. */ @@ -566,10 +728,10 @@ default MemorySegment copyFrom(MemorySegment src) { * implementation-specific mapping modes. *

    * - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if this segment is not a mapped memory segment, e.g. if * {@code isMapped() == false}. * @throws UncheckedIOException if there is an I/O error writing the contents of this segment to the associated storage device @@ -580,7 +742,7 @@ default MemorySegment copyFrom(MemorySegment src) { * Wraps this segment in a {@link ByteBuffer}. Some properties of the returned buffer are linked to * the properties of this segment. For instance, if this segment is immutable * (e.g. the segment is a read-only segment, see {@link #isReadOnly()}), then the resulting buffer is read-only - * (see {@link ByteBuffer#isReadOnly()}). Additionally, if this is a native memory segment, the resulting buffer is + * (see {@link ByteBuffer#isReadOnly()}). Additionally, if this is a native segment, the resulting buffer is * direct (see {@link ByteBuffer#isDirect()}). *

    * The returned buffer's position (see {@link ByteBuffer#position()}) is initially set to zero, while @@ -589,13 +751,12 @@ default MemorySegment copyFrom(MemorySegment src) { * returned if this segment' size is greater than {@link Integer#MAX_VALUE}. *

    * The life-cycle of the returned buffer will be tied to that of this segment. That is, accessing the returned buffer - * after the memory session associated with this segment has been closed (see {@link MemorySession#close()}), will - * throw an {@link IllegalStateException}. Similarly, accessing the returned buffer from a thread other than - * the thread {@linkplain MemorySession#ownerThread() owning} this segment's memory session will throw - * a {@link WrongThreadException}. + * after the scope associated with this segment is no longer {@linkplain SegmentScope#isAlive() alive}, will + * throw an {@link IllegalStateException}. Similarly, accessing the returned buffer from a thread {@code T} + * such that {@code scope().isAccessible(T) == false} will throw a {@link WrongThreadException}. *

    - * If this segment is associated with a confined memory session, calling read/write I/O operations on the resulting buffer - * might result in an unspecified exception being thrown. Examples of such problematic operations are + * If this segment is associated with a scope that can only be accessed from a single thread, calling read/write I/O + * operations on the resulting buffer might result in an unspecified exception being thrown. Examples of such problematic operations are * {@link java.nio.channels.AsynchronousSocketChannel#read(ByteBuffer)} and * {@link java.nio.channels.AsynchronousSocketChannel#write(ByteBuffer)}. *

    @@ -614,10 +775,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new byte array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code byte[]} instance, * e.g. its size is greater than {@link Integer#MAX_VALUE}. */ @@ -628,10 +789,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new short array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code short[]} instance, * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE} */ @@ -642,10 +803,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new char array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code char[]} instance, * e.g. because {@code byteSize() % 2 != 0}, or {@code byteSize() / 2 > Integer#MAX_VALUE}. */ @@ -656,10 +817,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new int array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code int[]} instance, * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}. */ @@ -670,10 +831,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new float array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code float[]} instance, * e.g. because {@code byteSize() % 4 != 0}, or {@code byteSize() / 4 > Integer#MAX_VALUE}. */ @@ -684,10 +845,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new long array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code long[]} instance, * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}. */ @@ -698,10 +859,10 @@ default MemorySegment copyFrom(MemorySegment src) { * @param elementLayout the source element layout. If the byte order associated with the layout is * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @return a new double array whose contents are copied from this memory segment. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. * @throws IllegalStateException if this segment's contents cannot be copied into a {@code double[]} instance, * e.g. because {@code byteSize() % 8 != 0}, or {@code byteSize() / 8 > Integer#MAX_VALUE}. */ @@ -714,17 +875,16 @@ default MemorySegment copyFrom(MemorySegment src) { * sequences with this charset's default replacement string. The {@link * java.nio.charset.CharsetDecoder} class should be used when more control * over the decoding process is required. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @return a Java string constructed from the bytes read from the given starting address up to (but not including) * the first {@code '\0'} terminator character (assuming one is found). * @throws IllegalArgumentException if the size of the UTF-8 string is greater than the largest string supported by the platform. - * @throws IndexOutOfBoundsException if {@code S + offset > byteSize()}, where {@code S} is the size of the UTF-8 + * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code S + offset > byteSize()}, where {@code S} is the size of the UTF-8 * string (including the terminator character). - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. */ default String getUtf8String(long offset) { return SharedUtils.toJavaStringInternal(this, offset); @@ -742,15 +902,14 @@ default String getUtf8String(long offset) { * copied as well. This means that, depending on the method used to read * the string, such as {@link MemorySegment#getUtf8String(long)}, the string * will appear truncated when read again. - * - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * the final address of this write operation can be expressed as {@code address() + offset}. * @param str the Java string to be written into this segment. - * @throws IndexOutOfBoundsException if {@code str.getBytes().length() + offset >= byteSize()}. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. + * @throws IndexOutOfBoundsException if {@code offset < 0} or {@code str.getBytes().length() + offset >= byteSize()}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. */ default void setUtf8String(long offset, String str) { Utils.toCString(str.getBytes(StandardCharsets.UTF_8), SegmentAllocator.prefixAllocator(asSlice(offset))); @@ -758,112 +917,212 @@ default void setUtf8String(long offset, String str) { /** - * Creates a buffer memory segment that models the memory associated with the given {@link Buffer} instance. + * Creates a memory segment that is backed by the same region of memory that backs the given {@link Buffer} instance. * The segment starts relative to the buffer's position (inclusive) and ends relative to the buffer's limit (exclusive). *

    - * If the buffer is {@linkplain ByteBuffer#isReadOnly() read-only}, the resulting segment will also be - * {@linkplain ByteBuffer#isReadOnly() read-only}. The memory session associated with this segment can either be the - * {@linkplain MemorySession#global() global} memory session, in case the buffer has been created independently, - * or some other memory session, in case the buffer has been obtained using {@link #asByteBuffer()}. + * If the buffer is {@linkplain Buffer#isReadOnly() read-only}, the resulting segment will also be + * {@linkplain ByteBuffer#isReadOnly() read-only}. Moreover, if the buffer is a {@linkplain Buffer#isDirect() direct buffer}, + * the returned segment is a native segment; otherwise the returned memory segment is a heap segment. *

    - * The resulting memory segment keeps a reference to the backing buffer, keeping it reachable. + * The scope {@code S} associated with the returned segment is computed as follows: + *

      + *
    • if the buffer has been obtained by calling {@link #asByteBuffer()} on a memory segment whose scope + * is {@code S'}, then {@code S = S'}; or
    • + *
    • if the buffer is a heap buffer, then {@code S} is the {@linkplain SegmentScope#global() global scope}; or + *
    • if the buffer is a direct buffer, then {@code S} is a scope that is always alive and which keeps the buffer reachable. + * Therefore, the off-heap region of memory backing the buffer instance will remain available as long as the + * returned segment is reachable.
    • + *
    * - * @param buffer the buffer instance backing the buffer memory segment. - * @return a buffer memory segment. + * @param buffer the buffer instance to be turned into a new memory segment. + * @return a memory segment, derived from the given buffer instance. + * @throws IllegalArgumentException if the provided {@code buffer} is a heap buffer but is not backed by an array. + * For example, buffers directly or indirectly obtained via + * ({@link CharBuffer#wrap(CharSequence)} or {@link CharBuffer#wrap(char[], int, int)} + * are not backed by an array. */ static MemorySegment ofBuffer(Buffer buffer) { return AbstractMemorySegmentImpl.ofBuffer(buffer); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated byte array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given byte array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param byteArray the primitive array backing the heap memory segment. + * @return a heap memory segment backed by a byte array. */ - static MemorySegment ofArray(byte[] arr) { - return HeapMemorySegmentImpl.OfByte.fromArray(arr); + static MemorySegment ofArray(byte[] byteArray) { + return HeapMemorySegmentImpl.OfByte.fromArray(byteArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated char array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given char array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param charArray the primitive array backing the heap segment. + * @return a heap memory segment backed by a char array. */ - static MemorySegment ofArray(char[] arr) { - return HeapMemorySegmentImpl.OfChar.fromArray(arr); + static MemorySegment ofArray(char[] charArray) { + return HeapMemorySegmentImpl.OfChar.fromArray(charArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated short array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given short array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param shortArray the primitive array backing the heap segment. + * @return a heap memory segment backed by a short array. */ - static MemorySegment ofArray(short[] arr) { - return HeapMemorySegmentImpl.OfShort.fromArray(arr); + static MemorySegment ofArray(short[] shortArray) { + return HeapMemorySegmentImpl.OfShort.fromArray(shortArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated int array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given int array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param intArray the primitive array backing the heap segment. + * @return a heap memory segment backed by an int array. */ - static MemorySegment ofArray(int[] arr) { - return HeapMemorySegmentImpl.OfInt.fromArray(arr); + static MemorySegment ofArray(int[] intArray) { + return HeapMemorySegmentImpl.OfInt.fromArray(intArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated float array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given float array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param floatArray the primitive array backing the heap segment. + * @return a heap memory segment backed by a float array. */ - static MemorySegment ofArray(float[] arr) { - return HeapMemorySegmentImpl.OfFloat.fromArray(arr); + static MemorySegment ofArray(float[] floatArray) { + return HeapMemorySegmentImpl.OfFloat.fromArray(floatArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated long array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given long array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param longArray the primitive array backing the heap segment. + * @return a heap memory segment backed by a long array. */ - static MemorySegment ofArray(long[] arr) { - return HeapMemorySegmentImpl.OfLong.fromArray(arr); + static MemorySegment ofArray(long[] longArray) { + return HeapMemorySegmentImpl.OfLong.fromArray(longArray); } /** - * Creates an array memory segment that models the memory associated with the given heap-allocated double array. - * The returned segment is associated with the {@linkplain MemorySession#global() global} memory session. + * Creates a heap segment backed by the on-heap region of memory that holds the given double array. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}, and + * its {@link #address()} is set to zero. * - * @param arr the primitive array backing the array memory segment. - * @return an array memory segment. + * @param doubleArray the primitive array backing the heap segment. + * @return a heap memory segment backed by a double array. */ - static MemorySegment ofArray(double[] arr) { - return HeapMemorySegmentImpl.OfDouble.fromArray(arr); + static MemorySegment ofArray(double[] doubleArray) { + return HeapMemorySegmentImpl.OfDouble.fromArray(doubleArray); } + /** + * A zero-length native segment modelling the {@code NULL} address. + */ + MemorySegment NULL = NativeMemorySegmentImpl.makeNativeSegmentUnchecked(0L, 0); /** - * Creates a native memory segment with the given size, base address, and memory session. + * Creates a zero-length native segment from the given {@linkplain #address() address value}. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}. + *

    + * This is equivalent to the following code: + * {@snippet lang = java: + * ofAddress(address, 0); + *} + * @param address the address of the returned native segment. + * @return a zero-length native segment with the given address. + */ + static MemorySegment ofAddress(long address) { + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(address, 0); + } + + /** + * Creates a native segment with the given size and {@linkplain #address() address value}. + * The returned segment is associated with the {@linkplain SegmentScope#global() global scope}. + *

    + * This is equivalent to the following code: + * {@snippet lang = java: + * ofAddress(address, byteSize, SegmentScope.global()); + *} + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * @param address the address of the returned native segment. + * @param byteSize the size (in bytes) of the returned native segment. + * @return a zero-length native segment with the given address and size. + * @throws IllegalArgumentException if {@code byteSize < 0}. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + static MemorySegment ofAddress(long address, long byteSize) { + Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemorySegment.class, "ofAddress"); + return MemorySegment.ofAddress(address, byteSize, SegmentScope.global()); + } + + /** + * Creates a native segment with the given size, address, and scope. * This method can be useful when interacting with custom memory sources (e.g. custom allocators), - * where an address to some underlying memory region is typically obtained from foreign code + * where an address to some underlying region of memory is typically obtained from foreign code * (often as a plain {@code long} value). *

    * The returned segment is not read-only (see {@link MemorySegment#isReadOnly()}), and is associated with the - * provided memory session. + * provided scope. + *

    + * This is equivalent to the following code: + * {@snippet lang = java: + * ofAddress(address, byteSize, scope, null); + *} + * + * @param address the returned segment's address. + * @param byteSize the desired size. + * @param scope the scope associated with the returned native segment. + * @return a native segment with the given address, size and scope. + * @throws IllegalArgumentException if {@code byteSize < 0}. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. + * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option + * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or + * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + */ + @CallerSensitive + @ForceInline + static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope) { + Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemorySegment.class, "ofAddress"); + Objects.requireNonNull(scope); + Utils.checkAllocationSizeAndAlign(byteSize, 1); + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(address, byteSize, scope, null); + } + + /** + * Creates a native segment with the given size, address, and scope. + * This method can be useful when interacting with custom memory sources (e.g. custom allocators), + * where an address to some underlying region of memory is typically obtained from foreign code + * (often as a plain {@code long} value). + *

    + * The returned segment is not read-only (see {@link MemorySegment#isReadOnly()}), and is associated with the + * provided scope. + *

    + * The provided cleanup action (if any) will be invoked when the scope becomes not {@linkplain SegmentScope#isAlive() alive}. *

    * Clients should ensure that the address and bounds refer to a valid region of memory that is accessible for reading and, - * if appropriate, writing; an attempt to access an invalid memory location from Java code will either return an arbitrary value, + * if appropriate, writing; an attempt to access an invalid address from Java code will either return an arbitrary value, * have no visible effect, or cause an unspecified exception to be thrown. *

    * This method is restricted. @@ -872,97 +1131,127 @@ static MemorySegment ofArray(double[] arr) { * restricted methods, and use safe and supported functionalities, where possible. * * - * @param address the returned segment's base address. - * @param bytesSize the desired size. - * @param session the native segment memory session. - * @return a native memory segment with the given base address, size and memory session. - * @throws IllegalArgumentException if {@code bytesSize < 0}. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @param address the returned segment's address. + * @param byteSize the desired size. + * @param scope the scope associated with the returned native segment. + * @param cleanupAction the custom cleanup action to be associated to the returned segment (can be null). + * @return a native segment with the given address, size and scope. + * @throws IllegalArgumentException if {@code byteSize < 0}. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - static MemorySegment ofAddress(MemoryAddress address, long bytesSize, MemorySession session) { + static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope, Runnable cleanupAction) { Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemorySegment.class, "ofAddress"); - Objects.requireNonNull(address); - Objects.requireNonNull(session); - Utils.checkAllocationSizeAndAlign(bytesSize, 1); - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(address, bytesSize, session); + Objects.requireNonNull(scope); + Utils.checkAllocationSizeAndAlign(byteSize, 1); + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(address, byteSize, scope, cleanupAction); } /** - * Creates a native memory segment with the given layout and memory session. - * A client is responsible for ensuring that the memory session associated with the returned segment is closed - * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. + * Creates a native segment with the given layout and scope. + *

    + * The lifetime off-heap region of memory associated with the returned native segment is determined by the + * provided scope. The off-heap memory region is deallocated when the scope becomes not + * {@linkplain SegmentScope#isAlive() alive}. If the scope has been obtained using an {@link Arena}, + * clients are responsible for ensuring that the arena is closed when the returned segment is no longer in use + * Failure to do so will result in off-heap memory leaks. As an alternative, an {@linkplain SegmentScope#auto() automatic scope} + * can be used, allowing the off-heap memory region associated with the returned native segment to be + * automatically released some unspecified time after the scope is no longer referenced. + *

    + * The {@linkplain #address() address} of the returned memory segment is the starting address of + * the newly allocated off-heap region backing the segment. Moreover, the {@linkplain #address() address} + * of the returned segment will be aligned according to the alignment constraint of the provided layout. *

    * This is equivalent to the following code: * {@snippet lang=java : - * allocateNative(layout.bytesSize(), layout.bytesAlignment(), session); + * allocateNative(layout.bytesSize(), layout.bytesAlignment(), scope); * } *

    - * The block of off-heap memory associated with the returned native memory segment is initialized to zero. + * The region of off-heap region backing the returned native segment is initialized to zero. * - * @param layout the layout of the off-heap memory block backing the native memory segment. - * @param session the segment memory session. - * @return a new native memory segment. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @param layout the layout of the off-heap memory region backing the native segment. + * @param scope the scope associated with the returned native segment. + * @return a new native segment. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. */ - static MemorySegment allocateNative(MemoryLayout layout, MemorySession session) { - Objects.requireNonNull(session); + static MemorySegment allocateNative(MemoryLayout layout, SegmentScope scope) { Objects.requireNonNull(layout); - return allocateNative(layout.byteSize(), layout.byteAlignment(), session); + Objects.requireNonNull(scope); + return allocateNative(layout.byteSize(), layout.byteAlignment(), scope); } /** - * Creates a native memory segment with the given size (in bytes) and memory session. - * A client is responsible for ensuring that the memory session associated with the returned segment is closed - * when the segment is no longer in use. Failure to do so will result in off-heap memory leaks. + * Creates a native segment with the given size (in bytes) and scope. + *

    + * The lifetime off-heap region of memory associated with the returned native segment is determined by the + * provided scope. The off-heap memory region is deallocated when the scope becomes not + * {@linkplain SegmentScope#isAlive() alive}. If the scope has been obtained using an {@link Arena}, + * clients are responsible for ensuring that the arena is closed when the returned segment is no longer in use + * Failure to do so will result in off-heap memory leaks. As an alternative, an {@linkplain SegmentScope#auto() automatic scope} + * can be used, allowing the off-heap memory region associated with the returned native segment to be + * automatically released some unspecified time after the scope is no longer referenced. + *

    + * The {@linkplain #address() address} of the returned memory segment is the starting address of + * the newly allocated off-heap region backing the segment. Moreover, the {@linkplain #address() address} + * of the returned segment is guaranteed to be at least 1-byte aligned. *

    * This is equivalent to the following code: * {@snippet lang=java : - * allocateNative(bytesSize, 1, session); + * allocateNative(bytesSize, 1, scope); * } *

    - * The block of off-heap memory associated with the returned native memory segment is initialized to zero. + * The region of off-heap region backing the returned native segment is initialized to zero. * - * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment. - * @param session the segment temporal bounds. + * @param byteSize the size (in bytes) of the off-heap memory region of memory backing the native memory segment. + * @param scope the scope associated with the returned native segment. * @return a new native memory segment. - * @throws IllegalArgumentException if {@code bytesSize < 0}. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @throws IllegalArgumentException if {@code byteSize < 0}. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. */ - static MemorySegment allocateNative(long bytesSize, MemorySession session) { - return allocateNative(bytesSize, 1, session); + static MemorySegment allocateNative(long byteSize, SegmentScope scope) { + return allocateNative(byteSize, 1, scope); } /** - * Creates a native memory segment with the given size (in bytes), alignment constraint (in bytes) and memory session. - * A client is responsible for ensuring that the memory session associated with the returned segment is closed when the - * segment is no longer in use. Failure to do so will result in off-heap memory leaks. + * Creates a native segment with the given size (in bytes), alignment (in bytes) and scope. + *

    + * The lifetime off-heap region of memory associated with the returned native segment is determined by the + * provided scope. The off-heap memory region is deallocated when the scope becomes not + * {@linkplain SegmentScope#isAlive() alive}. If the scope has been obtained using an {@link Arena}, + * clients are responsible for ensuring that the arena is closed when the returned segment is no longer in use + * Failure to do so will result in off-heap memory leaks. As an alternative, an {@linkplain SegmentScope#auto() automatic scope} + * can be used, allowing the off-heap memory region associated with the returned native segment to be + * automatically released some unspecified time after the scope is no longer referenced. *

    - * The block of off-heap memory associated with the returned native memory segment is initialized to zero. + * The {@linkplain #address() address} of the returned memory segment is the starting address of + * the newly allocated off-heap region backing the segment. Moreover, the {@linkplain #address() address} + * of the returned segment will be aligned according to the provided alignment constraint. + *

    + * The region of off-heap region backing the returned native segment is initialized to zero. * - * @param bytesSize the size (in bytes) of the off-heap memory block backing the native memory segment. - * @param alignmentBytes the alignment constraint (in bytes) of the off-heap memory block backing the native memory segment. - * @param session the segment memory session. + * @param byteSize the size (in bytes) of the off-heap region of memory backing the native memory segment. + * @param byteAlignment the alignment constraint (in bytes) of the off-heap region of memory backing the native memory segment. + * @param scope the scope associated with the returned native segment. * @return a new native memory segment. - * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes <= 0}, or if {@code alignmentBytes} - * is not a power of 2. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. - */ - static MemorySegment allocateNative(long bytesSize, long alignmentBytes, MemorySession session) { - Objects.requireNonNull(session); - Utils.checkAllocationSizeAndAlign(bytesSize, alignmentBytes); - return NativeMemorySegmentImpl.makeNativeSegment(bytesSize, alignmentBytes, session); + * @throws IllegalArgumentException if {@code byteSize < 0}, {@code byteAlignment <= 0}, or if {@code byteAlignment} + * is not a power of 2. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. + */ + static MemorySegment allocateNative(long byteSize, long byteAlignment, SegmentScope scope) { + Objects.requireNonNull(scope); + Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment); + return NativeMemorySegmentImpl.makeNativeSegment(byteSize, byteAlignment, scope); } /** @@ -988,14 +1277,14 @@ static MemorySegment allocateNative(long bytesSize, long alignmentBytes, MemoryS * @param dstSegment the destination segment. * @param dstOffset the starting offset, in bytes, of the destination segment. * @param bytes the number of bytes to be copied. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code srcSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code srcSegment}. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code dstSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code dstSegment}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code srcSegment.scope().isAccessibleBy(T) == false}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code dstSegment.scope().isAccessibleBy(T) == false}. * @throws IndexOutOfBoundsException if {@code srcOffset + bytes > srcSegment.byteSize()} or if * {@code dstOffset + bytes > dstSegment.byteSize()}, or if either {@code srcOffset}, {@code dstOffset} * or {@code bytes} are {@code < 0}. @@ -1033,16 +1322,16 @@ static void copy(MemorySegment srcSegment, long srcOffset, MemorySegment dstSegm * @param dstOffset the starting offset, in bytes, of the destination segment. * @param elementCount the number of elements to be copied. * @throws IllegalArgumentException if the element layouts have different sizes, if the source (resp. destination) segment/offset are - * incompatible with the alignment constraints in the source + * incompatible with the alignment constraint in the source * (resp. destination) element layout, or if the source (resp. destination) element layout alignment is greater than its size. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code srcSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this {@code srcSegment}. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code dstSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code dstSegment}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code srcSegment().scope().isAccessibleBy(T) == false}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code dstSegment().scope().isAccessibleBy(T) == false}. * @throws IndexOutOfBoundsException if {@code srcOffset + (elementCount * S) > srcSegment.byteSize()} or if * {@code dstOffset + (elementCount * S) > dstSegment.byteSize()}, where {@code S} is the byte size * of the element layouts, or if either {@code srcOffset}, {@code dstOffset} or {@code elementCount} are {@code < 0}. @@ -1085,429 +1374,414 @@ static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long sr /** * Reads a byte from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a byte value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a byte value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default byte get(ValueLayout.OfByte layout, long offset) { - return (byte)layout.accessHandle().get(this, offset); + return (byte) ((ValueLayouts.OfByteImpl) layout).accessHandle().get(this, offset); } /** * Writes a byte into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the byte value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfByte layout, long offset, byte value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfByteImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a boolean from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a boolean value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a boolean value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default boolean get(ValueLayout.OfBoolean layout, long offset) { - return (boolean)layout.accessHandle().get(this, offset); + return (boolean) ((ValueLayouts.OfBooleanImpl) layout).accessHandle().get(this, offset); } /** * Writes a boolean into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the boolean value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfBoolean layout, long offset, boolean value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfBooleanImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a char from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a char value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a char value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default char get(ValueLayout.OfChar layout, long offset) { - return (char)layout.accessHandle().get(this, offset); + return (char) ((ValueLayouts.OfCharImpl) layout).accessHandle().get(this, offset); } /** * Writes a char into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the char value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfChar layout, long offset, char value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfCharImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a short from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a short value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a short value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default short get(ValueLayout.OfShort layout, long offset) { - return (short)layout.accessHandle().get(this, offset); + return (short) ((ValueLayouts.OfShortImpl) layout).accessHandle().get(this, offset); } /** * Writes a short into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the short value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfShort layout, long offset, short value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfShortImpl) layout).accessHandle().set(this, offset, value); } /** * Reads an int from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return an int value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return an int value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default int get(ValueLayout.OfInt layout, long offset) { - return (int)layout.accessHandle().get(this, offset); + return (int) ((ValueLayouts.OfIntImpl) layout).accessHandle().get(this, offset); } /** * Writes an int into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the int value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfInt layout, long offset, int value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfIntImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a float from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a float value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a float value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default float get(ValueLayout.OfFloat layout, long offset) { - return (float)layout.accessHandle().get(this, offset); + return (float)((ValueLayouts.OfFloatImpl) layout).accessHandle().get(this, offset); } /** * Writes a float into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the float value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfFloat layout, long offset, float value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfFloatImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a long from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a long value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a long value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default long get(ValueLayout.OfLong layout, long offset) { - return (long)layout.accessHandle().get(this, offset); + return (long) ((ValueLayouts.OfLongImpl) layout).accessHandle().get(this, offset); } /** * Writes a long into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the long value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfLong layout, long offset, long value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfLongImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a double from this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return a double value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a double value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default double get(ValueLayout.OfDouble layout, long offset) { - return (double)layout.accessHandle().get(this, offset); + return (double) ((ValueLayouts.OfDoubleImpl) layout).accessHandle().get(this, offset); } /** * Writes a double into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the double value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline default void set(ValueLayout.OfDouble layout, long offset, double value) { - layout.accessHandle().set(this, offset, value); + ((ValueLayouts.OfDoubleImpl) layout).accessHandle().set(this, offset, value); } /** - * Reads an address from this segment at the given offset, with the given layout. - * - * @param layout the layout of the memory region to be read. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + offset}. - * @return an address value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * Reads an address from this segment at the given offset, with the given layout. The read address is wrapped in + * a native segment, associated with the {@linkplain SegmentScope#global() global scope}. Under normal conditions, + * the size of the returned segment is {@code 0}. However, if the provided layout is an + * {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout, then the size of the returned + * segment is {@code Long.MAX_VALUE}. + * @param layout the layout of the region of memory to be read. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. + * @return a native segment wrapping an address read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline - default MemoryAddress get(ValueLayout.OfAddress layout, long offset) { - return (MemoryAddress)layout.accessHandle().get(this, offset); + default MemorySegment get(ValueLayout.OfAddress layout, long offset) { + return (MemorySegment) ((ValueLayouts.OfAddressImpl) layout).accessHandle().get(this, offset); } /** * Writes an address into this segment at the given offset, with the given layout. * - * @param layout the layout of the memory region to be written. - * @param offset offset in bytes (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + offset}. + * @param layout the layout of the region of memory to be written. + * @param offset offset in bytes (relative to this segment address) at which this access operation will occur. * @param value the address value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout. + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline - default void set(ValueLayout.OfAddress layout, long offset, Addressable value) { - layout.accessHandle().set(this, offset, value.address()); + default void set(ValueLayout.OfAddress layout, long offset, MemorySegment value) { + ((ValueLayouts.OfAddressImpl) layout).accessHandle().set(this, offset, value); } /** * Reads a char from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return a char value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a char value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default char getAtIndex(ValueLayout.OfChar layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (char)layout.accessHandle().get(this, index * layout.byteSize()); + return (char) ((ValueLayouts.OfCharImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes a char into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the char value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1515,48 +1789,48 @@ default char getAtIndex(ValueLayout.OfChar layout, long index) { default void setAtIndex(ValueLayout.OfChar layout, long index, char value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfCharImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Reads a short from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return a short value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a short value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default short getAtIndex(ValueLayout.OfShort layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (short)layout.accessHandle().get(this, index * layout.byteSize()); + return (short) ((ValueLayouts.OfShortImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes a short into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the short value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1564,48 +1838,48 @@ default short getAtIndex(ValueLayout.OfShort layout, long index) { default void setAtIndex(ValueLayout.OfShort layout, long index, short value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfShortImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Reads an int from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return an int value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return an int value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default int getAtIndex(ValueLayout.OfInt layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (int)layout.accessHandle().get(this, index * layout.byteSize()); + return (int) ((ValueLayouts.OfIntImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes an int into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the int value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1613,48 +1887,48 @@ default int getAtIndex(ValueLayout.OfInt layout, long index) { default void setAtIndex(ValueLayout.OfInt layout, long index, int value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfIntImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Reads a float from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return a float value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a float value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default float getAtIndex(ValueLayout.OfFloat layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (float)layout.accessHandle().get(this, index * layout.byteSize()); + return (float) ((ValueLayouts.OfFloatImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes a float into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the float value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1662,48 +1936,48 @@ default float getAtIndex(ValueLayout.OfFloat layout, long index) { default void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfFloatImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Reads a long from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return a long value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a long value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default long getAtIndex(ValueLayout.OfLong layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (long)layout.accessHandle().get(this, index * layout.byteSize()); + return (long) ((ValueLayouts.OfLongImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes a long into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the long value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1711,48 +1985,48 @@ default long getAtIndex(ValueLayout.OfLong layout, long index) { default void setAtIndex(ValueLayout.OfLong layout, long index, long value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfLongImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Reads a double from this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return a double value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a double value read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline default double getAtIndex(ValueLayout.OfDouble layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (double)layout.accessHandle().get(this, index * layout.byteSize()); + return (double) ((ValueLayouts.OfDoubleImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes a double into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the double value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @@ -1760,78 +2034,82 @@ default double getAtIndex(ValueLayout.OfDouble layout, long index) { default void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value); + ((ValueLayouts.OfDoubleImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** - * Reads an address from this segment at the given index, scaled by the given layout size. - * - * @param layout the layout of the memory region to be read. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this read operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. - * @return an address value read from this address. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * Reads an address from this segment at the given at the given index, scaled by the given layout size. The read address is wrapped in + * a native segment, associated with the {@linkplain SegmentScope#global() global scope}. Under normal conditions, + * the size of the returned segment is {@code 0}. However, if the provided layout is an + * {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} address layout, then the size of the returned + * segment is {@code Long.MAX_VALUE}. + * + * @param layout the layout of the region of memory to be read. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. + * @return a native segment wrapping an address read from this segment. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. */ @ForceInline - default MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { + default MemorySegment getAtIndex(ValueLayout.OfAddress layout, long index) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - return (MemoryAddress)layout.accessHandle().get(this, index * layout.byteSize()); + return (MemorySegment) ((ValueLayouts.OfAddressImpl) layout).accessHandle().get(this, index * layout.byteSize()); } /** * Writes an address into this segment at the given index, scaled by the given layout size. * - * @param layout the layout of the memory region to be written. - * @param index index (relative to this segment). For instance, if this segment is a {@linkplain #isNative() native} segment, - * the final address of this write operation can be expressed as {@code address().toRawLongValue() + (index * layout.byteSize())}. + * @param layout the layout of the region of memory to be written. + * @param index a logical index. The offset in bytes (relative to this segment address) at which the access operation + * will occur can be expressed as {@code (index * layout.byteSize())}. * @param value the address value to be written. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this segment is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this segment. - * @throws IllegalArgumentException if the dereference operation is - * incompatible with the alignment constraints in the provided layout, + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with this segment is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope().isAccessibleBy(T) == false}. + * @throws IllegalArgumentException if the access operation is + * incompatible with the alignment constraint in the provided layout, * or if the layout alignment is greater than its size. - * @throws IndexOutOfBoundsException when the dereference operation falls outside the spatial bounds of the + * @throws IndexOutOfBoundsException when the access operation falls outside the spatial bounds of the * memory segment. * @throws UnsupportedOperationException if this segment is {@linkplain #isReadOnly() read-only}. */ @ForceInline - default void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { + default void setAtIndex(ValueLayout.OfAddress layout, long index, MemorySegment value) { Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); // note: we know size is a small value (as it comes from ValueLayout::byteSize()) - layout.accessHandle().set(this, index * layout.byteSize(), value.address()); + ((ValueLayouts.OfAddressImpl) layout).accessHandle().set(this, index * layout.byteSize(), value); } /** * Compares the specified object with this memory segment for equality. Returns {@code true} if and only if the specified - * object is also a memory segment, and if that segment refers to the same memory region as this segment. More specifically, - * for two segments to be considered equals, all the following must be true: + * object is also a memory segment, and if the two segments refer to the same location, in some region of memory. + * More specifically, for two segments {@code s1} and {@code s2} to be considered equals, all the following must be true: *

      - *
    • the two segments must be of the same kind; either both are {@linkplain #isNative() native segments}, - * backed by off-heap memory, or both are backed by on-heap memory; - *
    • if the two segments are {@linkplain #isNative() native segments}, their {@link #address() base address} - * must be {@linkplain MemoryAddress#equals(Object) equal}. Otherwise, the two segments must wrap the - * same Java array instance, at the same starting offset;
    • - *
    • the two segments must have the same {@linkplain #byteSize() size}; and
    • - *
    • the two segments must have the {@linkplain MemorySession#equals(Object) same} {@linkplain #session() temporal bounds}. + *
    • {@code s1.array().equals(s2.array())}, that is, the two segments must be of the same kind; + * either both are {@linkplain #isNative() native segments}, backed by off-heap memory, or both are backed by + * the same on-heap Java array; + *
    • {@code s1.address() == s2.address()}, that is, the address of the two segments should be the same. + * This means that the two segments either refer to the same location in some off-heap region, or they refer + * to the same position inside their associated Java array instance.
    • *
    * @apiNote This method does not perform a structural comparison of the contents of the two memory segments. Clients can - * compare memory segments structurally by using the {@link #mismatch(MemorySegment)} method instead. + * compare memory segments structurally by using the {@link #mismatch(MemorySegment)} method instead. Note that this + * method does not compare the temporal and spatial bounds of two segments. As such it is suitable + * to perform address checks, such as checking if a native segment has the {@code NULL} address. * * @param that the object to be compared for equality with this memory segment. * @return {@code true} if the specified object is equal to this memory segment. * @see #mismatch(MemorySegment) - * @see #asOverlappingSlice(MemorySegment) */ @Override boolean equals(Object that); @@ -1855,13 +2133,13 @@ default void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable va * @param dstArray the destination array. * @param dstIndex the starting index of the destination array. * @param elementCount the number of array elements to be copied. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code srcSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code srcSegment}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code srcSegment().isAccessibleBy(T) == false}. * @throws IllegalArgumentException if {@code dstArray} is not an array, or if it is an array but whose type is not supported, * if the destination array component type does not match the carrier of the source element layout, if the source - * segment/offset are incompatible with the alignment constraints in the source element layout, + * segment/offset are incompatible with the alignment constraint in the source element layout, * or if the destination element layout alignment is greater than its size. */ @ForceInline @@ -1871,28 +2149,10 @@ static void copy( Objects.requireNonNull(srcSegment); Objects.requireNonNull(dstArray); Objects.requireNonNull(srcLayout); - long baseAndScale = getBaseAndScale(dstArray.getClass()); - if (dstArray.getClass().componentType() != srcLayout.carrier()) { - throw new IllegalArgumentException("Incompatible value layout: " + srcLayout); - } - int dstBase = (int)baseAndScale; - int dstWidth = (int)(baseAndScale >> 32); - AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; - Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size"); - if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) { - throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); - } - srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true); - Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray)); - if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) { - ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null, - srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, - dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth); - } else { - ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null, - srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, - dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth, dstWidth); - } + + AbstractMemorySegmentImpl.copy(srcSegment, srcLayout, srcOffset, + dstArray, dstIndex, + elementCount); } /** @@ -1907,13 +2167,13 @@ static void copy( * different from the {@linkplain ByteOrder#nativeOrder native order}, a byte swap operation will be performed on each array element. * @param dstOffset the starting offset, in bytes, of the destination segment. * @param elementCount the number of array elements to be copied. - * @throws IllegalStateException if the {@linkplain #session() session} associated with {@code dstSegment} is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with {@code dstSegment}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code dstSegment().isAccessibleBy(T) == false}. * @throws IllegalArgumentException if {@code srcArray} is not an array, or if it is an array but whose type is not supported, * if the source array component type does not match the carrier of the destination element layout, if the destination - * segment/offset are incompatible with the alignment constraints in the destination element layout, + * segment/offset are incompatible with the alignment constraint in the destination element layout, * or if the destination element layout alignment is greater than its size. */ @ForceInline @@ -1923,47 +2183,52 @@ static void copy( Objects.requireNonNull(srcArray); Objects.requireNonNull(dstSegment); Objects.requireNonNull(dstLayout); - long baseAndScale = getBaseAndScale(srcArray.getClass()); - if (srcArray.getClass().componentType() != dstLayout.carrier()) { - throw new IllegalArgumentException("Incompatible value layout: " + dstLayout); - } - int srcBase = (int)baseAndScale; - int srcWidth = (int)(baseAndScale >> 32); - Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray)); - AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment; - Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size"); - if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) { - throw new IllegalArgumentException("Destination segment incompatible with alignment constraints"); - } - destImpl.checkAccess(dstOffset, elementCount * srcWidth, false); - if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) { - ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(), - srcArray, srcBase + (srcIndex * srcWidth), - destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth); - } else { - ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(), - srcArray, srcBase + (srcIndex * srcWidth), - destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth); - } + + AbstractMemorySegmentImpl.copy(srcArray, srcIndex, + dstSegment, dstLayout, dstOffset, + elementCount); } - private static long getBaseAndScale(Class arrayType) { - if (arrayType.equals(byte[].class)) { - return (long)Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32); - } else if (arrayType.equals(char[].class)) { - return (long)Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32); - } else if (arrayType.equals(short[].class)) { - return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32); - } else if (arrayType.equals(int[].class)) { - return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32); - } else if (arrayType.equals(float[].class)) { - return (long)Unsafe.ARRAY_FLOAT_BASE_OFFSET | ((long)Unsafe.ARRAY_FLOAT_INDEX_SCALE << 32); - } else if (arrayType.equals(long[].class)) { - return (long)Unsafe.ARRAY_LONG_BASE_OFFSET | ((long)Unsafe.ARRAY_LONG_INDEX_SCALE << 32); - } else if (arrayType.equals(double[].class)) { - return (long)Unsafe.ARRAY_DOUBLE_BASE_OFFSET | ((long)Unsafe.ARRAY_DOUBLE_INDEX_SCALE << 32); - } else { - throw new IllegalArgumentException("Not a supported array class: " + arrayType.getSimpleName()); - } + /** + * Finds and returns the relative offset, in bytes, of the first mismatch between the source and the destination + * segments. More specifically, the bytes at offset {@code srcFromOffset} through {@code srcToOffset - 1} in the + * source segment are compared against the bytes at offset {@code dstFromOffset} through {@code dstToOffset - 1} + * in the destination segment. + *

    + * If the two segments, over the specified ranges, share a common prefix then the returned offset is the length + * of the common prefix, and it follows that there is a mismatch between the two segments at that relative offset + * within the respective segments. If one segment is a proper prefix of the other, over the specified ranges, + * then the returned offset is the smallest range, and it follows that the relative offset is only + * valid for the segment with the larger range. Otherwise, there is no mismatch and {@code -1} is returned. + * + * @param srcSegment the source segment. + * @param srcFromOffset the offset (inclusive) of the first byte in the source segment to be tested. + * @param srcToOffset the offset (exclusive) of the last byte in the source segment to be tested. + * @param dstSegment the destination segment. + * @param dstFromOffset the offset (inclusive) of the first byte in the destination segment to be tested. + * @param dstToOffset the offset (exclusive) of the last byte in the destination segment to be tested. + * @return the relative offset, in bytes, of the first mismatch between the source and destination segments, + * otherwise -1 if no mismatch. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code srcSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code srcSegment.scope().isAccessibleBy(T) == false}. + * @throws IllegalStateException if the {@linkplain #scope() scope} associated with {@code dstSegment} is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code dstSegment.scope().isAccessibleBy(T) == false}. + * @throws IndexOutOfBoundsException if {@code srcFromOffset < 0}, {@code srcToOffset < srcFromOffset} or + * {@code srcToOffset > srcSegment.byteSize()} + * @throws IndexOutOfBoundsException if {@code dstFromOffset < 0}, {@code dstToOffset < dstFromOffset} or + * {@code dstToOffset > dstSegment.byteSize()} + * + * @see MemorySegment#mismatch(MemorySegment) + * @see Arrays#mismatch(Object[], int, int, Object[], int, int) + */ + static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOffset, + MemorySegment dstSegment, long dstFromOffset, long dstToOffset) { + return AbstractMemorySegmentImpl.mismatch(srcSegment, srcFromOffset, srcToOffset, + dstSegment, dstFromOffset, dstToOffset); } + } diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySession.java b/src/java.base/share/classes/java/lang/foreign/MemorySession.java deleted file mode 100644 index c7f21293dfd..00000000000 --- a/src/java.base/share/classes/java/lang/foreign/MemorySession.java +++ /dev/null @@ -1,285 +0,0 @@ -/* - * Copyright (c) 2021, 2022, 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. - */ - -package java.lang.foreign; - -import java.lang.ref.Cleaner; -import java.util.Objects; - -import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.javac.PreviewFeature; - -/** - * A memory session manages the lifecycle of one or more resources. Resources (e.g. {@link MemorySegment}) associated - * with a memory session can only be accessed while the memory session is {@linkplain #isAlive() alive}, - * and by the {@linkplain #ownerThread() thread} associated with the memory session (if any). - *

    - * Memory sessions can be closed. When a memory session is closed, it is no longer {@linkplain #isAlive() alive}, - * and subsequent operations on resources associated with that session (e.g. attempting to access a {@link MemorySegment} instance) - * will fail with {@link IllegalStateException}. - *

    - * A memory session is associated with one or more {@linkplain #addCloseAction(Runnable) close actions}. Close actions - * can be used to specify the cleanup code that must run when a given resource (or set of resources) is no longer in use. - * When a memory session is closed, the {@linkplain #addCloseAction(Runnable) close actions} - * associated with that session are executed (in unspecified order). For instance, closing the memory session associated with - * one or more {@linkplain MemorySegment#allocateNative(long, long, MemorySession) native memory segments} results in releasing - * the off-heap memory associated with said segments. - *

    - * The {@linkplain #global() global session} is a memory session that cannot be closed. - * As a result, resources associated with the global session are never released. Examples of resources associated with - * the global memory session are {@linkplain MemorySegment#ofArray(int[]) heap segments}. - * - *

    Thread confinement

    - * - * Memory sessions can be divided into two categories: thread-confined memory sessions, and shared - * memory sessions. - *

    - * Confined memory sessions, support strong thread-confinement guarantees. Upon creation, - * they are assigned an {@linkplain #ownerThread() owner thread}, typically the thread which initiated the creation operation. - * After creating a confined memory session, only the owner thread will be allowed to directly manipulate the resources - * associated with this memory session. Any attempt to perform resource access from a thread other than the - * owner thread will fail with {@link WrongThreadException}. - *

    - * Shared memory sessions, on the other hand, have no owner thread; as such, resources associated with shared memory sessions - * can be accessed by multiple threads. This might be useful when multiple threads need to access the same resource concurrently - * (e.g. in the case of parallel processing). - * - *

    Closeable memory sessions

    - * - * When a session is associated with off-heap resources, it is often desirable for said resources to be released in a timely fashion, - * rather than waiting for the session to be deemed unreachable - * by the garbage collector. In this scenario, a client might consider using a {@linkplain #isCloseable() closeable} memory session. - * Closeable memory sessions are memory sessions that can be {@linkplain MemorySession#close() closed} deterministically, as demonstrated - * in the following example: - * - * {@snippet lang=java : - * try (MemorySession session = MemorySession.openConfined()) { - * MemorySegment segment1 = MemorySegment.allocateNative(100); - * MemorySegment segment1 = MemorySegment.allocateNative(200); - * ... - * } // all memory released here - * } - * - * The above code creates a confined, closeable session. Then it allocates two segments associated with that session. - * When the session is {@linkplain #close() closed} (above, this is done implicitly, using the try-with-resources construct), - * all memory allocated within the session will be released - *

    - * Closeable memory sessions, while powerful, must be used with caution. Closeable memory sessions must be closed - * when no longer in use, either explicitly (by calling the {@link #close} method), or implicitly (by wrapping the use of - * a closeable memory session in a try-with-resources construct). A failure to do so might result in memory leaks. - * To mitigate this problem, closeable memory sessions can be associated with a {@link Cleaner} instance, - * so that they are also closed automatically, once the session instance becomes unreachable. - * This can be useful to allow for predictable, deterministic resource deallocation, while still preventing accidental - * native memory leaks. In case a client closes a memory session managed by a cleaner, no further action will be taken when - * the session becomes unreachable; that is, {@linkplain #addCloseAction(Runnable) close actions} associated with a - * memory session, whether managed or not, are called exactly once. - * - *

    Non-closeable views

    - * - * There are situations in which it might not be desirable for a memory session to be reachable from one or - * more resources associated with it. For instance, an API might create a private memory session, and allocate - * a memory segment, and then expose one or more slices of this segment to its clients. Since the API's memory session - * would be reachable from the slices (using the {@link MemorySegment#session()} accessor), it might be possible for - * clients to compromise the API (e.g. by closing the session prematurely). To avoid leaking private memory sessions - * to untrusted clients, an API can instead return segments based on a non-closeable view of the session it created, as follows: - * - * {@snippet lang=java : - * MemorySession session = MemorySession.openConfined(); - * MemorySession nonCloseableSession = session.asNonCloseable(); - * MemorySegment segment = MemorySegment.allocateNative(100, nonCloseableSession); - * segment.session().close(); // throws - * session.close(); //ok - * } - * - * In other words, only the owner of the original {@code session} object can close the session. External clients can only - * access the non-closeable session, and have no access to the underlying API session. - * - * @implSpec - * Implementations of this interface are thread-safe. - * - * @see MemorySegment - * @see SymbolLookup - * @see Linker - * @see VaList - * - * @since 19 - */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed interface MemorySession extends AutoCloseable, SegmentAllocator permits MemorySessionImpl, MemorySessionImpl.NonCloseableView { - - /** - * {@return {@code true}, if this memory session is alive} - */ - boolean isAlive(); - - /** - * {@return {@code true}, if this session is a closeable memory session}. - */ - boolean isCloseable(); - - /** - * {@return the owner thread associated with this memory session, or {@code null} if this session is shared - * across multiple threads} - */ - Thread ownerThread(); - - /** - * Runs a critical action while this memory session is kept alive. - * @param action the action to be run. - */ - void whileAlive(Runnable action); - - /** - * Adds a custom cleanup action which will be executed when the memory session is closed. - * The order in which custom cleanup actions are invoked once the memory session is closed is unspecified. - * @apiNote The provided action should not keep a strong reference to this memory session, so that implicitly - * closed sessions can be handled correctly by a {@link Cleaner} instance. - * @param runnable the custom cleanup action to be associated with this memory session. - * @throws IllegalStateException if this memory session is not {@linkplain #isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain #ownerThread() owning} this memory session. - */ - void addCloseAction(Runnable runnable); - - /** - * Closes this memory session. If this operation completes without exceptions, this session - * will be marked as not alive, the {@linkplain #addCloseAction(Runnable) close actions} associated - * with this session will be executed, and all the resources associated with this session will be released. - * - * @apiNote This operation is not idempotent; that is, closing an already closed memory session always results in an - * exception being thrown. This reflects a deliberate design choice: memory session state transitions should be - * manifest in the client code; a failure in any of these transitions reveals a bug in the underlying application - * logic. - * - * @see MemorySession#isAlive() - * - * @throws IllegalStateException if this memory session is not {@linkplain #isAlive() alive}. - * @throws IllegalStateException if this session is {@linkplain #whileAlive(Runnable) kept alive} by another client. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain #ownerThread() owning} this memory session. - * @throws UnsupportedOperationException if this memory session is not {@linkplain #isCloseable() closeable}. - */ - void close(); - - /** - * Returns a non-closeable view of this memory session. If this session is {@linkplain #isCloseable() non-closeable}, - * this session is returned. Otherwise, this method returns a non-closeable view of this memory session. - * @apiNote a non-closeable view of a memory session {@code S} keeps {@code S} reachable. As such, {@code S} - * cannot be closed implicitly (e.g. by a {@link Cleaner}) as long as one or more non-closeable views of {@code S} - * are reachable. - * @return a non-closeable view of this memory session. - */ - MemorySession asNonCloseable(); - - /** - * Compares the specified object with this memory session for equality. Returns {@code true} if and only if the specified - * object is also a memory session, and it refers to the same memory session as this memory session. - * {@linkplain #asNonCloseable() A non-closeable view} {@code V} of a memory session {@code S} is considered - * equal to {@code S}. - * - * @param that the object to be compared for equality with this memory session. - * @return {@code true} if the specified object is equal to this memory session. - */ - @Override - boolean equals(Object that); - - /** - * {@return the hash code value for this memory session} - */ - @Override - int hashCode(); - - /** - * Allocates a native segment, using this session. Equivalent to the following code: - * {@snippet lang=java : - * MemorySegment.allocateNative(size, align, this); - * } - * - * @throws IllegalStateException if this memory session is not {@linkplain #isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain #ownerThread() owning} this memory session. - * @return a new native segment, associated with this session. - */ - @Override - default MemorySegment allocate(long bytesSize, long bytesAlignment) { - return MemorySegment.allocateNative(bytesSize, bytesAlignment, this); - } - - /** - * Creates a closeable confined memory session. - * @return a new closeable confined memory session. - */ - static MemorySession openConfined() { - return MemorySessionImpl.createConfined(Thread.currentThread(), null); - } - - /** - * Creates a closeable confined memory session, managed by the provided cleaner instance. - * @param cleaner the cleaner to be associated with the returned memory session. - * @return a new closeable confined memory session, managed by {@code cleaner}. - */ - static MemorySession openConfined(Cleaner cleaner) { - Objects.requireNonNull(cleaner); - return MemorySessionImpl.createConfined(Thread.currentThread(), cleaner); - } - - /** - * Creates a closeable shared memory session. - * @return a new closeable shared memory session. - */ - static MemorySession openShared() { - return MemorySessionImpl.createShared(null); - } - - /** - * Creates a closeable shared memory session, managed by the provided cleaner instance. - * @param cleaner the cleaner to be associated with the returned memory session. - * @return a new closeable shared memory session, managed by {@code cleaner}. - */ - static MemorySession openShared(Cleaner cleaner) { - Objects.requireNonNull(cleaner); - return MemorySessionImpl.createShared(cleaner); - } - - /** - * Creates a non-closeable shared memory session, managed by a private {@link Cleaner} instance. - * Equivalent to (but likely more efficient than) the following code: - * {@snippet lang=java : - * openShared(Cleaner.create()).asNonCloseable(); - * } - * @return a non-closeable shared memory session, managed by a private {@link Cleaner} instance. - */ - static MemorySession openImplicit() { - return MemorySessionImpl.createImplicit(); - } - - /** - * Returns the global memory session. - * @return the global memory session. - */ - static MemorySession global() { - return MemorySessionImpl.GLOBAL; - } -} diff --git a/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java b/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java index 0a21c804ad1..47848641edc 100644 --- a/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/PaddingLayout.java @@ -25,76 +25,30 @@ */ package java.lang.foreign; -import java.util.Objects; -import java.util.Optional; +import jdk.internal.foreign.layout.PaddingLayoutImpl; +import jdk.internal.javac.PreviewFeature; /** * A padding layout. A padding layout specifies the size of extra space which is typically not accessed by applications, * and is typically used for aligning member layouts around word boundaries. * * @implSpec - * This class is immutable, thread-safe and value-based. + * Implementing classes are immutable, thread-safe and value-based. + * + * @since 20 */ -/* package-private */ final class PaddingLayout extends AbstractLayout implements MemoryLayout { - - PaddingLayout(long size) { - this(size, 1, Optional.empty()); - } - - PaddingLayout(long size, long alignment, Optional name) { - super(size, alignment, name); - } - - @Override - public String toString() { - return decorateLayoutString("x" + bitSize()); - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!super.equals(other)) { - return false; - } - if (!(other instanceof PaddingLayout p)) { - return false; - } - return bitSize() == p.bitSize(); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), bitSize()); - } - - @Override - PaddingLayout dup(long alignment, Optional name) { - return new PaddingLayout(bitSize(), alignment, name); - } - - @Override - public boolean hasNaturalAlignment() { - return true; - } - - //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout - //but that causes issues with javadoc, see JDK-8224052 +@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) +public sealed interface PaddingLayout extends MemoryLayout permits PaddingLayoutImpl { /** * {@inheritDoc} */ @Override - public PaddingLayout withName(String name) { - return (PaddingLayout)super.withName(name); - } + PaddingLayout withName(String name); /** * {@inheritDoc} */ @Override - public PaddingLayout withBitAlignment(long alignmentBits) { - return (PaddingLayout)super.withBitAlignment(alignmentBits); - } + PaddingLayout withBitAlignment(long bitAlignment); } diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java index 57bd9e704da..e7a3c7efb5e 100644 --- a/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java +++ b/src/java.base/share/classes/java/lang/foreign/SegmentAllocator.java @@ -32,7 +32,8 @@ import java.util.Objects; import java.util.function.Function; import jdk.internal.foreign.AbstractMemorySegmentImpl; -import jdk.internal.foreign.ArenaAllocator; +import jdk.internal.foreign.MemorySessionImpl; +import jdk.internal.foreign.SlicingAllocator; import jdk.internal.foreign.Utils; import jdk.internal.javac.PreviewFeature; @@ -45,17 +46,17 @@ *

    * This interface also defines factories for commonly used allocators: *

      - *
    • {@link #newNativeArena(MemorySession)} creates a more efficient arena-style allocator, where off-heap memory - * is allocated in bigger blocks, which are then sliced accordingly to fit allocation requests;
    • - *
    • {@link #implicitAllocator()} obtains an allocator which allocates native memory segment in independent, - * {@linkplain MemorySession#openImplicit() implicit memory sessions}; and
    • + *
    • {@link #nativeAllocator(SegmentScope)} obtains a simple allocator which can + * be used to allocate native segments;
    • + *
    • {@link #slicingAllocator(MemorySegment)} obtains an efficient slicing allocator, where memory + * is allocated by repeatedly slicing the provided memory segment;
    • *
    • {@link #prefixAllocator(MemorySegment)} obtains an allocator which wraps a segment (either on-heap or off-heap) * and recycles its content upon each new allocation request.
    • *
    *

    * Passing a segment allocator to an API can be especially useful in circumstances where a client wants to communicate where * the results of a certain operation (performed by the API) should be stored, as a memory segment. For instance, - * {@linkplain Linker#downcallHandle(FunctionDescriptor) downcall method handles} can accept an additional + * {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handles} can accept an additional * {@link SegmentAllocator} parameter if the underlying foreign function is known to return a struct by-value. Effectively, * the allocator parameter tells the linker runtime where to store the return value of the foreign function. */ @@ -80,7 +81,7 @@ public interface SegmentAllocator { * @implSpec the default implementation for this method copies the contents of the provided Java string * into a new memory segment obtained by calling {@code this.allocate(str.length() + 1)}. * @param str the Java string to be converted into a C string. - * @return a new native memory segment containing the converted C string. + * @return a new native segment containing the converted C string. */ default MemorySegment allocateUtf8String(String str) { Objects.requireNonNull(str); @@ -200,11 +201,11 @@ default MemorySegment allocate(ValueLayout.OfDouble layout, double value) { * @param value the value to be set on the newly allocated memory block. * @return a segment for the newly allocated memory block. */ - default MemorySegment allocate(ValueLayout.OfAddress layout, Addressable value) { + default MemorySegment allocate(ValueLayout.OfAddress layout, MemorySegment value) { Objects.requireNonNull(value); Objects.requireNonNull(layout); MemorySegment segment = allocate(layout); - layout.varHandle().set(segment, value.address()); + layout.varHandle().set(segment, value); return segment; } @@ -287,10 +288,8 @@ default MemorySegment allocateArray(ValueLayout.OfDouble elementLayout, double.. private MemorySegment copyArrayWithSwapIfNeeded(Z array, ValueLayout elementLayout, Function heapSegmentFactory) { - Objects.requireNonNull(array); - Objects.requireNonNull(elementLayout); - int size = Array.getLength(array); - MemorySegment addr = allocateArray(elementLayout, size); + int size = Array.getLength(Objects.requireNonNull(array)); + MemorySegment addr = allocateArray(Objects.requireNonNull(elementLayout), size); if (size > 0) { MemorySegment.copy(heapSegmentFactory.apply(array), elementLayout, 0, addr, elementLayout.withOrder(ByteOrder.nativeOrder()), 0, size); @@ -327,105 +326,39 @@ default MemorySegment allocateArray(MemoryLayout elementLayout, long count) { /** * Allocates a memory segment with the given size. - * @implSpec the default implementation for this method calls {@code this.allocate(bytesSize, 1)}. - * @param bytesSize the size (in bytes) of the block of memory to be allocated. + * @implSpec the default implementation for this method calls {@code this.allocate(byteSize, 1)}. + * @param byteSize the size (in bytes) of the block of memory to be allocated. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code bytesSize < 0} + * @throws IllegalArgumentException if {@code byteSize < 0} */ - default MemorySegment allocate(long bytesSize) { - return allocate(bytesSize, 1); + default MemorySegment allocate(long byteSize) { + return allocate(byteSize, 1); } /** - * Allocates a memory segment with the given size and alignment constraints. - * @param bytesSize the size (in bytes) of the block of memory to be allocated. - * @param bytesAlignment the alignment (in bytes) of the block of memory to be allocated. + * Allocates a memory segment with the given size and alignment constraint. + * @param byteSize the size (in bytes) of the block of memory to be allocated. + * @param byteAlignment the alignment (in bytes) of the block of memory to be allocated. * @return a segment for the newly allocated memory block. - * @throws IllegalArgumentException if {@code bytesSize < 0}, {@code alignmentBytes <= 0}, + * @throws IllegalArgumentException if {@code byteSize < 0}, {@code byteAlignment <= 0}, * or if {@code alignmentBytes} is not a power of 2. */ - MemorySegment allocate(long bytesSize, long bytesAlignment); - - /** - * Creates an unbounded arena-based allocator used to allocate native memory segments. - * The returned allocator features a predefined block size and maximum arena size, and the segments it allocates - * are associated with the provided memory session. Equivalent to the following code: - * {@snippet lang=java : - * SegmentAllocator.newNativeArena(Long.MAX_VALUE, predefinedBlockSize, session); - * } - * - * @param session the memory session associated with the segments allocated by the arena-based allocator. - * @return a new unbounded arena-based allocator - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. - */ - static SegmentAllocator newNativeArena(MemorySession session) { - return newNativeArena(Long.MAX_VALUE, ArenaAllocator.DEFAULT_BLOCK_SIZE, session); - } - - /** - * Creates an arena-based allocator used to allocate native memory segments. - * The returned allocator features a block size set to the specified arena size, and the native segments - * it allocates are associated with the provided memory session. Equivalent to the following code: - * {@snippet lang=java : - * SegmentAllocator.newNativeArena(arenaSize, arenaSize, session); - * } - * - * @param arenaSize the size (in bytes) of the allocation arena. - * @param session the memory session associated with the segments allocated by the arena-based allocator. - * @return a new unbounded arena-based allocator - * @throws IllegalArgumentException if {@code arenaSize <= 0}. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. - */ - static SegmentAllocator newNativeArena(long arenaSize, MemorySession session) { - return newNativeArena(arenaSize, arenaSize, session); - } + MemorySegment allocate(long byteSize, long byteAlignment); /** - * Creates an arena-based allocator used to allocate native memory segments. The returned allocator features - * the given block size {@code B} and the given arena size {@code A}, and the native segments - * it allocates are associated with the provided memory session. + * Returns a segment allocator which responds to allocation requests by returning consecutive slices + * obtained from the provided segment. Each new allocation request will return a new slice starting at the + * current offset (modulo additional padding to satisfy alignment constraint), with given size. *

    - * The allocator arena is first initialized by {@linkplain MemorySegment#allocateNative(long, MemorySession) allocating} a - * native memory segment {@code S} of size {@code B}. The allocator then responds to allocation requests in one of the following ways: - *

      - *
    • if the size of the allocation requests is smaller than the size of {@code S}, and {@code S} has a free - * slice {@code S'} which fits that allocation request, return that {@code S'}. - *
    • if the size of the allocation requests is smaller than the size of {@code S}, and {@code S} has no free - * slices which fits that allocation request, allocate a new segment {@code S'}, with size {@code B}, - * and set {@code S = S'}; the allocator then tries to respond to the same allocation request again. - *
    • if the size of the allocation requests is bigger than the size of {@code S}, allocate a new segment {@code S'}, - * which has a sufficient size to satisfy the allocation request, and return {@code S'}. - *
    - *

    - * This segment allocator can be useful when clients want to perform multiple allocation requests while avoiding the - * cost associated with allocating a new off-heap memory region upon each allocation request. - *

    - * The returned allocator might throw an {@link OutOfMemoryError} if the total memory allocated with this allocator - * exceeds the arena size {@code A}, or the system capacity. Furthermore, the returned allocator is not thread safe. - * Concurrent allocation needs to be guarded with synchronization primitives. + * When the returned allocator cannot satisfy an allocation request, e.g. because a slice of the provided + * segment with the requested size cannot be found, an {@link IndexOutOfBoundsException} is thrown. * - * @param arenaSize the size (in bytes) of the allocation arena. - * @param blockSize the block size associated with the arena-based allocator. - * @param session the memory session associated with the segments returned by the arena-based allocator. - * @return a new unbounded arena-based allocator - * @throws IllegalArgumentException if {@code blockSize <= 0}, if {@code arenaSize <= 0} or if {@code arenaSize < blockSize}. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @param segment the segment which the returned allocator should slice from. + * @return a new slicing allocator */ - static SegmentAllocator newNativeArena(long arenaSize, long blockSize, MemorySession session) { - Objects.requireNonNull(session); - if (blockSize <= 0) { - throw new IllegalArgumentException("Invalid block size: " + blockSize); - } - if (arenaSize <= 0 || arenaSize < blockSize) { - throw new IllegalArgumentException("Invalid arena size: " + arenaSize); - } - return new ArenaAllocator(blockSize, arenaSize, session); + static SegmentAllocator slicingAllocator(MemorySegment segment) { + Objects.requireNonNull(segment); + return new SlicingAllocator(segment); } /** @@ -449,24 +382,33 @@ static SegmentAllocator newNativeArena(long arenaSize, long blockSize, MemorySes * @return an allocator which recycles an existing segment upon each new allocation request. */ static SegmentAllocator prefixAllocator(MemorySegment segment) { - Objects.requireNonNull(segment); - return (AbstractMemorySegmentImpl)segment; + return (AbstractMemorySegmentImpl)Objects.requireNonNull(segment); } /** - * Returns an allocator which allocates native segments in independent {@linkplain MemorySession#openImplicit() implicit memory sessions}. - * Equivalent to (but likely more efficient than) the following code: - * {@snippet lang=java : - * SegmentAllocator implicitAllocator = (size, align) -> MemorySegment.allocateNative(size, align, MemorySession.openImplicit()); + * Simple allocator used to allocate native segments. The returned allocator responds to an allocation request by + * returning a native segment backed by a fresh off-heap region of memory, with given byte size and alignment constraint. + *

    + * Each native segment obtained by the returned allocator is associated with the provided scope. As such, + * the off-heap region which backs the returned segment is freed when the scope becomes not + * {@linkplain SegmentScope#isAlive() alive}. + *

    + * The {@link MemorySegment#address()} of the native segments obtained by the returned allocator is the starting address of + * the newly allocated off-heap memory region backing the segment. Moreover, the {@linkplain MemorySegment#address() address} + * of the native segment will be aligned according the provided alignment constraint. + *

    + * The off-heap region of memory backing a native segment obtained by the returned allocator is initialized to zero. + *

    + * This is equivalent to the following code: + * {@snippet lang = java: + * SegmentAllocator nativeAllocator = (byteSize, byteAlignment) -> + * MemorySegment.allocateNative(byteSize, byteAlignment, scope); * } - * - * @return an allocator which allocates native segments in independent {@linkplain MemorySession#openImplicit() implicit memory sessions}. + * @param scope the scope associated with the segments returned by the native allocator. + * @return a simple allocator used to allocate native segments. */ - static SegmentAllocator implicitAllocator() { - class Holder { - static final SegmentAllocator IMPLICIT_ALLOCATOR = (size, align) -> - MemorySegment.allocateNative(size, align, MemorySession.openImplicit()); - } - return Holder.IMPLICIT_ALLOCATOR; + static SegmentAllocator nativeAllocator(SegmentScope scope) { + Objects.requireNonNull(scope); + return (MemorySessionImpl)scope; } } diff --git a/src/java.base/share/classes/java/lang/foreign/SegmentScope.java b/src/java.base/share/classes/java/lang/foreign/SegmentScope.java new file mode 100644 index 00000000000..a85dec0fb28 --- /dev/null +++ b/src/java.base/share/classes/java/lang/foreign/SegmentScope.java @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2022, 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. + * + */ +package java.lang.foreign; + +import jdk.internal.foreign.MemorySessionImpl; +import jdk.internal.javac.PreviewFeature; +import jdk.internal.ref.CleanerFactory; + +/** + * A segment scope controls access to memory segments. + *

    + * A memory segment can only be accessed while its scope is {@linkplain #isAlive() alive}. Moreover, + * depending on how the segment scope has been obtained, access might additionally be + * restricted to specific threads. + *

    + * The simplest segment scope is the {@linkplain SegmentScope#global() global scope}. The global scope + * is always alive. As a result, segments associated with the global scope are always accessible and their backing + * regions of memory are never deallocated. Moreover, memory segments associated with the global scope + * can be {@linkplain #isAccessibleBy(Thread) accessed} from any thread. + * {@snippet lang = java: + * MemorySegment segment = MemorySegment.allocateNative(100, SegmentScope.global()); + * ... + * // segment is never deallocated! + *} + *

    + * Alternatively, clients can obtain an {@linkplain SegmentScope#auto() automatic scope}, that is a segment + * scope that is managed, automatically, by the garbage collector. The regions of memory backing memory segments associated + * with an automatic scope are deallocated at some unspecified time after they become + * unreachable, as shown below: + * + * {@snippet lang = java: + * MemorySegment segment = MemorySegment.allocateNative(100, SegmentScope.auto()); + * ... + * segment = null; // the segment region becomes available for deallocation after this point + *} + * Memory segments associated with an automatic scope can also be {@linkplain #isAccessibleBy(Thread) accessed} from any thread. + *

    + * Finally, clients can obtain a segment scope from an existing {@linkplain Arena arena}, the arena scope. The regions of memory + * backing memory segments associated with an arena scope are deallocated when the arena is {@linkplain Arena#close() closed}. + * When this happens, the arena scope becomes not {@linkplain #isAlive() alive} and subsequent access operations on segments + * associated with the arena scope will fail {@link IllegalStateException}. + * + * {@snippet lang = java: + * MemorySegment segment = null; + * try (Arena arena = Arena.openConfined()) { + * segment = MemorySegment.allocateNative(100, arena.scope()); + * ... + * } // segment region deallocated here + * segment.get(ValueLayout.JAVA_BYTE, 0); // throws IllegalStateException + * } + * + * Which threads can {@link #isAccessibleBy(Thread) access} memory segments associated with an arena scope depends + * on the arena kind. For instance, segments associated with the scope of a {@linkplain Arena#openConfined() confined arena} + * can only be accessed by the thread that created the arena. Conversely, segments associated with the scope of + * {@linkplain Arena#openConfined() shared arena} can be accessed by any thread. + * + * @implSpec + * Implementations of this interface are thread-safe. + * + * @see Arena + * @see MemorySegment + * + * @since 20 + */ +@PreviewFeature(feature =PreviewFeature.Feature.FOREIGN) +sealed public interface SegmentScope permits MemorySessionImpl { + + /** + * Creates a new scope that is managed, automatically, by the garbage collector. + * Segments associated with the returned scope can be + * {@linkplain SegmentScope#isAccessibleBy(Thread) accessed} by any thread. + * + * @return a new scope that is managed, automatically, by the garbage collector. + */ + static SegmentScope auto() { + return MemorySessionImpl.createImplicit(CleanerFactory.cleaner()); + } + + /** + * Obtains the global scope. Segments associated with the global scope can be + * {@linkplain SegmentScope#isAccessibleBy(Thread) accessed} by any thread. + * + * @return the global scope. + */ + static SegmentScope global() { + return MemorySessionImpl.GLOBAL; + } + + /** + * {@return {@code true}, if this scope is alive} + */ + boolean isAlive(); + + /** + * {@return {@code true} if the provided thread can access and/or associate segments with this scope} + * @param thread the thread to be tested. + */ + boolean isAccessibleBy(Thread thread); + + /** + * Runs a critical action while this scope is kept alive. + * @param action the action to be run. + * @throws IllegalStateException if this scope is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code isAccessibleBy(T) == false}. + */ + void whileAlive(Runnable action); + +} diff --git a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java index d25ba35ead1..e73cac56851 100644 --- a/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/SequenceLayout.java @@ -25,9 +25,7 @@ */ package java.lang.foreign; -import java.util.Objects; -import java.util.Optional; - +import jdk.internal.foreign.layout.SequenceLayoutImpl; import jdk.internal.javac.PreviewFeature; /** @@ -55,46 +53,27 @@ * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public final class SequenceLayout extends AbstractLayout implements MemoryLayout { - - private final long elemCount; - private final MemoryLayout elementLayout; - - SequenceLayout(long elemCount, MemoryLayout elementLayout) { - this(elemCount, elementLayout, elementLayout.bitAlignment(), Optional.empty()); - } +public sealed interface SequenceLayout extends MemoryLayout permits SequenceLayoutImpl { - SequenceLayout(long elemCount, MemoryLayout elementLayout, long alignment, Optional name) { - super(Math.multiplyExact(elemCount, elementLayout.bitSize()), alignment, name); - this.elemCount = elemCount; - this.elementLayout = elementLayout; - } /** * {@return the element layout associated with this sequence layout} */ - public MemoryLayout elementLayout() { - return elementLayout; - } + MemoryLayout elementLayout(); /** * {@return the element count of this sequence layout} */ - public long elementCount() { - return elemCount; - } + long elementCount(); /** - * Returns a sequence layout with the same element layout, alignment constraints and name as this sequence layout, + * Returns a sequence layout with the same element layout, alignment constraint and name as this sequence layout, * but with the specified element count. * @param elementCount the new element count. * @return a sequence layout with the given element count. * @throws IllegalArgumentException if {@code elementCount < 0}. */ - public SequenceLayout withElementCount(long elementCount) { - AbstractLayout.checkSize(elementCount, true); - return new SequenceLayout(elementCount, elementLayout, alignment, name()); - } + SequenceLayout withElementCount(long elementCount); /** * Re-arrange the elements in this sequence layout into a multi-dimensional sequence layout. @@ -129,47 +108,7 @@ public SequenceLayout withElementCount(long elementCount) { * multiplying the element counts does not yield the same element count as the flattened projection of this * sequence layout. */ - public SequenceLayout reshape(long... elementCounts) { - Objects.requireNonNull(elementCounts); - if (elementCounts.length == 0) { - throw new IllegalArgumentException(); - } - SequenceLayout flat = flatten(); - long expectedCount = flat.elementCount(); - - long actualCount = 1; - int inferPosition = -1; - for (int i = 0 ; i < elementCounts.length ; i++) { - if (elementCounts[i] == -1) { - if (inferPosition == -1) { - inferPosition = i; - } else { - throw new IllegalArgumentException("Too many unspecified element counts"); - } - } else if (elementCounts[i] <= 0) { - throw new IllegalArgumentException("Invalid element count: " + elementCounts[i]); - } else { - actualCount = elementCounts[i] * actualCount; - } - } - - // infer an unspecified element count (if any) - if (inferPosition != -1) { - long inferredCount = expectedCount / actualCount; - elementCounts[inferPosition] = inferredCount; - actualCount = actualCount * inferredCount; - } - - if (actualCount != expectedCount) { - throw new IllegalArgumentException("Element counts do not match expected size: " + expectedCount); - } - - MemoryLayout res = flat.elementLayout(); - for (int i = elementCounts.length - 1 ; i >= 0 ; i--) { - res = MemoryLayout.sequenceLayout(elementCounts[i], res); - } - return (SequenceLayout)res; - } + SequenceLayout reshape(long... elementCounts); /** * Returns a flattened sequence layout. The element layout of the returned sequence layout @@ -187,66 +126,11 @@ public SequenceLayout reshape(long... elementCounts) { * @return a sequence layout with the same size as this layout (but, possibly, with different * element count), whose element layout is not a sequence layout. */ - public SequenceLayout flatten() { - long count = elementCount(); - MemoryLayout elemLayout = elementLayout(); - while (elemLayout instanceof SequenceLayout elemSeq) { - count = count * elemSeq.elementCount(); - elemLayout = elemSeq.elementLayout(); - } - return MemoryLayout.sequenceLayout(count, elemLayout); - } - - @Override - public String toString() { - return decorateLayoutString(String.format("[%s:%s]", - elemCount, elementLayout)); - } - - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!super.equals(other)) { - return false; - } - return other instanceof SequenceLayout otherSeq && - elemCount == otherSeq.elemCount && - elementLayout.equals(otherSeq.elementLayout); - } + SequenceLayout flatten(); @Override - public int hashCode() { - return Objects.hash(super.hashCode(), elemCount, elementLayout); - } + SequenceLayout withName(String name); @Override - SequenceLayout dup(long alignment, Optional name) { - return new SequenceLayout(elementCount(), elementLayout, alignment, name); - } - - @Override - boolean hasNaturalAlignment() { - return alignment == elementLayout.bitAlignment(); - } - - //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout - //but that causes issues with javadoc, see JDK-8224052 - - /** - * {@inheritDoc} - */ - @Override - public SequenceLayout withName(String name) { - return (SequenceLayout)super.withName(name); - } - - /** - * {@inheritDoc} - */ - @Override - public SequenceLayout withBitAlignment(long alignmentBits) { - return (SequenceLayout)super.withBitAlignment(alignmentBits); - } + SequenceLayout withBitAlignment(long bitAlignment); } diff --git a/src/java.base/share/classes/java/lang/foreign/StructLayout.java b/src/java.base/share/classes/java/lang/foreign/StructLayout.java new file mode 100644 index 00000000000..b94b6a97d85 --- /dev/null +++ b/src/java.base/share/classes/java/lang/foreign/StructLayout.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package java.lang.foreign; + +import jdk.internal.foreign.layout.StructLayoutImpl; +import jdk.internal.javac.PreviewFeature; + +/** + * A group layout whose member layouts are laid out one after the other. + * + * @implSpec + * Implementing classes are immutable, thread-safe and value-based. + * + * @since 20 + */ +@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) +public sealed interface StructLayout extends GroupLayout permits StructLayoutImpl { + + @Override + StructLayout withName(String name); + + @Override + StructLayout withBitAlignment(long bitAlignment); +} diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index c6fb83b61a9..50575f6b106 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -42,35 +42,35 @@ import java.util.function.BiFunction; /** - * A symbol lookup is an object that may be used to retrieve the address of a symbol in one or more libraries. + * A symbol lookup retrieves the address of a symbol in one or more libraries. * A symbol is a named entity, such as a function or a global variable. *

    - * A symbol lookup is created with respect to a particular library (or libraries). Subsequently, the {@link SymbolLookup#lookup(String)} + * A symbol lookup is created with respect to a particular library (or libraries). Subsequently, the {@link SymbolLookup#find(String)} * method takes the name of a symbol and returns the address of the symbol in that library. *

    * The address of a symbol is modelled as a zero-length {@linkplain MemorySegment memory segment}. The segment can be used in different ways: *

      - *
    • It can be passed to a {@link Linker} to create a downcall method handle, which can then be used to call the foreign function at the segment's base address.
    • - *
    • It can be passed to an existing {@linkplain Linker#downcallHandle(FunctionDescriptor) downcall method handle}, as an argument to the underlying foreign function.
    • - *
    • It can be {@linkplain MemorySegment#set(ValueLayout.OfAddress, long, Addressable) stored} inside another memory segment.
    • - *
    • It can be used to dereference memory associated with a global variable (this might require - * {@link MemorySegment#ofAddress(MemoryAddress, long, MemorySession) resizing} the segment first).
    • + *
    • It can be passed to a {@link Linker} to create a downcall method handle, which can then be used to call the foreign function at the segment's address.
    • + *
    • It can be passed to an existing {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handle}, as an argument to the underlying foreign function.
    • + *
    • It can be {@linkplain MemorySegment#set(ValueLayout.OfAddress, long, MemorySegment) stored} inside another memory segment.
    • + *
    • It can be used to access the region of memory backing a global variable (this might require + * {@link MemorySegment#ofAddress(long, long, SegmentScope) resizing} the segment first).
    • *
    * *

    Obtaining a symbol lookup

    * - * The factory methods {@link #libraryLookup(String, MemorySession)} and {@link #libraryLookup(Path, MemorySession)} + * The factory methods {@link #libraryLookup(String, SegmentScope)} and {@link #libraryLookup(Path, SegmentScope)} * create a symbol lookup for a library known to the operating system. The library is specified by either its name or a path. * The library is loaded if not already loaded. The symbol lookup, which is known as a library lookup, is associated - * with a {@linkplain MemorySession memory session}; when the session is {@linkplain MemorySession#close() closed}, the library is unloaded: + * with a {@linkplain SegmentScope scope}; when the scope becomes not {@link SegmentScope#isAlive()}, the library is unloaded: * - * {@snippet lang=java : - * try (MemorySession session = MemorySession.openConfined()) { - * SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so"); // libGL.so loaded here - * MemorySegment glGetString = libGL.lookup("glGetString").orElseThrow(); + * {@snippet lang = java: + * try (Arena arena = Arena.openConfined()) { + * SymbolLookup libGL = SymbolLookup.libraryLookup("libGL.so", arena.scope()); // libGL.so loaded here + * MemorySegment glGetString = libGL.find("glGetString").orElseThrow(); * ... * } // libGL.so unloaded here - * } + *} *

    * If a library was previously loaded through JNI, i.e., by {@link System#load(String)} * or {@link System#loadLibrary(String)}, then the library was also associated with a particular class loader. The factory @@ -80,7 +80,7 @@ * System.loadLibrary("GL"); // libGL.so loaded here * ... * SymbolLookup libGL = SymbolLookup.loaderLookup(); - * MemorySegment glGetString = libGL.lookup("glGetString").orElseThrow(); + * MemorySegment glGetString = libGL.find("glGetString").orElseThrow(); * } * * This symbol lookup, which is known as a loader lookup, is dynamic with respect to the libraries associated @@ -91,18 +91,18 @@ * by {@link System#load(String)} or {@link System#loadLibrary(String)}. A loader lookup does not expose symbols in libraries * that were loaded in the course of creating a library lookup: * - * {@snippet lang=java : - * libraryLookup("libGL.so", session).lookup("glGetString").isPresent(); // true - * loaderLookup().lookup("glGetString").isPresent(); // false - * } + * {@snippet lang = java: + * libraryLookup("libGL.so", scope).find("glGetString").isPresent(); // true + * loaderLookup().find("glGetString").isPresent(); // false + *} * * Note also that a library lookup for library {@code L} exposes symbols in {@code L} even if {@code L} was previously loaded * through JNI (the association with a class loader is immaterial to the library lookup): * - * {@snippet lang=java : + * {@snippet lang = java: * System.loadLibrary("GL"); // libGL.so loaded here - * libraryLookup("libGL.so", session).lookup("glGetString").isPresent(); // true - * } + * libraryLookup("libGL.so", scope).find("glGetString").isPresent(); // true + *} * *

    * Finally, each {@link Linker} provides a symbol lookup for libraries that are commonly used on the OS and processor @@ -110,11 +110,11 @@ * helps clients to quickly find addresses of well-known symbols. For example, a {@link Linker} for Linux/x64 might choose to * expose symbols in {@code libc} through the default lookup: * - * {@snippet lang=java : + * {@snippet lang = java: * Linker nativeLinker = Linker.nativeLinker(); * SymbolLookup stdlib = nativeLinker.defaultLookup(); - * MemorySegment malloc = stdlib.lookup("malloc").orElseThrow(); - * } + * MemorySegment malloc = stdlib.find("malloc").orElseThrow(); + *} */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) @FunctionalInterface @@ -123,9 +123,9 @@ public interface SymbolLookup { /** * Returns the address of the symbol with the given name. * @param name the symbol name. - * @return a zero-length memory segment whose base address indicates the address of the symbol, if found. + * @return a zero-length memory segment whose address indicates the address of the symbol, if found. */ - Optional lookup(String name); + Optional find(String name); /** * Returns a symbol lookup for symbols in the libraries associated with the caller's class loader. @@ -139,8 +139,8 @@ public interface SymbolLookup { *

    * Libraries associated with a class loader are unloaded when the class loader becomes * unreachable. The symbol lookup - * returned by this method is backed by a {@linkplain MemorySession#asNonCloseable() non-closeable}, shared memory - * session which keeps the caller's class loader reachable. Therefore, libraries associated with the caller's class + * returned by this method is backed by a scope that is always alive and which keeps the caller's + * class loader reachable. Therefore, libraries associated with the caller's class * loader are kept loaded (and their symbols available) as long as a loader lookup for that class loader is reachable. *

    * In cases where this method is called from a context where there is no caller frame on the stack @@ -158,24 +158,24 @@ static SymbolLookup loaderLookup() { ClassLoader loader = caller != null ? caller.getClassLoader() : ClassLoader.getSystemClassLoader(); - MemorySession loaderSession = (loader == null || loader instanceof BuiltinClassLoader) ? - MemorySession.global() : // builtin loaders never go away + SegmentScope loaderScope = (loader == null || loader instanceof BuiltinClassLoader) ? + SegmentScope.global() : // builtin loaders never go away MemorySessionImpl.heapSession(loader); return name -> { Objects.requireNonNull(name); JavaLangAccess javaLangAccess = SharedSecrets.getJavaLangAccess(); // note: ClassLoader::findNative supports a null loader - MemoryAddress addr = MemoryAddress.ofLong(javaLangAccess.findNative(loader, name)); - return addr == MemoryAddress.NULL ? + long addr = javaLangAccess.findNative(loader, name); + return addr == 0L ? Optional.empty() : - Optional.of(MemorySegment.ofAddress(addr, 0L, loaderSession)); + Optional.of(MemorySegment.ofAddress(addr, 0L, loaderScope)); }; } /** * Loads a library with the given name (if not already loaded) and creates a symbol lookup for symbols in that library. - * The library will be unloaded when the provided memory session is {@linkplain MemorySession#close() closed}, - * if no other library lookup is still using it. + * The library will be unloaded when the provided scope becomes + * not {@linkplain SegmentScope#isAlive() alive}, if no other library lookup is still using it. * @implNote The process of resolving a library name is OS-specific. For instance, in a POSIX-compliant OS, * the library name is resolved according to the specification of the {@code dlopen} function for that OS. * In Windows, the library name is resolved according to the specification of the {@code LoadLibrary} function. @@ -186,7 +186,7 @@ static SymbolLookup loaderLookup() { * restricted methods, and use safe and supported functionalities, where possible. * * @param name the name of the library in which symbols should be looked up. - * @param session the memory session which controls the library lifecycle. + * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given name. * @throws IllegalArgumentException if {@code name} does not identify a valid library. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option @@ -194,15 +194,15 @@ static SymbolLookup loaderLookup() { * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - static SymbolLookup libraryLookup(String name, MemorySession session) { + static SymbolLookup libraryLookup(String name, SegmentScope scope) { Reflection.ensureNativeAccess(Reflection.getCallerClass(), SymbolLookup.class, "libraryLookup"); - return libraryLookup(name, RawNativeLibraries::load, session); + return libraryLookup(name, RawNativeLibraries::load, scope); } /** * Loads a library from the given path (if not already loaded) and creates a symbol lookup for symbols - * in that library. The library will be unloaded when the provided memory session is {@linkplain MemorySession#close() closed}, - * if no other library lookup is still using it. + * in that library. The library will be unloaded when the provided scope becomes + * not {@linkplain SegmentScope#isAlive() alive}, if no other library lookup is still using it. *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash @@ -212,7 +212,7 @@ static SymbolLookup libraryLookup(String name, MemorySession session) { * @implNote On Linux, the functionalities provided by this factory method and the returned symbol lookup are * implemented using the {@code dlopen}, {@code dlsym} and {@code dlclose} functions. * @param path the path of the library in which symbols should be looked up. - * @param session the memory session which controls the library lifecycle. + * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given path. * @throws IllegalArgumentException if {@code path} does not point to a valid library. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option @@ -220,22 +220,22 @@ static SymbolLookup libraryLookup(String name, MemorySession session) { * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - static SymbolLookup libraryLookup(Path path, MemorySession session) { + static SymbolLookup libraryLookup(Path path, SegmentScope scope) { Reflection.ensureNativeAccess(Reflection.getCallerClass(), SymbolLookup.class, "libraryLookup"); - return libraryLookup(path, RawNativeLibraries::load, session); + return libraryLookup(path, RawNativeLibraries::load, scope); } - private static SymbolLookup libraryLookup(Z libDesc, BiFunction loadLibraryFunc, MemorySession session) { + private static SymbolLookup libraryLookup(Z libDesc, BiFunction loadLibraryFunc, SegmentScope libScope) { Objects.requireNonNull(libDesc); - Objects.requireNonNull(session); + Objects.requireNonNull(libScope); // attempt to load native library from path or name RawNativeLibraries nativeLibraries = RawNativeLibraries.newInstance(MethodHandles.lookup()); NativeLibrary library = loadLibraryFunc.apply(nativeLibraries, libDesc); if (library == null) { throw new IllegalArgumentException("Cannot open library: " + libDesc); } - // register hook to unload library when session is closed - MemorySessionImpl.toSessionImpl(session).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { + // register hook to unload library when 'libScope' becomes not alive + ((MemorySessionImpl) libScope).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { @Override public void cleanup() { nativeLibraries.unload(library); @@ -243,10 +243,10 @@ public void cleanup() { }); return name -> { Objects.requireNonNull(name); - MemoryAddress addr = MemoryAddress.ofLong(library.find(name)); - return addr == MemoryAddress.NULL - ? Optional.empty() : - Optional.of(MemorySegment.ofAddress(addr, 0L, session)); + long addr = library.find(name); + return addr == 0L ? + Optional.empty() : + Optional.of(MemorySegment.ofAddress(addr, 0, libScope)); }; } } diff --git a/src/java.base/share/classes/java/lang/foreign/UnionLayout.java b/src/java.base/share/classes/java/lang/foreign/UnionLayout.java new file mode 100644 index 00000000000..155f47bb4df --- /dev/null +++ b/src/java.base/share/classes/java/lang/foreign/UnionLayout.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package java.lang.foreign; + +import jdk.internal.foreign.layout.UnionLayoutImpl; +import jdk.internal.javac.PreviewFeature; + +/** + * A group layout whose member layouts are laid out at the same starting offset. + * + * @implSpec + * Implementing classes are immutable, thread-safe and value-based. + * + * @since 20 + */ +@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) +public sealed interface UnionLayout extends GroupLayout permits UnionLayoutImpl { + + /** + * {@inheritDoc} + */ + @Override + UnionLayout withName(String name); + + /** + * {@inheritDoc} + */ + @Override + UnionLayout withBitAlignment(long bitAlignment); +} diff --git a/src/java.base/share/classes/java/lang/foreign/VaList.java b/src/java.base/share/classes/java/lang/foreign/VaList.java index 872031dcc68..0f6dd9fef47 100644 --- a/src/java.base/share/classes/java/lang/foreign/VaList.java +++ b/src/java.base/share/classes/java/lang/foreign/VaList.java @@ -39,10 +39,40 @@ import jdk.internal.reflect.Reflection; /** - * A variable argument list, similar in functionality to a C {@code va_list}. + * Helper class to create and manipulate variable argument lists, similar in functionality to a C {@code va_list}. *

    - * A variable argument list is a stateful cursor used to iterate over a set of arguments. A variable argument list - * can be passed by reference e.g. to a {@linkplain Linker#downcallHandle(FunctionDescriptor) downcall method handle}. + * A variable argument list can be created using the {@link #make(Consumer, SegmentScope)} factory, as follows: + * {@snippet lang = java: + * VaList vaList = VaList.make(builder -> + * builder.addVarg(C_INT, 42) + * .addVarg(C_DOUBLE, 3.8d)); + *} + * Once created, clients can obtain the platform-dependent {@linkplain #segment() memory segment} associated with a variable + * argument list, which can then be passed to {@linkplain Linker#downcallHandle(FunctionDescriptor, Linker.Option...) downcall method handles} + * targeting native functions using the C {@code va_list} type. + *

    + * The contents of a foreign memory segment modelling a variable argument list can be accessed by unsafely creating + * a variable argument list, as follows: + * {@snippet lang = java: + * void upcall(int n, MemorySegment vaListSegment) { + * try (Arena arena = Arena.openConfined()) { + * VaList vaList = VaList.ofAddress(vaListSegment.address(), arena.scope()); + * VaList copy = vaList.copy(); + * int i = vaList.nextVarg(C_INT); + * double d = vaList.nextVarg(C_DOUBLE); + * // and again + * int i = copy.nextVarg(C_INT); + * double d = copy.nextVarg(C_DOUBLE); + * } + * } + *} + * The above method receives a foreign segment modelling a variable argument list; the contents of the segment are accessed by creating + * a new variable argument list, from the segment address. Note that the variable argument list is first copied into + * a second list before any element is accessed: this will allow us to iterate through the elements twice. Elements in + * the variable argument list are accessed using {@link #nextVarg(ValueLayout.OfInt)} and + * {@link #nextVarg(ValueLayout.OfDouble)}. These methods (as well as other access methods in the {@link VaList} class) + * take the layout of the element that needs to be accessed and perform all the necessary alignment checks as well + * as endianness conversions. *

    * Per the C specification (see C99 standard 6.5.2.2 Function calls - item 6), * arguments to variadic calls are erased by way of 'default argument promotions', @@ -64,22 +94,17 @@ *

    * Whether this detection succeeds depends on the factory method used to create the variable argument list: *

      - *
    • Variable argument lists created safely, using {@link #make(Consumer, MemorySession)} are capable of detecting out-of-bounds reads;
    • - *
    • Variable argument lists created unsafely, using {@link #ofAddress(MemoryAddress, MemorySession)} are not capable of detecting out-of-bounds reads
    • + *
    • Variable argument lists created safely, using {@link #make(Consumer, SegmentScope)} are capable of detecting out-of-bounds reads;
    • + *
    • Variable argument lists created unsafely, using {@link #ofAddress(long, SegmentScope)} are not capable of detecting out-of-bounds reads
    • *
    *

    * This class is not thread safe, and all accesses should occur within a single thread - * (regardless of the memory session associated with the variable arity list). + * (regardless of the scope used to obtain the variable arity list). * * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -sealed public interface VaList extends Addressable permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList { - - /** - * {@return the memory session associated with this variable argument list} - */ - MemorySession session(); +public sealed interface VaList permits WinVaList, SysVVaList, LinuxAArch64VaList, MacOsAArch64VaList, SharedUtils.EmptyVaList { /** * Reads the next value as an {@code int} and advances this variable argument list's position. The behavior of this @@ -87,10 +112,10 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * * @param layout the layout of the value to be read. * @return the {@code int} value read from this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ int nextVarg(ValueLayout.OfInt layout); @@ -101,10 +126,10 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * * @param layout the layout of the value to be read. * @return the {@code long} value read from this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ long nextVarg(ValueLayout.OfLong layout); @@ -115,32 +140,37 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * * @param layout the layout of the value * @return the {@code double} value read from this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ double nextVarg(ValueLayout.OfDouble layout); /** - * Reads the next value as a {@code MemoryAddress} and advances this variable argument list's position. The behavior of this - * method is equivalent to the C {@code va_arg} function. + * Reads the next address value, wraps it into a native segment, and advances this variable argument list's position. + * The behavior of this method is equivalent to the C {@code va_arg} function. The returned segment's base + * {@linkplain MemorySegment#address()} is set to the value read from the variable argument list, and the segment + * is associated with the {@linkplain SegmentScope#global() global scope}. Under normal conditions, the size of the returned + * segment is {@code 0}. However, if the provided layout is an {@linkplain ValueLayout.OfAddress#asUnbounded() unbounded} + * address layout, then the size of the returned segment is {@code Long.MAX_VALUE}. * * @param layout the layout of the value to be read. - * @return the {@code MemoryAddress} value read from this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @return a native segment whose {@linkplain MemorySegment#address() address} is the value read from + * this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ - MemoryAddress nextVarg(ValueLayout.OfAddress layout); + MemorySegment nextVarg(ValueLayout.OfAddress layout); /** - * Reads the next value as a {@code MemorySegment}, and advances this variable argument list's position. The behavior of this - * method is equivalent to the C {@code va_arg} function. The provided group layout must correspond to a C struct or union - * type. + * Reads the next composite value into a new {@code MemorySegment}, allocated with the provided allocator, + * and advances this variable argument list's position. The behavior of this method is equivalent to the C + * {@code va_arg} function. The provided group layout must correspond to a C struct or union type. *

    * How the value is read in the returned segment is ABI-dependent: calling this method on a group layout * with member layouts {@code L_1, L_2, ... L_n} is not guaranteed to be semantically equivalent to perform distinct @@ -152,10 +182,10 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * @param allocator the allocator to be used to create a segment where the contents of the variable argument list * will be copied. * @return the {@code MemorySegment} value read from this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ MemorySegment nextVarg(GroupLayout layout, SegmentAllocator allocator); @@ -164,17 +194,17 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * Skips a number of elements with the given memory layouts, and advances this variable argument list's position. * * @param layouts the layouts of the values to be skipped. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. * @throws NoSuchElementException if an out-of-bounds read is detected. */ void skip(MemoryLayout... layouts); /** * Copies this variable argument list at its current position into a new variable argument list associated - * with the same memory session as this variable argument list. The behavior of this method is equivalent to the C + * with the same scope as this variable argument list. The behavior of this method is equivalent to the C * {@code va_copy} function. *

    * Copying is useful to traverse the variable argument list elements, starting from the current position, @@ -182,59 +212,57 @@ sealed public interface VaList extends Addressable permits WinVaList, SysVVaList * traversed multiple times. * * @return a copy of this variable argument list. - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * @throws IllegalStateException if the scope associated with this variable argument list is not + * {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code segment().scope().isAccessibleBy(T) == false}. */ VaList copy(); /** - * {@return the {@linkplain MemoryAddress memory address} associated with this variable argument list} - * @throws IllegalStateException if the {@linkplain #session() session} associated with this variable argument list is not - * {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread owning - * the {@linkplain #session() session} associated with this variable argument list. + * Returns a zero-length {@linkplain MemorySegment memory segment} associated with this variable argument list. + * The contents of the returned memory segment are platform-dependent. Whether and how the contents of + * the returned segment are updated when iterating the contents of a variable argument list is also + * platform-dependent. + * @return a zero-length {@linkplain MemorySegment memory segment} associated with this variable argument list. */ - @Override - MemoryAddress address(); + MemorySegment segment(); /** - * Creates a variable argument list from a memory address pointing to an existing variable argument list, - * with the given memory session. + * Creates a variable argument list from the give address value and scope. The address is typically obtained + * by calling {@link MemorySegment#address()} on a foreign memory segment instance. The provided scope determines + * the lifecycle of the returned variable argument list: the returned variable argument list will no longer be accessible, + * and its associated off-heap memory region will be deallocated when the scope becomes not + * {@linkplain SegmentScope#isAlive() alive}. *

    * This method is restricted. * Restricted methods are unsafe, and, if used incorrectly, their use might crash * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on * restricted methods, and use safe and supported functionalities, where possible. * - * @implNote variable argument lists created using this method can not detect out-of-bounds reads. - * - * @param address a memory address pointing to an existing variable argument list. - * @param session the memory session to be associated with the returned variable argument list. - * @return a new variable argument list backed by the memory region at {@code address}. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @param address the address of the variable argument list. + * @param scope the scope associated with the returned variable argument list. + * @return a new variable argument list backed by an off-heap region of memory starting at the given address value. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if the underlying native platform is not supported. * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. */ @CallerSensitive - static VaList ofAddress(MemoryAddress address, MemorySession session) { + static VaList ofAddress(long address, SegmentScope scope) { Reflection.ensureNativeAccess(Reflection.getCallerClass(), VaList.class, "ofAddress"); - Objects.requireNonNull(address); - Objects.requireNonNull(session); - return SharedUtils.newVaListOfAddress(address, session); + Objects.requireNonNull(scope); + return SharedUtils.newVaListOfAddress(address, scope); } /** * Creates a variable argument list using a builder (see {@link Builder}), with the given - * memory session. - *

    - * If this method needs to allocate memory, such memory will be managed by the given - * memory session, and will be released when the memory session is {@linkplain MemorySession#close closed}. + * scope. The provided scope determines the lifecycle of the returned variable argument list: the + * returned variable argument list will no longer be accessible, and its associated off-heap memory region will be + * deallocated when the scope becomes not {@linkplain SegmentScope#isAlive() alive}. *

    * Note that when there are no elements added to the created va list, * this method will return the same as {@link #empty()}. @@ -243,23 +271,23 @@ static VaList ofAddress(MemoryAddress address, MemorySession session) { * * @param actions a consumer for a builder (see {@link Builder}) which can be used to specify the elements * of the underlying variable argument list. - * @param session the memory session to be associated with the new variable arity list. + * @param scope the scope to be associated with the new variable arity list. * @return a new variable argument list. * @throws UnsupportedOperationException if the underlying native platform is not supported. - * @throws IllegalStateException if {@code session} is not {@linkplain MemorySession#isAlive() alive}. - * @throws WrongThreadException if this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} {@code session}. + * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. + * @throws WrongThreadException if this method is called from a thread {@code T}, + * such that {@code scope.isAccessibleBy(T) == false}. */ - static VaList make(Consumer actions, MemorySession session) { + static VaList make(Consumer actions, SegmentScope scope) { Objects.requireNonNull(actions); - Objects.requireNonNull(session); - return SharedUtils.newVaList(actions, session); + Objects.requireNonNull(scope); + return SharedUtils.newVaList(actions, scope); } /** - * Returns an empty variable argument list, associated with the {@linkplain MemorySession#global() global} - * memory session. The resulting variable argument list does not contain any argument, and throws {@link UnsupportedOperationException} - * on all operations, except for {@link VaList#address()}, {@link VaList#copy()} and {@link VaList#session()}. + * Returns an empty variable argument list, associated with the {@linkplain SegmentScope#global() global scope}. + * The resulting variable argument list does not contain any argument, and throws {@link UnsupportedOperationException} + * on all operations, except for {@link VaList#segment()}, {@link VaList#copy()}. * @return an empty variable argument list. * @throws UnsupportedOperationException if the underlying native platform is not supported. */ @@ -303,16 +331,17 @@ sealed interface Builder permits WinVaList.Builder, SysVVaList.Builder, LinuxAAr Builder addVarg(ValueLayout.OfDouble layout, double value); /** - * Writes an {@code Addressable} value to the variable argument list being constructed. + * Writes the {@linkplain MemorySegment#address() address} of the provided native segment + * to the variable argument list being constructed. * * @param layout the layout of the value to be written. - * @param value the {@code Addressable} value to be written. + * @param segment the segment whose {@linkplain MemorySegment#address() address} is to be written. * @return this builder. */ - Builder addVarg(ValueLayout.OfAddress layout, Addressable value); + Builder addVarg(ValueLayout.OfAddress layout, MemorySegment segment); /** - * Writes a {@code MemorySegment} value, with the given layout, to the variable argument list being constructed. + * Writes a {@code MemorySegment}, with the given layout, to the variable argument list being constructed. * * @param layout the layout of the value to be written. * @param value the {@code MemorySegment} whose contents will be copied. diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java index 0bbea651c38..f9a62419598 100644 --- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java @@ -28,102 +28,49 @@ import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.ByteOrder; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; -import java.util.Optional; -import jdk.internal.foreign.Utils; +import jdk.internal.foreign.layout.ValueLayouts; import jdk.internal.javac.PreviewFeature; -import jdk.internal.misc.Unsafe; -import jdk.internal.vm.annotation.ForceInline; -import jdk.internal.vm.annotation.Stable; -import sun.invoke.util.Wrapper; +import jdk.internal.reflect.CallerSensitive; /** - * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as integral types - * (either signed or unsigned) and floating-point types. Each value layout has a size, an alignment (in bits), + * A layout that models values of basic data types. Examples of values modelled by a value layout are + * integral values (either signed or unsigned), floating-point values and + * address values. + *

    + * Each value layout has a size, an alignment (in bits), * a {@linkplain ByteOrder byte order}, and a carrier, that is, the Java type that should be used when - * {@linkplain MemorySegment#get(OfInt, long) accessing} a memory region using the value layout. + * {@linkplain MemorySegment#get(OfInt, long) accessing} a region of memory using the value layout. *

    * This class defines useful value layout constants for Java primitive types and addresses. * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default}, * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}. * - * @implSpec - * This class and its subclasses are immutable, thread-safe and value-based. + * @implSpec implementing classes and subclasses are immutable, thread-safe and value-based. * * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed class ValueLayout extends AbstractLayout implements MemoryLayout { - - private final Class carrier; - private final ByteOrder order; - - private static final int ADDRESS_SIZE_BITS = Unsafe.ADDRESS_SIZE * 8; - - ValueLayout(Class carrier, ByteOrder order, long size) { - this(carrier, order, size, size, Optional.empty()); - } - - ValueLayout(Class carrier, ByteOrder order, long size, long alignment, Optional name) { - super(size, alignment, name); - this.carrier = carrier; - this.order = order; - checkCarrierSize(carrier, size); - } +public sealed interface ValueLayout extends MemoryLayout { /** * {@return the value's byte order} */ - public ByteOrder order() { - return order; - } + ByteOrder order(); /** - * Returns a value layout with the same carrier, alignment constraints and name as this value layout, + * Returns a value layout with the same carrier, alignment constraint and name as this value layout, * but with the specified byte order. * * @param order the desired byte order. * @return a value layout with the given byte order. */ - public ValueLayout withOrder(ByteOrder order) { - return new ValueLayout(carrier, Objects.requireNonNull(order), bitSize(), alignment, name()); - } - - /** - * {@inheritDoc} - */ - @Override - public String toString() { - char descriptor = carrier == MemoryAddress.class ? 'A' : carrier.descriptorString().charAt(0); - if (order == ByteOrder.LITTLE_ENDIAN) { - descriptor = Character.toLowerCase(descriptor); - } - return decorateLayoutString(String.format("%s%d", descriptor, bitSize())); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(Object other) { - if (this == other) { - return true; - } - if (!super.equals(other)) { - return false; - } - return other instanceof ValueLayout otherValue && - carrier.equals(otherValue.carrier) && - order.equals(otherValue.order); - } + ValueLayout withOrder(ByteOrder order); /** - * Creates a strided access var handle that can be used to dereference a multi-dimensional array. The - * layout of this array is a sequence layout with {@code shape.length} nested sequence layouts. The element + * Creates a strided var handle that can be used to access a memory segment as multi-dimensional + * array. The layout of this array is a sequence layout with {@code shape.length} nested sequence layouts. The element * layout of the sequence layout at depth {@code shape.length} is this value layout. * As a result, if {@code shape.length == 0}, the array layout will feature only one dimension. *

    @@ -138,15 +85,15 @@ public boolean equals(Object other) { * * Can be used to access a multi-dimensional array whose layout is as follows: * - * {@snippet lang=java : - * SequenceLayout arrayLayout = MemoryLayout.sequenceLayout(-1, + * {@snippet lang = java: + * SequenceLayout arrayLayout = MemoryLayout.sequenceLayout( * MemoryLayout.sequenceLayout(10, * MemoryLayout.sequenceLayout(20, ValueLayout.JAVA_INT))); - * } + *} * * The resulting var handle {@code arrayHandle} will feature 3 coordinates of type {@code long}; each coordinate * is interpreted as an index into the corresponding sequence layout. If we refer to the var handle coordinates, from left - * to right, as {@code x}, {@code y} and {@code z} respectively, the final offset dereferenced by the var handle can be + * to right, as {@code x}, {@code y} and {@code z} respectively, the final offset accessed by the var handle can be * computed with the following formula: * *

    {@code
    @@ -170,7 +117,8 @@ public boolean equals(Object other) {
          * as the value for {@code z} is outside its specified bounds.
          *
          * @param shape the size of each nested array dimension.
    -     * @return a var handle which can be used to dereference a multi-dimensional array, featuring {@code shape.length + 1}
    +     * @return a var handle which can be used to access a memory segment as a multi-dimensional array,
    +     * featuring {@code shape.length + 1}
          * {@code long} coordinates.
          * @throws IllegalArgumentException if {@code shape[i] < 0}, for at least one index {@code i}.
          * @throws UnsupportedOperationException if {@code bitAlignment() > bitSize()}.
    @@ -178,504 +126,385 @@ public boolean equals(Object other) {
          * @see MemoryLayout#varHandle(PathElement...)
          * @see SequenceLayout
          */
    -    public VarHandle arrayElementVarHandle(int... shape) {
    -        Objects.requireNonNull(shape);
    -        MemoryLayout layout = this;
    -        List path = new ArrayList<>();
    -        for (int i = shape.length ; i > 0 ; i--) {
    -            int size = shape[i - 1];
    -            if (size < 0) throw new IllegalArgumentException("Invalid shape size: " + size);
    -            layout = MemoryLayout.sequenceLayout(size, layout);
    -            path.add(PathElement.sequenceElement());
    -        }
    -        layout = MemoryLayout.sequenceLayout(-1, layout);
    -        path.add(PathElement.sequenceElement());
    -        return layout.varHandle(path.toArray(new PathElement[0]));
    -    }
    +    VarHandle arrayElementVarHandle(int... shape);
     
         /**
          * {@return the carrier associated with this value layout}
          */
    -    public Class carrier() {
    -        return carrier;
    -    }
    +    Class carrier();
     
         /**
          * {@inheritDoc}
          */
         @Override
    -    public int hashCode() {
    -        return Objects.hash(super.hashCode(), order, carrier);
    -    }
    -
    -    @Override
    -    ValueLayout dup(long alignment, Optional name) {
    -        return new ValueLayout(carrier, order, bitSize(), alignment, name());
    -    }
    -
    -    //hack: the declarations below are to make javadoc happy; we could have used generics in AbstractLayout
    -    //but that causes issues with javadoc, see JDK-8224052
    -
    -    /**
    -     * {@inheritDoc}
    -     */
    -    @Override
    -    public ValueLayout withName(String name) {
    -        return (ValueLayout)super.withName(name);
    -    }
    +    ValueLayout withName(String name);
     
         /**
          * {@inheritDoc}
          */
         @Override
    -    public ValueLayout withBitAlignment(long alignmentBits) {
    -        return (ValueLayout)super.withBitAlignment(alignmentBits);
    -    }
     
    -    static void checkCarrierSize(Class carrier, long size) {
    -        if (!isValidCarrier(carrier)) {
    -            throw new IllegalArgumentException("Invalid carrier: " + carrier.getName());
    -        }
    -        if (carrier == MemoryAddress.class && size != ADDRESS_SIZE_BITS) {
    -            throw new IllegalArgumentException("Address size mismatch: " + ADDRESS_SIZE_BITS + " != " + size);
    -        }
    -        if (carrier.isPrimitive()) {
    -            int expectedSize =  carrier == boolean.class ? 8 : Wrapper.forPrimitiveType(carrier).bitWidth();
    -            if (size != expectedSize) {
    -                throw new IllegalArgumentException("Carrier size mismatch: " + carrier.getName() + " != " + size);
    -            }
    -        }
    -    }
    -
    -    static boolean isValidCarrier(Class carrier) {
    -        return carrier == boolean.class
    -                || carrier == byte.class
    -                || carrier == short.class
    -                || carrier == char.class
    -                || carrier == int.class
    -                || carrier == long.class
    -                || carrier == float.class
    -                || carrier == double.class
    -                || carrier == MemoryAddress.class;
    -    }
    -
    -    @Stable
    -    private VarHandle handle;
    -
    -    @ForceInline
    -    VarHandle accessHandle() {
    -        if (handle == null) {
    -            // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity
    -            handle = Utils.makeSegmentViewVarHandle(this);
    -        }
    -        return handle;
    -    }
    +    ValueLayout withBitAlignment(long bitAlignment);
     
         /**
          * A value layout whose carrier is {@code boolean.class}.
          *
    +     * @see #JAVA_BOOLEAN
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfBoolean extends ValueLayout {
    -        OfBoolean(ByteOrder order) {
    -            super(boolean.class, order, 8);
    -        }
    -
    -        OfBoolean(ByteOrder order, long alignment, Optional name) {
    -            super(boolean.class, order, 8, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfBoolean extends ValueLayout permits ValueLayouts.OfBooleanImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfBoolean dup(long alignment, Optional name) {
    -            return new OfBoolean(order(), alignment, name);
    -        }
    +        OfBoolean withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfBoolean withName(String name) {
    -            return (OfBoolean)super.withName(name);
    -        }
    +        OfBoolean withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfBoolean withBitAlignment(long alignmentBits) {
    -            return (OfBoolean)super.withBitAlignment(alignmentBits);
    -        }
    +        OfBoolean withOrder(ByteOrder order);
     
    -        @Override
    -        public OfBoolean withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfBoolean(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code byte.class}.
          *
    +     * @see #JAVA_BYTE
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfByte extends ValueLayout {
    -        OfByte(ByteOrder order) {
    -            super(byte.class, order, 8);
    -        }
    -
    -        OfByte(ByteOrder order, long alignment, Optional name) {
    -            super(byte.class, order, 8, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfByte extends ValueLayout permits ValueLayouts.OfByteImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfByte dup(long alignment, Optional name) {
    -            return new OfByte(order(), alignment, name);
    -        }
    +        OfByte withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfByte withName(String name) {
    -            return (OfByte)super.withName(name);
    -        }
    +        OfByte withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfByte withBitAlignment(long alignmentBits) {
    -            return (OfByte)super.withBitAlignment(alignmentBits);
    -        }
    +        OfByte withOrder(ByteOrder order);
     
    -        @Override
    -        public OfByte withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfByte(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code char.class}.
          *
    +     * @see #JAVA_CHAR
    +     * @see #JAVA_CHAR_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfChar extends ValueLayout {
    -        OfChar(ByteOrder order) {
    -            super(char.class, order, 16);
    -        }
    -
    -        OfChar(ByteOrder order, long alignment, Optional name) {
    -            super(char.class, order, 16, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfChar extends ValueLayout permits ValueLayouts.OfCharImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfChar dup(long alignment, Optional name) {
    -            return new OfChar(order(), alignment, name);
    -        }
    +        OfChar withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfChar withName(String name) {
    -            return (OfChar)super.withName(name);
    -        }
    +        OfChar withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfChar withBitAlignment(long alignmentBits) {
    -            return (OfChar)super.withBitAlignment(alignmentBits);
    -        }
    +        OfChar withOrder(ByteOrder order);
     
    -        @Override
    -        public OfChar withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfChar(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code short.class}.
          *
    +     * @see #JAVA_SHORT
    +     * @see #JAVA_SHORT_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfShort extends ValueLayout {
    -        OfShort(ByteOrder order) {
    -            super(short.class, order, 16);
    -        }
    -
    -        OfShort(ByteOrder order, long alignment, Optional name) {
    -            super(short.class, order, 16, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfShort extends ValueLayout permits ValueLayouts.OfShortImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfShort dup(long alignment, Optional name) {
    -            return new OfShort(order(), alignment, name);
    -        }
    +        OfShort withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfShort withName(String name) {
    -            return (OfShort)super.withName(name);
    -        }
    +        OfShort withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfShort withBitAlignment(long alignmentBits) {
    -            return (OfShort)super.withBitAlignment(alignmentBits);
    -        }
    +        OfShort withOrder(ByteOrder order);
     
    -        @Override
    -        public OfShort withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfShort(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code int.class}.
          *
    +     * @see #JAVA_INT
    +     * @see #JAVA_INT_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfInt extends ValueLayout {
    -        OfInt(ByteOrder order) {
    -            super(int.class, order, 32);
    -        }
    -
    -        OfInt(ByteOrder order, long alignment, Optional name) {
    -            super(int.class, order, 32, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfInt extends ValueLayout permits ValueLayouts.OfIntImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfInt dup(long alignment, Optional name) {
    -            return new OfInt(order(), alignment, name);
    -        }
    +        OfInt withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfInt withName(String name) {
    -            return (OfInt)super.withName(name);
    -        }
    +        OfInt withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfInt withBitAlignment(long alignmentBits) {
    -            return (OfInt)super.withBitAlignment(alignmentBits);
    -        }
    +        OfInt withOrder(ByteOrder order);
     
    -        @Override
    -        public OfInt withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfInt(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code float.class}.
          *
    +     * @see #JAVA_FLOAT
    +     * @see #JAVA_FLOAT_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfFloat extends ValueLayout {
    -        OfFloat(ByteOrder order) {
    -            super(float.class, order, 32);
    -        }
    -
    -        OfFloat(ByteOrder order, long alignment, Optional name) {
    -            super(float.class, order, 32, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfFloat extends ValueLayout permits ValueLayouts.OfFloatImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfFloat dup(long alignment, Optional name) {
    -            return new OfFloat(order(), alignment, name);
    -        }
    +        OfFloat withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfFloat withName(String name) {
    -            return (OfFloat)super.withName(name);
    -        }
    +        OfFloat withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfFloat withBitAlignment(long alignmentBits) {
    -            return (OfFloat)super.withBitAlignment(alignmentBits);
    -        }
    +        OfFloat withOrder(ByteOrder order);
     
    -        @Override
    -        public OfFloat withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfFloat(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code long.class}.
          *
    +     * @see #JAVA_LONG
    +     * @see #JAVA_LONG_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfLong extends ValueLayout {
    -        OfLong(ByteOrder order) {
    -            super(long.class, order, 64);
    -        }
    -
    -        OfLong(ByteOrder order, long alignment, Optional name) {
    -            super(long.class, order, 64, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfLong extends ValueLayout permits ValueLayouts.OfLongImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfLong dup(long alignment, Optional name) {
    -            return new OfLong(order(), alignment, name);
    -        }
    +        OfLong withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfLong withName(String name) {
    -            return (OfLong)super.withName(name);
    -        }
    +        OfLong withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfLong withBitAlignment(long alignmentBits) {
    -            return (OfLong)super.withBitAlignment(alignmentBits);
    -        }
    +        OfLong withOrder(ByteOrder order);
     
    -        @Override
    -        public OfLong withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfLong(order, alignment, name());
    -        }
         }
     
         /**
          * A value layout whose carrier is {@code double.class}.
          *
    +     * @see #JAVA_DOUBLE
    +     * @see #JAVA_DOUBLE_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfDouble extends ValueLayout {
    -        OfDouble(ByteOrder order) {
    -            super(double.class, order, 64);
    -        }
    -
    -        OfDouble(ByteOrder order, long alignment, Optional name) {
    -            super(double.class, order, 64, alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfDouble extends ValueLayout permits ValueLayouts.OfDoubleImpl {
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        OfDouble dup(long alignment, Optional name) {
    -            return new OfDouble(order(), alignment, name);
    -        }
    +        OfDouble withName(String name);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfDouble withName(String name) {
    -            return (OfDouble)super.withName(name);
    -        }
    +        OfDouble withBitAlignment(long bitAlignment);
     
    +        /**
    +         * {@inheritDoc}
    +         */
             @Override
    -        public OfDouble withBitAlignment(long alignmentBits) {
    -            return (OfDouble)super.withBitAlignment(alignmentBits);
    -        }
    +        OfDouble withOrder(ByteOrder order);
     
    -        @Override
    -        public OfDouble withOrder(ByteOrder order) {
    -            Objects.requireNonNull(order);
    -            return new OfDouble(order, alignment, name());
    -        }
         }
     
         /**
    -     * A value layout whose carrier is {@code MemoryAddress.class}.
    +     * A value layout whose carrier is {@code MemorySegment.class}.
          *
    +     * @see #ADDRESS
    +     * @see #ADDRESS_UNALIGNED
          * @since 19
          */
    -    @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN)
    -    public static final class OfAddress extends ValueLayout {
    -        OfAddress(ByteOrder order) {
    -            super(MemoryAddress.class, order, ADDRESS_SIZE_BITS);
    -        }
    -
    -        OfAddress(ByteOrder order, long size, long alignment, Optional name) {
    -            super(MemoryAddress.class, order, size, alignment, name);
    -        }
    -
    -        @Override
    -        OfAddress dup(long alignment, Optional name) {
    -            return new OfAddress(order(), bitSize(), alignment, name);
    -        }
    +    @PreviewFeature(feature = PreviewFeature.Feature.FOREIGN)
    +    sealed interface OfAddress extends ValueLayout permits ValueLayouts.OfAddressImpl {
    +
    +        /**
    +         * {@inheritDoc}
    +         */
    +        @Override
    +        OfAddress withName(String name);
    +
    +        /**
    +         * {@inheritDoc}
    +         */
    +        @Override
    +        OfAddress withBitAlignment(long bitAlignment);
    +
    +        /**
    +         * {@inheritDoc}
    +         */
    +        @Override
    +        OfAddress withOrder(ByteOrder order);
    +
    +        /**
    +         * Returns an unbounded address layout with the same carrier, alignment constraint, name and order as this address layout,
    +         * but with the specified pointee layout. An unbounded address layout allow raw addresses to be accessed
    +         * as {@linkplain MemorySegment memory segments} whose size is set to {@link Long#MAX_VALUE}. As such,
    +         * these segments can be used in subsequent access operations.
    +         * 

    + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. + * + * @return an unbounded address layout with same characteristics as this layout. + * @see #isUnbounded() + */ + @CallerSensitive + OfAddress asUnbounded(); + + /** + * {@return {@code true}, if this address layout is an {@linkplain #asUnbounded() unbounded address layout}}. + */ + boolean isUnbounded(); - @Override - public OfAddress withName(String name) { - return (OfAddress)super.withName(name); - } - - @Override - public OfAddress withBitAlignment(long alignmentBits) { - return (OfAddress)super.withBitAlignment(alignmentBits); - } - - @Override - public OfAddress withOrder(ByteOrder order) { - Objects.requireNonNull(order); - return new OfAddress(order, bitSize(), alignment, name()); - } } /** * A value layout constant whose size is the same as that of a machine address ({@code size_t}), - * bit alignment set to {@code sizeof(size_t) * 8}, and byte order set to {@link ByteOrder#nativeOrder()}. + * bit alignment set to {@code sizeof(size_t) * 8}, byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(MemoryAddress.class, ByteOrder.nativeOrder()) - * .withBitAlignment(

    ); + * MemoryLayout.valueLayout(MemorySegment.class, ByteOrder.nativeOrder()); * } */ - public static final OfAddress ADDRESS = new OfAddress(ByteOrder.nativeOrder()) - .withBitAlignment(ValueLayout.ADDRESS_SIZE_BITS); + OfAddress ADDRESS = ValueLayouts.OfAddressImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code byte}, * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * MemoryLayout.valueLayout(byte.class, ByteOrder.nativeOrder()); * } */ - public static final OfByte JAVA_BYTE = new OfByte(ByteOrder.nativeOrder()).withBitAlignment(8); + OfByte JAVA_BYTE = ValueLayouts.OfByteImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code boolean}, * bit alignment set to 8, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()).withBitAlignment(8); + * MemoryLayout.valueLayout(boolean.class, ByteOrder.nativeOrder()); * } */ - public static final OfBoolean JAVA_BOOLEAN = new OfBoolean(ByteOrder.nativeOrder()).withBitAlignment(8); + OfBoolean JAVA_BOOLEAN = ValueLayouts.OfBooleanImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code char}, * bit alignment set to 16, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(16); + * MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()); * } */ - public static final OfChar JAVA_CHAR = new OfChar(ByteOrder.nativeOrder()).withBitAlignment(16); + OfChar JAVA_CHAR = ValueLayouts.OfCharImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code short}, * bit alignment set to 16, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()).withBitAlignment(16); + * MemoryLayout.valueLayout(short.class, ByteOrder.nativeOrder()); * } */ - public static final OfShort JAVA_SHORT = new OfShort(ByteOrder.nativeOrder()).withBitAlignment(16); + OfShort JAVA_SHORT = ValueLayouts.OfShortImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code int}, * bit alignment set to 32, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()).withBitAlignment(32); + * MemoryLayout.valueLayout(int.class, ByteOrder.nativeOrder()); * } */ - public static final OfInt JAVA_INT = new OfInt(ByteOrder.nativeOrder()).withBitAlignment(32); + OfInt JAVA_INT = ValueLayouts.OfIntImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code long}, * bit alignment set to 64, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()).withBitAlignment(64); + * MemoryLayout.valueLayout(long.class, ByteOrder.nativeOrder()); * } */ - public static final OfLong JAVA_LONG = new OfLong(ByteOrder.nativeOrder()) - .withBitAlignment(64); + OfLong JAVA_LONG = ValueLayouts.OfLongImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code float}, @@ -685,15 +514,100 @@ public OfAddress withOrder(ByteOrder order) { * MemoryLayout.valueLayout(float.class, ByteOrder.nativeOrder()).withBitAlignment(32); * } */ - public static final OfFloat JAVA_FLOAT = new OfFloat(ByteOrder.nativeOrder()).withBitAlignment(32); + OfFloat JAVA_FLOAT = ValueLayouts.OfFloatImpl.of(ByteOrder.nativeOrder()); /** * A value layout constant whose size is the same as that of a Java {@code double}, * bit alignment set to 64, and byte order set to {@link ByteOrder#nativeOrder()}. * Equivalent to the following code: * {@snippet lang=java : - * MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()).withBitAlignment(64); + * MemoryLayout.valueLayout(double.class, ByteOrder.nativeOrder()); + * } + */ + OfDouble JAVA_DOUBLE = ValueLayouts.OfDoubleImpl.of(ByteOrder.nativeOrder()); + + /** + * An unaligned value layout constant whose size is the same as that of a machine address ({@code size_t}), + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * ADDRESS.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfAddress ADDRESS_UNALIGNED = ADDRESS.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code char} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_CHAR.withBitAlignment(8); * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. */ - public static final OfDouble JAVA_DOUBLE = new OfDouble(ByteOrder.nativeOrder()).withBitAlignment(64); + OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code short} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_SHORT.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code int} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_INT.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code long} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_LONG.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code float} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_FLOAT.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); + + /** + * An unaligned value layout constant whose size is the same as that of a Java {@code double} + * and byte order set to {@link ByteOrder#nativeOrder()}. + * Equivalent to the following code: + * {@snippet lang=java : + * JAVA_DOUBLE.withBitAlignment(8); + * } + * @apiNote Care should be taken when using unaligned value layouts as they may induce + * performance and portability issues. + */ + OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8); + } diff --git a/src/java.base/share/classes/java/lang/foreign/package-info.java b/src/java.base/share/classes/java/lang/foreign/package-info.java index 87cfc200735..020661b1c94 100644 --- a/src/java.base/share/classes/java/lang/foreign/package-info.java +++ b/src/java.base/share/classes/java/lang/foreign/package-info.java @@ -31,29 +31,36 @@ * *

    * The main abstraction introduced to support foreign memory access is {@link java.lang.foreign.MemorySegment}, which - * models a contiguous memory region, residing either inside or outside the Java heap. The contents of a memory + * models a contiguous region of memory, residing either inside or outside the Java heap. The contents of a memory * segment can be described using a {@link java.lang.foreign.MemoryLayout memory layout}, which provides * basic operations to query sizes, offsets and alignment constraints. Memory layouts also provide - * an alternate, more abstract way, to dereference memory segments - * using {@linkplain java.lang.foreign.MemoryLayout#varHandle(java.lang.foreign.MemoryLayout.PathElement...) access var handles}, + * an alternate, more abstract way, to access memory segments + * using {@linkplain java.lang.foreign.MemoryLayout#varHandle(java.lang.foreign.MemoryLayout.PathElement...) var handles}, * which can be computed using layout paths. * - * For example, to allocate an off-heap memory region big enough to hold 10 values of the primitive type {@code int}, and fill it with values - * ranging from {@code 0} to {@code 9}, we can use the following code: + * For example, to allocate an off-heap region of memory big enough to hold 10 values of the primitive type {@code int}, + * and fill it with values ranging from {@code 0} to {@code 9}, we can use the following code: * - * {@snippet lang=java : - * MemorySegment segment = MemorySegment.allocateNative(10 * 4, MemorySession.openImplicit()); + * {@snippet lang = java: + * MemorySegment segment = MemorySegment.allocateNative(10 * 4, SegmentScope.auto()); * for (int i = 0 ; i < 10 ; i++) { * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); * } - * } + *} * * This code creates a native memory segment, that is, a memory segment backed by * off-heap memory; the size of the segment is 40 bytes, enough to store 10 values of the primitive type {@code int}. + * The segment is associated with an {@linkplain java.lang.foreign.SegmentScope#auto() automatic scope}. This + * means that the off-heap region of memory backing the segment is managed, automatically, by the garbage collector. + * As such, the off-heap memory backing the native segment will be released at some unspecified + * point after the segment becomes unreachable. + * This is similar to what happens with direct buffers created via {@link java.nio.ByteBuffer#allocateDirect(int)}. + * It is also possible to manage the lifecycle of allocated native segments more directly, as shown in a later section. + *

    * Inside a loop, we then initialize the contents of the memory segment; note how the - * {@linkplain java.lang.foreign.MemorySegment#setAtIndex(ValueLayout.OfInt, long, int) dereference method} - * accepts a {@linkplain java.lang.foreign.ValueLayout value layout}, which specifies the size, alignment constraints, - * byte order as well as the Java type ({@code int}, in this case) associated with the dereference operation. More specifically, + * {@linkplain java.lang.foreign.MemorySegment#setAtIndex(ValueLayout.OfInt, long, int) access method} + * accepts a {@linkplain java.lang.foreign.ValueLayout value layout}, which specifies the size, alignment constraint, + * byte order as well as the Java type ({@code int}, in this case) associated with the access operation. More specifically, * if we view the memory segment as a set of 10 adjacent slots, {@code s[i]}, where {@code 0 <= i < 10}, * where the size of each slot is exactly 4 bytes, the initialization logic above will set each slot * so that {@code s[i] = i}, again where {@code 0 <= i < 10}. @@ -64,35 +71,37 @@ * often crucial that the resources associated with a memory segment are released when the segment is no longer in use, * and in a timely fashion. For this reason, there might be cases where waiting for the garbage collector to determine that a segment * is unreachable is not optimal. - * Clients that operate under these assumptions might want to programmatically release the memory associated - * with a memory segment. This can be done, using the {@link java.lang.foreign.MemorySession} abstraction, as shown below: + * Clients that operate under these assumptions might want to programmatically release the memory backing a memory segment. + * This can be done, using the {@link java.lang.foreign.Arena} abstraction, as shown below: * - * {@snippet lang=java : - * try (MemorySession session = MemorySession.openConfined()) { - * MemorySegment segment = MemorySegment.allocateNative(10 * 4, session); + * {@snippet lang = java: + * try (Arena arena = Arena.openConfined()) { + * MemorySegment segment = arena.allocate(10 * 4); * for (int i = 0 ; i < 10 ; i++) { * segment.setAtIndex(ValueLayout.JAVA_INT, i, i); * } * } - * } + *} * - * This example is almost identical to the prior one; this time we first create a so called memory session, - * which is used to bind the life-cycle of the segment created immediately afterwards. Note the use of the - * try-with-resources construct: this idiom ensures that all the memory resources associated with the segment will be released - * at the end of the block, according to the semantics described in Section {@jls 14.20.3} of The Java Language Specification. + * This example is almost identical to the prior one; this time we first create an arena + * which is used to allocate multiple native segments which share the same life-cycle. That is, all the segments + * allocated by the arena will be associated with the same {@linkplain java.lang.foreign.SegmentScope scope}. + * Note the use of the try-with-resources construct: this idiom ensures that the off-heap region of memory backing the + * native segment will be released at the end of the block, according to the semantics described in Section {@jls 14.20.3} + * of The Java Language Specification. * *

    Safety

    * * This API provides strong safety guarantees when it comes to memory access. First, when dereferencing a memory segment, * the access coordinates are validated (upon access), to make sure that access does not occur at any address which resides - * outside the boundaries of the memory segment used by the dereference operation. We call this guarantee spatial safety; + * outside the boundaries of the memory segment used by the access operation. We call this guarantee spatial safety; * in other words, access to memory segments is bounds-checked, in the same way as array access is, as described in * Section {@jls 15.10.4} of The Java Language Specification. *

    - * Since memory segments can be closed (see above), segments are also validated (upon access) to make sure that - * the memory session associated with the segment being accessed has not been closed prematurely. + * Since memory segments created with an arena can become invalid (see above), segments are also validated (upon access) to make sure that + * the scope associated with the segment being accessed is still alive. * We call this guarantee temporal safety. Together, spatial and temporal safety ensure that each memory access - * operation either succeeds - and accesses a valid memory location - or fails. + * operation either succeeds - and accesses a valid location within the region of memory backing the memory segment - or fails. * *

    Foreign function access

    * The key abstractions introduced to support foreign function access are {@link java.lang.foreign.SymbolLookup}, @@ -105,134 +114,118 @@ * For example, to compute the length of a string using the C standard library function {@code strlen} on a Linux x64 platform, * we can use the following code: * - * {@snippet lang=java : + * {@snippet lang = java: * Linker linker = Linker.nativeLinker(); * SymbolLookup stdlib = linker.defaultLookup(); * MethodHandle strlen = linker.downcallHandle( - * stdlib.lookup("strlen").get(), + * stdlib.find("strlen").get(), * FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS) * ); * - * try (MemorySession session = MemorySession.openConfined()) { - * MemorySegment cString = MemorySegment.allocateNative(5 + 1, session); - * cString.setUtf8String(0, "Hello"); + * try (Arena arena = Arena.openConfined()) { + * MemorySegment cString = arena.allocateUtf8String("Hello"); * long len = (long)strlen.invoke(cString); // 5 * } - * } + *} * * Here, we obtain a {@linkplain java.lang.foreign.Linker#nativeLinker() native linker} and we use it - * to {@linkplain java.lang.foreign.SymbolLookup#lookup(java.lang.String) look up} the {@code strlen} symbol in the + * to {@linkplain java.lang.foreign.SymbolLookup#find(java.lang.String) look up} the {@code strlen} symbol in the * standard C library; a downcall method handle targeting said symbol is subsequently - * {@linkplain java.lang.foreign.Linker#downcallHandle(java.lang.foreign.FunctionDescriptor) obtained}. + * {@linkplain java.lang.foreign.Linker#downcallHandle(FunctionDescriptor, Linker.Option...) obtained}. * To complete the linking successfully, we must provide a {@link java.lang.foreign.FunctionDescriptor} instance, * describing the signature of the {@code strlen} function. * From this information, the linker will uniquely determine the sequence of steps which will turn * the method handle invocation (here performed using {@link java.lang.invoke.MethodHandle#invoke(java.lang.Object...)}) * into a foreign function call, according to the rules specified by the ABI of the underlying platform. - * The {@link java.lang.foreign.MemorySegment} class also provides many useful methods for - * interacting with foreign code, such as converting Java strings - * {@linkplain java.lang.foreign.MemorySegment#setUtf8String(long, java.lang.String) into} zero-terminated, UTF-8 strings and - * {@linkplain java.lang.foreign.MemorySegment#getUtf8String(long) back}, as demonstrated in the above example. - * - *

    Foreign addresses

    - * - * When a memory segment is created from Java code, the segment properties (spatial bounds, temporal bounds and confinement) - * are fully known at segment creation. But when interacting with foreign functions, clients will often receive raw pointers. - * Such pointers have no spatial bounds. For example, the C type {@code char*} can refer to a single {@code char} value, - * or an array of {@code char} values, of given size. Nor do said pointers have any notion of temporal bounds or thread-confinement. - *

    - * Raw pointers are modelled using the {@link java.lang.foreign.MemoryAddress} class. When clients receive a - * memory address instance from a foreign function call, they can perform memory dereference on it directly, - * using one of the many unsafe - * {@linkplain java.lang.foreign.MemoryAddress#get(java.lang.foreign.ValueLayout.OfInt, long) dereference methods} - * provided: - * - * {@snippet lang=java : - * MemoryAddress addr = ... // obtain address from foreign function call - * int x = addr.get(ValueLayout.JAVA_INT, 0); - * } - * - * Alternatively, the client can - * {@linkplain java.lang.foreign.MemorySegment#ofAddress(java.lang.foreign.MemoryAddress, long, java.lang.foreign.MemorySession) create} - * a memory segment unsafely. This allows the client to inject extra knowledge about spatial bounds which might, - * for instance, be available in the documentation of the foreign function which produced the native address. - * Here is how an unsafe segment can be created from a memory address: - * - * {@snippet lang=java : - * MemorySession session = ... // initialize a memory session object - * MemoryAddress addr = ... // obtain address from foreign function call - * MemorySegment segment = MemorySegment.ofAddress(addr, 4, session); // segment is 4 bytes long - * int x = segment.get(ValueLayout.JAVA_INT, 0); - * } + * The {@link java.lang.foreign.Arena} class also provides many useful methods for + * interacting with foreign code, such as + * {@linkplain java.lang.foreign.SegmentAllocator#allocateUtf8String(java.lang.String) converting} Java strings into + * zero-terminated, UTF-8 strings, as demonstrated in the above example. * *

    Upcalls

    * The {@link java.lang.foreign.Linker} interface also allows clients to turn an existing method handle (which might point - * to a Java method) into a memory address, so that Java code can effectively be passed to other foreign functions. + * to a Java method) into a memory segment, so that Java code can effectively be passed to other foreign functions. * For instance, we can write a method that compares two integer values, as follows: * * {@snippet lang=java : * class IntComparator { - * static int intCompare(MemoryAddress addr1, MemoryAddress addr2) { - * return addr1.get(ValueLayout.JAVA_INT, 0) - addr2.get(ValueLayout.JAVA_INT, 0); + * static int intCompare(MemorySegment addr1, MemorySegment addr2) { + * return addr1.get(ValueLayout.JAVA_INT, 0) - + * addr2.get(ValueLayout.JAVA_INT, 0); + * * } * } * } * - * The above method dereferences two memory addresses containing an integer value, and performs a simple comparison + * The above method accesses two foreign memory segments containing an integer value, and performs a simple comparison * by returning the difference between such values. We can then obtain a method handle which targets the above static * method, as follows: * - * {@snippet lang=java : - * FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, ValueLayout.ADDRESS, ValueLayout.ADDRESS); + * {@snippet lang = java: + * FunctionDescriptor intCompareDescriptor = FunctionDescriptor.of(ValueLayout.JAVA_INT, + * ValueLayout.ADDRESS.asUnbounded(), + * ValueLayout.ADDRESS.asUnbounded()); * MethodHandle intCompareHandle = MethodHandles.lookup().findStatic(IntComparator.class, * "intCompare", - * Linker.upcallType(comparFunction)); - * } + * intCompareDescriptor.toMethodType()); + *} * * As before, we need to create a {@link java.lang.foreign.FunctionDescriptor} instance, this time describing the signature * of the function pointer we want to create. The descriptor can be used to - * {@linkplain java.lang.foreign.Linker#upcallType(java.lang.foreign.FunctionDescriptor) derive} a method type + * {@linkplain java.lang.foreign.FunctionDescriptor#toMethodType() derive} a method type * that can be used to look up the method handle for {@code IntComparator.intCompare}. *

    * Now that we have a method handle instance, we can turn it into a fresh function pointer, * using the {@link java.lang.foreign.Linker} interface, as follows: * - * {@snippet lang=java : - * MemorySession session = ... - * Addressable comparFunc = Linker.nativeLinker().upcallStub( - * intCompareHandle, intCompareDescriptor, session); + * {@snippet lang = java: + * SegmentScope scope = ... + * MemorySegment comparFunc = Linker.nativeLinker().upcallStub( + * intCompareHandle, intCompareDescriptor, scope); * ); - * } + *} * * The {@link java.lang.foreign.FunctionDescriptor} instance created in the previous step is then used to - * {@linkplain java.lang.foreign.Linker#upcallStub(java.lang.invoke.MethodHandle, java.lang.foreign.FunctionDescriptor, java.lang.foreign.MemorySession) create} + * {@linkplain java.lang.foreign.Linker#upcallStub(java.lang.invoke.MethodHandle, FunctionDescriptor, SegmentScope) create} * a new upcall stub; the layouts in the function descriptors allow the linker to determine the sequence of steps which * allow foreign code to call the stub for {@code intCompareHandle} according to the rules specified by the ABI of the * underlying platform. - * The lifecycle of the upcall stub is tied to the {@linkplain java.lang.foreign.MemorySession memory session} - * provided when the upcall stub is created. This same session is made available by the {@link java.lang.foreign.MemorySegment} + * The lifecycle of the upcall stub is tied to the {@linkplain java.lang.foreign.SegmentScope scope} + * provided when the upcall stub is created. This same scope is made available by the {@link java.lang.foreign.MemorySegment} * instance returned by that method. * *

    Restricted methods

    * Some methods in this package are considered restricted. Restricted methods are typically used to bind native * foreign data and/or functions to first-class Java API elements which can then be used directly by clients. For instance - * the restricted method {@link java.lang.foreign.MemorySegment#ofAddress(MemoryAddress, long, MemorySession)} + * the restricted method {@link java.lang.foreign.MemorySegment#ofAddress(long, long, SegmentScope)} * can be used to create a fresh segment with the given spatial bounds out of a native address. *

    - * Binding foreign data and/or functions is generally unsafe and, if done incorrectly, can result in VM crashes, or memory corruption when the bound Java API element is accessed. - * For instance, in the case of {@link java.lang.foreign.MemorySegment#ofAddress(MemoryAddress, long, MemorySession)}, - * if the provided spatial bounds are incorrect, a client of the segment returned by that method might crash the VM, or corrupt - * memory when attempting to dereference said segment. For these reasons, it is crucial for code that calls a restricted method + * Binding foreign data and/or functions is generally unsafe and, if done incorrectly, can result in VM crashes, + * or memory corruption when the bound Java API element is accessed. For instance, in the case of + * {@link java.lang.foreign.MemorySegment#ofAddress(long, long, SegmentScope)}, if the provided spatial bounds are + * incorrect, a client of the segment returned by that method might crash the VM, or corrupt + * memory when attempting to access said segment. For these reasons, it is crucial for code that calls a restricted method * to never pass arguments that might cause incorrect binding of foreign data and/or functions to a Java API. *

    - * Access to restricted methods can be controlled using the command line option {@code --enable-native-access=M1,M2, ... Mn}, - * where {@code M1}, {@code M2}, {@code ... Mn} are module names (for the unnamed module, the special value {@code ALL-UNNAMED} - * can be used). If this option is specified, access to restricted methods is only granted to the modules listed by that - * option. If this option is not specified, access to restricted methods is enabled for all modules, but - * access to restricted methods will result in runtime warnings. + * Given the potential danger of restricted methods, the Java runtime issues a warning on the standard error stream + * every time a restricted method is invoked. Such warnings can be disabled by granting access to restricted methods + * to selected modules. This can be done either via implementation-specific command line options, or programmatically, e.g. by calling + * {@link java.lang.ModuleLayer.Controller#enableNativeAccess(java.lang.Module)}. *

    * For every class in this package, unless specified otherwise, any method arguments of reference * type must not be null, and any null argument will elicit a {@code NullPointerException}. This fact is not individually * documented for methods of this API. + * + * @apiNote Usual memory model guarantees, for example stated in {@jls 6.6} and {@jls 10.4}, do not apply + * when accessing native memory segments as these segments are backed by off-heap regions of memory. + * + * @implNote + * In the reference implementation, access to restricted methods can be granted to specific modules using the command line option + * {@code --enable-native-access=M1,M2, ... Mn}, where {@code M1}, {@code M2}, {@code ... Mn} are module names + * (for the unnamed module, the special value {@code ALL-UNNAMED} can be used). If this option is specified, access to + * restricted methods is only granted to the modules listed by that option. If this option is not specified, + * access to restricted methods is enabled for all modules, but access to restricted methods will result in runtime warnings. + * */ package java.lang.foreign; + diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java index 28e7b3e8dec..a63f53d3ca1 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandles.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandles.java @@ -45,8 +45,8 @@ import java.lang.constant.ConstantDescs; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.lang.invoke.LambdaForm.BasicType; import java.lang.reflect.Constructor; @@ -7910,21 +7910,21 @@ private static MethodType tableSwitchChecks(MethodHandle defaultCase, MethodHand * access modes {@code get} and {@code set} for {@code long} and * {@code double} on 32-bit platforms. *

  • atomic update access modes for {@code int}, {@code long}, - * {@code float}, {@code double} or {@link MemoryAddress}. + * {@code float}, {@code double} or {@link MemorySegment}. * (Future major platform releases of the JDK may support additional * types for certain currently unsupported access modes.) - *
  • numeric atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}. + *
  • numeric atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. * (Future major platform releases of the JDK may support additional * numeric types for certain currently unsupported access modes.) - *
  • bitwise atomic update access modes for {@code int}, {@code long} and {@link MemoryAddress}. + *
  • bitwise atomic update access modes for {@code int}, {@code long} and {@link MemorySegment}. * (Future major platform releases of the JDK may support additional * numeric types for certain currently unsupported access modes.) * * - * If {@code T} is {@code float}, {@code double} or {@link MemoryAddress} then atomic + * If {@code T} is {@code float}, {@code double} or {@link MemorySegment} then atomic * update access modes compare values using their bitwise representation * (see {@link Float#floatToRawIntBits}, - * {@link Double#doubleToRawLongBits} and {@link MemoryAddress#toRawLongValue()}, respectively). + * {@link Double#doubleToRawLongBits} and {@link MemorySegment#address()}, respectively). *

    * Alternatively, a memory access operation is partially aligned if it occurs at a memory address {@code A} * which is only compatible with the alignment constraint {@code B}; in such cases, access for anything other than the diff --git a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java index 176ee7db459..996b51487c9 100644 --- a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java @@ -52,24 +52,32 @@ private NativeMethodHandle(MethodType type, LambdaForm form, NativeEntryPoint ne */ public static MethodHandle make(NativeEntryPoint nep) { MethodType type = nep.type(); - if (!allTypesPrimitive(type)) - throw new IllegalArgumentException("Type must only contain primitives: " + type); + if (hasIllegalType(type)) + throw new IllegalArgumentException("Illegal type(s) found: " + type); LambdaForm lform = preparedLambdaForm(type); return new NativeMethodHandle(type, lform, nep); } - private static boolean allTypesPrimitive(MethodType type) { - if (!type.returnType().isPrimitive()) - return false; + private static boolean hasIllegalType(MethodType type) { + if (isIllegalType(type.returnType())) + return true; for (Class pType : type.parameterArray()) { - if (!pType.isPrimitive()) - return false; + if (isIllegalType(pType)) + return true; } - return true; + return false; + } + + private static boolean isIllegalType(Class pType) { + return !(pType == long.class + || pType == int.class + || pType == float.class + || pType == double.class + || pType == void.class); } private static final MemberName.Factory IMPL_NAMES = MemberName.getFactory(); diff --git a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template index 05923554f19..08495f2e58d 100644 --- a/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template +++ b/src/java.base/share/classes/java/lang/invoke/X-VarHandleByteArrayView.java.template @@ -34,7 +34,6 @@ import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import java.util.List; diff --git a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template index 1f1af9a6fd5..b65306f6e21 100644 --- a/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template +++ b/src/java.base/share/classes/java/nio/Direct-X-Buffer.java.template @@ -29,7 +29,6 @@ package java.nio; import java.io.FileDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.ref.Reference; import java.util.Objects; import jdk.internal.foreign.MemorySessionImpl; diff --git a/src/java.base/share/classes/java/nio/channels/FileChannel.java b/src/java.base/share/classes/java/nio/channels/FileChannel.java index b4a4a195023..9ec890dcac0 100644 --- a/src/java.base/share/classes/java/nio/channels/FileChannel.java +++ b/src/java.base/share/classes/java/nio/channels/FileChannel.java @@ -27,7 +27,7 @@ import java.io.IOException; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.spi.AbstractInterruptibleChannel; @@ -1001,6 +1001,9 @@ public abstract MappedByteBuffer map(MapMode mode, long position, long size) /** * Maps a region of this channel's file into a new mapped memory segment, * with the given offset, size and memory session. + * The {@linkplain MemorySegment#address() address} of the returned memory + * segment is the starting address of the mapped off-heap region backing + * the segment. * *

    If the specified mapping mode is * {@linkplain FileChannel.MapMode#READ_ONLY READ_ONLY}, the resulting @@ -1053,11 +1056,11 @@ public abstract MappedByteBuffer map(MapMode mode, long position, long size) * * @throws IllegalStateException * If the {@code session} is not - * {@linkplain MemorySession#isAlive() alive}. + * {@linkplain SegmentScope#isAlive() alive}. * * @throws WrongThreadException * If this method is called from a thread other than the thread - * {@linkplain MemorySession#ownerThread() owning} the + * {@linkplain SegmentScope#isAccessibleBy(Thread) owning} the * {@code session}. * * @throws NonReadableChannelException @@ -1080,7 +1083,7 @@ public abstract MappedByteBuffer map(MapMode mode, long position, long size) * @since 19 */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) - public MemorySegment map(MapMode mode, long offset, long size, MemorySession session) + public MemorySegment map(MapMode mode, long offset, long size, SegmentScope session) throws IOException { throw new UnsupportedOperationException(); diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index bc1aeedc7af..be8ee9d91f6 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -270,12 +270,13 @@ public interface JavaLangAccess { /** * Updates all unnamed modules to allow access to restricted methods. */ - void addEnableNativeAccessAllUnnamed(); + void addEnableNativeAccessToAllUnnamed(); /** - * Returns true if module m can access restricted methods. + * Ensure that the given module has native access. If not, warn or + * throw exception depending on the configuration. */ - boolean isEnableNativeAccess(Module m); + void ensureNativeAccess(Module m, Class owner, String methodName); /** * Returns the ServicesCatalog for the given Layer. diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 3bfa39cc9b9..9080e1482a8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -25,12 +25,12 @@ package jdk.internal.foreign; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; +import java.lang.reflect.Array; import java.nio.Buffer; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -51,6 +51,7 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.access.foreign.UnmapperProxy; import jdk.internal.misc.ScopedMemoryAccess; +import jdk.internal.misc.Unsafe; import jdk.internal.util.ArraysSupport; import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.ForceInline; @@ -66,26 +67,26 @@ * are defined for each memory segment kind, see {@link NativeMemorySegmentImpl}, {@link HeapMemorySegmentImpl} and * {@link MappedMemorySegmentImpl}. */ -public abstract non-sealed class AbstractMemorySegmentImpl implements MemorySegment, SegmentAllocator, Scoped, BiFunction, RuntimeException> { +public abstract sealed class AbstractMemorySegmentImpl + implements MemorySegment, SegmentAllocator, BiFunction, RuntimeException> + permits HeapMemorySegmentImpl, NativeMemorySegmentImpl { private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - static final long NONCE = new Random().nextLong(); - - static final JavaNioAccess nioAccess = SharedSecrets.getJavaNioAccess(); + static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); final long length; final boolean readOnly; - final MemorySession session; + final SegmentScope session; @ForceInline - AbstractMemorySegmentImpl(long length, boolean readOnly, MemorySession session) { + AbstractMemorySegmentImpl(long length, boolean readOnly, SegmentScope session) { this.length = length; this.readOnly = readOnly; this.session = session; } - abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session); + abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session); abstract ByteBuffer makeByteBuffer(); @@ -125,7 +126,7 @@ public Spliterator spliterator(MemoryLayout elementLayout) { if (!isAlignedForElement(0, elementLayout)) { throw new IllegalArgumentException("Incompatible alignment constraints"); } - if (!Utils.isAligned(byteSize(), elementLayout.byteSize())) { + if ((byteSize() % elementLayout.byteSize()) != 0) { throw new IllegalArgumentException("Segment size is not a multiple of layout size"); } return new SegmentSplitter(elementLayout.byteSize(), byteSize() / elementLayout.byteSize(), @@ -145,52 +146,15 @@ public final MemorySegment fill(byte value){ } @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - Utils.checkAllocationSizeAndAlign(bytesSize, bytesAlignment); - return asSlice(0, bytesSize); - } - - @Override - public long mismatch(MemorySegment other) { - AbstractMemorySegmentImpl that = (AbstractMemorySegmentImpl)Objects.requireNonNull(other); - final long thisSize = this.byteSize(); - final long thatSize = that.byteSize(); - final long length = Math.min(thisSize, thatSize); - this.checkAccess(0, length, true); - that.checkAccess(0, length, true); - if (this == other) { - checkValidState(); - return -1; - } - - long i = 0; - if (length > 7) { - if (get(JAVA_BYTE, 0) != that.get(JAVA_BYTE, 0)) { - return 0; - } - i = vectorizedMismatchLargeForBytes(sessionImpl(), that.sessionImpl(), - this.unsafeGetBase(), this.unsafeGetOffset(), - that.unsafeGetBase(), that.unsafeGetOffset(), - length); - if (i >= 0) { - return i; - } - long remaining = ~i; - assert remaining < 8 : "remaining greater than 7: " + remaining; - i = length - remaining; - } - for (; i < length; i++) { - if (get(JAVA_BYTE, i) != that.get(JAVA_BYTE, i)) { - return i; - } - } - return thisSize != thatSize ? length : -1; + public MemorySegment allocate(long byteSize, long byteAlignment) { + Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment); + return asSlice(0, byteSize); } /** * Mismatch over long lengths. */ - private static long vectorizedMismatchLargeForBytes(MemorySessionImpl aSession, MemorySessionImpl bSession, + public static long vectorizedMismatchLargeForBytes(MemorySessionImpl aSession, MemorySessionImpl bSession, Object a, long aOffset, Object b, long bOffset, long length) { @@ -219,11 +183,6 @@ private static long vectorizedMismatchLargeForBytes(MemorySessionImpl aSession, return ~remaining; } - @Override - public MemoryAddress address() { - throw new UnsupportedOperationException("Cannot obtain address of on-heap segment"); - } - @Override public final ByteBuffer asByteBuffer() { checkArraySize("ByteBuffer", 1); @@ -279,21 +238,25 @@ public final long segmentOffset(MemorySegment other) { @Override public void load() { - throw new UnsupportedOperationException("Not a mapped segment"); + throw notAMappedSegment(); } @Override public void unload() { - throw new UnsupportedOperationException("Not a mapped segment"); + throw notAMappedSegment(); } @Override public boolean isLoaded() { - throw new UnsupportedOperationException("Not a mapped segment"); + throw notAMappedSegment(); } @Override public void force() { + throw notAMappedSegment(); + } + + private static UnsupportedOperationException notAMappedSegment() { throw new UnsupportedOperationException("Not a mapped segment"); } @@ -366,6 +329,7 @@ public final boolean isAlignedForElement(long offset, MemoryLayout layout) { } private int checkArraySize(String typeName, int elemSize) { + // elemSize is guaranteed to be a power of two, so we can use an alignment check if (!Utils.isAligned(length, elemSize)) { throw new IllegalStateException(String.format("Segment size is not a multiple of %d. Size: %d", elemSize, length)); } @@ -394,20 +358,20 @@ public RuntimeException apply(String s, List numbers) { } @Override - public MemorySession session() { + public SegmentScope scope() { return session; } + @ForceInline + public final MemorySessionImpl sessionImpl() { + return (MemorySessionImpl)session; + } + private IndexOutOfBoundsException outOfBoundException(long offset, long length) { return new IndexOutOfBoundsException(String.format("Out of bound access on segment %s; new offset = %d; new length = %d", this, offset, length)); } - protected int id() { - //compute a stable and random id for this memory segment - return Math.abs(Objects.hash(unsafeGetBase(), unsafeGetOffset(), NONCE)); - } - static class SegmentSplitter implements Spliterator { AbstractMemorySegmentImpl segment; long elemCount; @@ -486,42 +450,38 @@ public int characteristics() { @Override public String toString() { - return "MemorySegment{ id=0x" + Long.toHexString(id()) + " limit: " + length + " }"; + return "MemorySegment{ array: " + array() + " address:" + address() + " limit: " + length + " }"; } @Override public boolean equals(Object o) { return o instanceof AbstractMemorySegmentImpl that && - isNative() == that.isNative() && - unsafeGetOffset() == that.unsafeGetOffset() && unsafeGetBase() == that.unsafeGetBase() && - length == that.length && - session.equals(that.session); + unsafeGetOffset() == that.unsafeGetOffset(); } @Override public int hashCode() { return Objects.hash( - isNative(), unsafeGetOffset(), - unsafeGetBase(), - length, - session - ); + unsafeGetBase()); } public static AbstractMemorySegmentImpl ofBuffer(Buffer bb) { Objects.requireNonNull(bb); - long bbAddress = nioAccess.getBufferAddress(bb); - Object base = nioAccess.getBufferBase(bb); - UnmapperProxy unmapper = nioAccess.unmapper(bb); + Object base = NIO_ACCESS.getBufferBase(bb); + if (!bb.isDirect() && base == null) { + throw new IllegalArgumentException("The provided heap buffer is not backed by an array."); + } + long bbAddress = NIO_ACCESS.getBufferAddress(bb); + UnmapperProxy unmapper = NIO_ACCESS.unmapper(bb); int pos = bb.position(); int limit = bb.limit(); int size = limit - pos; - AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl)nioAccess.bufferSegment(bb); - final MemorySession bufferSession; + AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl) NIO_ACCESS.bufferSegment(bb); + final SegmentScope bufferSession; if (bufferSegment != null) { bufferSession = bufferSegment.session; } else { @@ -574,4 +534,152 @@ private static int getScaleFactor(Buffer buffer) { throw new AssertionError("Cannot get here"); } } + + @ForceInline + public static void copy(MemorySegment srcSegment, ValueLayout srcElementLayout, long srcOffset, + MemorySegment dstSegment, ValueLayout dstElementLayout, long dstOffset, + long elementCount) { + + AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; + AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)dstSegment; + if (srcElementLayout.byteSize() != dstElementLayout.byteSize()) { + throw new IllegalArgumentException("Source and destination layouts must have same size"); + } + Utils.checkElementAlignment(srcElementLayout, "Source layout alignment greater than its size"); + Utils.checkElementAlignment(dstElementLayout, "Destination layout alignment greater than its size"); + if (!srcImpl.isAlignedForElement(srcOffset, srcElementLayout)) { + throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); + } + if (!dstImpl.isAlignedForElement(dstOffset, dstElementLayout)) { + throw new IllegalArgumentException("Destination segment incompatible with alignment constraints"); + } + long size = elementCount * srcElementLayout.byteSize(); + srcImpl.checkAccess(srcOffset, size, true); + dstImpl.checkAccess(dstOffset, size, false); + if (srcElementLayout.byteSize() == 1 || srcElementLayout.order() == dstElementLayout.order()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(), + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), dstImpl.sessionImpl(), + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstOffset, size, srcElementLayout.byteSize()); + } + } + + @ForceInline + public static void copy(MemorySegment srcSegment, ValueLayout srcLayout, long srcOffset, + Object dstArray, int dstIndex, + int elementCount) { + + long baseAndScale = getBaseAndScale(dstArray.getClass()); + if (dstArray.getClass().componentType() != srcLayout.carrier()) { + throw new IllegalArgumentException("Incompatible value layout: " + srcLayout); + } + int dstBase = (int)baseAndScale; + long dstWidth = (int)(baseAndScale >> 32); // Use long arithmetics below + AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)srcSegment; + Utils.checkElementAlignment(srcLayout, "Source layout alignment greater than its size"); + if (!srcImpl.isAlignedForElement(srcOffset, srcLayout)) { + throw new IllegalArgumentException("Source segment incompatible with alignment constraints"); + } + srcImpl.checkAccess(srcOffset, elementCount * dstWidth, true); + Objects.checkFromIndexSize(dstIndex, elementCount, Array.getLength(dstArray)); + if (dstWidth == 1 || srcLayout.order() == ByteOrder.nativeOrder()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(srcImpl.sessionImpl(), null, + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(srcImpl.sessionImpl(), null, + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcOffset, + dstArray, dstBase + (dstIndex * dstWidth), elementCount * dstWidth, dstWidth); + } + } + + @ForceInline + public static void copy(Object srcArray, int srcIndex, + MemorySegment dstSegment, ValueLayout dstLayout, long dstOffset, + int elementCount) { + + long baseAndScale = getBaseAndScale(srcArray.getClass()); + if (srcArray.getClass().componentType() != dstLayout.carrier()) { + throw new IllegalArgumentException("Incompatible value layout: " + dstLayout); + } + int srcBase = (int)baseAndScale; + long srcWidth = (int)(baseAndScale >> 32); // Use long arithmetics below + Objects.checkFromIndexSize(srcIndex, elementCount, Array.getLength(srcArray)); + AbstractMemorySegmentImpl destImpl = (AbstractMemorySegmentImpl)dstSegment; + Utils.checkElementAlignment(dstLayout, "Destination layout alignment greater than its size"); + if (!destImpl.isAlignedForElement(dstOffset, dstLayout)) { + throw new IllegalArgumentException("Destination segment incompatible with alignment constraints"); + } + destImpl.checkAccess(dstOffset, elementCount * srcWidth, false); + if (srcWidth == 1 || dstLayout.order() == ByteOrder.nativeOrder()) { + ScopedMemoryAccess.getScopedMemoryAccess().copyMemory(null, destImpl.sessionImpl(), + srcArray, srcBase + (srcIndex * srcWidth), + destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth); + } else { + ScopedMemoryAccess.getScopedMemoryAccess().copySwapMemory(null, destImpl.sessionImpl(), + srcArray, srcBase + (srcIndex * srcWidth), + destImpl.unsafeGetBase(), destImpl.unsafeGetOffset() + dstOffset, elementCount * srcWidth, srcWidth); + } + } + + public static long mismatch(MemorySegment srcSegment, long srcFromOffset, long srcToOffset, + MemorySegment dstSegment, long dstFromOffset, long dstToOffset) { + AbstractMemorySegmentImpl srcImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(srcSegment); + AbstractMemorySegmentImpl dstImpl = (AbstractMemorySegmentImpl)Objects.requireNonNull(dstSegment); + long srcBytes = srcToOffset - srcFromOffset; + long dstBytes = dstToOffset - dstFromOffset; + srcImpl.checkAccess(srcFromOffset, srcBytes, true); + dstImpl.checkAccess(dstFromOffset, dstBytes, true); + if (dstImpl == srcImpl) { + srcImpl.checkValidState(); + return -1; + } + + long bytes = Math.min(srcBytes, dstBytes); + long i = 0; + if (bytes > 7) { + if (srcImpl.get(JAVA_BYTE, srcFromOffset) != dstImpl.get(JAVA_BYTE, dstFromOffset)) { + return 0; + } + i = AbstractMemorySegmentImpl.vectorizedMismatchLargeForBytes(srcImpl.sessionImpl(), dstImpl.sessionImpl(), + srcImpl.unsafeGetBase(), srcImpl.unsafeGetOffset() + srcFromOffset, + dstImpl.unsafeGetBase(), dstImpl.unsafeGetOffset() + dstFromOffset, + bytes); + if (i >= 0) { + return i; + } + long remaining = ~i; + assert remaining < 8 : "remaining greater than 7: " + remaining; + i = bytes - remaining; + } + for (; i < bytes; i++) { + if (srcImpl.get(JAVA_BYTE, srcFromOffset + i) != dstImpl.get(JAVA_BYTE, dstFromOffset + i)) { + return i; + } + } + return srcBytes != dstBytes ? bytes : -1; + } + + private static long getBaseAndScale(Class arrayType) { + if (arrayType.equals(byte[].class)) { + return (long) Unsafe.ARRAY_BYTE_BASE_OFFSET | ((long)Unsafe.ARRAY_BYTE_INDEX_SCALE << 32); + } else if (arrayType.equals(char[].class)) { + return (long) Unsafe.ARRAY_CHAR_BASE_OFFSET | ((long)Unsafe.ARRAY_CHAR_INDEX_SCALE << 32); + } else if (arrayType.equals(short[].class)) { + return (long)Unsafe.ARRAY_SHORT_BASE_OFFSET | ((long)Unsafe.ARRAY_SHORT_INDEX_SCALE << 32); + } else if (arrayType.equals(int[].class)) { + return (long)Unsafe.ARRAY_INT_BASE_OFFSET | ((long) Unsafe.ARRAY_INT_INDEX_SCALE << 32); + } else if (arrayType.equals(float[].class)) { + return (long)Unsafe.ARRAY_FLOAT_BASE_OFFSET | ((long)Unsafe.ARRAY_FLOAT_INDEX_SCALE << 32); + } else if (arrayType.equals(long[].class)) { + return (long)Unsafe.ARRAY_LONG_BASE_OFFSET | ((long)Unsafe.ARRAY_LONG_INDEX_SCALE << 32); + } else if (arrayType.equals(double[].class)) { + return (long)Unsafe.ARRAY_DOUBLE_BASE_OFFSET | ((long)Unsafe.ARRAY_DOUBLE_INDEX_SCALE << 32); + } else { + throw new IllegalArgumentException("Not a supported array class: " + arrayType.getSimpleName()); + } + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/ArenaAllocator.java b/src/java.base/share/classes/jdk/internal/foreign/ArenaAllocator.java deleted file mode 100644 index 0ae38e3dc39..00000000000 --- a/src/java.base/share/classes/jdk/internal/foreign/ArenaAllocator.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2021, 2022, 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. - */ - -package jdk.internal.foreign; - -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; - -public final class ArenaAllocator implements SegmentAllocator { - - public static final long DEFAULT_BLOCK_SIZE = 4 * 1024; - - private MemorySegment segment; - - private long sp = 0L; - private long size = 0; - private final long blockSize; - private final long arenaSize; - private final MemorySession session; - - public ArenaAllocator(long blockSize, long arenaSize, MemorySession session) { - this.blockSize = blockSize; - this.arenaSize = arenaSize; - this.session = session; - this.segment = newSegment(blockSize, 1); - } - - MemorySegment trySlice(long bytesSize, long bytesAlignment) { - long min = segment.address().toRawLongValue(); - long start = Utils.alignUp(min + sp, bytesAlignment) - min; - if (segment.byteSize() - start < bytesSize) { - return null; - } else { - MemorySegment slice = segment.asSlice(start, bytesSize); - sp = start + bytesSize; - return slice; - } - } - - private MemorySegment newSegment(long bytesSize, long bytesAlignment) { - long allocatedSize = Utils.alignUp(bytesSize, bytesAlignment); - if (size + allocatedSize > arenaSize) { - throw new OutOfMemoryError(); - } - size += allocatedSize; - return MemorySegment.allocateNative(bytesSize, bytesAlignment, session); - } - - @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - Utils.checkAllocationSizeAndAlign(bytesSize, bytesAlignment); - // try to slice from current segment first... - MemorySegment slice = trySlice(bytesSize, bytesAlignment); - if (slice != null) { - return slice; - } else { - long maxPossibleAllocationSize = bytesSize + bytesAlignment - 1; - if (maxPossibleAllocationSize < 0) { - throw new OutOfMemoryError(); - } else if (maxPossibleAllocationSize > blockSize) { - // too big - return newSegment(bytesSize, bytesAlignment); - } else { - // allocate a new segment and slice from there - sp = 0L; - segment = newSegment(blockSize, 1L); - slice = trySlice(bytesSize, bytesAlignment); - return slice; - } - } - } -} diff --git a/src/java.base/share/classes/jdk/internal/foreign/CABI.java b/src/java.base/share/classes/jdk/internal/foreign/CABI.java index 4b4d95149f8..59d5e1e42c8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/CABI.java +++ b/src/java.base/share/classes/jdk/internal/foreign/CABI.java @@ -29,10 +29,10 @@ import static sun.security.action.GetPropertyAction.privilegedGetProperty; public enum CABI { - SysV, - Win64, - LinuxAArch64, - MacOsAArch64; + SYS_V, + WIN_64, + LINUX_AARCH_64, + MAC_OS_AARCH_64; private static final CABI ABI; private static final String ARCH; @@ -47,16 +47,16 @@ public enum CABI { // addressSize will be correctly 32 if ((ARCH.equals("amd64") || ARCH.equals("x86_64")) && ADDRESS_SIZE == 64) { if (OS.startsWith("Windows")) { - ABI = Win64; + ABI = WIN_64; } else { - ABI = SysV; + ABI = SYS_V; } } else if (ARCH.equals("aarch64")) { if (OS.startsWith("Mac")) { - ABI = MacOsAArch64; + ABI = MAC_OS_AARCH_64; } else { // The Linux ABI follows the standard AAPCS ABI - ABI = LinuxAArch64; + ABI = LINUX_AARCH_64; } } else { // unsupported diff --git a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java index b5ef673b92b..4961cecde5e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/ConfinedSession.java @@ -51,8 +51,8 @@ final class ConfinedSession extends MemorySessionImpl { } } - public ConfinedSession(Thread owner, Cleaner cleaner) { - super(owner, new ConfinedResourceList(), cleaner); + public ConfinedSession(Thread owner) { + super(owner, new ConfinedResourceList()); } @Override @@ -81,10 +81,12 @@ public void release0() { void justClose() { checkValidState(); - if (state == 0 || state - ((int)ASYNC_RELEASE_COUNT.getVolatile(this)) == 0) { + int asyncCount = (int)ASYNC_RELEASE_COUNT.getVolatile(this); + if ((state == 0 && asyncCount == 0) + || ((state - asyncCount) == 0)) { state = CLOSED; } else { - throw alreadyAcquired(state); + throw alreadyAcquired(state - asyncCount); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/FunctionDescriptorImpl.java b/src/java.base/share/classes/jdk/internal/foreign/FunctionDescriptorImpl.java new file mode 100644 index 00000000000..0723af6ba0d --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/FunctionDescriptorImpl.java @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2020, 2022, 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. + */ +package jdk.internal.foreign; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodType; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import static java.util.Objects.requireNonNull; + +/** + * @implSpec This class and its subclasses are immutable, thread-safe and value-based. + */ +public final class FunctionDescriptorImpl implements FunctionDescriptor { + + private final MemoryLayout resLayout; // Nullable + private final List argLayouts; + + private FunctionDescriptorImpl(MemoryLayout resLayout, List argLayouts) { + this.resLayout = resLayout; + this.argLayouts = List.copyOf(argLayouts); + } + + /** + * {@return the return layout (if any) associated with this function descriptor} + */ + public Optional returnLayout() { + return Optional.ofNullable(resLayout); + } + + /** + * {@return the argument layouts associated with this function descriptor (as an immutable list)}. + */ + public List argumentLayouts() { + return argLayouts; + } + + /** + * Returns a function descriptor with the given argument layouts appended to the argument layout array + * of this function descriptor. + * + * @param addedLayouts the argument layouts to append. + * @return the new function descriptor. + */ + public FunctionDescriptorImpl appendArgumentLayouts(MemoryLayout... addedLayouts) { + return insertArgumentLayouts(argLayouts.size(), addedLayouts); + } + + /** + * Returns a function descriptor with the given argument layouts inserted at the given index, into the argument + * layout array of this function descriptor. + * + * @param index the index at which to insert the arguments + * @param addedLayouts the argument layouts to insert at given index. + * @return the new function descriptor. + * @throws IllegalArgumentException if {@code index < 0 || index > argumentLayouts().size()}. + */ + public FunctionDescriptorImpl insertArgumentLayouts(int index, MemoryLayout... addedLayouts) { + if (index < 0 || index > argLayouts.size()) + throw new IllegalArgumentException("Index out of bounds: " + index); + List added = List.of(addedLayouts); // null check on array and its elements + List newLayouts = new ArrayList<>(argLayouts.size() + addedLayouts.length); + newLayouts.addAll(argLayouts.subList(0, index)); + newLayouts.addAll(added); + newLayouts.addAll(argLayouts.subList(index, argLayouts.size())); + return new FunctionDescriptorImpl(resLayout, newLayouts); + } + + /** + * Returns a function descriptor with the given memory layout as the new return layout. + * + * @param newReturn the new return layout. + * @return the new function descriptor. + */ + public FunctionDescriptorImpl changeReturnLayout(MemoryLayout newReturn) { + requireNonNull(newReturn); + return new FunctionDescriptorImpl(newReturn, argLayouts); + } + + /** + * Returns a function descriptor with the return layout dropped. This is useful to model functions + * which return no values. + * + * @return the new function descriptor. + */ + public FunctionDescriptorImpl dropReturnLayout() { + return new FunctionDescriptorImpl(null, argLayouts); + } + + private static Class carrierTypeFor(MemoryLayout layout) { + if (layout instanceof ValueLayout valueLayout) { + return valueLayout.carrier(); + } else if (layout instanceof GroupLayout) { + return MemorySegment.class; + } else { + throw new IllegalArgumentException("Unsupported layout: " + layout); + } + } + + @Override + public MethodType toMethodType() { + Class returnValue = resLayout != null ? carrierTypeFor(resLayout) : void.class; + Class[] argCarriers = new Class[argLayouts.size()]; + for (int i = 0; i < argCarriers.length; i++) { + argCarriers[i] = carrierTypeFor(argLayouts.get(i)); + } + return MethodType.methodType(returnValue, argCarriers); + } + + /** + * {@return the string representation of this function descriptor} + */ + @Override + public String toString() { + return String.format("(%s)%s", + argLayouts.stream().map(Object::toString) + .collect(Collectors.joining()), + returnLayout() + .map(Object::toString) + .orElse("v")); + } + + /** + * Compares the specified object with this function descriptor for equality. Returns {@code true} if and only if the specified + * object is also a function descriptor, and all the following conditions are met: + *

      + *
    • the two function descriptors have equals return layouts (see {@link MemoryLayout#equals(Object)}), or both have no return layout;
    • + *
    • the two function descriptors have argument layouts that are pair-wise {@linkplain MemoryLayout#equals(Object) equal}; and
    • + *
    + * + * @param other the object to be compared for equality with this function descriptor. + * @return {@code true} if the specified object is equal to this function descriptor. + */ + @Override + public boolean equals(Object other) { + return other instanceof FunctionDescriptorImpl f && + Objects.equals(resLayout, f.resLayout) && + Objects.equals(argLayouts, f.argLayouts); + } + + /** + * {@return the hash code value for this function descriptor} + */ + @Override + public int hashCode() { + return Objects.hash(argLayouts, resLayout); + } + + public static FunctionDescriptor of(MemoryLayout resLayout, List argLayouts) { + return new FunctionDescriptorImpl(resLayout, argLayouts); + } + + public static FunctionDescriptor ofVoid(List argLayouts) { + return new FunctionDescriptorImpl(null, argLayouts); + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java new file mode 100644 index 00000000000..2d78a66eb6f --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/GlobalSession.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022, 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. + */ + +package jdk.internal.foreign; + +import jdk.internal.vm.annotation.ForceInline; + +/** + * The global, non-closeable, shared session. Similar to a shared session, but its {@link #close()} method throws unconditionally. + * Adding new resources to the global session, does nothing: as the session can never become not-alive, there is nothing to track. + * Acquiring and or releasing a memory session similarly does nothing. + */ +final class GlobalSession extends MemorySessionImpl { + + final Object ref; + + public GlobalSession(Object ref) { + super(null, null); + this.ref = ref; + } + + @Override + @ForceInline + public void release0() { + // do nothing + } + + @Override + public boolean isCloseable() { + return false; + } + + @Override + @ForceInline + public void acquire0() { + // do nothing + } + + @Override + void addInternal(ResourceList.ResourceCleanup resource) { + // do nothing + } + + @Override + public void justClose() { + throw nonCloseable(); + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java index 3d7d05e7d40..4967f438c00 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java @@ -27,9 +27,11 @@ package jdk.internal.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.util.Objects; +import java.util.Optional; + import jdk.internal.access.JavaNioAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; @@ -44,9 +46,9 @@ * the field type storing the 'base' coordinate is just Object; similarly, all the constructor in the subclasses * accept an Object 'base' parameter instead of a sharper type (e.g. {@code byte[]}). This is deliberate, as * using sharper types would require use of type-conversions, which in turn would inhibit some C2 optimizations, - * such as the elimination of store barriers in methods like {@link HeapMemorySegmentImpl#dup(long, long, int, MemorySession)}. + * such as the elimination of store barriers in methods like {@link HeapMemorySegmentImpl#dup(long, long, boolean, SegmentScope)}. */ -public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl { +public abstract sealed class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl { private static final Unsafe UNSAFE = Unsafe.getUnsafe(); private static final int BYTE_ARR_BASE = UNSAFE.arrayBaseOffset(byte[].class); @@ -59,9 +61,14 @@ public abstract class HeapMemorySegmentImpl extends AbstractMemorySegmentImpl { final long offset; final Object base; + @Override + public Optional array() { + return Optional.of(base); + } + @ForceInline HeapMemorySegmentImpl(long offset, Object base, long length, boolean readOnly) { - super(length, readOnly, MemorySessionImpl.GLOBAL); + super(length, readOnly, SegmentScope.global()); this.offset = offset; this.base = base; } @@ -72,7 +79,7 @@ public long unsafeGetOffset() { } @Override - abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session); + abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session); @Override ByteBuffer makeByteBuffer() { @@ -85,14 +92,14 @@ ByteBuffer makeByteBuffer() { // factories - public static class OfByte extends HeapMemorySegmentImpl { + public static final class OfByte extends HeapMemorySegmentImpl { OfByte(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfByte dup(long offset, long size, boolean readOnly, MemorySession session) { + OfByte dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfByte(this.offset + offset, base, size, readOnly); } @@ -111,16 +118,21 @@ public static MemorySegment fromArray(byte[] arr) { public long maxAlignMask() { return MAX_ALIGN_1; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_BYTE_BASE_OFFSET; + } } - public static class OfChar extends HeapMemorySegmentImpl { + public static final class OfChar extends HeapMemorySegmentImpl { OfChar(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfChar dup(long offset, long size, boolean readOnly, MemorySession session) { + OfChar dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfChar(this.offset + offset, base, size, readOnly); } @@ -139,16 +151,21 @@ public static MemorySegment fromArray(char[] arr) { public long maxAlignMask() { return MAX_ALIGN_2; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_CHAR_BASE_OFFSET; + } } - public static class OfShort extends HeapMemorySegmentImpl { + public static final class OfShort extends HeapMemorySegmentImpl { OfShort(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfShort dup(long offset, long size, boolean readOnly, MemorySession session) { + OfShort dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfShort(this.offset + offset, base, size, readOnly); } @@ -167,16 +184,21 @@ public static MemorySegment fromArray(short[] arr) { public long maxAlignMask() { return MAX_ALIGN_2; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_SHORT_BASE_OFFSET; + } } - public static class OfInt extends HeapMemorySegmentImpl { + public static final class OfInt extends HeapMemorySegmentImpl { OfInt(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfInt dup(long offset, long size, boolean readOnly, MemorySession session) { + OfInt dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfInt(this.offset + offset, base, size, readOnly); } @@ -195,16 +217,21 @@ public static MemorySegment fromArray(int[] arr) { public long maxAlignMask() { return MAX_ALIGN_4; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_INT_BASE_OFFSET; + } } - public static class OfLong extends HeapMemorySegmentImpl { + public static final class OfLong extends HeapMemorySegmentImpl { OfLong(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfLong dup(long offset, long size, boolean readOnly, MemorySession session) { + OfLong dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfLong(this.offset + offset, base, size, readOnly); } @@ -223,16 +250,21 @@ public static MemorySegment fromArray(long[] arr) { public long maxAlignMask() { return MAX_ALIGN_8; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_LONG_BASE_OFFSET; + } } - public static class OfFloat extends HeapMemorySegmentImpl { + public static final class OfFloat extends HeapMemorySegmentImpl { OfFloat(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfFloat dup(long offset, long size, boolean readOnly, MemorySession session) { + OfFloat dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfFloat(this.offset + offset, base, size, readOnly); } @@ -251,16 +283,21 @@ public static MemorySegment fromArray(float[] arr) { public long maxAlignMask() { return MAX_ALIGN_4; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_FLOAT_BASE_OFFSET; + } } - public static class OfDouble extends HeapMemorySegmentImpl { + public static final class OfDouble extends HeapMemorySegmentImpl { OfDouble(long offset, Object base, long length, boolean readOnly) { super(offset, base, length, readOnly); } @Override - OfDouble dup(long offset, long size, boolean readOnly, MemorySession session) { + OfDouble dup(long offset, long size, boolean readOnly, SegmentScope session) { return new OfDouble(this.offset + offset, base, size, readOnly); } @@ -279,6 +316,11 @@ public static MemorySegment fromArray(double[] arr) { public long maxAlignMask() { return MAX_ALIGN_8; } + + @Override + public long address() { + return offset - Unsafe.ARRAY_DOUBLE_BASE_OFFSET; + } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java new file mode 100644 index 00000000000..0eb3642508c --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/ImplicitSession.java @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2022, 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. + */ + +package jdk.internal.foreign; + +import sun.nio.ch.DirectBuffer; + +import java.lang.ref.Cleaner; +import java.lang.ref.Reference; + +/** + * This is an implicit, GC-backed memory session. Implicit sessions cannot be closed explicitly. + * While it would be possible to model an implicit session as a non-closeable view of a shared + * session, it is better to capture the fact that an implicit session is not just a non-closeable + * view of some session which might be closeable. This is useful e.g. in the implementations of + * {@link DirectBuffer#address()}, where obtaining an address of a buffer instance associated + * with a potentially closeable session is forbidden. + */ +final class ImplicitSession extends SharedSession { + + public ImplicitSession(Cleaner cleaner) { + super(); + cleaner.register(this, resourceList); + } + + @Override + public void release0() { + Reference.reachabilityFence(this); + } + + @Override + public void acquire0() { + // do nothing + } + + @Override + public boolean isCloseable() { + return false; + } + + @Override + public void justClose() { + throw nonCloseable(); + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java index 6d339f2b882..8e1ae388bbb 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java +++ b/src/java.base/share/classes/jdk/internal/foreign/LayoutPath.java @@ -31,6 +31,7 @@ import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.SequenceLayout; +import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -50,6 +51,9 @@ */ public class LayoutPath { + private static final long[] EMPTY_STRIDES = new long[0]; + private static final long[] EMPTY_BOUNDS = new long[0]; + private static final MethodHandle MH_ADD_SCALED_OFFSET; private static final MethodHandle MH_SLICE; @@ -123,7 +127,7 @@ public LayoutPath groupElement(String name) { l.name().get().equals(name)) { elem = l; break; - } else if (g.isStruct()) { + } else if (g instanceof StructLayout) { offset += l.bitSize(); } } @@ -180,11 +184,11 @@ public MethodHandle offsetHandle() { public MethodHandle sliceHandle() { if (strides.length == 0) { // trigger checks eagerly - Utils.bitsToBytesOrThrow(offset, Utils.bitsToBytesThrowOffset); + Utils.bitsToBytesOrThrow(offset, Utils.BITS_TO_BYTES_THROW_OFFSET); } MethodHandle offsetHandle = offsetHandle(); // bit offset - offsetHandle = MethodHandles.filterReturnValue(offsetHandle, Utils.MH_bitsToBytesOrThrowForOffset); // byte offset + offsetHandle = MethodHandles.filterReturnValue(offsetHandle, Utils.MH_BITS_TO_BYTES_OR_THROW_FOR_OFFSET); // byte offset MethodHandle sliceHandle = MH_SLICE; // (MS, long, long) -> MS sliceHandle = MethodHandles.insertArguments(sliceHandle, 2, layout.byteSize()); // (MS, long) -> MS @@ -257,9 +261,6 @@ private long[] addBound(long maxIndex) { return newBounds; } - private static final long[] EMPTY_STRIDES = new long[0]; - private static final long[] EMPTY_BOUNDS = new long[0]; - /** * This class provides an immutable implementation for the {@code PathElement} interface. A path element implementation * is simply a pointer to one of the selector methods provided by the {@code LayoutPath} class. diff --git a/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java index 8ca0630995a..1d9465b8b41 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java @@ -26,7 +26,7 @@ package jdk.internal.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import jdk.internal.access.foreign.UnmapperProxy; import jdk.internal.misc.ScopedMemoryAccess; @@ -37,25 +37,25 @@ * memory mapped segment, such as the file descriptor associated with the mapping. This information is crucial * in order to correctly reconstruct a byte buffer object from the segment (see {@link #makeByteBuffer()}). */ -public class MappedMemorySegmentImpl extends NativeMemorySegmentImpl { +public sealed class MappedMemorySegmentImpl extends NativeMemorySegmentImpl { private final UnmapperProxy unmapper; - static ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); + static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, MemorySession session) { + public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, SegmentScope session) { super(min, length, readOnly, session); this.unmapper = unmapper; } @Override ByteBuffer makeByteBuffer() { - return nioAccess.newMappedByteBuffer(unmapper, min, (int)length, null, + return NIO_ACCESS.newMappedByteBuffer(unmapper, min, (int)length, null, session == MemorySessionImpl.GLOBAL ? null : this); } @Override - MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) { + MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session) { return new MappedMemorySegmentImpl(min + offset, unmapper, size, readOnly, session); } @@ -93,7 +93,7 @@ public void force() { SCOPED_MEMORY_ACCESS.force(sessionImpl(), unmapper.fileDescriptor(), min, unmapper.isSync(), 0, length); } - public static class EmptyMappedMemorySegmentImpl extends MappedMemorySegmentImpl { + public static final class EmptyMappedMemorySegmentImpl extends MappedMemorySegmentImpl { public EmptyMappedMemorySegmentImpl(boolean readOnly, MemorySessionImpl session) { super(0, null, 0, readOnly, session); diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemoryAddressImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemoryAddressImpl.java deleted file mode 100644 index 69002934c38..00000000000 --- a/src/java.base/share/classes/jdk/internal/foreign/MemoryAddressImpl.java +++ /dev/null @@ -1,389 +0,0 @@ -/* - * Copyright (c) 2019, 2022, 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. - * - */ -package jdk.internal.foreign; - -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.ValueLayout; -import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.reflect.CallerSensitive; -import jdk.internal.reflect.Reflection; -import jdk.internal.vm.annotation.ForceInline; - -/** - * This class provides an immutable implementation for the {@code MemoryAddress} interface. This class contains information - * about the segment this address is associated with, as well as an offset into such segment. - */ -public final class MemoryAddressImpl implements MemoryAddress, Scoped { - - private final long offset; - - public MemoryAddressImpl(long offset) { - this.offset = offset; - } - - // MemoryAddress methods - - @Override - public MemoryAddress addOffset(long offset) { - return new MemoryAddressImpl(this.offset + offset); - } - - @Override - public long toRawLongValue() { - return offset; - } - - @Override - public final MemoryAddress address() { - return this; - } - - // Object methods - - @Override - public int hashCode() { - return (int) toRawLongValue(); - } - - @Override - public boolean equals(Object that) { - return (that instanceof MemoryAddressImpl addressImpl && - offset == addressImpl.offset); - } - - @Override - public String toString() { - return "MemoryAddress{ offset=0x" + Long.toHexString(offset) + " }"; - } - - public static MemorySegment ofLongUnchecked(long value) { - return ofLongUnchecked(value, Long.MAX_VALUE); - } - - public static MemorySegment ofLongUnchecked(long value, long byteSize, MemorySession session) { - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, session); - } - - public static MemorySegment ofLongUnchecked(long value, long byteSize) { - return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(MemoryAddress.ofLong(value), byteSize, MemorySessionImpl.GLOBAL); - } - - @Override - public MemorySessionImpl session() { - return MemorySessionImpl.GLOBAL; - } - - @Override - @CallerSensitive - @ForceInline - public String getUtf8String(long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getUtf8String"); - SharedUtils.checkAddress(this); - return NativeMemorySegmentImpl.EVERYTHING.getUtf8String(toRawLongValue() + offset); - } - - @Override - @CallerSensitive - @ForceInline - public void setUtf8String(long offset, String str) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setUtf8String"); - SharedUtils.checkAddress(this); - NativeMemorySegmentImpl.EVERYTHING.setUtf8String(toRawLongValue() + offset, str); - } - - @Override - @ForceInline - @CallerSensitive - public byte get(ValueLayout.OfByte layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfByte layout, long offset, byte value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public boolean get(ValueLayout.OfBoolean layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfBoolean layout, long offset, boolean value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public char get(ValueLayout.OfChar layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfChar layout, long offset, char value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public short get(ValueLayout.OfShort layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfShort layout, long offset, short value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public int get(ValueLayout.OfInt layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfInt layout, long offset, int value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public float get(ValueLayout.OfFloat layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfFloat layout, long offset, float value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public long get(ValueLayout.OfLong layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfLong layout, long offset, long value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public double get(ValueLayout.OfDouble layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfDouble layout, long offset, double value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value); - } - - @Override - @ForceInline - @CallerSensitive - public MemoryAddress get(ValueLayout.OfAddress layout, long offset) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "get"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + offset); - } - - @Override - @ForceInline - @CallerSensitive - public void set(ValueLayout.OfAddress layout, long offset, Addressable value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "set"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + offset, value.address()); - } - - @Override - @ForceInline - @CallerSensitive - public char getAtIndex(ValueLayout.OfChar layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfChar layout, long index, char value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public short getAtIndex(ValueLayout.OfShort layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfShort layout, long index, short value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public int getAtIndex(ValueLayout.OfInt layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfInt layout, long index, int value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public float getAtIndex(ValueLayout.OfFloat layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfFloat layout, long index, float value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public long getAtIndex(ValueLayout.OfLong layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfLong layout, long index, long value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public double getAtIndex(ValueLayout.OfDouble layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfDouble layout, long index, double value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value); - } - - @Override - @ForceInline - @CallerSensitive - public MemoryAddress getAtIndex(ValueLayout.OfAddress layout, long index) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "getAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - return NativeMemorySegmentImpl.EVERYTHING.get(layout, toRawLongValue() + (index * layout.byteSize())); - } - - @Override - @ForceInline - @CallerSensitive - public void setAtIndex(ValueLayout.OfAddress layout, long index, Addressable value) { - Reflection.ensureNativeAccess(Reflection.getCallerClass(), MemoryAddress.class, "setAtIndex"); - Utils.checkElementAlignment(layout, "Layout alignment greater than its size"); - NativeMemorySegmentImpl.EVERYTHING.set(layout, toRawLongValue() + (index * layout.byteSize()), value.address()); - } -} diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index 97264782a2b..b8d1036baab 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -26,23 +26,21 @@ package jdk.internal.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.lang.ref.Cleaner; -import java.lang.ref.Reference; import java.util.Objects; import jdk.internal.misc.ScopedMemoryAccess; -import jdk.internal.ref.CleanerFactory; import jdk.internal.vm.annotation.ForceInline; -import sun.nio.ch.DirectBuffer; /** * This class manages the temporal bounds associated with a memory segment as well * as thread confinement. A session has a liveness bit, which is updated when the session is closed - * (this operation is triggered by {@link MemorySession#close()}). This bit is consulted prior + * (this operation is triggered by {@link MemorySessionImpl#close()}). This bit is consulted prior * to memory access (see {@link #checkValidStateRaw()}). * There are two kinds of memory session: confined memory session and shared memory session. * A confined memory session has an associated owner thread that confines some operations to @@ -52,30 +50,54 @@ * shared sessions use a more sophisticated synchronization mechanism, which guarantees that no concurrent * access is possible when a session is being closed (see {@link jdk.internal.misc.ScopedMemoryAccess}). */ -public abstract non-sealed class MemorySessionImpl implements MemorySession, SegmentAllocator { - final ResourceList resourceList; - final Cleaner.Cleanable cleanable; - final Thread owner; - +public abstract sealed class MemorySessionImpl + implements SegmentScope, SegmentAllocator + permits ConfinedSession, GlobalSession, SharedSession { static final int OPEN = 0; static final int CLOSING = -1; static final int CLOSED = -2; - int state = OPEN; - static final VarHandle STATE; + static final int MAX_FORKS = Integer.MAX_VALUE; + + public static final MemorySessionImpl GLOBAL = new GlobalSession(null); + + static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed); + static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread); + + final ResourceList resourceList; + final Thread owner; + int state = OPEN; static { try { STATE = MethodHandles.lookup().findVarHandle(MemorySessionImpl.class, "state", int.class); - } catch (Throwable ex) { + } catch (Exception ex) { throw new ExceptionInInitializerError(ex); } } - static final int MAX_FORKS = Integer.MAX_VALUE; + public Arena asArena() { + return new Arena() { + @Override + public SegmentScope scope() { + return MemorySessionImpl.this; + } + + @Override + public void close() { + MemorySessionImpl.this.close(); + } + + @Override + public boolean isCloseableBy(Thread thread) { + Objects.requireNonNull(thread); + return ownerThread() == null || // shared + ownerThread() == thread; + } + }; + } - @Override public void addCloseAction(Runnable runnable) { Objects.requireNonNull(runnable); addInternal(ResourceList.ResourceCleanup.ofRunnable(runnable)); @@ -111,45 +133,33 @@ void addInternal(ResourceList.ResourceCleanup resource) { resourceList.add(resource); } - protected MemorySessionImpl(Thread owner, ResourceList resourceList, Cleaner cleaner) { + protected MemorySessionImpl(Thread owner, ResourceList resourceList) { this.owner = owner; this.resourceList = resourceList; - cleanable = (cleaner != null) ? - cleaner.register(this, resourceList) : null; } - public static MemorySession createConfined(Thread thread, Cleaner cleaner) { - return new ConfinedSession(thread, cleaner); + public static MemorySessionImpl createConfined(Thread thread) { + return new ConfinedSession(thread); } - public static MemorySession createShared(Cleaner cleaner) { - return new SharedSession(cleaner); + public static MemorySessionImpl createShared() { + return new SharedSession(); } - public static MemorySessionImpl createImplicit() { - return new ImplicitSession(); + public static MemorySessionImpl createImplicit(Cleaner cleaner) { + return new ImplicitSession(cleaner); } @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - return MemorySegment.allocateNative(bytesSize, bytesAlignment, this); + public MemorySegment allocate(long byteSize, long byteAlignment) { + Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment); + return NativeMemorySegmentImpl.makeNativeSegment(byteSize, byteAlignment, this); } public abstract void release0(); public abstract void acquire0(); - @Override - public final boolean equals(Object o) { - return (o instanceof MemorySession other) && - toSessionImpl(other) == this; - } - - @Override - public final int hashCode() { - return super.hashCode(); - } - @Override public void whileAlive(Runnable action) { Objects.requireNonNull(action); @@ -161,14 +171,21 @@ public void whileAlive(Runnable action) { } } - /** - * Returns "owner" thread of this session. - * @return owner thread (or null for a shared session) - */ public final Thread ownerThread() { return owner; } + public static boolean sameOwnerThread(SegmentScope session1, SegmentScope session2) { + return ((MemorySessionImpl) session1).ownerThread() == + ((MemorySessionImpl) session2).ownerThread(); + } + + @Override + public final boolean isAccessibleBy(Thread thread) { + Objects.requireNonNull(thread); + return owner == thread; + } + /** * Returns true, if this session is still open. This method may be called in any thread. * @return {@code true} if this session is not closed yet. @@ -177,18 +194,6 @@ public boolean isAlive() { return state >= OPEN; } - @Override - public MemorySession asNonCloseable() { - return isCloseable() ? - new NonCloseableView(this) : this; - } - - @ForceInline - public static MemorySessionImpl toSessionImpl(MemorySession session) { - return session instanceof MemorySessionImpl sessionImpl ? - sessionImpl : ((NonCloseableView)session).session; - } - /** * This is a faster version of {@link #checkValidState()}, which is called upon memory access, and which * relies on invariants associated with the memory session implementations (volatile access @@ -225,7 +230,6 @@ protected Object clone() throws CloneNotSupportedException { throw new CloneNotSupportedException(); } - @Override public boolean isCloseable() { return true; } @@ -235,163 +239,15 @@ public boolean isCloseable() { * @throws IllegalStateException if this session is already closed or if this is * a confined session and this method is called outside of the owner thread. */ - @Override public void close() { - try { - justClose(); - if (cleanable != null) { - cleanable.clean(); - } else { - resourceList.cleanup(); - } - } finally { - Reference.reachabilityFence(this); - } + justClose(); + resourceList.cleanup(); } abstract void justClose(); - /** - * The global, non-closeable, shared session. Similar to a shared session, but its {@link #close()} method throws unconditionally. - * Adding new resources to the global session, does nothing: as the session can never become not-alive, there is nothing to track. - * Acquiring and or releasing a memory session similarly does nothing. - */ - static class GlobalSessionImpl extends MemorySessionImpl { - - final Object ref; - - public GlobalSessionImpl(Object ref) { - super(null, null ,null); - this.ref = ref; - } - - @Override - @ForceInline - public void release0() { - // do nothing - } - - @Override - public boolean isCloseable() { - return false; - } - - @Override - @ForceInline - public void acquire0() { - // do nothing - } - - @Override - void addInternal(ResourceList.ResourceCleanup resource) { - // do nothing - } - - @Override - public void justClose() { - throw nonCloseable(); - } - } - - public static final MemorySessionImpl GLOBAL = new GlobalSessionImpl(null); - public static MemorySessionImpl heapSession(Object ref) { - return new GlobalSessionImpl(ref); - } - - /** - * This is an implicit, GC-backed memory session. Implicit sessions cannot be closed explicitly. - * While it would be possible to model an implicit session as a non-closeable view of a shared - * session, it is better to capture the fact that an implicit session is not just a non-closeable - * view of some session which might be closeable. This is useful e.g. in the implementations of - * {@link DirectBuffer#address()}, where obtaining an address of a buffer instance associated - * with a potentially closeable session is forbidden. - */ - static class ImplicitSession extends SharedSession { - - public ImplicitSession() { - super(CleanerFactory.cleaner()); - } - - @Override - public void release0() { - Reference.reachabilityFence(this); - } - - @Override - public void acquire0() { - // do nothing - } - - @Override - public boolean isCloseable() { - return false; - } - - @Override - public void justClose() { - throw nonCloseable(); - } - } - - /** - * This is a non-closeable view of another memory session. Instances of this class are used in resource session - * accessors (see {@link MemorySegment#session()}). This class forwards all session methods to the underlying - * "root" session implementation, and throws {@link UnsupportedOperationException} on close. This class contains - * a strong reference to the original session, so even if the original session is dropped by the client - * it would still be reachable by the GC, which is important if the session is implicitly closed. - */ - public final static class NonCloseableView implements MemorySession { - final MemorySessionImpl session; - - public NonCloseableView(MemorySessionImpl session) { - this.session = session; - } - - @Override - public boolean isAlive() { - return session.isAlive(); - } - - @Override - public boolean isCloseable() { - return false; - } - - @Override - public Thread ownerThread() { - return session.ownerThread(); - } - - @Override - public boolean equals(Object o) { - return session.equals(o); - } - - @Override - public int hashCode() { - return session.hashCode(); - } - - @Override - public void whileAlive(Runnable action) { - session.whileAlive(action); - } - - @Override - public MemorySession asNonCloseable() { - return this; - } - - @Override - public void addCloseAction(Runnable runnable) { - session.addCloseAction(runnable); - } - - @Override - public void close() { - throw new UnsupportedOperationException(); - } + return new GlobalSession(ref); } /** @@ -464,7 +320,4 @@ static UnsupportedOperationException nonCloseable() { return new UnsupportedOperationException("Attempted to close a non-closeable session"); } - static final ScopedMemoryAccess.ScopedAccessError ALREADY_CLOSED = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::alreadyClosed); - - static final ScopedMemoryAccess.ScopedAccessError WRONG_THREAD = new ScopedMemoryAccess.ScopedAccessError(MemorySessionImpl::wrongThread); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java index 6d3c786550f..388937b823d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java @@ -26,10 +26,11 @@ package jdk.internal.foreign; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; +import java.util.Optional; + import jdk.internal.misc.Unsafe; import jdk.internal.misc.VM; import jdk.internal.vm.annotation.ForceInline; @@ -39,51 +40,42 @@ * Implementation for native memory segments. A native memory segment is essentially a wrapper around * a native long address. */ -public class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl { - - public static final MemorySegment EVERYTHING = new NativeMemorySegmentImpl(0, Long.MAX_VALUE, false, MemorySessionImpl.GLOBAL) { - @Override - void checkBounds(long offset, long length) { - // do nothing - } +public sealed class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl permits MappedMemorySegmentImpl { - @Override - NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) { - throw new IllegalStateException(); - } - }; - - private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final Unsafe UNSAFE = Unsafe.getUnsafe(); // The maximum alignment supported by malloc - typically 16 on // 64-bit platforms and 8 on 32-bit platforms. private static final long MAX_MALLOC_ALIGN = Unsafe.ADDRESS_SIZE == 4 ? 8 : 16; - - private static final boolean skipZeroMemory = GetBooleanAction.privilegedGetProperty("jdk.internal.foreign.skipZeroMemory"); + private static final boolean SKIP_ZERO_MEMORY = GetBooleanAction.privilegedGetProperty("jdk.internal.foreign.skipZeroMemory"); final long min; @ForceInline - NativeMemorySegmentImpl(long min, long length, boolean readOnly, MemorySession session) { + NativeMemorySegmentImpl(long min, long length, boolean readOnly, SegmentScope session) { super(length, readOnly, session); this.min = min; } - @ForceInline @Override - public MemoryAddress address() { - checkValidState(); - return MemoryAddress.ofLong(unsafeGetOffset()); + public long address() { + return min; + } + + @Override + public Optional array() { + return Optional.empty(); } + @ForceInline @Override - NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, MemorySession session) { + NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session) { return new NativeMemorySegmentImpl(min + offset, size, readOnly, session); } @Override ByteBuffer makeByteBuffer() { - return nioAccess.newDirectByteBuffer(min, (int) this.length, null, + return NIO_ACCESS.newDirectByteBuffer(min, (int) this.length, null, session == MemorySessionImpl.GLOBAL ? null : this); } @@ -109,42 +101,62 @@ public long maxAlignMask() { // factories - public static MemorySegment makeNativeSegment(long bytesSize, long alignmentBytes, MemorySession session) { - MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session); + public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, SegmentScope session) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; sessionImpl.checkValidState(); if (VM.isDirectMemoryPageAligned()) { - alignmentBytes = Math.max(alignmentBytes, nioAccess.pageSize()); + byteAlignment = Math.max(byteAlignment, NIO_ACCESS.pageSize()); } - long alignedSize = Math.max(1L, alignmentBytes > MAX_MALLOC_ALIGN ? - bytesSize + (alignmentBytes - 1) : - bytesSize); + long alignedSize = Math.max(1L, byteAlignment > MAX_MALLOC_ALIGN ? + byteSize + (byteAlignment - 1) : + byteSize); - nioAccess.reserveMemory(alignedSize, bytesSize); + NIO_ACCESS.reserveMemory(alignedSize, byteSize); - long buf = unsafe.allocateMemory(alignedSize); - if (!skipZeroMemory) { - unsafe.setMemory(buf, alignedSize, (byte)0); + long buf = UNSAFE.allocateMemory(alignedSize); + if (!SKIP_ZERO_MEMORY) { + UNSAFE.setMemory(buf, alignedSize, (byte)0); } - long alignedBuf = Utils.alignUp(buf, alignmentBytes); + long alignedBuf = Utils.alignUp(buf, byteAlignment); AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize, false, session); sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { @Override public void cleanup() { - unsafe.freeMemory(buf); - nioAccess.unreserveMemory(alignedSize, bytesSize); + UNSAFE.freeMemory(buf); + NIO_ACCESS.unreserveMemory(alignedSize, byteSize); } }); - if (alignedSize != bytesSize) { + if (alignedSize != byteSize) { long delta = alignedBuf - buf; - segment = segment.asSlice(delta, bytesSize); + segment = segment.asSlice(delta, byteSize); } return segment; } - public static MemorySegment makeNativeSegmentUnchecked(MemoryAddress min, long bytesSize, MemorySession session) { - MemorySessionImpl.toSessionImpl(session).checkValidState(); - AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(min.toRawLongValue(), bytesSize, false, session); - return segment; + // Unsafe native segment factories. These are used by the implementation code, to skip the sanity checks + // associated with MemorySegment::ofAddress. + + @ForceInline + public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope session, Runnable action) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + if (action == null) { + sessionImpl.checkValidState(); + } else { + sessionImpl.addCloseAction(action); + } + return new NativeMemorySegmentImpl(min, byteSize, false, session); + } + + @ForceInline + public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope session) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + sessionImpl.checkValidState(); + return new NativeMemorySegmentImpl(min, byteSize, false, session); + } + + @ForceInline + public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize) { + return new NativeMemorySegmentImpl(min, byteSize, false, SegmentScope.global()); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/PlatformLayouts.java b/src/java.base/share/classes/jdk/internal/foreign/PlatformLayouts.java index ab99b1fabeb..6307b7a5737 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/PlatformLayouts.java +++ b/src/java.base/share/classes/jdk/internal/foreign/PlatformLayouts.java @@ -25,10 +25,13 @@ */ package jdk.internal.foreign; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.ValueLayout; -public class PlatformLayouts { +public final class PlatformLayouts { + + private PlatformLayouts() { + //just the one + } /** * This class defines layout constants modelling standard primitive types supported by the x64 SystemV ABI. @@ -81,7 +84,7 @@ private SysV() { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64).asUnbounded(); /** * The {@code va_list} native type, as it is passed to a function. @@ -140,7 +143,7 @@ private Win64() { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64).asUnbounded(); /** * The {@code va_list} native type, as it is passed to a function. @@ -200,7 +203,7 @@ private AArch64() { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64).asUnbounded(); /** * The {@code va_list} native type, as it is passed to a function. diff --git a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java index 0955d66d91f..984d9d99921 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SharedSession.java @@ -40,12 +40,12 @@ * Since it is the responsibility of the closing thread to make sure that no concurrent access is possible, * checking the liveness bit upon access can be performed in plain mode, as in the confined case. */ -class SharedSession extends MemorySessionImpl { +sealed class SharedSession extends MemorySessionImpl permits ImplicitSession { private static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - SharedSession(Cleaner cleaner) { - super(null, new SharedResourceList(), cleaner); + SharedSession() { + super(null, new SharedResourceList()); } @Override diff --git a/src/java.base/share/classes/java/lang/foreign/Addressable.java b/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java similarity index 51% rename from src/java.base/share/classes/java/lang/foreign/Addressable.java rename to src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java index c1b8f5fc29d..435381a3021 100644 --- a/src/java.base/share/classes/java/lang/foreign/Addressable.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SlicingAllocator.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, 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,25 +23,35 @@ * questions. */ -package java.lang.foreign; +package jdk.internal.foreign; -import jdk.internal.javac.PreviewFeature; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; -/** - * An object that may be projected down to a {@linkplain #address() memory address}. - * Examples of addressable types are {@link MemorySegment}, {@link MemoryAddress} and {@link VaList}. - *

    - * The {@link Addressable} type is used by a {@linkplain Linker linker} to model the types of - * {@linkplain Linker#downcallHandle(FunctionDescriptor) downcall handle} parameters that must be passed by reference - * (e.g. memory addresses, variable argument lists and upcall stubs). - * - * @since 19 - */ -@PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) -public sealed interface Addressable permits MemorySegment, MemoryAddress, VaList { +public final class SlicingAllocator implements SegmentAllocator { + + private final MemorySegment segment; + private final long maxAlign; + + private long sp = 0L; + + public SlicingAllocator(MemorySegment segment) { + this.segment = segment; + this.maxAlign = ((AbstractMemorySegmentImpl)segment).maxAlignMask(); + } + + MemorySegment trySlice(long byteSize, long byteAlignment) { + long min = segment.address(); + long start = Utils.alignUp(min + sp, byteAlignment) - min; + MemorySegment slice = segment.asSlice(start, byteSize); + sp = start + byteSize; + return slice; + } - /** - * {@return the {@linkplain MemoryAddress memory address} associated with this addressable} - */ - MemoryAddress address(); + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + Utils.checkAllocationSizeAndAlign(byteSize, byteAlignment, maxAlign); + // try to slice from current segment first... + return trySlice(byteSize, byteAlignment); + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java index 0e526577c62..8fad1abf294 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java +++ b/src/java.base/share/classes/jdk/internal/foreign/SystemLookup.java @@ -25,9 +25,8 @@ package jdk.internal.foreign; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandles; import java.nio.file.Files; @@ -41,32 +40,32 @@ import static java.lang.foreign.ValueLayout.ADDRESS; -public class SystemLookup implements SymbolLookup { +public final class SystemLookup implements SymbolLookup { private SystemLookup() { } - static final SystemLookup INSTANCE = new SystemLookup(); + private static final SystemLookup INSTANCE = new SystemLookup(); /* A fallback lookup, used when creation of system lookup fails. */ - private static final SymbolLookup fallbackLookup = name -> Optional.empty(); + private static final SymbolLookup FALLBACK_LOOKUP = name -> Optional.empty(); /* * On POSIX systems, dlsym will allow us to lookup symbol in library dependencies; the same trick doesn't work * on Windows. For this reason, on Windows we do not generate any side-library, and load msvcrt.dll directly instead. */ - private static final SymbolLookup syslookup = makeSystemLookup(); + private static final SymbolLookup SYSTEM_LOOKUP = makeSystemLookup(); - private static final SymbolLookup makeSystemLookup() { + private static SymbolLookup makeSystemLookup() { try { return switch (CABI.current()) { - case SysV, LinuxAArch64, MacOsAArch64 -> libLookup(libs -> libs.load(jdkLibraryPath("syslookup"))); - case Win64 -> makeWindowsLookup(); // out of line to workaround javac crash + case SYS_V, LINUX_AARCH_64, MAC_OS_AARCH_64 -> libLookup(libs -> libs.load(jdkLibraryPath("syslookup"))); + case WIN_64 -> makeWindowsLookup(); // out of line to workaround javac crash }; } catch (Throwable ex) { // This can happen in the event of a library loading failure - e.g. if one of the libraries the // system lookup depends on cannot be loaded for some reason. In such extreme cases, rather than // fail, return a dummy lookup. - return fallbackLookup; + return FALLBACK_LOOKUP; } } @@ -86,14 +85,14 @@ private static SymbolLookup makeWindowsLookup() { libLookup(libs -> libs.load(jdkLibraryPath("syslookup"))); int numSymbols = WindowsFallbackSymbols.values().length; - MemorySegment funcs = MemorySegment.ofAddress(fallbackLibLookup.lookup("funcs").orElseThrow().address(), - ADDRESS.byteSize() * numSymbols, MemorySession.global()); + MemorySegment funcs = MemorySegment.ofAddress(fallbackLibLookup.find("funcs").orElseThrow().address(), + ADDRESS.byteSize() * numSymbols, SegmentScope.global()); Function> fallbackLookup = name -> Optional.ofNullable(WindowsFallbackSymbols.valueOfOrNull(name)) - .map(symbol -> MemorySegment.ofAddress(funcs.getAtIndex(ADDRESS, symbol.ordinal()), 0L, MemorySession.global())); + .map(symbol -> MemorySegment.ofAddress(funcs.getAtIndex(ADDRESS, symbol.ordinal()).address(), 0L, SegmentScope.global())); final SymbolLookup finalLookup = lookup; - lookup = name -> finalLookup.lookup(name).or(() -> fallbackLookup.apply(name)); + lookup = name -> finalLookup.find(name).or(() -> fallbackLookup.apply(name)); } return lookup; @@ -107,7 +106,7 @@ private static SymbolLookup libLookup(Function "lib"; - case Win64 -> "bin"; + case SYS_V, LINUX_AARCH_64, MAC_OS_AARCH_64 -> "lib"; + case WIN_64 -> "bin"; }; String libname = System.mapLibraryName(name); return javahome.resolve(lib).resolve(libname); @@ -133,8 +132,8 @@ public static SystemLookup getInstance() { } @Override - public Optional lookup(String name) { - return syslookup.lookup(name); + public Optional find(String name) { + return SYSTEM_LOOKUP.find(name); } // fallback symbols missing from ucrtbase.dll diff --git a/src/java.base/share/classes/jdk/internal/foreign/Utils.java b/src/java.base/share/classes/jdk/internal/foreign/Utils.java index 0c43fefa284..f00c49bb442 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Utils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/Utils.java @@ -26,7 +26,6 @@ package jdk.internal.foreign; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import java.lang.foreign.SegmentAllocator; @@ -49,11 +48,12 @@ public final class Utils { private static final MethodHandle BYTE_TO_BOOL; private static final MethodHandle BOOL_TO_BYTE; private static final MethodHandle ADDRESS_TO_LONG; - private static final MethodHandle LONG_TO_ADDRESS; - public static final MethodHandle MH_bitsToBytesOrThrowForOffset; + private static final MethodHandle LONG_TO_ADDRESS_SAFE; + private static final MethodHandle LONG_TO_ADDRESS_UNSAFE; + public static final MethodHandle MH_BITS_TO_BYTES_OR_THROW_FOR_OFFSET; - public static final Supplier bitsToBytesThrowOffset - = () -> new UnsupportedOperationException("Cannot compute byte offset; bit offset is not a multiple of 8"); + public static final Supplier BITS_TO_BYTES_THROW_OFFSET + = () -> new UnsupportedOperationException("Cannot compute byte offset; bit offset is not a multiple of 8"); static { try { @@ -62,15 +62,17 @@ public final class Utils { MethodType.methodType(boolean.class, byte.class)); BOOL_TO_BYTE = lookup.findStatic(Utils.class, "booleanToByte", MethodType.methodType(byte.class, boolean.class)); - ADDRESS_TO_LONG = lookup.findVirtual(MemoryAddress.class, "toRawLongValue", + ADDRESS_TO_LONG = lookup.findVirtual(MemorySegment.class, "address", MethodType.methodType(long.class)); - LONG_TO_ADDRESS = lookup.findStatic(MemoryAddress.class, "ofLong", - MethodType.methodType(MemoryAddress.class, long.class)); - MH_bitsToBytesOrThrowForOffset = MethodHandles.insertArguments( - lookup.findStatic(Utils.class, "bitsToBytesOrThrow", - MethodType.methodType(long.class, long.class, Supplier.class)), - 1, - bitsToBytesThrowOffset); + LONG_TO_ADDRESS_SAFE = lookup.findStatic(Utils.class, "longToAddressSafe", + MethodType.methodType(MemorySegment.class, long.class)); + LONG_TO_ADDRESS_UNSAFE = lookup.findStatic(Utils.class, "longToAddressUnsafe", + MethodType.methodType(MemorySegment.class, long.class)); + MH_BITS_TO_BYTES_OR_THROW_FOR_OFFSET = MethodHandles.insertArguments( + lookup.findStatic(Utils.class, "bitsToBytesOrThrow", + MethodType.methodType(long.class, long.class, Supplier.class)), + 1, + BITS_TO_BYTES_THROW_OFFSET); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } @@ -80,13 +82,8 @@ public static long alignUp(long n, long alignment) { return (n + alignment - 1) & -alignment; } - public static MemoryAddress alignUp(MemoryAddress ma, long alignment) { - long offset = ma.toRawLongValue(); - return ma.addOffset(alignUp(offset, alignment) - offset); - } - public static MemorySegment alignUp(MemorySegment ms, long alignment) { - long offset = ms.address().toRawLongValue(); + long offset = ms.address(); return ms.asSlice(alignUp(offset, alignment) - offset); } @@ -108,7 +105,7 @@ static VarHandle put(ValueLayout layout, VarHandle handle) { } } Class baseCarrier = layout.carrier(); - if (layout.carrier() == MemoryAddress.class) { + if (layout.carrier() == MemorySegment.class) { baseCarrier = switch ((int) ValueLayout.ADDRESS.byteSize()) { case 8 -> long.class; case 4 -> int.class; @@ -123,15 +120,16 @@ static VarHandle put(ValueLayout layout, VarHandle handle) { if (layout.carrier() == boolean.class) { handle = MethodHandles.filterValue(handle, BOOL_TO_BYTE, BYTE_TO_BOOL); - } else if (layout.carrier() == MemoryAddress.class) { + } else if (layout instanceof ValueLayout.OfAddress addressLayout) { handle = MethodHandles.filterValue(handle, - MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemoryAddress.class)), - MethodHandles.explicitCastArguments(LONG_TO_ADDRESS, MethodType.methodType(MemoryAddress.class, baseCarrier))); + MethodHandles.explicitCastArguments(ADDRESS_TO_LONG, MethodType.methodType(baseCarrier, MemorySegment.class)), + MethodHandles.explicitCastArguments(addressLayout.isUnbounded() ? + LONG_TO_ADDRESS_UNSAFE : LONG_TO_ADDRESS_SAFE, MethodType.methodType(MemorySegment.class, baseCarrier))); } return VarHandleCache.put(layout, handle); } - private static boolean byteToBoolean(byte b) { + public static boolean byteToBoolean(byte b) { return b != 0; } @@ -139,6 +137,16 @@ private static byte booleanToByte(boolean b) { return b ? (byte)1 : (byte)0; } + @ForceInline + private static MemorySegment longToAddressSafe(long addr) { + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, 0); + } + + @ForceInline + private static MemorySegment longToAddressUnsafe(long addr) { + return NativeMemorySegmentImpl.makeNativeSegmentUnchecked(addr, Long.MAX_VALUE); + } + public static void copy(MemorySegment addr, byte[] bytes) { var heapSegment = MemorySegment.ofArray(bytes); addr.copyFrom(heapSegment); @@ -163,16 +171,31 @@ public static void checkElementAlignment(MemoryLayout layout, String msg) { } } - public static void checkAllocationSizeAndAlign(long bytesSize, long alignmentBytes) { + public static long pointeeSize(MemoryLayout layout) { + if (layout instanceof ValueLayout.OfAddress addressLayout) { + return addressLayout.isUnbounded() ? Long.MAX_VALUE : 0L; + } else { + throw new UnsupportedOperationException(); + } + } + + public static void checkAllocationSizeAndAlign(long byteSize, long byteAlignment, long maxAlignment) { + checkAllocationSizeAndAlign(byteSize, byteAlignment); + if (maxAlignment != 0 && byteAlignment > maxAlignment) { + throw new IllegalArgumentException("Invalid alignment constraint : " + byteAlignment + " > " + maxAlignment); + } + } + + public static void checkAllocationSizeAndAlign(long byteSize, long byteAlignment) { // size should be >= 0 - if (bytesSize < 0) { - throw new IllegalArgumentException("Invalid allocation size : " + bytesSize); + if (byteSize < 0) { + throw new IllegalArgumentException("Invalid allocation size : " + byteSize); } // alignment should be > 0, and power of two - if (alignmentBytes <= 0 || - ((alignmentBytes & (alignmentBytes - 1)) != 0L)) { - throw new IllegalArgumentException("Invalid alignment constraint : " + alignmentBytes); + if (byteAlignment <= 0 || + ((byteAlignment & (byteAlignment - 1)) != 0L)) { + throw new IllegalArgumentException("Invalid alignment constraint : " + byteAlignment); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index 2cafff4f424..ef5ab91142d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -29,11 +29,15 @@ import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; +import jdk.internal.foreign.layout.AbstractLayout; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SequenceLayout; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.Objects; @@ -41,29 +45,35 @@ public abstract sealed class AbstractLinker implements Linker permits LinuxAArch64Linker, MacOsAArch64Linker, SysVx64Linker, Windowsx64Linker { - private final SoftReferenceCache DOWNCALL_CACHE = new SoftReferenceCache<>(); + private record LinkRequest(FunctionDescriptor descriptor, LinkerOptions options) {} + private final SoftReferenceCache DOWNCALL_CACHE = new SoftReferenceCache<>(); @Override - public MethodHandle downcallHandle(FunctionDescriptor function) { + public MethodHandle downcallHandle(FunctionDescriptor function, Option... options) { Objects.requireNonNull(function); + Objects.requireNonNull(options); + checkHasNaturalAlignment(function); + LinkerOptions optionSet = LinkerOptions.of(options); - return DOWNCALL_CACHE.get(function, fd -> { - MethodType type = SharedUtils.inferMethodType(fd, false); - MethodHandle handle = arrangeDowncall(type, fd); - handle = SharedUtils.maybeInsertAllocator(handle); + return DOWNCALL_CACHE.get(new LinkRequest(function, optionSet), linkRequest -> { + FunctionDescriptor fd = linkRequest.descriptor(); + MethodType type = fd.toMethodType(); + MethodHandle handle = arrangeDowncall(type, fd, linkRequest.options()); + handle = SharedUtils.maybeInsertAllocator(fd, handle); return handle; }); } - protected abstract MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function); + protected abstract MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options); @Override - public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, MemorySession scope) { + public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function, SegmentScope scope) { Objects.requireNonNull(scope); Objects.requireNonNull(target); Objects.requireNonNull(function); + checkHasNaturalAlignment(function); SharedUtils.checkExceptions(target); - MethodType type = SharedUtils.inferMethodType(function, true); + MethodType type = function.toMethodType(); if (!type.equals(target.type())) { throw new IllegalArgumentException("Wrong method handle type: " + target.type()); } @@ -71,10 +81,35 @@ public MemorySegment upcallStub(MethodHandle target, FunctionDescriptor function } protected abstract MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, - FunctionDescriptor function, MemorySession scope); + FunctionDescriptor function, SegmentScope scope); @Override public SystemLookup defaultLookup() { return SystemLookup.getInstance(); } + + // Current limitation of the implementation: + // We don't support packed structs on some platforms, + // so reject them here explicitly + private static void checkHasNaturalAlignment(FunctionDescriptor descriptor) { + descriptor.returnLayout().ifPresent(AbstractLinker::checkHasNaturalAlignmentRecursive); + descriptor.argumentLayouts().forEach(AbstractLinker::checkHasNaturalAlignmentRecursive); + } + + private static void checkHasNaturalAlignmentRecursive(MemoryLayout layout) { + checkHasNaturalAlignment(layout); + if (layout instanceof GroupLayout gl) { + for (MemoryLayout member : gl.memberLayouts()) { + checkHasNaturalAlignmentRecursive(member); + } + } else if (layout instanceof SequenceLayout sl) { + checkHasNaturalAlignmentRecursive(sl.elementLayout()); + } + } + + private static void checkHasNaturalAlignment(MemoryLayout layout) { + if (!((AbstractLayout) layout).hasNaturalAlignment()) { + throw new IllegalArgumentException("Layout bit alignment must be natural alignment: " + layout); + } + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java index 96a74a897b2..39c1116a2ca 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java @@ -24,27 +24,19 @@ */ package jdk.internal.foreign.abi; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; +import jdk.internal.foreign.NativeMemorySegmentImpl; + +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.ValueLayout; -import jdk.internal.foreign.MemoryAddressImpl; - import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.Deque; import java.util.List; -import java.util.Objects; - -import java.lang.invoke.VarHandle; -import java.nio.ByteOrder; - -import static java.lang.invoke.MethodType.methodType; /** * The binding operators defined in the Binding class can be combined into argument and return value processing 'recipes'. @@ -199,19 +191,19 @@ * * -------------------- */ -public abstract class Binding { +public interface Binding { /** * A binding context is used as an helper to carry out evaluation of certain bindings; for instance, * it helps {@link Allocate} bindings, by providing the {@link SegmentAllocator} that should be used for - * the allocation operation, or {@link ToSegment} bindings, by providing the {@link MemorySession} that + * the allocation operation, or {@link BoxAddress} bindings, by providing the {@link SegmentScope} that * should be used to create an unsafe struct from a memory address. */ - public static class Context implements AutoCloseable { + class Context implements AutoCloseable { private final SegmentAllocator allocator; - private final MemorySession session; + private final SegmentScope session; - private Context(SegmentAllocator allocator, MemorySession session) { + private Context(SegmentAllocator allocator, SegmentScope session) { this.allocator = allocator; this.session = session; } @@ -220,21 +212,26 @@ public SegmentAllocator allocator() { return allocator; } - public MemorySession session() { + public SegmentScope session() { return session; } @Override public void close() { - session().close(); + throw new UnsupportedOperationException(); } /** * Create a binding context from given native scope. */ public static Context ofBoundedAllocator(long size) { - MemorySession scope = MemorySession.openConfined(); - return new Context(SegmentAllocator.newNativeArena(size, scope), scope); + Arena arena = Arena.openConfined(); + return new Context(SegmentAllocator.slicingAllocator(MemorySegment.allocateNative(size, arena.scope())), arena.scope()) { + @Override + public void close() { + arena.close(); + } + }; } /** @@ -244,7 +241,7 @@ public static Context ofBoundedAllocator(long size) { public static Context ofAllocator(SegmentAllocator allocator) { return new Context(allocator, null) { @Override - public MemorySession session() { + public SegmentScope session() { throw new UnsupportedOperationException(); } }; @@ -255,10 +252,15 @@ public MemorySession session() { * the context's allocator is accessed. */ public static Context ofSession() { - MemorySession scope = MemorySession.openConfined(); - return new Context(null, scope) { + Arena arena = Arena.openConfined(); + return new Context(null, arena.scope()) { @Override public SegmentAllocator allocator() { throw new UnsupportedOperationException(); } + + @Override + public void close() { + arena.close(); + } }; } @@ -273,7 +275,7 @@ public SegmentAllocator allocator() { } @Override - public MemorySession session() { + public SegmentScope session() { throw new UnsupportedOperationException(); } @@ -293,24 +295,16 @@ enum Tag { ALLOC_BUFFER, BOX_ADDRESS, UNBOX_ADDRESS, - TO_SEGMENT, - DUP + DUP, + CAST } - private final Tag tag; + Tag tag(); - private Binding(Tag tag) { - this.tag = tag; - } - - public Tag tag() { - return tag; - } + void verify(Deque> stack); - public abstract void verify(Deque> stack); - - public abstract void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, - BindingInterpreter.LoadFunc loadFunc, Context context); + void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, + BindingInterpreter.LoadFunc loadFunc, Context context); private static void checkType(Class type) { if (!type.isPrimitive() || type == void.class) @@ -322,91 +316,93 @@ private static void checkOffset(long offset) { throw new IllegalArgumentException("Negative offset: " + offset); } - public static VMStore vmStore(VMStorage storage, Class type) { + static VMStore vmStore(VMStorage storage, Class type) { checkType(type); return new VMStore(storage, type); } - public static VMLoad vmLoad(VMStorage storage, Class type) { + static VMLoad vmLoad(VMStorage storage, Class type) { checkType(type); return new VMLoad(storage, type); } - public static BufferStore bufferStore(long offset, Class type) { + static BufferStore bufferStore(long offset, Class type) { checkType(type); checkOffset(offset); return new BufferStore(offset, type); } - public static BufferLoad bufferLoad(long offset, Class type) { + static BufferLoad bufferLoad(long offset, Class type) { checkType(type); checkOffset(offset); return new BufferLoad(offset, type); } - public static Copy copy(MemoryLayout layout) { + static Copy copy(MemoryLayout layout) { return new Copy(layout.byteSize(), layout.byteAlignment()); } - public static Allocate allocate(MemoryLayout layout) { + static Allocate allocate(MemoryLayout layout) { return new Allocate(layout.byteSize(), layout.byteAlignment()); } - public static BoxAddress boxAddress() { - return BoxAddress.INSTANCE; - } - - public static UnboxAddress unboxAddress() { - return UnboxAddress.INSTANCE.get(MemoryAddress.class); + static BoxAddress boxAddressRaw(long size) { + return new BoxAddress(size, false); } - public static UnboxAddress unboxAddress(Class carrier) { - return UnboxAddress.INSTANCE.get(carrier); + static BoxAddress boxAddress(MemoryLayout layout) { + return new BoxAddress(layout.byteSize(), true); } - public static ToSegment toSegment(MemoryLayout layout) { - return new ToSegment(layout.byteSize()); + static BoxAddress boxAddress(long byteSize) { + return new BoxAddress(byteSize, true); } - public static ToSegment toSegment(long byteSize) { - return new ToSegment(byteSize); + static UnboxAddress unboxAddress() { + return UnboxAddress.INSTANCE; } - public static Dup dup() { + static Dup dup() { return Dup.INSTANCE; } - - public static Binding.Builder builder() { - return new Binding.Builder(); + static Binding cast(Class fromType, Class toType) { + return new Cast(fromType, toType); } - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - Binding binding = (Binding) o; - return tag == binding.tag; - } - @Override - public int hashCode() { - return Objects.hash(tag); + static Binding.Builder builder() { + return new Binding.Builder(); } /** * A builder helper class for generating lists of Bindings */ - public static class Builder { + class Builder { private final List bindings = new ArrayList<>(); + private static boolean isSubIntType(Class type) { + return type == boolean.class || type == byte.class || type == short.class || type == char.class; + } + public Binding.Builder vmStore(VMStorage storage, Class type) { + if (isSubIntType(type)) { + bindings.add(Binding.cast(type, int.class)); + type = int.class; + } bindings.add(Binding.vmStore(storage, type)); return this; } public Binding.Builder vmLoad(VMStorage storage, Class type) { - bindings.add(Binding.vmLoad(storage, type)); + Class loadType = type; + if (isSubIntType(type)) { + loadType = int.class; + } + bindings.add(Binding.vmLoad(storage, loadType)); + if (isSubIntType(type)) { + bindings.add(Binding.cast(int.class, type)); + } return this; } @@ -430,23 +426,18 @@ public Binding.Builder allocate(MemoryLayout layout) { return this; } - public Binding.Builder boxAddress() { - bindings.add(Binding.boxAddress()); - return this; - } - - public Binding.Builder unboxAddress() { - bindings.add(Binding.unboxAddress()); + public Binding.Builder boxAddressRaw(long size) { + bindings.add(Binding.boxAddressRaw(size)); return this; } - public Binding.Builder unboxAddress(Class carrier) { - bindings.add(Binding.unboxAddress(carrier)); + public Binding.Builder boxAddress(MemoryLayout layout) { + bindings.add(Binding.boxAddress(layout)); return this; } - public Binding.Builder toSegment(MemoryLayout layout) { - bindings.add(Binding.toSegment(layout)); + public Binding.Builder unboxAddress() { + bindings.add(Binding.unboxAddress()); return this; } @@ -456,42 +447,13 @@ public Binding.Builder dup() { } public List build() { - return new ArrayList<>(bindings); + return List.copyOf(bindings); } } - abstract static class Move extends Binding { - private final VMStorage storage; - private final Class type; - - private Move(Tag tag, VMStorage storage, Class type) { - super(tag); - this.storage = storage; - this.type = type; - } - - public VMStorage storage() { - return storage; - } - - public Class type() { - return type; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Move move = (Move) o; - return Objects.equals(storage, move.storage) && - Objects.equals(type, move.type); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), storage, type); - } + interface Move extends Binding { + VMStorage storage(); + Class type(); } /** @@ -499,9 +461,10 @@ public int hashCode() { * Pops a [type] from the operand stack, and moves it to [storage location] * The [type] must be one of byte, short, char, int, long, float, or double */ - public static class VMStore extends Move { - private VMStore(VMStorage storage, Class type) { - super(Tag.VM_STORE, storage, type); + record VMStore(VMStorage storage, Class type) implements Move { + @Override + public Tag tag() { + return Tag.VM_STORE; } @Override @@ -516,14 +479,6 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun BindingInterpreter.LoadFunc loadFunc, Context context) { storeFunc.store(storage(), type(), stack.pop()); } - - @Override - public String toString() { - return "VMStore{" + - "storage=" + storage() + - ", type=" + type() + - '}'; - } } /** @@ -531,9 +486,10 @@ public String toString() { * Loads a [type] from [storage location], and pushes it onto the operand stack. * The [type] must be one of byte, short, char, int, long, float, or double */ - public static class VMLoad extends Move { - private VMLoad(VMStorage storage, Class type) { - super(Tag.VM_LOAD, storage, type); + record VMLoad(VMStorage storage, Class type) implements Move { + @Override + public Tag tag() { + return Tag.VM_LOAD; } @Override @@ -546,56 +502,11 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun BindingInterpreter.LoadFunc loadFunc, Context context) { stack.push(loadFunc.load(storage(), type())); } - - @Override - public String toString() { - return "VMLoad{" + - "storage=" + storage() + - ", type=" + type() + - '}'; - } } - private abstract static class Dereference extends Binding { - private final long offset; - private final Class type; - - private Dereference(Tag tag, long offset, Class type) { - super(tag); - this.offset = offset; - this.type = type; - } - - public long offset() { - return offset; - } - - public Class type() { - return type; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Dereference that = (Dereference) o; - return offset == that.offset && - Objects.equals(type, that.type); - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), offset, type); - } - - public VarHandle varHandle() { - // alignment is set to 1 byte here to avoid exceptions for cases where we do super word - // copies of e.g. 2 int fields of a struct as a single long, while the struct is only - // 4-byte-aligned (since it only contains ints) - ValueLayout layout = MemoryLayout.valueLayout(type(), ByteOrder.nativeOrder()).withBitAlignment(8); - return MethodHandles.insertCoordinates(MethodHandles.memorySegmentViewVarHandle(layout), 1, offset); - } + interface Dereference extends Binding { + long offset(); + Class type(); } /** @@ -604,9 +515,10 @@ public VarHandle varHandle() { * Stores the [type] to [offset into memory region]. * The [type] must be one of byte, short, char, int, long, float, or double */ - public static class BufferStore extends Dereference { - private BufferStore(long offset, Class type) { - super(Tag.BUFFER_STORE, offset, type); + record BufferStore(long offset, Class type) implements Dereference { + @Override + public Tag tag() { + return Tag.BUFFER_STORE; } @Override @@ -625,14 +537,6 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun MemorySegment writeAddress = operand.asSlice(offset()); SharedUtils.write(writeAddress, type(), value); } - - @Override - public String toString() { - return "BufferStore{" + - "offset=" + offset() + - ", type=" + type() + - '}'; - } } /** @@ -641,9 +545,10 @@ public String toString() { * and then stores [type] to [offset into memory region] of the MemorySegment. * The [type] must be one of byte, short, char, int, long, float, or double */ - public static class BufferLoad extends Dereference { - private BufferLoad(long offset, Class type) { - super(Tag.BUFFER_LOAD, offset, type); + record BufferLoad(long offset, Class type) implements Dereference { + @Override + public Tag tag() { + return Tag.BUFFER_LOAD; } @Override @@ -661,14 +566,6 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun MemorySegment readAddress = operand.asSlice(offset()); stack.push(SharedUtils.read(readAddress, type())); } - - @Override - public String toString() { - return "BufferLoad{" + - "offset=" + offset() + - ", type=" + type() + - '}'; - } } /** @@ -677,36 +574,15 @@ public String toString() { * and copies contents from a MemorySegment popped from the top of the operand stack into this new buffer, * and pushes the new buffer onto the operand stack */ - public static class Copy extends Binding { - private final long size; - private final long alignment; - - private Copy(long size, long alignment) { - super(Tag.COPY_BUFFER); - this.size = size; - this.alignment = alignment; - } - + record Copy(long size, long alignment) implements Binding { private static MemorySegment copyBuffer(MemorySegment operand, long size, long alignment, Context context) { return context.allocator().allocate(size, alignment) .copyFrom(operand.asSlice(0, size)); } - public long size() { - return size; - } - - public long alignment() { - return alignment; - } - @Override - public String toString() { - return "Copy{" + - "tag=" + tag() + - ", size=" + size + - ", alignment=" + alignment + - '}'; + public Tag tag() { + return Tag.COPY_BUFFER; } @Override @@ -723,56 +599,20 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun MemorySegment copy = copyBuffer(operand, size, alignment, context); stack.push(copy); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Copy copy = (Copy) o; - return size == copy.size && - alignment == copy.alignment; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), size, alignment); - } } /** * ALLOCATE([size], [alignment]) * Creates a new MemorySegment with the give [size] and [alignment], and pushes it onto the operand stack. */ - public static class Allocate extends Binding { - private final long size; - private final long alignment; - - private Allocate(long size, long alignment) { - super(Tag.ALLOC_BUFFER); - this.size = size; - this.alignment = alignment; - } - + record Allocate(long size, long alignment) implements Binding { private static MemorySegment allocateBuffer(long size, long alignment, Context context) { return context.allocator().allocate(size, alignment); } - public long size() { - return size; - } - - public long alignment() { - return alignment; - } - @Override - public String toString() { - return "AllocateBuffer{" + - "tag=" + tag() + - "size=" + size + - ", alignment=" + alignment + - '}'; + public Tag tag() { + return Tag.ALLOC_BUFFER; } @Override @@ -785,189 +625,120 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun BindingInterpreter.LoadFunc loadFunc, Context context) { stack.push(allocateBuffer(size, alignment, context)); } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - Allocate allocate = (Allocate) o; - return size == allocate.size && - alignment == allocate.alignment; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), size, alignment); - } } /** * UNBOX_ADDRESS() * Pops a 'MemoryAddress' from the operand stack, converts it to a 'long', - * and pushes that onto the operand stack. + * with the given size, and pushes that onto the operand stack */ - public static class UnboxAddress extends Binding { - - static final ClassValue INSTANCE = new ClassValue<>() { - @Override - protected UnboxAddress computeValue(Class type) { - return new UnboxAddress(type); - } - }; - - final Class carrier; - final MethodHandle toAddress; + record UnboxAddress() implements Binding { + static final UnboxAddress INSTANCE = new UnboxAddress(); - private UnboxAddress(Class carrier) { - super(Tag.UNBOX_ADDRESS); - this.carrier = carrier; - try { - this.toAddress = MethodHandles.lookup().findVirtual(carrier, "address", MethodType.methodType(MemoryAddress.class)); - } catch (Throwable ex) { - throw new IllegalArgumentException(ex); - } + @Override + public Tag tag() { + return Tag.UNBOX_ADDRESS; } @Override public void verify(Deque> stack) { Class actualType = stack.pop(); - SharedUtils.checkType(actualType, carrier); + SharedUtils.checkType(actualType, MemorySegment.class); stack.push(long.class); } @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - stack.push(((Addressable)stack.pop()).address().toRawLongValue()); - } - - @Override - public String toString() { - return "UnboxAddress{}"; + stack.push(((MemorySegment)stack.pop()).address()); } } /** * BOX_ADDRESS() - * Pops a 'long' from the operand stack, converts it to a 'MemoryAddress', - * and pushes that onto the operand stack. + * Pops a 'long' from the operand stack, converts it to a 'MemorySegment', with the given size and memory session + * (either the context session, or the global session), and pushes that onto the operand stack. */ - public static class BoxAddress extends Binding { - private static final BoxAddress INSTANCE = new BoxAddress(); - private BoxAddress() { - super(Tag.BOX_ADDRESS); + record BoxAddress(long size, boolean needsSession) implements Binding { + + @Override + public Tag tag() { + return Tag.BOX_ADDRESS; } @Override public void verify(Deque> stack) { Class actualType = stack.pop(); SharedUtils.checkType(actualType, long.class); - stack.push(MemoryAddress.class); + stack.push(MemorySegment.class); } @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - stack.push(MemoryAddress.ofLong((long) stack.pop())); - } - - @Override - public String toString() { - return "BoxAddress{}"; + SegmentScope session = needsSession ? + context.session() : SegmentScope.global(); + stack.push(NativeMemorySegmentImpl.makeNativeSegmentUnchecked((long) stack.pop(), size, session)); } } /** - * TO_SEGMENT([size]) - * Pops a MemoryAddress from the operand stack, and converts it to a MemorySegment - * with the given size, and pushes that onto the operand stack + * DUP() + * Duplicates the value on the top of the operand stack (without popping it!), + * and pushes the duplicate onto the operand stack */ - public static class ToSegment extends Binding { - private final long size; - // FIXME alignment? - - public ToSegment(long size) { - super(Tag.TO_SEGMENT); - this.size = size; - } - - public long size() { - return size; - } + record Dup() implements Binding { + static final Dup INSTANCE = new Dup(); - private static MemorySegment toSegment(MemoryAddress operand, long size, Context context) { - return MemoryAddressImpl.ofLongUnchecked(operand.toRawLongValue(), size, context.session); + @Override + public Tag tag() { + return Tag.DUP; } @Override public void verify(Deque> stack) { - Class actualType = stack.pop(); - SharedUtils.checkType(actualType, MemoryAddress.class); - stack.push(MemorySegment.class); + stack.push(stack.peekLast()); } @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - MemoryAddress operand = (MemoryAddress) stack.pop(); - MemorySegment segment = toSegment(operand, size, context); - stack.push(segment); - } - - @Override - public String toString() { - return "ToSegemnt{" + - "size=" + size + - '}'; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - if (!super.equals(o)) return false; - ToSegment toSegemnt = (ToSegment) o; - return size == toSegemnt.size; - } - - @Override - public int hashCode() { - return Objects.hash(super.hashCode(), size); + stack.push(stack.peekLast()); } } /** - * DUP() - * Duplicates the value on the top of the operand stack (without popping it!), - * and pushes the duplicate onto the operand stack + * CAST([fromType], [toType]) + * Pop a [fromType] from the stack, convert it to [toType], and push the resulting + * value onto the stack. + * */ - public static class Dup extends Binding { - private static final Dup INSTANCE = new Dup(); - private Dup() { - super(Tag.DUP); + record Cast(Class fromType, Class toType) implements Binding { + + @Override + public Tag tag() { + return Tag.CAST; } @Override public void verify(Deque> stack) { - stack.push(stack.peekLast()); + Class actualType = stack.pop(); + SharedUtils.checkType(actualType, fromType); + stack.push(toType); } @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - stack.push(stack.peekLast()); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - return o != null && getClass() == o.getClass(); - } - - @Override - public String toString() { - return "Dup{}"; + Object arg = stack.pop(); + MethodHandle converter = MethodHandles.explicitCastArguments(MethodHandles.identity(toType), + MethodType.methodType(toType, fromType)); + try { + Object result = converter.invoke(arg); + stack.push(result); + } catch (Throwable e) { + throw new InternalError(e); + } } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 328cac67af8..13bfb7054d6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -24,9 +24,10 @@ */ package jdk.internal.foreign.abi; -import jdk.internal.foreign.MemoryAddressImpl; +import jdk.internal.foreign.AbstractMemorySegmentImpl; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; +import jdk.internal.foreign.NativeMemorySegmentImpl; +import jdk.internal.foreign.Utils; import jdk.internal.misc.VM; import jdk.internal.org.objectweb.asm.ClassReader; import jdk.internal.org.objectweb.asm.ClassWriter; @@ -43,11 +44,10 @@ import java.io.IOException; import java.io.PrintWriter; import java.lang.constant.ConstantDescs; -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -60,9 +60,7 @@ import java.util.Arrays; import java.util.Deque; import java.util.List; -import java.util.function.BiPredicate; -import static java.lang.foreign.ValueLayout.*; import static java.lang.invoke.MethodType.methodType; import static jdk.internal.org.objectweb.asm.Opcodes.*; @@ -84,14 +82,13 @@ public class BindingSpecializer { private static final String OF_BOUNDED_ALLOCATOR_DESC = methodType(Binding.Context.class, long.class).descriptorString(); private static final String OF_SESSION_DESC = methodType(Binding.Context.class).descriptorString(); private static final String ALLOCATOR_DESC = methodType(SegmentAllocator.class).descriptorString(); - private static final String SESSION_DESC = methodType(MemorySession.class).descriptorString(); + private static final String SESSION_DESC = methodType(SegmentScope.class).descriptorString(); private static final String SESSION_IMPL_DESC = methodType(MemorySessionImpl.class).descriptorString(); private static final String CLOSE_DESC = VOID_DESC; - private static final String ADDRESS_DESC = methodType(MemoryAddress.class).descriptorString(); + private static final String UNBOX_SEGMENT_DESC = methodType(long.class, MemorySegment.class).descriptorString(); private static final String COPY_DESC = methodType(void.class, MemorySegment.class, long.class, MemorySegment.class, long.class, long.class).descriptorString(); - private static final String TO_RAW_LONG_VALUE_DESC = methodType(long.class).descriptorString(); - private static final String OF_LONG_DESC = methodType(MemoryAddress.class, long.class).descriptorString(); - private static final String OF_LONG_UNCHECKED_DESC = methodType(MemorySegment.class, long.class, long.class, MemorySession.class).descriptorString(); + private static final String OF_LONG_DESC = methodType(MemorySegment.class, long.class, long.class).descriptorString(); + private static final String OF_LONG_UNCHECKED_DESC = methodType(MemorySegment.class, long.class, long.class, SegmentScope.class).descriptorString(); private static final String ALLOCATE_DESC = methodType(MemorySegment.class, long.class, long.class).descriptorString(); private static final String HANDLE_UNCAUGHT_EXCEPTION_DESC = methodType(void.class, Throwable.class).descriptorString(); private static final String METHOD_HANDLES_INTRN = Type.getInternalName(MethodHandles.class); @@ -131,7 +128,7 @@ public class BindingSpecializer { private int[] scopeSlots; private int curScopeLocalIdx = -1; private int returnAllocatorIdx = -1; - private int CONTEXT_IDX = -1; + private int contextIdx = -1; private int returnBufferIdx = -1; private int retValIdx = -1; private Deque> typeStack; @@ -248,12 +245,8 @@ private void pushType(Class type) { } private Class popType(Class expected) { - return popType(expected, ASSERT_EQUALS); - } - - private Class popType(Class expected, BiPredicate, Class> typePredicate) { - Class found; - if (!typePredicate.test(expected, found = typeStack.pop())) { + Class found = typeStack.pop(); + if (!expected.equals(found)) { throw new IllegalStateException( String.format("Invalid type on binding operand stack; found %s - expected %s", found.descriptorString(), expected.descriptorString())); @@ -261,9 +254,6 @@ private Class popType(Class expected, BiPredicate, Class> type return found; } - private static final BiPredicate, Class> ASSERT_EQUALS = Class::equals; - private static final BiPredicate, Class> ASSERT_ASSIGNABLE = Class::isAssignableFrom; - // specialization private void specialize() { @@ -288,7 +278,7 @@ private void specialize() { int[] initialScopeSlots = new int[callerMethodType.parameterCount()]; int numScopes = 0; for (int i = 0; i < callerMethodType.parameterCount(); i++) { - if (shouldAcquire(callerMethodType.parameterType(i))) { + if (shouldAcquire(i)) { int scopeLocal = newLocal(Object.class); initialScopeSlots[numScopes++] = scopeLocal; emitConst(null); @@ -308,8 +298,8 @@ private void specialize() { } else { emitGetStatic(Binding.Context.class, "DUMMY", BINDING_CONTEXT_DESC); } - CONTEXT_IDX = newLocal(Object.class); - emitStore(Object.class, CONTEXT_IDX); + contextIdx = newLocal(Object.class); + emitStore(Object.class, contextIdx); // in case the call needs a return buffer, allocate it here. // for upcalls the VM wrapper stub allocates the buffer. @@ -443,11 +433,26 @@ private void specialize() { } private boolean needsSession() { - return callingSequence.argumentBindings().anyMatch(Binding.ToSegment.class::isInstance); + return callingSequence.argumentBindings() + .filter(Binding.BoxAddress.class::isInstance) + .map(Binding.BoxAddress.class::cast) + .anyMatch(Binding.BoxAddress::needsSession); } - private static boolean shouldAcquire(Class type) { - return type == Addressable.class; + private boolean shouldAcquire(int paramIndex) { + if (!callingSequence.forDowncall() || // we only acquire in downcalls + paramIndex == 0) { // the first parameter in a downcall is SegmentAllocator + return false; + } + + // if call needs return buffer, the descriptor has an extra leading layout + int offset = callingSequence.needsReturnBuffer() ? 0 : 1; + MemoryLayout paramLayout = callingSequence.functionDesc() + .argumentLayouts() + .get(paramIndex - offset); + + // is this an address layout? + return paramLayout instanceof ValueLayout.OfAddress; } private void emitCleanup() { @@ -466,10 +471,10 @@ private void doBindings(List bindings) { case BUFFER_LOAD -> emitBufferLoad((Binding.BufferLoad) binding); case COPY_BUFFER -> emitCopyBuffer((Binding.Copy) binding); case ALLOC_BUFFER -> emitAllocBuffer((Binding.Allocate) binding); - case BOX_ADDRESS -> emitBoxAddress(); + case BOX_ADDRESS -> emitBoxAddress((Binding.BoxAddress) binding); case UNBOX_ADDRESS -> emitUnboxAddress(); - case TO_SEGMENT -> emitToSegment((Binding.ToSegment) binding); case DUP -> emitDupBinding(); + case CAST -> emitCast((Binding.Cast) binding); } } } @@ -483,7 +488,7 @@ private void emitGetInput() { Class highLevelType = callerMethodType.parameterType(paramIndex); emitLoad(highLevelType, paramIndex2ParamSlot[paramIndex]); - if (shouldAcquire(highLevelType)) { + if (shouldAcquire(paramIndex)) { emitDup(Object.class); emitAcquireScope(); } @@ -493,8 +498,8 @@ private void emitGetInput() { } private void emitAcquireScope() { - emitCheckCast(Scoped.class); - emitInvokeInterface(Scoped.class, "sessionImpl", SESSION_IMPL_DESC); + emitCheckCast(AbstractMemorySegmentImpl.class); + emitInvokeVirtual(AbstractMemorySegmentImpl.class, "sessionImpl", SESSION_IMPL_DESC); Label skipAcquire = new Label(); Label end = new Label(); @@ -510,8 +515,9 @@ private void emitAcquireScope() { // 1 scope to acquire on the stack emitDup(Object.class); int nextScopeLocal = scopeSlots[curScopeLocalIdx++]; - emitStore(Object.class, nextScopeLocal); // store off one to release later + // call acquire first here. So that if it fails, we don't call release emitInvokeVirtual(MemorySessionImpl.class, "acquire0", ACQUIRE0_DESC); // call acquire on the other + emitStore(Object.class, nextScopeLocal); // store off one to release later if (hasOtherScopes) { // avoid ASM generating a bunch of nops for the dead code mv.visitJumpInsn(GOTO, end); @@ -553,43 +559,33 @@ private int newLocal(Class type) { } private void emitLoadInternalSession() { - assert CONTEXT_IDX != -1; - emitLoad(Object.class, CONTEXT_IDX); + assert contextIdx != -1; + emitLoad(Object.class, contextIdx); emitInvokeVirtual(Binding.Context.class, "session", SESSION_DESC); } private void emitLoadInternalAllocator() { - assert CONTEXT_IDX != -1; - emitLoad(Object.class, CONTEXT_IDX); + assert contextIdx != -1; + emitLoad(Object.class, contextIdx); emitInvokeVirtual(Binding.Context.class, "allocator", ALLOCATOR_DESC); } private void emitCloseContext() { - assert CONTEXT_IDX != -1; - emitLoad(Object.class, CONTEXT_IDX); + assert contextIdx != -1; + emitLoad(Object.class, contextIdx); emitInvokeVirtual(Binding.Context.class, "close", CLOSE_DESC); } - private void emitToSegment(Binding.ToSegment binding) { - long size = binding.size(); - popType(MemoryAddress.class); - - emitToRawLongValue(); - emitConst(size); - emitLoadInternalSession(); - emitInvokeStatic(MemoryAddressImpl.class, "ofLongUnchecked", OF_LONG_UNCHECKED_DESC); - - pushType(MemorySegment.class); - } - - private void emitToRawLongValue() { - emitInvokeInterface(MemoryAddress.class, "toRawLongValue", TO_RAW_LONG_VALUE_DESC); - } - - private void emitBoxAddress() { + private void emitBoxAddress(Binding.BoxAddress boxAddress) { popType(long.class); - emitInvokeStatic(MemoryAddress.class, "ofLong", OF_LONG_DESC); - pushType(MemoryAddress.class); + emitConst(boxAddress.size()); + if (needsSession()) { + emitLoadInternalSession(); + emitInvokeStatic(NativeMemorySegmentImpl.class, "makeNativeSegmentUnchecked", OF_LONG_UNCHECKED_DESC); + } else { + emitInvokeStatic(NativeMemorySegmentImpl.class, "makeNativeSegmentUnchecked", OF_LONG_DESC); + } + pushType(MemorySegment.class); } private void emitAllocBuffer(Binding.Allocate binding) { @@ -619,7 +615,6 @@ private void emitBufferStore(Binding.BufferStore bufferStore) { emitInvokeInterface(MemorySegment.class, "set", descriptor); } - // VM_STORE and VM_LOAD are emulated, which is different for down/upcalls private void emitVMStore(Binding.VMStore vmStore) { Class storeType = vmStore.type(); @@ -670,16 +665,56 @@ private void emitVMLoad(Binding.VMLoad vmLoad) { emitGetInput(); } } + private void emitDupBinding() { Class dupType = typeStack.peek(); emitDup(dupType); pushType(dupType); } + private void emitCast(Binding.Cast cast) { + Class fromType = cast.fromType(); + Class toType = cast.toType(); + + if (fromType == int.class) { + popType(int.class); + + if (toType == boolean.class) { + // implement least significant byte non-zero test + + // select first byte + emitConst(0xFF); + mv.visitInsn(IAND); + + // convert to boolean + emitInvokeStatic(Utils.class, "byteToBoolean", "(B)Z"); + } else if (toType == byte.class) { + mv.visitInsn(I2B); + } else if (toType == short.class) { + mv.visitInsn(I2S); + } else { + assert toType == char.class; + mv.visitInsn(I2C); + } + + pushType(toType); + } else { + popType(fromType); + + assert fromType == boolean.class + || fromType == byte.class + || fromType == short.class + || fromType == char.class; + // no-op in bytecode + + assert toType == int.class; + pushType(int.class); + } + } + private void emitUnboxAddress() { - popType(Addressable.class, ASSERT_ASSIGNABLE); - emitInvokeInterface(Addressable.class, "address", ADDRESS_DESC); - emitToRawLongValue(); + popType(MemorySegment.class); + emitInvokeStatic(SharedUtils.class, "unboxSegment", UNBOX_SEGMENT_DESC); pushType(long.class); } @@ -730,15 +765,15 @@ private void emitAllocateCall(long size, long alignment) { private Class emitLoadLayoutConstant(Class type) { Class valueLayoutType = valueLayoutTypeFor(type); String valueLayoutConstantName = valueLayoutConstantFor(type); - emitGetStatic(BindingSpecializer.Runtime.class, valueLayoutConstantName, valueLayoutType.descriptorString()); + emitGetStatic(ValueLayout.class, valueLayoutConstantName, valueLayoutType.descriptorString()); return valueLayoutType; } private static String valueLayoutConstantFor(Class type) { if (type == boolean.class) { - return "JAVA_BOOLEAN_UNALIGNED"; + return "JAVA_BOOLEAN"; } else if (type == byte.class) { - return "JAVA_BYTE_UNALIGNED"; + return "JAVA_BYTE"; } else if (type == short.class) { return "JAVA_SHORT_UNALIGNED"; } else if (type == char.class) { @@ -751,7 +786,7 @@ private static String valueLayoutConstantFor(Class type) { return "JAVA_FLOAT_UNALIGNED"; } else if (type == double.class) { return "JAVA_DOUBLE_UNALIGNED"; - } else if (type == MemoryAddress.class) { + } else if (type == MemorySegment.class) { return "ADDRESS_UNALIGNED"; } else { throw new IllegalStateException("Unknown type: " + type); @@ -775,7 +810,7 @@ private static Class valueLayoutTypeFor(Class type) { return ValueLayout.OfFloat.class; } else if (type == double.class) { return ValueLayout.OfDouble.class; - } else if (type == MemoryAddress.class) { + } else if (type == MemorySegment.class) { return ValueLayout.OfAddress.class; } else { throw new IllegalStateException("Unknown type: " + type); @@ -920,18 +955,4 @@ private void emitReturn(Class type) { mv.visitInsn(opcode); } - // constants that are accessed from the generated bytecode - // see emitLoadLayoutConstant - static class Runtime { - // unaligned constants - static final ValueLayout.OfBoolean JAVA_BOOLEAN_UNALIGNED = JAVA_BOOLEAN; - static final ValueLayout.OfByte JAVA_BYTE_UNALIGNED = JAVA_BYTE; - static final ValueLayout.OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8); - static final ValueLayout.OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8); - static final ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - static final ValueLayout.OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8); - static final ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - static final ValueLayout.OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8); - static final ValueLayout.OfAddress ADDRESS_UNALIGNED = ADDRESS.withBitAlignment(8); - } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java index adf0ee30256..665f0204fd3 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java @@ -27,7 +27,6 @@ import jdk.internal.foreign.Utils; import sun.security.action.GetPropertyAction; -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; @@ -96,12 +95,12 @@ public CallingSequence build() { MethodType callerMethodType; MethodType calleeMethodType; if (!forUpcall) { - addArgumentBinding(0, Addressable.class, ValueLayout.ADDRESS, List.of( - Binding.unboxAddress(Addressable.class), + addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of( + Binding.unboxAddress(), Binding.vmStore(abi.targetAddrStorage(), long.class))); if (needsReturnBuffer) { addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of( - Binding.unboxAddress(MemorySegment.class), + Binding.unboxAddress(), Binding.vmStore(abi.retBufAddrStorage(), long.class))); } @@ -111,8 +110,7 @@ public CallingSequence build() { if (needsReturnBuffer) { addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of( Binding.vmLoad(abi.retBufAddrStorage(), long.class), - Binding.boxAddress(), - Binding.toSegment(returnBufferSize))); + Binding.boxAddress(returnBufferSize))); } callerMethodType = computeCallerTypeForUpcall(); @@ -195,8 +193,8 @@ private void verifyBindings(boolean forArguments, Class carrier, List inType, List bindings) { @@ -223,8 +221,8 @@ private static void verifyUnboxBindings(Class inType, List bindings) ALLOC_BUFFER, BOX_ADDRESS, //UNBOX_ADDRESS, - TO_SEGMENT, - DUP + DUP, + CAST ); private static void verifyBoxBindings(Class expectedOutType, List bindings) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java index a0475725b41..0275b20921d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java @@ -28,7 +28,6 @@ import jdk.internal.access.SharedSecrets; import sun.security.action.GetPropertyAction; -import java.lang.foreign.Addressable; import java.lang.foreign.MemorySegment; import java.lang.foreign.SegmentAllocator; import java.lang.invoke.MethodHandle; @@ -60,7 +59,7 @@ public class DowncallLinker { MH_INVOKE_INTERP_BINDINGS = lookup.findVirtual(DowncallLinker.class, "invokeInterpBindings", methodType(Object.class, SegmentAllocator.class, Object[].class, InvocationData.class)); MH_CHECK_SYMBOL = lookup.findStatic(SharedUtils.class, "checkSymbol", - methodType(void.class, Addressable.class)); + methodType(void.class, MemorySegment.class)); } catch (ReflectiveOperationException e) { throw new RuntimeException(e); } @@ -110,7 +109,7 @@ public MethodHandle getBoundMethodHandle() { } assert handle.type().parameterType(0) == SegmentAllocator.class; - assert handle.type().parameterType(1) == Addressable.class; + assert handle.type().parameterType(1) == MemorySegment.class; handle = foldArguments(handle, 1, MH_CHECK_SYMBOL); handle = SharedUtils.swapArguments(handle, 0, 1); // normalize parameter order @@ -169,9 +168,7 @@ Object invokeInterpBindings(SegmentAllocator allocator, Object[] args, Invocatio for (int i = 0; i < args.length; i++) { Object arg = args[i]; BindingInterpreter.unbox(arg, callingSequence.argumentBindings(i), - (storage, type, value) -> { - leafArgs[invData.argIndexMap.get(storage)] = value; - }, unboxContext); + (storage, type, value) -> leafArgs[invData.argIndexMap.get(storage)] = value, unboxContext); } // call leaf diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java new file mode 100644 index 00000000000..9b0d08c1257 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2022, 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. + */ +package jdk.internal.foreign.abi; + +import java.lang.foreign.Linker; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +public class LinkerOptions { + + private static final LinkerOptions EMPTY = LinkerOptions.of(); + private final Map, Linker.Option> optionsMap; + + private LinkerOptions(Map, Linker.Option> optionsMap) { + this.optionsMap = optionsMap; + } + + public static LinkerOptions of(Linker.Option... options) { + Map, Linker.Option> optionMap = new HashMap<>(); + + for (Linker.Option option : options) { + if (optionMap.containsKey(option.getClass())) { + throw new IllegalArgumentException("Duplicate option: " + option); + } + optionMap.put(option.getClass(), option); + } + + return new LinkerOptions(optionMap); + } + + public static LinkerOptions empty() { + return EMPTY; + } + + private T getOption(Class type) { + return type.cast(optionsMap.get(type)); + } + + public boolean isVarargsIndex(int argIndex) { + FirstVariadicArg fva = getOption(FirstVariadicArg.class); + return fva != null && argIndex >= fva.index(); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + return o instanceof LinkerOptions that + && Objects.equals(optionsMap, that.optionsMap); + } + + @Override + public int hashCode() { + return Objects.hash(optionsMap); + } + + public record FirstVariadicArg(int index) implements Linker.Option { } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index d9e27af746b..991b44067f2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -28,24 +28,19 @@ import jdk.internal.access.JavaLangInvokeAccess; import jdk.internal.access.SharedSecrets; import jdk.internal.foreign.CABI; -import jdk.internal.foreign.MemoryAddressImpl; -import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; import jdk.internal.foreign.abi.x64.sysv.SysVx64Linker; import jdk.internal.foreign.abi.x64.windows.Windowsx64Linker; +import jdk.internal.vm.annotation.ForceInline; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.SequenceLayout; import java.lang.foreign.VaList; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -66,26 +61,26 @@ import static java.lang.invoke.MethodHandles.*; import static java.lang.invoke.MethodType.methodType; -public class SharedUtils { +public final class SharedUtils { + + private SharedUtils() { + } private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); private static final JavaLangInvokeAccess JLIA = SharedSecrets.getJavaLangInvokeAccess(); private static final MethodHandle MH_ALLOC_BUFFER; - private static final MethodHandle MH_BASEADDRESS; private static final MethodHandle MH_BUFFER_COPY; - private static final MethodHandle MH_REACHBILITY_FENCE; + private static final MethodHandle MH_REACHABILITY_FENCE; static { try { MethodHandles.Lookup lookup = MethodHandles.lookup(); MH_ALLOC_BUFFER = lookup.findVirtual(SegmentAllocator.class, "allocate", methodType(MemorySegment.class, MemoryLayout.class)); - MH_BASEADDRESS = lookup.findVirtual(MemorySegment.class, "address", - methodType(MemoryAddress.class)); MH_BUFFER_COPY = lookup.findStatic(SharedUtils.class, "bufferCopy", - methodType(MemoryAddress.class, MemoryAddress.class, MemorySegment.class)); - MH_REACHBILITY_FENCE = lookup.findStatic(Reference.class, "reachabilityFence", + methodType(MemorySegment.class, MemorySegment.class, MemorySegment.class)); + MH_REACHABILITY_FENCE = lookup.findStatic(Reference.class, "reachabilityFence", methodType(void.class, Object.class)); } catch (ReflectiveOperationException e) { throw new BootstrapMethodError(e); @@ -97,62 +92,12 @@ public class SharedUtils { throw new IllegalStateException("Cannot get here"); }; - /** - * Align the specified type from a given address - * @return The address the data should be at based on alignment requirement - */ - public static long align(MemoryLayout t, boolean isVar, long addr) { - return alignUp(addr, alignment(t, isVar)); - } - public static long alignUp(long addr, long alignment) { return ((addr - 1) | (alignment - 1)) + 1; } /** - * The alignment requirement for a given type - * @param isVar indicate if the type is a standalone variable. This change how - * array is aligned. for example. - */ - public static long alignment(MemoryLayout t, boolean isVar) { - if (t instanceof ValueLayout) { - return alignmentOfScalar((ValueLayout) t); - } else if (t instanceof SequenceLayout) { - // when array is used alone - return alignmentOfArray((SequenceLayout) t, isVar); - } else if (t instanceof GroupLayout) { - return alignmentOfContainer((GroupLayout) t); - } else if (t.isPadding()) { - return 1; - } else { - throw new IllegalArgumentException("Invalid type: " + t); - } - } - - private static long alignmentOfScalar(ValueLayout st) { - return st.byteSize(); - } - - private static long alignmentOfArray(SequenceLayout ar, boolean isVar) { - if (ar.elementCount() == 0) { - // VLA or incomplete - return 16; - } else if ((ar.byteSize()) >= 16 && isVar) { - return 16; - } else { - // align as element type - MemoryLayout elementType = ar.elementLayout(); - return alignment(elementType, false); - } - } - - private static long alignmentOfContainer(GroupLayout ct) { - // Most strict member - return ct.memberLayouts().stream().mapToLong(t -> alignment(t, false)).max().orElse(1); - } - - /** - * Takes a MethodHandle that takes an input buffer as a first argument (a MemoryAddress), and returns nothing, + * Takes a MethodHandle that takes an input buffer as a first argument (a MemorySegment), and returns nothing, * and adapts it to return a MemorySegment, by allocating a MemorySegment for the input * buffer, calling the target MethodHandle, and then returning the allocated MemorySegment. * @@ -166,24 +111,23 @@ private static long alignmentOfContainer(GroupLayout ct) { public static MethodHandle adaptDowncallForIMR(MethodHandle handle, FunctionDescriptor cDesc) { if (handle.type().returnType() != void.class) throw new IllegalArgumentException("return expected to be void for in memory returns: " + handle.type()); - if (handle.type().parameterType(2) != MemoryAddress.class) - throw new IllegalArgumentException("MemoryAddress expected as third param: " + handle.type()); + if (handle.type().parameterType(2) != MemorySegment.class) + throw new IllegalArgumentException("MemorySegment expected as third param: " + handle.type()); if (cDesc.returnLayout().isEmpty()) throw new IllegalArgumentException("Return layout needed: " + cDesc); MethodHandle ret = identity(MemorySegment.class); // (MemorySegment) MemorySegment - handle = collectArguments(ret, 1, handle); // (MemorySegment, Addressable, SegmentAllocator, MemoryAddress, ...) MemorySegment - handle = collectArguments(handle, 3, MH_BASEADDRESS); // (MemorySegment, Addressable, SegmentAllocator, MemorySegment, ...) MemorySegment - handle = mergeArguments(handle, 0, 3); // (MemorySegment, Addressable, SegmentAllocator, ...) MemorySegment - handle = collectArguments(handle, 0, insertArguments(MH_ALLOC_BUFFER, 1, cDesc.returnLayout().get())); // (SegmentAllocator, Addressable, SegmentAllocator, ...) MemoryAddress - handle = mergeArguments(handle, 0, 2); // (SegmentAllocator, Addressable, ...) MemoryAddress - handle = swapArguments(handle, 0, 1); // (Addressable, SegmentAllocator, ...) MemoryAddress + handle = collectArguments(ret, 1, handle); // (MemorySegment, MemorySegment, SegmentAllocator, MemorySegment, ...) MemorySegment + handle = mergeArguments(handle, 0, 3); // (MemorySegment, MemorySegment, SegmentAllocator, ...) MemorySegment + handle = collectArguments(handle, 0, insertArguments(MH_ALLOC_BUFFER, 1, cDesc.returnLayout().get())); // (SegmentAllocator, MemorySegment, SegmentAllocator, ...) MemorySegment + handle = mergeArguments(handle, 0, 2); // (SegmentAllocator, MemorySegment, ...) MemorySegment + handle = swapArguments(handle, 0, 1); // (MemorySegment, SegmentAllocator, ...) MemorySegment return handle; } /** * Takes a MethodHandle that returns a MemorySegment, and adapts it to take an input buffer as a first argument - * (a MemoryAddress), and upon invocation, copies the contents of the returned MemorySegment into the input buffer + * (a MemorySegment), and upon invocation, copies the contents of the returned MemorySegment into the input buffer * passed as the first argument. * * @param target the target handle to adapt @@ -193,22 +137,21 @@ public static MethodHandle adaptUpcallForIMR(MethodHandle target, boolean dropRe if (target.type().returnType() != MemorySegment.class) throw new IllegalArgumentException("Must return MemorySegment for IMR"); - target = collectArguments(MH_BUFFER_COPY, 1, target); // (MemoryAddress, ...) MemoryAddress + target = collectArguments(MH_BUFFER_COPY, 1, target); // (MemorySegment, ...) MemorySegment if (dropReturn) { // no handling for return value, need to drop it target = dropReturn(target); } else { // adjust return type so it matches the inferred type of the effective // function descriptor - target = target.asType(target.type().changeReturnType(Addressable.class)); + target = target.asType(target.type().changeReturnType(MemorySegment.class)); } return target; } - private static MemoryAddress bufferCopy(MemoryAddress dest, MemorySegment buffer) { - MemoryAddressImpl.ofLongUnchecked(dest.toRawLongValue(), buffer.byteSize()).copyFrom(buffer); - return dest; + private static MemorySegment bufferCopy(MemorySegment dest, MemorySegment buffer) { + return dest.copyFrom(buffer); } public static Class primitiveCarrierForSize(long size, boolean useFloat) { @@ -235,10 +178,10 @@ public static Class primitiveCarrierForSize(long size, boolean useFloat) { public static Linker getSystemLinker() { return switch (CABI.current()) { - case Win64 -> Windowsx64Linker.getInstance(); - case SysV -> SysVx64Linker.getInstance(); - case LinuxAArch64 -> LinuxAArch64Linker.getInstance(); - case MacOsAArch64 -> MacOsAArch64Linker.getInstance(); + case WIN_64 -> Windowsx64Linker.getInstance(); + case SYS_V -> SysVx64Linker.getInstance(); + case LINUX_AARCH_64 -> LinuxAArch64Linker.getInstance(); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.getInstance(); }; } @@ -305,7 +248,7 @@ static MethodHandle swapArguments(MethodHandle mh, int firstArg, int secondArg) } private static MethodHandle reachabilityFenceHandle(Class type) { - return MH_REACHBILITY_FENCE.asType(MethodType.methodType(void.class, type)); + return MH_REACHABILITY_FENCE.asType(MethodType.methodType(void.class, type)); } static void handleUncaughtException(Throwable t) { @@ -315,6 +258,13 @@ static void handleUncaughtException(Throwable t) { } } + static long unboxSegment(MemorySegment segment) { + if (!segment.isNative()) { + throw new IllegalArgumentException("Heap segment not allowed: " + segment); + } + return segment.address(); + } + public static void checkExceptions(MethodHandle target) { Class[] exceptions = JLIA.exceptionTypes(target); if (exceptions != null && exceptions.length != 0) { @@ -322,52 +272,45 @@ public static void checkExceptions(MethodHandle target) { } } - public static MethodHandle maybeInsertAllocator(MethodHandle handle) { - if (!handle.type().returnType().equals(MemorySegment.class)) { + public static MethodHandle maybeInsertAllocator(FunctionDescriptor descriptor, MethodHandle handle) { + if (descriptor.returnLayout().isEmpty() || !(descriptor.returnLayout().get() instanceof GroupLayout)) { // not returning segment, just insert a throwing allocator handle = insertArguments(handle, 1, THROWING_ALLOCATOR); } return handle; } - public static void checkSymbol(Addressable symbol) { - checkAddressable(symbol, "Symbol is NULL"); - } - - public static void checkAddress(MemoryAddress address) { - checkAddressable(address, "Address is NULL"); - } - - private static void checkAddressable(Addressable symbol, String msg) { + @ForceInline + public static void checkSymbol(MemorySegment symbol) { Objects.requireNonNull(symbol); - if (symbol.address().toRawLongValue() == 0) + if (symbol.equals(MemorySegment.NULL)) throw new IllegalArgumentException("Symbol is NULL: " + symbol); } - public static VaList newVaList(Consumer actions, MemorySession session) { + public static VaList newVaList(Consumer actions, SegmentScope session) { return switch (CABI.current()) { - case Win64 -> Windowsx64Linker.newVaList(actions, session); - case SysV -> SysVx64Linker.newVaList(actions, session); - case LinuxAArch64 -> LinuxAArch64Linker.newVaList(actions, session); - case MacOsAArch64 -> MacOsAArch64Linker.newVaList(actions, session); + case WIN_64 -> Windowsx64Linker.newVaList(actions, session); + case SYS_V -> SysVx64Linker.newVaList(actions, session); + case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaList(actions, session); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaList(actions, session); }; } - public static VaList newVaListOfAddress(MemoryAddress ma, MemorySession session) { + public static VaList newVaListOfAddress(long address, SegmentScope session) { return switch (CABI.current()) { - case Win64 -> Windowsx64Linker.newVaListOfAddress(ma, session); - case SysV -> SysVx64Linker.newVaListOfAddress(ma, session); - case LinuxAArch64 -> LinuxAArch64Linker.newVaListOfAddress(ma, session); - case MacOsAArch64 -> MacOsAArch64Linker.newVaListOfAddress(ma, session); + case WIN_64 -> Windowsx64Linker.newVaListOfAddress(address, session); + case SYS_V -> SysVx64Linker.newVaListOfAddress(address, session); + case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaListOfAddress(address, session); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaListOfAddress(address, session); }; } public static VaList emptyVaList() { return switch (CABI.current()) { - case Win64 -> Windowsx64Linker.emptyVaList(); - case SysV -> SysVx64Linker.emptyVaList(); - case LinuxAArch64 -> LinuxAArch64Linker.emptyVaList(); - case MacOsAArch64 -> MacOsAArch64Linker.emptyVaList(); + case WIN_64 -> Windowsx64Linker.emptyVaList(); + case SYS_V -> SysVx64Linker.emptyVaList(); + case LINUX_AARCH_64 -> LinuxAArch64Linker.emptyVaList(); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.emptyVaList(); }; } @@ -378,16 +321,11 @@ static void checkType(Class actualType, Class expectedType) { } } - public static boolean isVarargsIndex(FunctionDescriptor descriptor, int argIndex) { - int firstPos = descriptor.firstVariadicArgumentIndex(); - return firstPos != -1 && argIndex >= firstPos; - } - public static NoSuchElementException newVaListNSEE(MemoryLayout layout) { return new NoSuchElementException("No such element: " + layout); } - public static class SimpleVaArg { + public static final class SimpleVaArg { public final MemoryLayout layout; public final Object value; @@ -401,11 +339,11 @@ public VarHandle varHandle() { } } - public static non-sealed class EmptyVaList implements VaList, Scoped { + public static final class EmptyVaList implements VaList { - private final MemoryAddress address; + private final MemorySegment address; - public EmptyVaList(MemoryAddress address) { + public EmptyVaList(MemorySegment address) { this.address = address; } @@ -429,7 +367,7 @@ public double nextVarg(ValueLayout.OfDouble layout) { } @Override - public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { + public MemorySegment nextVarg(ValueLayout.OfAddress layout) { throw uoe(); } @@ -443,18 +381,13 @@ public void skip(MemoryLayout... layouts) { throw uoe(); } - @Override - public MemorySession session() { - return MemorySessionImpl.GLOBAL; - } - @Override public VaList copy() { return this; } @Override - public MemoryAddress address() { + public MemorySegment segment() { return address; } } @@ -526,32 +459,4 @@ static Object read(MemorySegment ptr, Class type) { throw new IllegalArgumentException("Unsupported carrier: " + type); } } - - // unaligned constants - public final static ValueLayout.OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8); - public final static ValueLayout.OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8); - public final static ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - public final static ValueLayout.OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8); - public final static ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - public final static ValueLayout.OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8); - - public static MethodType inferMethodType(FunctionDescriptor descriptor, boolean upcall) { - MethodType type = MethodType.methodType(descriptor.returnLayout().isPresent() ? - carrierFor(descriptor.returnLayout().get(), upcall) : void.class); - for (MemoryLayout argLayout : descriptor.argumentLayouts()) { - type = type.appendParameterTypes(carrierFor(argLayout, !upcall)); - } - return type; - } - - static Class carrierFor(MemoryLayout layout, boolean forArg) { - if (layout instanceof ValueLayout valueLayout) { - return (forArg && valueLayout.carrier().equals(MemoryAddress.class)) ? - Addressable.class : valueLayout.carrier(); - } else if (layout instanceof GroupLayout) { - return MemorySegment.class; - } else { - throw new IllegalArgumentException("Unsupported layout: " + layout); - } - } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java index be02a69ba75..3e801600cb6 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SoftReferenceCache.java @@ -38,7 +38,7 @@ public V get(K key, Function valueFactory) { .get(key, valueFactory); // long lock, but just for the particular key } - private class Node { + private final class Node { private volatile SoftReference ref; public Node() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java index bb2bff5b067..40af3d64dd9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java @@ -28,7 +28,7 @@ import sun.security.action.GetPropertyAction; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -61,7 +61,7 @@ public class UpcallLinker { } } - public static MemorySegment make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, MemorySession session) { + public static MemorySegment make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, SegmentScope session) { assert callingSequence.forUpcall(); Binding.VMLoad[] argMoves = argMoveBindings(callingSequence); Binding.VMStore[] retMoves = retMoveBindings(callingSequence); @@ -196,7 +196,7 @@ private static Object invokeInterpBindings(Object[] lowLevelArgs, InvocationData } // used for transporting data into native code - private static record CallRegs(VMStorage[] argRegs, VMStorage[] retRegs) {} + private record CallRegs(VMStorage[] argRegs, VMStorage[] retRegs) {} static native long makeUpcallStub(MethodHandle mh, ABIDescriptor abi, CallRegs conv, boolean needsReturnBuffer, long returnBufferSize); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java index dec3b922209..041a96ac1c0 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java @@ -24,13 +24,15 @@ */ package jdk.internal.foreign.abi; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import jdk.internal.foreign.MemorySessionImpl; -public class UpcallStubs { +public final class UpcallStubs { + + private UpcallStubs() { + } private static void freeUpcallStub(long stubAddress) { if (!freeUpcallStub0(stubAddress)) { @@ -48,13 +50,13 @@ private static void freeUpcallStub(long stubAddress) { registerNatives(); } - static MemorySegment makeUpcall(long entry, MemorySession session) { - MemorySessionImpl.toSessionImpl(session).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { + static MemorySegment makeUpcall(long entry, SegmentScope session) { + ((MemorySessionImpl) session).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { @Override public void cleanup() { freeUpcallStub(entry); } }); - return MemorySegment.ofAddress(MemoryAddress.ofLong(entry), 0, session); + return MemorySegment.ofAddress(entry, 0, session); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index 59123bfd0c7..c0353581d33 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -27,7 +27,6 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.ABIDescriptor; @@ -35,6 +34,7 @@ import jdk.internal.foreign.abi.CallingSequence; import jdk.internal.foreign.abi.CallingSequenceBuilder; import jdk.internal.foreign.abi.DowncallLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.UpcallLinker; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.VMStorage; @@ -42,7 +42,7 @@ import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64CallArranger; import jdk.internal.foreign.Utils; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.List; @@ -92,15 +92,8 @@ public abstract class CallArranger { r10 // return buffer addr reg ); - // record - public static class Bindings { - public final CallingSequence callingSequence; - public final boolean isInMemoryReturn; - - Bindings(CallingSequence callingSequence, boolean isInMemoryReturn) { - this.callingSequence = callingSequence; - this.isInMemoryReturn = isInMemoryReturn; - } + public record Bindings(CallingSequence callingSequence, + boolean isInMemoryReturn) { } public static final CallArranger LINUX = new LinuxAArch64CallArranger(); @@ -122,6 +115,10 @@ public static class Bindings { protected CallArranger() {} public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { + return getBindings(mt, cDesc, forUpcall, LinkerOptions.empty()); + } + + public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { CallingSequenceBuilder csb = new CallingSequenceBuilder(C, forUpcall); BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); @@ -129,7 +126,7 @@ public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean for boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout()); if (returnInMemory) { - csb.addArgumentBindings(MemoryAddress.class, AArch64.C_POINTER, + csb.addArgumentBindings(MemorySegment.class, AArch64.C_POINTER, argCalc.getIndirectBindings()); } else if (cDesc.returnLayout().isPresent()) { Class carrier = mt.returnType(); @@ -140,7 +137,7 @@ public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean for for (int i = 0; i < mt.parameterCount(); i++) { Class carrier = mt.parameterType(i); MemoryLayout layout = cDesc.argumentLayouts().get(i); - if (varArgsOnStack() && SharedUtils.isVarargsIndex(cDesc, i)) { + if (varArgsOnStack() && options.isVarargsIndex(i)) { argCalc.storageCalculator.adjustForVarArgs(); } csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout)); @@ -149,8 +146,8 @@ public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean for return new Bindings(csb.build(), returnInMemory); } - public MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { - Bindings bindings = getBindings(mt, cDesc, false); + public MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc, LinkerOptions options) { + Bindings bindings = getBindings(mt, cDesc, false, options); MethodHandle handle = new DowncallLinker(C, bindings.callingSequence).getBoundMethodHandle(); @@ -161,7 +158,7 @@ public MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { return handle; } - public MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, MemorySession session) { + public MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { @@ -214,7 +211,7 @@ VMStorage stackAlloc(long size, long alignment) { } VMStorage stackAlloc(MemoryLayout layout) { - return stackAlloc(layout.byteSize(), SharedUtils.alignment(layout, true)); + return stackAlloc(layout.byteSize(), layout.byteAlignment()); } VMStorage[] regAlloc(int type, int count) { @@ -353,7 +350,7 @@ List getBindings(Class carrier, MemoryLayout layout) { case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; bindings.copy(layout) - .unboxAddress(MemorySegment.class); + .unboxAddress(); VMStorage storage = storageCalculator.nextStorage( StorageClasses.INTEGER, AArch64.C_POINTER); bindings.vmStore(storage, long.class); @@ -384,7 +381,7 @@ List getBindings(Class carrier, MemoryLayout layout) { break; } case POINTER: { - bindings.unboxAddress(carrier); + bindings.unboxAddress(); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmStore(storage, long.class); @@ -418,7 +415,7 @@ class BoxBindingCalculator extends BindingCalculator { List getIndirectBindings() { return Binding.builder() .vmLoad(INDIRECT_RESULT, long.class) - .boxAddress() + .boxAddressRaw(Long.MAX_VALUE) .build(); } @@ -427,11 +424,11 @@ List getBindings(Class carrier, MemoryLayout layout) { TypeClass argumentClass = TypeClass.classifyLayout(layout); Binding.Builder bindings = Binding.builder(); switch (argumentClass) { - case STRUCT_REGISTER: { + case STRUCT_REGISTER -> { assert carrier == MemorySegment.class; bindings.allocate(layout); VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.INTEGER, layout); + StorageClasses.INTEGER, layout); if (regs != null) { int regIndex = 0; long offset = 0; @@ -448,23 +445,20 @@ List getBindings(Class carrier, MemoryLayout layout) { } else { spillStructBox(bindings, layout); } - break; } - case STRUCT_REFERENCE: { + case STRUCT_REFERENCE -> { assert carrier == MemorySegment.class; VMStorage storage = storageCalculator.nextStorage( - StorageClasses.INTEGER, AArch64.C_POINTER); + StorageClasses.INTEGER, AArch64.C_POINTER); bindings.vmLoad(storage, long.class) - .boxAddress() - .toSegment(layout); - break; + .boxAddress(layout); } - case STRUCT_HFA: { + case STRUCT_HFA -> { assert carrier == MemorySegment.class; bindings.allocate(layout); - GroupLayout group = (GroupLayout)layout; + GroupLayout group = (GroupLayout) layout; VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.VECTOR, group.memberLayouts().size()); + StorageClasses.VECTOR, group.memberLayouts().size()); if (regs != null) { long offset = 0; for (int i = 0; i < group.memberLayouts().size(); i++) { @@ -480,29 +474,24 @@ List getBindings(Class carrier, MemoryLayout layout) { } else { spillStructBox(bindings, layout); } - break; } - case POINTER: { + case POINTER -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmLoad(storage, long.class) - .boxAddress(); - break; + .boxAddressRaw(Utils.pointeeSize(layout)); } - case INTEGER: { + case INTEGER -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageClasses.INTEGER, layout); bindings.vmLoad(storage, carrier); - break; } - case FLOAT: { + case FLOAT -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + storageCalculator.nextStorage(StorageClasses.VECTOR, layout); bindings.vmLoad(storage, carrier); - break; } - default: - throw new UnsupportedOperationException("Unhandled class " + argumentClass); + default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); } return bindings.build(); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java index 7a32e99c95e..722e47b8c06 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/TypeClass.java @@ -26,9 +26,8 @@ package jdk.internal.foreign.abi.aarch64; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.SequenceLayout; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; public enum TypeClass { @@ -48,7 +47,7 @@ private static TypeClass classifyValueType(ValueLayout type) { return INTEGER; } else if (carrier == float.class || carrier == double.class) { return FLOAT; - } else if (carrier == MemoryAddress.class) { + } else if (carrier == MemorySegment.class) { return POINTER; } else { throw new IllegalStateException("Cannot get here: " + carrier.getName()); @@ -60,11 +59,9 @@ static boolean isRegisterAggregate(MemoryLayout type) { } static boolean isHomogeneousFloatAggregate(MemoryLayout type) { - if (!(type instanceof GroupLayout)) + if (!(type instanceof GroupLayout groupLayout)) return false; - GroupLayout groupLayout = (GroupLayout)type; - final int numElements = groupLayout.memberLayouts().size(); if (numElements > 4 || numElements == 0) return false; @@ -107,10 +104,8 @@ public static TypeClass classifyLayout(MemoryLayout type) { return classifyValueType((ValueLayout) type); } else if (type instanceof GroupLayout) { return classifyStructType(type); - } else if (type instanceof SequenceLayout) { - return TypeClass.INTEGER; } else { - throw new IllegalArgumentException("Unhandled type " + type); + throw new IllegalArgumentException("Unsupported layout: " + type); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java index 58dd7c793cd..9114005695d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java @@ -26,12 +26,12 @@ package jdk.internal.foreign.abi.aarch64.linux; import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.aarch64.CallArranger; +import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.VaList; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -42,33 +42,37 @@ * the ARM 64-bit Architecture". */ public final class LinuxAArch64Linker extends AbstractLinker { - private static LinuxAArch64Linker instance; public static LinuxAArch64Linker getInstance() { - if (instance == null) { - instance = new LinuxAArch64Linker(); + final class Holder { + private static final LinuxAArch64Linker INSTANCE = new LinuxAArch64Linker(); } - return instance; + + return Holder.INSTANCE; + } + + private LinuxAArch64Linker() { + // Ensure there is only one instance } @Override - protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function) { - return CallArranger.LINUX.arrangeDowncall(inferredMethodType, function); + protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) { + return CallArranger.LINUX.arrangeDowncall(inferredMethodType, function, options); } @Override - protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, MemorySession scope) { + protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) { return CallArranger.LINUX.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, MemorySession session) { + public static VaList newVaList(Consumer actions, SegmentScope session) { LinuxAArch64VaList.Builder builder = LinuxAArch64VaList.builder(session); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(MemoryAddress ma, MemorySession session) { - return LinuxAArch64VaList.ofAddress(ma, session); + public static VaList newVaListOfAddress(long address, SegmentScope session) { + return LinuxAArch64VaList.ofAddress(address, session); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java index 656f5fd6a51..fc43f0193ae 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java @@ -25,13 +25,17 @@ */ package jdk.internal.foreign.abi.aarch64.linux; -import java.lang.foreign.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; +import java.lang.foreign.ValueLayout; +import java.lang.foreign.VaList; +import java.lang.foreign.SegmentAllocator; import jdk.internal.foreign.abi.aarch64.TypeClass; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.misc.Unsafe; import java.lang.invoke.VarHandle; import java.util.ArrayList; @@ -49,8 +53,7 @@ * Standard va_list implementation as defined by AAPCS document and used on * Linux. Variadic parameters may be passed in registers or on the stack. */ -public non-sealed class LinuxAArch64VaList implements VaList, Scoped { - private static final Unsafe U = Unsafe.getUnsafe(); +public non-sealed class LinuxAArch64VaList implements VaList { // See AAPCS Appendix B "Variable Argument Lists" for definition of // va_list on AArch64. @@ -117,50 +120,42 @@ private LinuxAArch64VaList(MemorySegment segment, MemorySegment stack, this.fpLimit = fpLimit; } - private static LinuxAArch64VaList readFromSegment(MemorySegment segment) { - MemorySegment stack = MemorySegment.ofAddress(stackPtr(segment), - Long.MAX_VALUE, segment.session()); // size unknown - - MemorySegment gpRegsArea = MemorySegment.ofAddress(grTop(segment).addOffset(-MAX_GP_OFFSET), - MAX_GP_OFFSET, segment.session()); - - MemorySegment fpRegsArea = MemorySegment.ofAddress(vrTop(segment).addOffset(-MAX_FP_OFFSET), - MAX_FP_OFFSET, segment.session()); + private static LinuxAArch64VaList readFromAddress(long address, SegmentScope session) { + MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), session); + MemorySegment stack = stackPtr(segment); // size unknown + MemorySegment gpRegsArea = MemorySegment.ofAddress(grTop(segment).address() - MAX_GP_OFFSET, MAX_GP_OFFSET, session); + MemorySegment fpRegsArea = MemorySegment.ofAddress(vrTop(segment).address() - MAX_FP_OFFSET, MAX_FP_OFFSET, session); return new LinuxAArch64VaList(segment, stack, gpRegsArea, MAX_GP_OFFSET, fpRegsArea, MAX_FP_OFFSET); } - private static MemoryAddress emptyListAddress() { - long ptr = U.allocateMemory(LAYOUT.byteSize()); - MemorySession session = MemorySession.openImplicit(); - session.addCloseAction(() -> U.freeMemory(ptr)); - MemorySegment ms = MemorySegment.ofAddress(MemoryAddress.ofLong(ptr), - LAYOUT.byteSize(), session); - VH_stack.set(ms, MemoryAddress.NULL); - VH_gr_top.set(ms, MemoryAddress.NULL); - VH_vr_top.set(ms, MemoryAddress.NULL); + private static MemorySegment emptyListAddress() { + MemorySegment ms = MemorySegment.allocateNative(LAYOUT, SegmentScope.auto()); + VH_stack.set(ms, MemorySegment.NULL); + VH_gr_top.set(ms, MemorySegment.NULL); + VH_vr_top.set(ms, MemorySegment.NULL); VH_gr_offs.set(ms, 0); VH_vr_offs.set(ms, 0); - return ms.address(); + return ms.asSlice(0, 0); } public static VaList empty() { return EMPTY; } - private MemoryAddress grTop() { + private MemorySegment grTop() { return grTop(segment); } - private static MemoryAddress grTop(MemorySegment segment) { - return (MemoryAddress) VH_gr_top.get(segment); + private static MemorySegment grTop(MemorySegment segment) { + return (MemorySegment) VH_gr_top.get(segment); } - private MemoryAddress vrTop() { + private MemorySegment vrTop() { return vrTop(segment); } - private static MemoryAddress vrTop(MemorySegment segment) { - return (MemoryAddress) VH_vr_top.get(segment); + private static MemorySegment vrTop(MemorySegment segment) { + return (MemorySegment) VH_vr_top.get(segment); } private int grOffs() { @@ -175,17 +170,17 @@ private int vrOffs() { return offs; } - private static MemoryAddress stackPtr(MemorySegment segment) { - return (MemoryAddress) VH_stack.get(segment); + private static MemorySegment stackPtr(MemorySegment segment) { + return (MemorySegment) VH_stack.get(segment); } - private MemoryAddress stackPtr() { + private MemorySegment stackPtr() { return stackPtr(segment); } private void setStack(MemorySegment newStack) { stack = newStack; - VH_stack.set(segment, stack.address()); + VH_stack.set(segment, stack); } private void consumeGPSlots(int num) { @@ -217,7 +212,7 @@ private long currentFPOffset() { private long preAlignOffset(MemoryLayout layout) { long alignmentOffset = 0; if (layout.byteAlignment() > STACK_SLOT_SIZE) { - long addr = stack.address().toRawLongValue(); + long addr = stack.address(); alignmentOffset = Utils.alignUp(addr, 16) - addr; } return alignmentOffset; @@ -247,8 +242,8 @@ public double nextVarg(ValueLayout.OfDouble layout) { } @Override - public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { - return (MemoryAddress) read(layout); + public MemorySegment nextVarg(ValueLayout.OfAddress layout) { + return (MemorySegment) read(layout); } @Override @@ -318,11 +313,11 @@ private Object read(MemoryLayout layout, SegmentAllocator allocator) { checkGPElement(layout, 1); // Struct is passed indirectly via a pointer in an integer register. VarHandle ptrReader = AArch64.C_POINTER.varHandle(); - MemoryAddress ptr = (MemoryAddress) ptrReader.get( + MemorySegment ptr = (MemorySegment) ptrReader.get( gpRegsArea.asSlice(currentGPOffset())); consumeGPSlots(1); - MemorySegment slice = MemorySegment.ofAddress(ptr, layout.byteSize(), session()); + MemorySegment slice = MemorySegment.ofAddress(ptr.address(), layout.byteSize(), segment.scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(slice); yield seg; @@ -366,7 +361,7 @@ private void checkStackElement(MemoryLayout layout) { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); - sessionImpl().checkValidState(); + ((MemorySessionImpl) segment.scope()).checkValidState(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); TypeClass typeClass = TypeClass.classifyLayout(layout); @@ -389,29 +384,25 @@ public void skip(MemoryLayout... layouts) { } } - static LinuxAArch64VaList.Builder builder(MemorySession session) { + static LinuxAArch64VaList.Builder builder(SegmentScope session) { return new LinuxAArch64VaList.Builder(session); } - public static VaList ofAddress(MemoryAddress ma, MemorySession session) { - return readFromSegment(MemorySegment.ofAddress(ma, LAYOUT.byteSize(), session)); - } - - @Override - public MemorySession session() { - return segment.session(); + public static VaList ofAddress(long address, SegmentScope session) { + return readFromAddress(address, session); } @Override public VaList copy() { - MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session()); + MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.scope()); copy.copyFrom(segment); return new LinuxAArch64VaList(copy, stack, gpRegsArea, gpLimit, fpRegsArea, fpLimit); } @Override - public MemoryAddress address() { - return segment.address(); + public MemorySegment segment() { + // make sure that returned segment cannot be accessed + return segment.asSlice(0, 0); } private static long numSlots(MemoryLayout layout) { @@ -441,7 +432,7 @@ public String toString() { } public static non-sealed class Builder implements VaList.Builder { - private final MemorySession session; + private final SegmentScope session; private final MemorySegment gpRegs; private final MemorySegment fpRegs; @@ -449,7 +440,7 @@ public static non-sealed class Builder implements VaList.Builder { private long currentFPOffset = 0; private final List stackArgs = new ArrayList<>(); - Builder(MemorySession session) { + Builder(SegmentScope session) { this.session = session; this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, session); this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, session); @@ -471,8 +462,8 @@ public Builder addVarg(ValueLayout.OfDouble layout, double value) { } @Override - public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { - return arg(layout, value.address()); + public Builder addVarg(ValueLayout.OfAddress layout, MemorySegment value) { + return arg(layout, value); } @Override @@ -518,7 +509,7 @@ private Builder arg(MemoryLayout layout, Object value) { MemorySegment valueSegment = (MemorySegment) value; VarHandle writer = AArch64.C_POINTER.varHandle(); writer.set(gpRegs.asSlice(currentGPOffset), - valueSegment.address()); + valueSegment); currentGPOffset += GP_SLOT_SIZE; } case POINTER, INTEGER -> { @@ -545,13 +536,12 @@ public VaList build() { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MemorySegment vaListSegment = allocator.allocate(LAYOUT); + MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, session); MemorySegment stackArgsSegment; if (!stackArgs.isEmpty()) { long stackArgsSize = stackArgs.stream() .reduce(0L, (acc, e) -> acc + Utils.alignUp(e.layout.byteSize(), STACK_SLOT_SIZE), Long::sum); - stackArgsSegment = allocator.allocate(stackArgsSize, 16); + stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, session); MemorySegment writeCursor = stackArgsSegment; for (SimpleVaArg arg : stackArgs) { final long alignedSize = Utils.alignUp(arg.layout.byteSize(), STACK_SLOT_SIZE); @@ -561,17 +551,17 @@ public VaList build() { writeCursor = writeCursor.asSlice(alignedSize); } } else { - stackArgsSegment = MemorySegment.ofAddress(MemoryAddress.NULL, 0, session); + stackArgsSegment = MemorySegment.NULL; } - VH_gr_top.set(vaListSegment, gpRegs.asSlice(gpRegs.byteSize()).address()); - VH_vr_top.set(vaListSegment, fpRegs.asSlice(fpRegs.byteSize()).address()); - VH_stack.set(vaListSegment, stackArgsSegment.address()); + VH_gr_top.set(vaListSegment, gpRegs.asSlice(gpRegs.byteSize())); + VH_vr_top.set(vaListSegment, fpRegs.asSlice(fpRegs.byteSize())); + VH_stack.set(vaListSegment, stackArgsSegment); VH_gr_offs.set(vaListSegment, -MAX_GP_OFFSET); VH_vr_offs.set(vaListSegment, -MAX_FP_OFFSET); - assert gpRegs.session().ownerThread() == vaListSegment.session().ownerThread(); - assert fpRegs.session().ownerThread() == vaListSegment.session().ownerThread(); + assert MemorySessionImpl.sameOwnerThread(gpRegs.scope(), vaListSegment.scope()); + assert MemorySessionImpl.sameOwnerThread(fpRegs.scope(), vaListSegment.scope()); return new LinuxAArch64VaList(vaListSegment, stackArgsSegment, gpRegs, currentGPOffset, fpRegs, currentFPOffset); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index c533207b02b..ab478f70faa 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -26,12 +26,12 @@ package jdk.internal.foreign.abi.aarch64.macos; import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.aarch64.CallArranger; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -42,33 +42,37 @@ * changes to va_list and passing arguments on the stack. */ public final class MacOsAArch64Linker extends AbstractLinker { - private static MacOsAArch64Linker instance; public static MacOsAArch64Linker getInstance() { - if (instance == null) { - instance = new MacOsAArch64Linker(); + final class Holder { + private static final MacOsAArch64Linker INSTANCE = new MacOsAArch64Linker(); } - return instance; + + return Holder.INSTANCE; + } + + private MacOsAArch64Linker() { + // Ensure there is only one instance } @Override - protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function) { - return CallArranger.MACOS.arrangeDowncall(inferredMethodType, function); + protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) { + return CallArranger.MACOS.arrangeDowncall(inferredMethodType, function, options); } @Override - protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, MemorySession scope) { + protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) { return CallArranger.MACOS.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, MemorySession session) { + public static VaList newVaList(Consumer actions, SegmentScope session) { MacOsAArch64VaList.Builder builder = MacOsAArch64VaList.builder(session); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(MemoryAddress ma, MemorySession session) { - return MacOsAArch64VaList.ofAddress(ma, session); + public static VaList newVaListOfAddress(long address, SegmentScope session) { + return MacOsAArch64VaList.ofAddress(address, session); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java index 72715aa8654..210b66ecde3 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64VaList.java @@ -25,10 +25,15 @@ */ package jdk.internal.foreign.abi.aarch64.macos; -import java.lang.foreign.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.VaList; +import java.lang.foreign.ValueLayout; import jdk.internal.foreign.abi.aarch64.TypeClass; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; @@ -45,21 +50,19 @@ * parameters are passed on the stack and the type of va_list decays to * char* instead of the structure defined in the AAPCS. */ -public non-sealed class MacOsAArch64VaList implements VaList, Scoped { +public non-sealed class MacOsAArch64VaList implements VaList { private static final long VA_SLOT_SIZE_BYTES = 8; private static final VarHandle VH_address = C_POINTER.varHandle(); - private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL); + private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemorySegment.NULL); private MemorySegment segment; - private final MemorySession session; - private MacOsAArch64VaList(MemorySegment segment, MemorySession session) { + private MacOsAArch64VaList(MemorySegment segment) { this.segment = segment; - this.session = session; } - public static final VaList empty() { + public static VaList empty() { return EMPTY; } @@ -79,8 +82,8 @@ public double nextVarg(ValueLayout.OfDouble layout) { } @Override - public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { - return (MemoryAddress) read(layout); + public MemorySegment nextVarg(ValueLayout.OfAddress layout) { + return (MemorySegment) read(layout); } @Override @@ -101,8 +104,8 @@ private Object read(MemoryLayout layout, SegmentAllocator allocator) { res = switch (typeClass) { case STRUCT_REFERENCE -> { checkElement(layout, VA_SLOT_SIZE_BYTES); - MemoryAddress structAddr = (MemoryAddress) VH_address.get(segment); - MemorySegment struct = MemorySegment.ofAddress(structAddr, layout.byteSize(), session()); + MemorySegment structAddr = (MemorySegment) VH_address.get(segment); + MemorySegment struct = MemorySegment.ofAddress(structAddr.address(), layout.byteSize(), segment.scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(struct); segment = segment.asSlice(VA_SLOT_SIZE_BYTES); @@ -137,7 +140,7 @@ private static long sizeOf(MemoryLayout layout) { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); - sessionImpl().checkValidState(); + ((MemorySessionImpl) segment.scope()).checkValidState(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); @@ -153,38 +156,34 @@ private void checkElement(MemoryLayout layout, long size) { } } - static MacOsAArch64VaList ofAddress(MemoryAddress addr, MemorySession session) { - MemorySegment segment = MemorySegment.ofAddress(addr, Long.MAX_VALUE, session); - return new MacOsAArch64VaList(segment, session); + static MacOsAArch64VaList ofAddress(long address, SegmentScope session) { + MemorySegment segment = MemorySegment.ofAddress(address, Long.MAX_VALUE, session); + return new MacOsAArch64VaList(segment); } - static Builder builder(MemorySession session) { + static Builder builder(SegmentScope session) { return new Builder(session); } - @Override - public MemorySession session() { - return session; - } - @Override public VaList copy() { - sessionImpl().checkValidState(); - return new MacOsAArch64VaList(segment, session); + ((MemorySessionImpl) segment.scope()).checkValidState(); + return new MacOsAArch64VaList(segment); } @Override - public MemoryAddress address() { - return segment.address(); + public MemorySegment segment() { + // make sure that returned segment cannot be accessed + return segment.asSlice(0, 0); } public static non-sealed class Builder implements VaList.Builder { - private final MemorySession session; + private final SegmentScope session; private final List args = new ArrayList<>(); - public Builder(MemorySession session) { - MemorySessionImpl.toSessionImpl(session).checkValidState(); + public Builder(SegmentScope session) { + ((MemorySessionImpl) session).checkValidState(); this.session = session; } @@ -211,8 +210,8 @@ public Builder addVarg(ValueLayout.OfDouble layout, double value) { } @Override - public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { - return arg(layout, value.address()); + public Builder addVarg(ValueLayout.OfAddress layout, MemorySegment value) { + return arg(layout, value); } @Override @@ -225,10 +224,8 @@ public VaList build() { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - long allocationSize = args.stream().reduce(0L, (acc, e) -> acc + sizeOf(e.layout), Long::sum); - MemorySegment segment = allocator.allocate(allocationSize); + MemorySegment segment = MemorySegment.allocateNative(allocationSize, session); MemorySegment cursor = segment; for (SimpleVaArg arg : args) { @@ -237,9 +234,9 @@ public VaList build() { TypeClass typeClass = TypeClass.classifyLayout(arg.layout); switch (typeClass) { case STRUCT_REFERENCE -> { - MemorySegment copy = allocator.allocate(arg.layout); + MemorySegment copy = MemorySegment.allocateNative(arg.layout, session); copy.copyFrom(msArg); // by-value - VH_address.set(cursor, copy.address()); + VH_address.set(cursor, copy); cursor = cursor.asSlice(VA_SLOT_SIZE_BYTES); } case STRUCT_REGISTER, STRUCT_HFA -> @@ -254,7 +251,7 @@ public VaList build() { } } - return new MacOsAArch64VaList(segment, session); + return new MacOsAArch64VaList(segment); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index 897ac3b9be9..441529c2765 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -25,6 +25,7 @@ */ package jdk.internal.foreign.abi.x64.sysv; +import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; @@ -34,12 +35,11 @@ import jdk.internal.foreign.abi.UpcallLinker; import jdk.internal.foreign.abi.VMStorage; +import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -73,17 +73,10 @@ public class CallArranger { r11 // ret buf addr reg ); - // record - public static class Bindings { - public final CallingSequence callingSequence; - public final boolean isInMemoryReturn; - public final int nVectorArgs; - - Bindings(CallingSequence callingSequence, boolean isInMemoryReturn, int nVectorArgs) { - this.callingSequence = callingSequence; - this.isInMemoryReturn = isInMemoryReturn; - this.nVectorArgs = nVectorArgs; - } + public record Bindings( + CallingSequence callingSequence, + boolean isInMemoryReturn, + int nVectorArgs) { } public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { @@ -94,7 +87,7 @@ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, bool boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout()); if (returnInMemory) { - Class carrier = MemoryAddress.class; + Class carrier = MemorySegment.class; MemoryLayout layout = SysV.C_POINTER; csb.addArgumentBindings(carrier, layout, argCalc.getBindings(carrier, layout)); } else if (cDesc.returnLayout().isPresent()) { @@ -131,7 +124,7 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe return handle; } - public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, MemorySession session) { + public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { @@ -212,26 +205,18 @@ VMStorage[] structStorages(TypeClass typeClass) { } int registerCount(int type) { - switch (type) { - case StorageClasses.INTEGER: - return nIntegerReg; - case StorageClasses.VECTOR: - return nVectorReg; - default: - throw new IllegalStateException(); - } + return switch (type) { + case StorageClasses.INTEGER -> nIntegerReg; + case StorageClasses.VECTOR -> nVectorReg; + default -> throw new IllegalStateException(); + }; } void incrementRegisterCount(int type) { switch (type) { - case StorageClasses.INTEGER: - nIntegerReg++; - break; - case StorageClasses.VECTOR: - nVectorReg++; - break; - default: - throw new IllegalStateException(); + case StorageClasses.INTEGER -> nIntegerReg++; + case StorageClasses.VECTOR -> nVectorReg++; + default -> throw new IllegalStateException(); } } } @@ -257,7 +242,7 @@ List getBindings(Class carrier, MemoryLayout layout) { TypeClass argumentClass = TypeClass.classifyLayout(layout); Binding.Builder bindings = Binding.builder(); switch (argumentClass.kind()) { - case STRUCT: { + case STRUCT -> { assert carrier == MemorySegment.class; VMStorage[] regs = storageCalculator.structStorages(argumentClass); int regIndex = 0; @@ -274,26 +259,21 @@ List getBindings(Class carrier, MemoryLayout layout) { .vmStore(storage, type); offset += copy; } - break; } - case POINTER: { - bindings.unboxAddress(carrier); + case POINTER -> { + bindings.unboxAddress(); VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, long.class); - break; - } - case INTEGER: { + } + case INTEGER -> { VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, carrier); - break; } - case FLOAT: { + case FLOAT -> { VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); bindings.vmStore(storage, carrier); - break; } - default: - throw new UnsupportedOperationException("Unhandled class " + argumentClass); + default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); } return bindings.build(); } @@ -310,7 +290,7 @@ List getBindings(Class carrier, MemoryLayout layout) { TypeClass argumentClass = TypeClass.classifyLayout(layout); Binding.Builder bindings = Binding.builder(); switch (argumentClass.kind()) { - case STRUCT: { + case STRUCT -> { assert carrier == MemorySegment.class; bindings.allocate(layout); VMStorage[] regs = storageCalculator.structStorages(argumentClass); @@ -326,26 +306,21 @@ List getBindings(Class carrier, MemoryLayout layout) { .bufferStore(offset, type); offset += copy; } - break; } - case POINTER: { + case POINTER -> { VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmLoad(storage, long.class) - .boxAddress(); - break; + .boxAddressRaw(Utils.pointeeSize(layout)); } - case INTEGER: { + case INTEGER -> { VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmLoad(storage, carrier); - break; } - case FLOAT: { + case FLOAT -> { VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); bindings.vmLoad(storage, carrier); - break; } - default: - throw new UnsupportedOperationException("Unhandled class " + argumentClass); + default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); } return bindings.build(); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java index 6cafc83396e..78264f69ae3 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java @@ -25,13 +25,17 @@ */ package jdk.internal.foreign.abi.x64.sysv; -import java.lang.foreign.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.VaList; +import java.lang.foreign.ValueLayout; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; import jdk.internal.foreign.Utils; import jdk.internal.foreign.abi.SharedUtils; -import jdk.internal.misc.Unsafe; import java.lang.invoke.VarHandle; import java.util.ArrayList; @@ -45,8 +49,7 @@ import static jdk.internal.foreign.abi.SharedUtils.THROWING_ALLOCATOR; // See https://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf "3.5.7 Variable Argument Lists" -public non-sealed class SysVVaList implements VaList, Scoped { - private static final Unsafe U = Unsafe.getUnsafe(); +public non-sealed class SysVVaList implements VaList { // struct typedef __va_list_tag __va_list_tag { // unsigned int gp_offset; /* 0 4 */ @@ -127,23 +130,20 @@ private SysVVaList(MemorySegment segment, this.fpLimit = fpLimit; } - private static SysVVaList readFromSegment(MemorySegment segment) { + private static SysVVaList readFromAddress(long address, SegmentScope session) { + MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), session); MemorySegment regSaveArea = getRegSaveArea(segment); MemorySegment overflowArgArea = getArgOverflowArea(segment); return new SysVVaList(segment, overflowArgArea, regSaveArea, MAX_GP_OFFSET, MAX_FP_OFFSET); } - private static MemoryAddress emptyListAddress() { - long ptr = U.allocateMemory(LAYOUT.byteSize()); - MemorySession session = MemorySession.openImplicit(); - session.addCloseAction(() -> U.freeMemory(ptr)); - MemorySegment base = MemorySegment.ofAddress(MemoryAddress.ofLong(ptr), - LAYOUT.byteSize(), session); + private static MemorySegment emptyListAddress() { + MemorySegment base = MemorySegment.allocateNative(LAYOUT, SegmentScope.auto()); VH_gp_offset.set(base, MAX_GP_OFFSET); VH_fp_offset.set(base, MAX_FP_OFFSET); - VH_overflow_arg_area.set(base, MemoryAddress.NULL); - VH_reg_save_area.set(base, MemoryAddress.NULL); - return base.address(); + VH_overflow_arg_area.set(base, MemorySegment.NULL); + VH_reg_save_area.set(base, MemorySegment.NULL); + return base.asSlice(0, 0); } public static VaList empty() { @@ -167,19 +167,18 @@ private void currentFPOffset(int i) { } private static MemorySegment getRegSaveArea(MemorySegment segment) { - return MemorySegment.ofAddress(((MemoryAddress)VH_reg_save_area.get(segment)), - LAYOUT_REG_SAVE_AREA.byteSize(), segment.session()); + return ((MemorySegment)VH_reg_save_area.get(segment)) + .asSlice(0, LAYOUT_REG_SAVE_AREA.byteSize()); } private static MemorySegment getArgOverflowArea(MemorySegment segment) { - return MemorySegment.ofAddress(((MemoryAddress)VH_overflow_arg_area.get(segment)), - Long.MAX_VALUE, segment.session()); // size unknown + return (MemorySegment)VH_overflow_arg_area.get(segment); // size unknown } private long preAlignOffset(MemoryLayout layout) { long alignmentOffset = 0; if (layout.byteAlignment() > STACK_SLOT_SIZE) { - long addr = overflowArgArea.address().toRawLongValue(); + long addr = overflowArgArea.address(); alignmentOffset = Utils.alignUp(addr, 16) - addr; } return alignmentOffset; @@ -187,7 +186,7 @@ private long preAlignOffset(MemoryLayout layout) { private void setOverflowArgArea(MemorySegment newSegment) { overflowArgArea = newSegment; - VH_overflow_arg_area.set(segment, overflowArgArea.address()); + VH_overflow_arg_area.set(segment, overflowArgArea); } private void preAlignStack(MemoryLayout layout) { @@ -214,8 +213,8 @@ public double nextVarg(ValueLayout.OfDouble layout) { } @Override - public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { - return (MemoryAddress) read(layout); + public MemorySegment nextVarg(ValueLayout.OfAddress layout) { + return (MemorySegment) read(layout); } @Override @@ -307,7 +306,7 @@ private void checkStackElement(MemoryLayout layout) { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); - sessionImpl().checkValidState(); + ((MemorySessionImpl) segment.scope()).checkValidState(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); TypeClass typeClass = TypeClass.classifyLayout(layout); @@ -323,29 +322,25 @@ public void skip(MemoryLayout... layouts) { } } - static SysVVaList.Builder builder(MemorySession session) { + static SysVVaList.Builder builder(SegmentScope session) { return new SysVVaList.Builder(session); } - public static VaList ofAddress(MemoryAddress ma, MemorySession session) { - return readFromSegment(MemorySegment.ofAddress(ma, LAYOUT.byteSize(), session)); - } - - @Override - public MemorySession session() { - return segment.session(); + public static VaList ofAddress(long address, SegmentScope session) { + return readFromAddress(address, session); } @Override public VaList copy() { - MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.session()); + MemorySegment copy = MemorySegment.allocateNative(LAYOUT, segment.scope()); copy.copyFrom(segment); return new SysVVaList(copy, overflowArgArea, regSaveArea, gpLimit, fpLimit); } @Override - public MemoryAddress address() { - return segment.address(); + public MemorySegment segment() { + // make sure that returned segment cannot be accessed + return segment.asSlice(0, 0); } private static boolean isRegOverflow(long currentGPOffset, long currentFPOffset, TypeClass typeClass) { @@ -364,13 +359,13 @@ public String toString() { } public static non-sealed class Builder implements VaList.Builder { - private final MemorySession session; + private final SegmentScope session; private final MemorySegment reg_save_area; private long currentGPOffset = 0; private long currentFPOffset = FP_OFFSET; private final List stackArgs = new ArrayList<>(); - public Builder(MemorySession session) { + public Builder(SegmentScope session) { this.session = session; this.reg_save_area = MemorySegment.allocateNative(LAYOUT_REG_SAVE_AREA, session); } @@ -391,8 +386,8 @@ public Builder addVarg(ValueLayout.OfDouble layout, double value) { } @Override - public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { - return arg(layout, value.address()); + public Builder addVarg(ValueLayout.OfAddress layout, MemorySegment value) { + return arg(layout, value); } @Override @@ -451,19 +446,18 @@ public VaList build() { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MemorySegment vaListSegment = allocator.allocate(LAYOUT); + MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, session); MemorySegment stackArgsSegment; if (!stackArgs.isEmpty()) { long stackArgsSize = stackArgs.stream().reduce(0L, (acc, e) -> acc + Utils.alignUp(e.layout.byteSize(), STACK_SLOT_SIZE), Long::sum); - stackArgsSegment = allocator.allocate(stackArgsSize, 16); + stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, session); MemorySegment writeCursor = stackArgsSegment; for (SimpleVaArg arg : stackArgs) { if (arg.layout.byteSize() > 8) { writeCursor = Utils.alignUp(writeCursor, Math.min(16, arg.layout.byteSize())); } - if (arg.value instanceof MemorySegment) { + if (arg.layout instanceof GroupLayout) { writeCursor.copyFrom((MemorySegment) arg.value); } else { VarHandle writer = arg.varHandle(); @@ -472,13 +466,13 @@ public VaList build() { writeCursor = writeCursor.asSlice(Utils.alignUp(arg.layout.byteSize(), STACK_SLOT_SIZE)); } } else { - stackArgsSegment = MemorySegment.ofAddress(MemoryAddress.NULL, 0, session); + stackArgsSegment = MemorySegment.NULL; } VH_fp_offset.set(vaListSegment, (int) FP_OFFSET); - VH_overflow_arg_area.set(vaListSegment, stackArgsSegment.address()); - VH_reg_save_area.set(vaListSegment, reg_save_area.address()); - assert reg_save_area.session().ownerThread() == vaListSegment.session().ownerThread(); + VH_overflow_arg_area.set(vaListSegment, stackArgsSegment); + VH_reg_save_area.set(vaListSegment, reg_save_area); + assert MemorySessionImpl.sameOwnerThread(reg_save_area.scope(), vaListSegment.scope()); return new SysVVaList(vaListSegment, stackArgsSegment, reg_save_area, currentGPOffset, currentFPOffset); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index f0b9f59e4c9..80896bdb9fc 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -26,11 +26,11 @@ import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; +import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.VaList; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -40,33 +40,36 @@ * ABI implementation based on System V ABI AMD64 supplement v.0.99.6 */ public final class SysVx64Linker extends AbstractLinker { - private static SysVx64Linker instance; public static SysVx64Linker getInstance() { - if (instance == null) { - instance = new SysVx64Linker(); + final class Holder { + private static final SysVx64Linker INSTANCE = new SysVx64Linker(); } - return instance; + + return Holder.INSTANCE; } + private SysVx64Linker() { + // Ensure there is only one instance + } @Override - protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function) { + protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) { return CallArranger.arrangeDowncall(inferredMethodType, function); } @Override - protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, MemorySession scope) { + protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) { return CallArranger.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, MemorySession scope) { + public static VaList newVaList(Consumer actions, SegmentScope scope) { SysVVaList.Builder builder = SysVVaList.builder(scope); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(MemoryAddress ma, MemorySession session) { - return SysVVaList.ofAddress(ma, session); + public static VaList newVaListOfAddress(long address, SegmentScope session) { + return SysVVaList.ofAddress(address, session); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java index 4a3627af651..8106f27059a 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/TypeClass.java @@ -25,9 +25,11 @@ package jdk.internal.foreign.abi.x64.sysv; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.PaddingLayout; import java.lang.foreign.SequenceLayout; +import java.lang.foreign.StructLayout; import java.lang.foreign.ValueLayout; import jdk.internal.foreign.Utils; @@ -106,14 +108,14 @@ private static List createMemoryClassArray(long size) { .collect(Collectors.toCollection(ArrayList::new)); } - private static ArgumentClassImpl argumentClassFor(MemoryLayout layout) { - Class carrier = ((ValueLayout)layout).carrier(); + private static ArgumentClassImpl argumentClassFor(ValueLayout layout) { + Class carrier = layout.carrier(); if (carrier == boolean.class || carrier == byte.class || carrier == char.class || carrier == short.class || carrier == int.class || carrier == long.class) { return ArgumentClassImpl.INTEGER; } else if (carrier == float.class || carrier == double.class) { return ArgumentClassImpl.SSE; - } else if (carrier == MemoryAddress.class) { + } else if (carrier == MemorySegment.class) { return ArgumentClassImpl.POINTER; } else { throw new IllegalStateException("Cannot get here: " + carrier.getName()); @@ -173,12 +175,12 @@ private static List classifyStructType(GroupLayout type) { static TypeClass classifyLayout(MemoryLayout type) { try { - if (type instanceof ValueLayout) { - return ofValue((ValueLayout)type); - } else if (type instanceof GroupLayout) { - return ofStruct((GroupLayout)type); + if (type instanceof ValueLayout valueLayout) { + return ofValue(valueLayout); + } else if (type instanceof GroupLayout groupLayout) { + return ofStruct(groupLayout); } else { - throw new IllegalArgumentException("Unhandled type " + type); + throw new IllegalArgumentException("Unsupported layout: " + type); } } catch (UnsupportedOperationException e) { System.err.println("Failed to classify layout: " + type); @@ -193,7 +195,7 @@ private static List[] groupByEightBytes(GroupLayout group) { List[] groups = new List[nEightbytes]; for (MemoryLayout l : group.memberLayouts()) { groupByEightBytes(l, offset, groups); - if (group.isStruct()) { + if (group instanceof StructLayout) { offset += l.byteSize(); } } @@ -201,32 +203,30 @@ private static List[] groupByEightBytes(GroupLayout group) { } private static void groupByEightBytes(MemoryLayout l, long offset, List[] groups) { - if (l instanceof GroupLayout) { - GroupLayout group = (GroupLayout)l; + if (l instanceof GroupLayout group) { for (MemoryLayout m : group.memberLayouts()) { groupByEightBytes(m, offset, groups); - if (group.isStruct()) { + if (group instanceof StructLayout) { offset += m.byteSize(); } } - } else if (l.isPadding()) { + } else if (l instanceof PaddingLayout) { return; - } else if (l instanceof SequenceLayout) { - SequenceLayout seq = (SequenceLayout)l; + } else if (l instanceof SequenceLayout seq) { MemoryLayout elem = seq.elementLayout(); for (long i = 0 ; i < seq.elementCount() ; i++) { groupByEightBytes(elem, offset, groups); offset += elem.byteSize(); } - } else if (l instanceof ValueLayout) { + } else if (l instanceof ValueLayout vl) { List layouts = groups[(int)offset / 8]; if (layouts == null) { layouts = new ArrayList<>(); groups[(int)offset / 8] = layouts; } // if the aggregate contains unaligned fields, it has class MEMORY - ArgumentClassImpl argumentClass = (offset % l.byteAlignment()) == 0 ? - argumentClassFor(l) : + ArgumentClassImpl argumentClass = (offset % vl.byteAlignment()) == 0 ? + argumentClassFor(vl) : ArgumentClassImpl.MEMORY; layouts.add(argumentClass); } else { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index e0403e71894..ff68ea08ea8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -30,17 +30,17 @@ import jdk.internal.foreign.abi.CallingSequence; import jdk.internal.foreign.abi.CallingSequenceBuilder; import jdk.internal.foreign.abi.DowncallLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.UpcallLinker; import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.x64.X86_64Architecture; +import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.List; @@ -73,18 +73,16 @@ public class CallArranger { r11 // ret buf addr reg ); - // record - public static class Bindings { - public final CallingSequence callingSequence; - public final boolean isInMemoryReturn; - - Bindings(CallingSequence callingSequence, boolean isInMemoryReturn) { - this.callingSequence = callingSequence; - this.isInMemoryReturn = isInMemoryReturn; - } + public record Bindings( + CallingSequence callingSequence, + boolean isInMemoryReturn) { } public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { + return getBindings(mt, cDesc, forUpcall, LinkerOptions.empty()); + } + + public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { class CallingSequenceBuilderHelper { final CallingSequenceBuilder csb = new CallingSequenceBuilder(CWindows, forUpcall); final BindingCalculator argCalc = @@ -104,7 +102,7 @@ void setReturnBindings(Class carrier, MemoryLayout layout) { boolean returnInMemory = isInMemoryReturn(cDesc.returnLayout()); if (returnInMemory) { - Class carrier = MemoryAddress.class; + Class carrier = MemorySegment.class; MemoryLayout layout = Win64.C_POINTER; csb.addArgumentBindings(carrier, layout, false); if (forUpcall) { @@ -115,14 +113,14 @@ void setReturnBindings(Class carrier, MemoryLayout layout) { } for (int i = 0; i < mt.parameterCount(); i++) { - csb.addArgumentBindings(mt.parameterType(i), cDesc.argumentLayouts().get(i), SharedUtils.isVarargsIndex(cDesc, i)); + csb.addArgumentBindings(mt.parameterType(i), cDesc.argumentLayouts().get(i), options.isVarargsIndex(i)); } return new Bindings(csb.csb.build(), returnInMemory); } - public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { - Bindings bindings = getBindings(mt, cDesc, false); + public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc, LinkerOptions options) { + Bindings bindings = getBindings(mt, cDesc, false, options); MethodHandle handle = new DowncallLinker(CWindows, bindings.callingSequence).getBoundMethodHandle(); @@ -133,7 +131,7 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe return handle; } - public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, MemorySession session) { + public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { @@ -160,12 +158,11 @@ public StorageCalculator(boolean forArguments) { this.forArguments = forArguments; } - VMStorage nextStorage(int type, MemoryLayout layout) { + VMStorage nextStorage(int type) { if (nRegs >= MAX_REGISTER_ARGUMENTS) { assert forArguments : "no stack returns"; // stack - long alignment = Math.max(SharedUtils.alignment(layout, true), STACK_SLOT_SIZE); - stackOffset = Utils.alignUp(stackOffset, alignment); + assert stackOffset == Utils.alignUp(stackOffset, STACK_SLOT_SIZE); // should always be aligned VMStorage storage = X86_64Architecture.stackStorage((int) (stackOffset / STACK_SLOT_SIZE)); stackOffset += STACK_SLOT_SIZE; @@ -201,7 +198,7 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean switch (argumentClass) { case STRUCT_REGISTER: { assert carrier == MemorySegment.class; - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); Class type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false); bindings.bufferLoad(0, type) .vmStore(storage, type); @@ -210,29 +207,29 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; bindings.copy(layout) - .unboxAddress(MemorySegment.class); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + .unboxAddress(); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, long.class); break; } case POINTER: { - bindings.unboxAddress(carrier); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + bindings.unboxAddress(); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, long.class); break; } case INTEGER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmStore(storage, carrier); break; } case FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); bindings.vmStore(storage, carrier); break; } case VARARG_FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); if (!INSTANCE.isStackType(storage.type())) { // need extra for register arg VMStorage extraStorage = storageCalculator.extraVarargsStorage(); bindings.dup() @@ -265,7 +262,7 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean assert carrier == MemorySegment.class; bindings.allocate(layout) .dup(); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); Class type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false); bindings.vmLoad(storage, type) .bufferStore(0, type); @@ -273,25 +270,24 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean } case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmLoad(storage, long.class) - .boxAddress() - .toSegment(layout); + .boxAddress(layout); break; } case POINTER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmLoad(storage, long.class) - .boxAddress(); + .boxAddressRaw(Utils.pointeeSize(layout)); break; } case INTEGER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); bindings.vmLoad(storage, carrier); break; } case FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); bindings.vmLoad(storage, carrier); break; } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java index 420fe027297..892e4c49318 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/TypeClass.java @@ -25,8 +25,8 @@ package jdk.internal.foreign.abi.x64.windows; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; enum TypeClass { @@ -38,7 +38,7 @@ enum TypeClass { VARARG_FLOAT; private static TypeClass classifyValueType(ValueLayout type, boolean isVararg) { - // No 128 bit integers in the Windows C ABI. There are __m128(i|d) intrinsic types but they act just + // No 128-bit integers in the Windows C ABI. There are __m128(i|d) intrinsic types but they act just // like a struct when passing as an argument (passed by pointer). // https://docs.microsoft.com/en-us/cpp/cpp/m128?view=vs-2019 @@ -57,7 +57,7 @@ private static TypeClass classifyValueType(ValueLayout type, boolean isVararg) { } else { return FLOAT; } - } else if (carrier == MemoryAddress.class) { + } else if (carrier == MemorySegment.class) { return POINTER; } else { throw new IllegalStateException("Cannot get here: " + carrier.getName()); @@ -85,7 +85,7 @@ static TypeClass typeClassFor(MemoryLayout type, boolean isVararg) { } else if (type instanceof GroupLayout) { return classifyStructType(type); } else { - throw new IllegalArgumentException("Unhandled type " + type); + throw new IllegalArgumentException("Unsupported layout: " + type); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java index f8dfe0a2e44..6d9bcf82f48 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java @@ -25,10 +25,15 @@ */ package jdk.internal.foreign.abi.x64.windows; -import java.lang.foreign.*; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; +import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.VaList; +import java.lang.foreign.ValueLayout; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.foreign.Scoped; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.SharedUtils.SimpleVaArg; @@ -36,7 +41,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; -import java.util.stream.Stream; import static jdk.internal.foreign.PlatformLayouts.Win64.C_POINTER; @@ -56,18 +60,16 @@ // ? **(t**)((ap += sizeof(__int64)) - sizeof(__int64)) \ // : *(t* )((ap += sizeof(__int64)) - sizeof(__int64))) // -public non-sealed class WinVaList implements VaList, Scoped { +public non-sealed class WinVaList implements VaList { private static final long VA_SLOT_SIZE_BYTES = 8; private static final VarHandle VH_address = C_POINTER.varHandle(); - private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemoryAddress.NULL); + private static final VaList EMPTY = new SharedUtils.EmptyVaList(MemorySegment.NULL); private MemorySegment segment; - private final MemorySession session; - private WinVaList(MemorySegment segment, MemorySession session) { + private WinVaList(MemorySegment segment) { this.segment = segment; - this.session = session; } public static final VaList empty() { @@ -90,8 +92,8 @@ public double nextVarg(ValueLayout.OfDouble layout) { } @Override - public MemoryAddress nextVarg(ValueLayout.OfAddress layout) { - return (MemoryAddress) read(layout); + public MemorySegment nextVarg(ValueLayout.OfAddress layout) { + return (MemorySegment) read(layout); } @Override @@ -112,8 +114,8 @@ private Object read(MemoryLayout layout, SegmentAllocator allocator) { TypeClass typeClass = TypeClass.typeClassFor(layout, false); res = switch (typeClass) { case STRUCT_REFERENCE -> { - MemoryAddress structAddr = (MemoryAddress) VH_address.get(segment); - MemorySegment struct = MemorySegment.ofAddress(structAddr, layout.byteSize(), session()); + MemorySegment structAddr = (MemorySegment) VH_address.get(segment); + MemorySegment struct = MemorySegment.ofAddress(structAddr.address(), layout.byteSize(), segment.scope()); MemorySegment seg = allocator.allocate(layout); seg.copyFrom(struct); yield seg; @@ -139,7 +141,7 @@ private void checkElement(MemoryLayout layout) { @Override public void skip(MemoryLayout... layouts) { Objects.requireNonNull(layouts); - sessionImpl().checkValidState(); + ((MemorySessionImpl) segment.scope()).checkValidState(); for (MemoryLayout layout : layouts) { Objects.requireNonNull(layout); checkElement(layout); @@ -147,38 +149,33 @@ public void skip(MemoryLayout... layouts) { } } - static WinVaList ofAddress(MemoryAddress addr, MemorySession session) { - MemorySegment segment = MemorySegment.ofAddress(addr, Long.MAX_VALUE, session); - return new WinVaList(segment, session); + static WinVaList ofAddress(long address, SegmentScope session) { + return new WinVaList(MemorySegment.ofAddress(address, Long.MAX_VALUE, session)); } - static Builder builder(MemorySession session) { + static Builder builder(SegmentScope session) { return new Builder(session); } - @Override - public MemorySession session() { - return session; - } - @Override public VaList copy() { - sessionImpl().checkValidState(); - return new WinVaList(segment, session); + ((MemorySessionImpl) segment.scope()).checkValidState(); + return new WinVaList(segment); } @Override - public MemoryAddress address() { - return segment.address(); + public MemorySegment segment() { + // make sure that returned segment cannot be accessed + return segment.asSlice(0, 0); } public static non-sealed class Builder implements VaList.Builder { - private final MemorySession session; + private final SegmentScope session; private final List args = new ArrayList<>(); - public Builder(MemorySession session) { - MemorySessionImpl.toSessionImpl(session).checkValidState(); + public Builder(SegmentScope session) { + ((MemorySessionImpl) session).checkValidState(); this.session = session; } @@ -205,8 +202,8 @@ public Builder addVarg(ValueLayout.OfDouble layout, double value) { } @Override - public Builder addVarg(ValueLayout.OfAddress layout, Addressable value) { - return arg(layout, value.address()); + public Builder addVarg(ValueLayout.OfAddress layout, MemorySegment value) { + return arg(layout, value); } @Override @@ -218,8 +215,8 @@ public VaList build() { if (args.isEmpty()) { return EMPTY; } - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MemorySegment segment = allocator.allocate(VA_SLOT_SIZE_BYTES * args.size()); + + MemorySegment segment = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size(), session); MemorySegment cursor = segment; for (SimpleVaArg arg : args) { @@ -228,9 +225,9 @@ public VaList build() { TypeClass typeClass = TypeClass.typeClassFor(arg.layout, false); switch (typeClass) { case STRUCT_REFERENCE -> { - MemorySegment copy = allocator.allocate(arg.layout); + MemorySegment copy = MemorySegment.allocateNative(arg.layout, session); copy.copyFrom(msArg); // by-value - VH_address.set(cursor, copy.address()); + VH_address.set(cursor, copy); } case STRUCT_REGISTER -> cursor.copyFrom(msArg.asSlice(0, VA_SLOT_SIZE_BYTES)); @@ -243,7 +240,7 @@ public VaList build() { cursor = cursor.asSlice(VA_SLOT_SIZE_BYTES); } - return new WinVaList(segment, session); + return new WinVaList(segment); } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java index e36651ecc81..24d12dd8c56 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java @@ -25,11 +25,11 @@ package jdk.internal.foreign.abi.x64.windows; import jdk.internal.foreign.abi.AbstractLinker; +import jdk.internal.foreign.abi.LinkerOptions; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -39,33 +39,37 @@ * ABI implementation based on Windows ABI AMD64 supplement v.0.99.6 */ public final class Windowsx64Linker extends AbstractLinker { - private static Windowsx64Linker instance; public static Windowsx64Linker getInstance() { - if (instance == null) { - instance = new Windowsx64Linker(); + final class Holder { + private static final Windowsx64Linker INSTANCE = new Windowsx64Linker(); } - return instance; + + return Holder.INSTANCE; + } + + private Windowsx64Linker() { + // Ensure there is only one instance } @Override - protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function) { - return CallArranger.arrangeDowncall(inferredMethodType, function); + protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) { + return CallArranger.arrangeDowncall(inferredMethodType, function, options); } @Override - protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, MemorySession scope) { + protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType, FunctionDescriptor function, SegmentScope scope) { return CallArranger.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, MemorySession scope) { + public static VaList newVaList(Consumer actions, SegmentScope scope) { WinVaList.Builder builder = WinVaList.builder(scope); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(MemoryAddress ma, MemorySession session) { - return WinVaList.ofAddress(ma, session); + public static VaList newVaListOfAddress(long address, SegmentScope session) { + return WinVaList.ofAddress(address, session); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java new file mode 100644 index 00000000000..7bb78eabd84 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractGroupLayout.java @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import java.lang.foreign.MemoryLayout; +import java.util.List; +import java.util.Objects; +import java.util.Optional; +import java.util.function.LongBinaryOperator; +import java.util.stream.Collectors; + +/** + * A compound layout that aggregates multiple member layouts. There are two ways in which member layouts + * can be combined: if member layouts are laid out one after the other, the resulting group layout is said to be a struct + * (see {@link MemoryLayout#structLayout(MemoryLayout...)}); conversely, if all member layouts are laid out at the same starting offset, + * the resulting group layout is said to be a union (see {@link MemoryLayout#unionLayout(MemoryLayout...)}). + * + * @implSpec + * This class is immutable, thread-safe and value-based. + * + * @since 19 + */ +public sealed abstract class AbstractGroupLayout & MemoryLayout> + extends AbstractLayout + permits StructLayoutImpl, UnionLayoutImpl { + + private final Kind kind; + private final List elements; + + AbstractGroupLayout(Kind kind, List elements) { + this(kind, elements, kind.alignof(elements), Optional.empty()); + } + + AbstractGroupLayout(Kind kind, List elements, long bitAlignment, Optional name) { + super(kind.sizeof(elements), bitAlignment, name); // Subclassing creates toctou problems here + this.kind = kind; + this.elements = List.copyOf(elements); + } + + /** + * Returns the member layouts associated with this group. + * + * @apiNote the order in which member layouts are returned is the same order in which member layouts have + * been passed to one of the group layout factory methods (see {@link MemoryLayout#structLayout(MemoryLayout...)}, + * {@link MemoryLayout#unionLayout(MemoryLayout...)}). + * + * @return the member layouts associated with this group. + */ + public final List memberLayouts() { + return elements; // "elements" are already unmodifiable. + } + + /** + * {@inheritDoc} + */ + @Override + public final String toString() { + return decorateLayoutString(elements.stream() + .map(Object::toString) + .collect(Collectors.joining(kind.delimTag, "[", "]"))); + } + + /** + * {@inheritDoc} + */ + @Override + public final boolean equals(Object other) { + if (this == other) { + return true; + } + if (!super.equals(other)) { + return false; + } + return other instanceof AbstractGroupLayout otherGroup && + kind == otherGroup.kind && + elements.equals(otherGroup.elements); + } + + /** + * {@inheritDoc} + */ + @Override + public final int hashCode() { + return Objects.hash(super.hashCode(), kind, elements); + } + + @Override + public final boolean hasNaturalAlignment() { + return bitAlignment() == kind.alignof(elements); + } + + /** + * The group kind. + */ + enum Kind { + /** + * A 'struct' kind. + */ + STRUCT("", Math::addExact), + /** + * A 'union' kind. + */ + UNION("|", Math::max); + + final String delimTag; + final LongBinaryOperator sizeOp; + + Kind(String delimTag, LongBinaryOperator sizeOp) { + this.delimTag = delimTag; + this.sizeOp = sizeOp; + } + + long sizeof(List elems) { + long size = 0; + for (MemoryLayout elem : elems) { + size = sizeOp.applyAsLong(size, elem.bitSize()); + } + return size; + } + + long alignof(List elems) { + return elems.stream() + .mapToLong(MemoryLayout::bitAlignment) + .max() // max alignment in case we have member layouts + .orElse(1); // or minimal alignment if no member layout is given + } + } +} diff --git a/src/java.base/share/classes/java/lang/foreign/AbstractLayout.java b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java similarity index 67% rename from src/java.base/share/classes/java/lang/foreign/AbstractLayout.java rename to src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java index 5b9bc1e8da6..48c64eb7fc4 100644 --- a/src/java.base/share/classes/java/lang/foreign/AbstractLayout.java +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/AbstractLayout.java @@ -23,101 +23,69 @@ * questions. * */ -package java.lang.foreign; +package jdk.internal.foreign.layout; -import java.util.Objects; -import java.util.Optional; import jdk.internal.foreign.Utils; import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.Stable; -abstract non-sealed class AbstractLayout implements MemoryLayout { +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SequenceLayout; +import java.lang.foreign.StructLayout; +import java.lang.foreign.UnionLayout; +import java.lang.foreign.ValueLayout; +import java.util.Objects; +import java.util.Optional; - private final long size; - final long alignment; +public abstract sealed class AbstractLayout & MemoryLayout> + permits AbstractGroupLayout, PaddingLayoutImpl, SequenceLayoutImpl, ValueLayouts.AbstractValueLayout { + + private final long bitSize; + private final long bitAlignment; private final Optional name; @Stable - long cachedSize; + private long byteSize; - public AbstractLayout(long size, long alignment, Optional name) { - this.size = size; - this.alignment = alignment; + AbstractLayout(long bitSize, long bitAlignment, Optional name) { + this.bitSize = bitSize; + this.bitAlignment = bitAlignment; this.name = name; } - @Override - public AbstractLayout withName(String name) { + public final L withName(String name) { Objects.requireNonNull(name); - return dup(alignment, Optional.of(name)); + return dup(bitAlignment, Optional.of(name)); } - @Override public final Optional name() { return name; } - abstract AbstractLayout dup(long alignment, Optional name); - - @Override - public AbstractLayout withBitAlignment(long alignmentBits) { - checkAlignment(alignmentBits); - return dup(alignmentBits, name); + public final L withBitAlignment(long bitAlignment) { + checkAlignment(bitAlignment); + return dup(bitAlignment, name); } - void checkAlignment(long alignmentBitCount) { - if (((alignmentBitCount & (alignmentBitCount - 1)) != 0L) || //alignment must be a power of two - (alignmentBitCount < 8)) { //alignment must be greater than 8 - throw new IllegalArgumentException("Invalid alignment: " + alignmentBitCount); - } - } - - static void checkSize(long size) { - checkSize(size, false); - } - - static void checkSize(long size, boolean includeZero) { - if (size < 0 || (!includeZero && size == 0)) { - throw new IllegalArgumentException("Invalid size for layout: " + size); - } - } - - @Override public final long bitAlignment() { - return alignment; + return bitAlignment; } - @Override @ForceInline - public long byteSize() { - if (cachedSize == 0) { - cachedSize = Utils.bitsToBytesOrThrow(bitSize(), + public final long byteSize() { + if (byteSize == 0) { + byteSize = Utils.bitsToBytesOrThrow(bitSize(), () -> new UnsupportedOperationException("Cannot compute byte size; bit size is not a multiple of 8")); } - return cachedSize; + return byteSize; } - @Override - public long bitSize() { - return size; + public final long bitSize() { + return bitSize; } - String decorateLayoutString(String s) { - if (name().isPresent()) { - s = String.format("%s(%s)", s, name().get()); - } - if (!hasNaturalAlignment()) { - s = alignment + "%" + s; - } - return s; - } - - boolean hasNaturalAlignment() { - return size == alignment; - } - - @Override - public boolean isPadding() { - return this instanceof PaddingLayout; + public boolean hasNaturalAlignment() { + return bitSize == bitAlignment; } // the following methods have to copy the same Javadoc as in MemoryLayout, or subclasses will just show @@ -128,7 +96,7 @@ public boolean isPadding() { */ @Override public int hashCode() { - return Objects.hash(name, size, alignment); + return Objects.hash(name, bitSize, bitAlignment); } /** @@ -141,8 +109,8 @@ public int hashCode() { * and {@linkplain ValueLayout#carrier() carrier} *
  • two sequence layouts are considered equal if they have the same element count (see {@link SequenceLayout#elementCount()}), and * if their element layouts (see {@link SequenceLayout#elementLayout()}) are also equal
  • - *
  • two group layouts are considered equal if they are of the same kind (see {@link GroupLayout#isStruct()}, - * {@link GroupLayout#isUnion()}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal
  • + *
  • two group layouts are considered equal if they are of the same type (see {@link StructLayout}, + * {@link UnionLayout}) and if their member layouts (see {@link GroupLayout#memberLayouts()}) are also equal
  • * * * @param other the object to be compared for equality with this layout. @@ -154,14 +122,35 @@ public boolean equals(Object other) { return true; } - return other instanceof AbstractLayout otherLayout && + return other instanceof AbstractLayout otherLayout && name.equals(otherLayout.name) && - size == otherLayout.size && - alignment == otherLayout.alignment; + bitSize == otherLayout.bitSize && + bitAlignment == otherLayout.bitAlignment; } /** * {@return the string representation of this layout} */ public abstract String toString(); + + abstract L dup(long alignment, Optional name); + + String decorateLayoutString(String s) { + if (name().isPresent()) { + s = String.format("%s(%s)", s, name().get()); + } + if (!hasNaturalAlignment()) { + s = bitAlignment + "%" + s; + } + return s; + } + + private static void checkAlignment(long alignmentBitCount) { + if (((alignmentBitCount & (alignmentBitCount - 1)) != 0L) || //alignment must be a power of two + (alignmentBitCount < 8)) { //alignment must be greater than 8 + throw new IllegalArgumentException("Invalid alignment: " + alignmentBitCount); + } + } + + } diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java new file mode 100644 index 00000000000..fa154bd09ba --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/MemoryLayoutUtil.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +public final class MemoryLayoutUtil { + + private MemoryLayoutUtil() { + } + + public static void checkSize(long size) { + checkSize(size, false); + } + + public static void checkSize(long size, boolean includeZero) { + if (size < 0 || (!includeZero && size == 0)) { + throw new IllegalArgumentException("Invalid size for layout: " + size); + } + } + +} \ No newline at end of file diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/PaddingLayoutImpl.java b/src/java.base/share/classes/jdk/internal/foreign/layout/PaddingLayoutImpl.java new file mode 100644 index 00000000000..3559a8d0f29 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/PaddingLayoutImpl.java @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import java.lang.foreign.PaddingLayout; +import java.util.Objects; +import java.util.Optional; + +public final class PaddingLayoutImpl extends AbstractLayout implements PaddingLayout { + + private PaddingLayoutImpl(long bitSize) { + this(bitSize, 1, Optional.empty()); + } + + private PaddingLayoutImpl(long bitSize, long bitAlignment, Optional name) { + super(bitSize, bitAlignment, name); + } + + @Override + public String toString() { + return decorateLayoutString("x" + bitSize()); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!super.equals(other)) { + return false; + } + if (!(other instanceof PaddingLayoutImpl p)) { + return false; + } + return bitSize() == p.bitSize(); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), bitSize()); + } + + @Override + PaddingLayoutImpl dup(long bitAlignment, Optional name) { + return new PaddingLayoutImpl(bitSize(), bitAlignment, name); + } + + @Override + public boolean hasNaturalAlignment() { + return true; + } + + public static PaddingLayout of(long bitSize) { + return new PaddingLayoutImpl(bitSize); + } + +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/SequenceLayoutImpl.java b/src/java.base/share/classes/jdk/internal/foreign/layout/SequenceLayoutImpl.java new file mode 100644 index 00000000000..c249f76f9ee --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/SequenceLayoutImpl.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SequenceLayout; +import java.util.Objects; +import java.util.Optional; + +public final class SequenceLayoutImpl extends AbstractLayout implements SequenceLayout { + + private final long elemCount; + private final MemoryLayout elementLayout; + + private SequenceLayoutImpl(long elemCount, MemoryLayout elementLayout) { + this(elemCount, elementLayout, elementLayout.bitAlignment(), Optional.empty()); + } + + private SequenceLayoutImpl(long elemCount, MemoryLayout elementLayout, long bitAlignment, Optional name) { + super(Math.multiplyExact(elemCount, elementLayout.bitSize()), bitAlignment, name); + this.elemCount = elemCount; + this.elementLayout = elementLayout; + } + + /** + * {@return the element layout associated with this sequence layout} + */ + public MemoryLayout elementLayout() { + return elementLayout; + } + + /** + * {@return the element count of this sequence layout} + */ + public long elementCount() { + return elemCount; + } + + /** + * Returns a sequence layout with the same element layout, alignment constraints and name as this sequence layout, + * but with the specified element count. + * + * @param elementCount the new element count. + * @return a sequence layout with the given element count. + * @throws IllegalArgumentException if {@code elementCount < 0}. + */ + public SequenceLayout withElementCount(long elementCount) { + MemoryLayoutUtil.checkSize(elementCount, true); + return new SequenceLayoutImpl(elementCount, elementLayout, bitAlignment(), name()); + } + + /** + * Re-arrange the elements in this sequence layout into a multi-dimensional sequence layout. + * The resulting layout is a sequence layout where element layouts in the flattened projection of this + * sequence layout (see {@link #flatten()}) are re-arranged into one or more nested sequence layouts + * according to the provided element counts. This transformation preserves the layout size; + * that is, multiplying the provided element counts must yield the same element count + * as the flattened projection of this sequence layout. + *

    + * For instance, given a sequence layout of the kind: + * {@snippet lang = java: + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + *} + * calling {@code seq.reshape(2, 6)} will yield the following sequence layout: + * {@snippet lang = java: + * var reshapeSeq = MemoryLayout.sequenceLayout(2, MemoryLayout.sequenceLayout(6, ValueLayout.JAVA_INT)); + *} + *

    + * If one of the provided element count is the special value {@code -1}, then the element + * count in that position will be inferred from the remaining element counts and the + * element count of the flattened projection of this layout. For instance, a layout equivalent to + * the above {@code reshapeSeq} can also be computed in the following ways: + * {@snippet lang = java: + * var reshapeSeqImplicit1 = seq.reshape(-1, 6); + * var reshapeSeqImplicit2 = seq.reshape(2, -1); + *} + * + * @param elementCounts an array of element counts, of which at most one can be {@code -1}. + * @return a sequence layout where element layouts in the flattened projection of this + * sequence layout (see {@link #flatten()}) are re-arranged into one or more nested sequence layouts. + * @throws IllegalArgumentException if two or more element counts are set to {@code -1}, or if one + * or more element count is {@code <= 0} (but other than {@code -1}) or, if, after any required inference, + * multiplying the element counts does not yield the same element count as the flattened projection of this + * sequence layout. + */ + public SequenceLayout reshape(long... elementCounts) { + Objects.requireNonNull(elementCounts); + if (elementCounts.length == 0) { + throw new IllegalArgumentException(); + } + SequenceLayout flat = flatten(); + long expectedCount = flat.elementCount(); + + long actualCount = 1; + int inferPosition = -1; + for (int i = 0; i < elementCounts.length; i++) { + if (elementCounts[i] == -1) { + if (inferPosition == -1) { + inferPosition = i; + } else { + throw new IllegalArgumentException("Too many unspecified element counts"); + } + } else if (elementCounts[i] <= 0) { + throw new IllegalArgumentException("Invalid element count: " + elementCounts[i]); + } else { + actualCount = elementCounts[i] * actualCount; + } + } + + // infer an unspecified element count (if any) + if (inferPosition != -1) { + long inferredCount = expectedCount / actualCount; + elementCounts[inferPosition] = inferredCount; + actualCount = actualCount * inferredCount; + } + + if (actualCount != expectedCount) { + throw new IllegalArgumentException("Element counts do not match expected size: " + expectedCount); + } + + MemoryLayout res = flat.elementLayout(); + for (int i = elementCounts.length - 1; i >= 0; i--) { + res = MemoryLayout.sequenceLayout(elementCounts[i], res); + } + return (SequenceLayoutImpl) res; + } + + /** + * Returns a flattened sequence layout. The element layout of the returned sequence layout + * is the first non-sequence element layout found by recursively traversing the element layouts of this sequence layout. + * This transformation preserves the layout size; nested sequence layout in this sequence layout will + * be dropped and their element counts will be incorporated into that of the returned sequence layout. + * For instance, given a sequence layout of the kind: + * {@snippet lang = java: + * var seq = MemoryLayout.sequenceLayout(4, MemoryLayout.sequenceLayout(3, ValueLayout.JAVA_INT)); + *} + * calling {@code seq.flatten()} will yield the following sequence layout: + * {@snippet lang = java: + * var flattenedSeq = MemoryLayout.sequenceLayout(12, ValueLayout.JAVA_INT); + *} + * + * @return a sequence layout with the same size as this layout (but, possibly, with different + * element count), whose element layout is not a sequence layout. + */ + public SequenceLayout flatten() { + long count = elementCount(); + MemoryLayout elemLayout = elementLayout(); + while (elemLayout instanceof SequenceLayoutImpl elemSeq) { + count = count * elemSeq.elementCount(); + elemLayout = elemSeq.elementLayout(); + } + return MemoryLayout.sequenceLayout(count, elemLayout); + } + + @Override + public String toString() { + return decorateLayoutString(String.format("[%s:%s]", + elemCount, elementLayout)); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!super.equals(other)) { + return false; + } + return other instanceof SequenceLayoutImpl otherSeq && + elemCount == otherSeq.elemCount && + elementLayout.equals(otherSeq.elementLayout); + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), elemCount, elementLayout); + } + + @Override + SequenceLayoutImpl dup(long bitAlignment, Optional name) { + return new SequenceLayoutImpl(elementCount(), elementLayout, bitAlignment, name); + } + + @Override + public boolean hasNaturalAlignment() { + return bitAlignment() == elementLayout.bitAlignment(); + } + + public static SequenceLayout of(long elementCount, MemoryLayout elementLayout) { + return new SequenceLayoutImpl(elementCount, elementLayout); + } + +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/StructLayoutImpl.java b/src/java.base/share/classes/jdk/internal/foreign/layout/StructLayoutImpl.java new file mode 100644 index 00000000000..339afd735bb --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/StructLayoutImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.StructLayout; +import java.util.List; +import java.util.Optional; + +public final class StructLayoutImpl extends AbstractGroupLayout implements StructLayout { + + private StructLayoutImpl(List elements) { + super(Kind.STRUCT, elements); + } + + private StructLayoutImpl(List elements, long bitAlignment, Optional name) { + super(Kind.STRUCT, elements, bitAlignment, name); + } + + @Override + StructLayoutImpl dup(long bitAlignment, Optional name) { + return new StructLayoutImpl(memberLayouts(), bitAlignment, name); + } + + public static StructLayout of(List elements) { + return new StructLayoutImpl(elements); + } + +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/UnionLayoutImpl.java b/src/java.base/share/classes/jdk/internal/foreign/layout/UnionLayoutImpl.java new file mode 100644 index 00000000000..d8adb186c62 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/UnionLayoutImpl.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.UnionLayout; +import java.util.List; +import java.util.Optional; + +public final class UnionLayoutImpl extends AbstractGroupLayout implements UnionLayout { + + private UnionLayoutImpl(List elements) { + super(Kind.UNION, elements); + } + + private UnionLayoutImpl(List elements, long bitAlignment, Optional name) { + super(Kind.UNION, elements, bitAlignment, name); + } + + @Override + UnionLayoutImpl dup(long bitAlignment, Optional name) { + return new UnionLayoutImpl(memberLayouts(), bitAlignment, name); + } + + public static UnionLayout of(List elements) { + return new UnionLayoutImpl(elements); + } + +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java new file mode 100644 index 00000000000..079cb123a39 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/layout/ValueLayouts.java @@ -0,0 +1,457 @@ +/* + * Copyright (c) 2019, 2022, 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. + * + */ +package jdk.internal.foreign.layout; + +import jdk.internal.foreign.Utils; +import jdk.internal.misc.Unsafe; +import jdk.internal.reflect.CallerSensitive; +import jdk.internal.reflect.Reflection; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Stable; +import sun.invoke.util.Wrapper; + +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.VarHandle; +import java.nio.ByteOrder; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.Optional; + +/** + * A value layout. A value layout is used to model the memory layout associated with values of basic data types, such as integral types + * (either signed or unsigned) and floating-point types. Each value layout has a size, an alignment (in bits), + * a {@linkplain ByteOrder byte order}, and a carrier, that is, the Java type that should be used when + * {@linkplain MemorySegment#get(ValueLayout.OfInt, long) accessing} a memory region using the value layout. + *

    + * This class defines useful value layout constants for Java primitive types and addresses. + * The layout constants in this class make implicit alignment and byte-ordering assumption: all layout + * constants in this class are byte-aligned, and their byte order is set to the {@linkplain ByteOrder#nativeOrder() platform default}, + * thus making it easy to work with other APIs, such as arrays and {@link java.nio.ByteBuffer}. + * + * @implSpec This class and its subclasses are immutable, thread-safe and value-based. + */ +public final class ValueLayouts { + + private ValueLayouts() { + } + + abstract sealed static class AbstractValueLayout & ValueLayout> extends AbstractLayout { + + static final int ADDRESS_SIZE_BITS = Unsafe.ADDRESS_SIZE * 8; + + private final Class carrier; + private final ByteOrder order; + @Stable + private VarHandle handle; + + AbstractValueLayout(Class carrier, ByteOrder order, long bitSize) { + this(carrier, order, bitSize, bitSize, Optional.empty()); + } + + AbstractValueLayout(Class carrier, ByteOrder order, long bitSize, long bitAlignment, Optional name) { + super(bitSize, bitAlignment, name); + this.carrier = carrier; + this.order = order; + checkCarrierSize(carrier, bitSize); + } + + /** + * {@return the value's byte order} + */ + public final ByteOrder order() { + return order; + } + + /** + * Returns a value layout with the same carrier, alignment constraints and name as this value layout, + * but with the specified byte order. + * + * @param order the desired byte order. + * @return a value layout with the given byte order. + */ + abstract V withOrder(ByteOrder order); + + @Override + public final String toString() { + char descriptor = carrier == MemorySegment.class ? 'A' : carrier.descriptorString().charAt(0); + if (order == ByteOrder.LITTLE_ENDIAN) { + descriptor = Character.toLowerCase(descriptor); + } + return decorateLayoutString(String.format("%s%d", descriptor, bitSize())); + } + + @Override + public boolean equals(Object other) { + if (this == other) { + return true; + } + if (!super.equals(other)) { + return false; + } + return other instanceof AbstractValueLayout otherValue && + carrier.equals(otherValue.carrier) && + order.equals(otherValue.order); + } + + public final VarHandle arrayElementVarHandle(int... shape) { + Objects.requireNonNull(shape); + MemoryLayout layout = self(); + List path = new ArrayList<>(); + for (int i = shape.length; i > 0; i--) { + int size = shape[i - 1]; + if (size < 0) throw new IllegalArgumentException("Invalid shape size: " + size); + layout = MemoryLayout.sequenceLayout(size, layout); + path.add(MemoryLayout.PathElement.sequenceElement()); + } + layout = MemoryLayout.sequenceLayout(layout); + path.add(MemoryLayout.PathElement.sequenceElement()); + return layout.varHandle(path.toArray(new MemoryLayout.PathElement[0])); + } + + /** + * {@return the carrier associated with this value layout} + */ + public final Class carrier() { + return carrier; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), order, carrier); + } + + @Override + abstract V dup(long bitAlignment, Optional name); + + static void checkCarrierSize(Class carrier, long size) { + if (!isValidCarrier(carrier)) { + throw new IllegalArgumentException("Invalid carrier: " + carrier.getName()); + } + if (carrier == MemorySegment.class && size != ADDRESS_SIZE_BITS) { + throw new IllegalArgumentException("Address size mismatch: " + ADDRESS_SIZE_BITS + " != " + size); + } + if (carrier.isPrimitive()) { + int expectedSize = carrier == boolean.class ? 8 : Wrapper.forPrimitiveType(carrier).bitWidth(); + if (size != expectedSize) { + throw new IllegalArgumentException("Carrier size mismatch: " + carrier.getName() + " != " + size); + } + } + } + + static boolean isValidCarrier(Class carrier) { + return carrier == boolean.class + || carrier == byte.class + || carrier == short.class + || carrier == char.class + || carrier == int.class + || carrier == long.class + || carrier == float.class + || carrier == double.class + || carrier == MemorySegment.class; + } + + + @ForceInline + public final VarHandle accessHandle() { + if (handle == null) { + // this store to stable field is safe, because return value of 'makeMemoryAccessVarHandle' has stable identity + handle = Utils.makeSegmentViewVarHandle(self()); + } + return handle; + } + + @SuppressWarnings("unchecked") + final V self() { + return (V) this; + } + } + + public static final class OfBooleanImpl extends AbstractValueLayout implements ValueLayout.OfBoolean { + + private OfBooleanImpl(ByteOrder order) { + super(boolean.class, order, 8); + } + + private OfBooleanImpl(ByteOrder order, long bitAlignment, Optional name) { + super(boolean.class, order, 8, bitAlignment, name); + } + + @Override + OfBooleanImpl dup(long bitAlignment, Optional name) { + return new OfBooleanImpl(order(), bitAlignment, name); + } + + @Override + public OfBooleanImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfBooleanImpl(order, bitAlignment(), name()); + } + + public static OfBoolean of(ByteOrder order) { + return new OfBooleanImpl(order); + } + } + + public static final class OfByteImpl extends AbstractValueLayout implements ValueLayout.OfByte { + + private OfByteImpl(ByteOrder order) { + super(byte.class, order, 8); + } + + private OfByteImpl(ByteOrder order, long bitAlignment, Optional name) { + super(byte.class, order, 8, bitAlignment, name); + } + + @Override + OfByteImpl dup(long bitAlignment, Optional name) { + return new OfByteImpl(order(), bitAlignment, name); + } + + @Override + public OfByteImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfByteImpl(order, bitAlignment(), name()); + } + + public static OfByte of(ByteOrder order) { + return new OfByteImpl(order); + } + } + + public static final class OfCharImpl extends AbstractValueLayout implements ValueLayout.OfChar { + + private OfCharImpl(ByteOrder order) { + super(char.class, order, 16); + } + + private OfCharImpl(ByteOrder order, long bitAlignment, Optional name) { + super(char.class, order, 16, bitAlignment, name); + } + + @Override + OfCharImpl dup(long bitAlignment, Optional name) { + return new OfCharImpl(order(), bitAlignment, name); + } + + @Override + public OfCharImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfCharImpl(order, bitAlignment(), name()); + } + + public static OfChar of(ByteOrder order) { + return new OfCharImpl(order); + } + } + + public static final class OfShortImpl extends AbstractValueLayout implements ValueLayout.OfShort { + + private OfShortImpl(ByteOrder order) { + super(short.class, order, 16); + } + + private OfShortImpl(ByteOrder order, long bitAlignment, Optional name) { + super(short.class, order, 16, bitAlignment, name); + } + + @Override + OfShortImpl dup(long bitAlignment, Optional name) { + return new OfShortImpl(order(), bitAlignment, name); + } + + @Override + public OfShortImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfShortImpl(order, bitAlignment(), name()); + } + + public static OfShort of(ByteOrder order) { + return new OfShortImpl(order); + } + } + + public static final class OfIntImpl extends AbstractValueLayout implements ValueLayout.OfInt { + + private OfIntImpl(ByteOrder order) { + super(int.class, order, 32); + } + + private OfIntImpl(ByteOrder order, long bitAlignment, Optional name) { + super(int.class, order, 32, bitAlignment, name); + } + + @Override + OfIntImpl dup(long bitAlignment, Optional name) { + return new OfIntImpl(order(), bitAlignment, name); + } + + @Override + public OfIntImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfIntImpl(order, bitAlignment(), name()); + } + + public static OfInt of(ByteOrder order) { + return new OfIntImpl(order); + } + } + + public static final class OfFloatImpl extends AbstractValueLayout implements ValueLayout.OfFloat { + + private OfFloatImpl(ByteOrder order) { + super(float.class, order, 32); + } + + private OfFloatImpl(ByteOrder order, long bitAlignment, Optional name) { + super(float.class, order, 32, bitAlignment, name); + } + + @Override + OfFloatImpl dup(long bitAlignment, Optional name) { + return new OfFloatImpl(order(), bitAlignment, name); + } + + @Override + public OfFloatImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfFloatImpl(order, bitAlignment(), name()); + } + + public static OfFloat of(ByteOrder order) { + return new OfFloatImpl(order); + } + } + + public static final class OfLongImpl extends AbstractValueLayout implements ValueLayout.OfLong { + + private OfLongImpl(ByteOrder order) { + super(long.class, order, 64); + } + + private OfLongImpl(ByteOrder order, long bitAlignment, Optional name) { + super(long.class, order, 64, bitAlignment, name); + } + + @Override + OfLongImpl dup(long bitAlignment, Optional name) { + return new OfLongImpl(order(), bitAlignment, name); + } + + @Override + public OfLongImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfLongImpl(order, bitAlignment(), name()); + } + + public static OfLong of(ByteOrder order) { + return new OfLongImpl(order); + } + } + + public static final class OfDoubleImpl extends AbstractValueLayout implements ValueLayout.OfDouble { + + private OfDoubleImpl(ByteOrder order) { + super(double.class, order, 64); + } + + private OfDoubleImpl(ByteOrder order, long bitAlignment, Optional name) { + super(double.class, order, 64, bitAlignment, name); + } + + @Override + OfDoubleImpl dup(long bitAlignment, Optional name) { + return new OfDoubleImpl(order(), bitAlignment, name); + } + + @Override + public OfDoubleImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfDoubleImpl(order, bitAlignment(), name()); + } + + public static OfDouble of(ByteOrder order) { + return new OfDoubleImpl(order); + } + + } + + public static final class OfAddressImpl extends AbstractValueLayout implements ValueLayout.OfAddress { + + private final boolean isUnbounded; + + private OfAddressImpl(ByteOrder order) { + super(MemorySegment.class, order, ADDRESS_SIZE_BITS); + this.isUnbounded = false; // safe + } + + private OfAddressImpl(ByteOrder order, long size, long bitAlignment, boolean isUnbounded, Optional name) { + super(MemorySegment.class, order, size, bitAlignment, name); + this.isUnbounded = isUnbounded; + } + + @Override + OfAddressImpl dup(long alignment, Optional name) { + return new OfAddressImpl(order(), bitSize(), alignment, isUnbounded, name); + } + + @Override + public OfAddressImpl withOrder(ByteOrder order) { + Objects.requireNonNull(order); + return new OfAddressImpl(order, bitSize(), bitAlignment(), isUnbounded, name()); + } + + @Override + public boolean equals(Object other) { + return super.equals(other) && + ((OfAddressImpl) other).isUnbounded == this.isUnbounded; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), isUnbounded); + } + + @Override + @CallerSensitive + public OfAddress asUnbounded() { + Reflection.ensureNativeAccess(Reflection.getCallerClass(), OfAddress.class, "asUnbounded"); + return new OfAddressImpl(order(), bitSize(), bitAlignment(), true, name()); + } + + @Override + public boolean isUnbounded() { + return isUnbounded; + } + + public static OfAddress of(ByteOrder order) { + return new OfAddressImpl(order); + } + } + +} diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index 62749190f07..26e2a92ea4a 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -70,7 +70,7 @@ public enum Feature { RECORD_PATTERNS, @JEP(number=425, title="Virtual Threads") VIRTUAL_THREADS, - @JEP(number=424, title="Foreign Function & Memory API") + @JEP(number=434, title="Foreign Function & Memory API", status="Second Preview") FOREIGN, /** * A key for testing. diff --git a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java index ddb06be3775..80faf5ecf9a 100644 --- a/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java +++ b/src/java.base/share/classes/jdk/internal/module/ModuleBootstrap.java @@ -789,7 +789,7 @@ public static boolean hasEnableNativeAccessFlag() { private static void addEnableNativeAccess(ModuleLayer layer) { for (String name : NATIVE_ACCESS_MODULES) { if (name.equals("ALL-UNNAMED")) { - JLA.addEnableNativeAccessAllUnnamed(); + JLA.addEnableNativeAccessToAllUnnamed(); } else { Optional module = layer.findModule(name); if (module.isPresent()) { diff --git a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java index 7171b4fb53d..81eaf1545ff 100644 --- a/src/java.base/share/classes/jdk/internal/reflect/Reflection.java +++ b/src/java.base/share/classes/jdk/internal/reflect/Reflection.java @@ -115,33 +115,7 @@ public static void ensureNativeAccess(Class currentClass, Class owner, Str Module module = currentClass != null ? currentClass.getModule() : ClassLoader.getSystemClassLoader().getUnnamedModule(); - boolean isNativeAccessEnabled = SharedSecrets.getJavaLangAccess().isEnableNativeAccess(module); - if (!isNativeAccessEnabled) { - synchronized(module) { - isNativeAccessEnabled = SharedSecrets.getJavaLangAccess().isEnableNativeAccess(module); - if (isNativeAccessEnabled) { - // some other thread got to it, do nothing - } else if (ModuleBootstrap.hasEnableNativeAccessFlag()) { - throw new IllegalCallerException("Illegal native access from: " + module); - } else { - // warn and set flag, so that only one warning is reported per module - String cls = owner.getName(); - String mtd = cls + "::" + methodName; - String mod = module.isNamed() ? "module " + module.getName() : "the unnamed module"; - String modflag = module.isNamed() ? module.getName() : "ALL-UNNAMED"; - System.err.printf(""" - WARNING: A restricted method in %s has been called - WARNING: %s has been called by %s - WARNING: Use --enable-native-access=%s to avoid a warning for this module - %n""", cls, mtd, mod, modflag); - if (module.isNamed()) { - SharedSecrets.getJavaLangAccess().addEnableNativeAccess(module); - } else { - SharedSecrets.getJavaLangAccess().addEnableNativeAccessAllUnnamed(); - } - } - } - } + SharedSecrets.getJavaLangAccess().ensureNativeAccess(module, owner, methodName); } /** diff --git a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java index b57b56bb051..d203910bf8c 100644 --- a/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/FileChannelImpl.java @@ -29,7 +29,7 @@ import java.io.IOException; import java.io.UncheckedIOException; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.ref.Cleaner.Cleanable; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; @@ -1208,12 +1208,12 @@ public MappedByteBuffer map(MapMode mode, long position, long size) throws IOExc @Override public MemorySegment map(MapMode mode, long offset, long size, - MemorySession session) + SegmentScope session) throws IOException { Objects.requireNonNull(mode,"Mode is null"); Objects.requireNonNull(session, "Session is null"); - MemorySessionImpl sessionImpl = MemorySessionImpl.toSessionImpl(session); + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; sessionImpl.checkValidState(); if (offset < 0) throw new IllegalArgumentException("Requested bytes offset must be >= 0."); diff --git a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java index aed3c9350de..25f18134127 100644 --- a/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java +++ b/test/hotspot/jtreg/gc/shenandoah/compiler/TestLinkToNativeRBP.java @@ -50,7 +50,7 @@ public class TestLinkToNativeRBP { final static Linker abi = Linker.nativeLinker(); static final SymbolLookup lookup = SymbolLookup.loaderLookup(); - final static MethodHandle foo = abi.downcallHandle(lookup.lookup("foo").get(), + final static MethodHandle foo = abi.downcallHandle(lookup.find("foo").get(), FunctionDescriptor.of(ValueLayout.JAVA_INT)); static int foo() throws Throwable { diff --git a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java index 01921182353..0c41fe75791 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java +++ b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java @@ -42,7 +42,7 @@ public class ClassFileVersionTest { * compilation. If a particular class becomes non-preview, any * currently preview class can be substituted in. */ - private static final Class PREVIEW_API = java.lang.foreign.MemoryAddress.class; + private static final Class PREVIEW_API = java.lang.foreign.MemorySegment.class; static Method m; public static void testIt(String className, int expectedResult) throws Exception { diff --git a/test/jdk/com/sun/jdi/JdbLastErrorTest.java b/test/jdk/com/sun/jdi/JdbLastErrorTest.java index c5eceb855e1..9cde54207a3 100644 --- a/test/jdk/com/sun/jdi/JdbLastErrorTest.java +++ b/test/jdk/com/sun/jdi/JdbLastErrorTest.java @@ -54,10 +54,10 @@ private static void testWindows() throws Throwable { System.loadLibrary("Kernel32"); SymbolLookup lookup = SymbolLookup.loaderLookup(); MethodHandle getLastError = linker.downcallHandle( - lookup.lookup("GetLastError").orElseThrow(), + lookup.find("GetLastError").orElseThrow(), FunctionDescriptor.of(ValueLayout.JAVA_INT)); MethodHandle setLastError = linker.downcallHandle( - lookup.lookup("SetLastError").orElseThrow(), + lookup.find("SetLastError").orElseThrow(), FunctionDescriptor.ofVoid(ValueLayout.JAVA_INT)); for (int i = 0; i < 10; i++) { diff --git a/test/jdk/java/foreign/CallGeneratorHelper.java b/test/jdk/java/foreign/CallGeneratorHelper.java index f075616f582..e1ef460603b 100644 --- a/test/jdk/java/foreign/CallGeneratorHelper.java +++ b/test/jdk/java/foreign/CallGeneratorHelper.java @@ -22,17 +22,9 @@ * */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; -import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.ValueLayout; +import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.VarHandle; import java.util.ArrayList; @@ -387,21 +379,21 @@ static void generateUpcallFunction(String fName, Ret ret, List params @SuppressWarnings("unchecked") static Object makeArg(MemoryLayout layout, List> checks, boolean check) throws ReflectiveOperationException { if (layout instanceof GroupLayout) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); initStruct(segment, (GroupLayout)layout, checks, check); return segment; } else if (isPointer(layout)) { - MemorySegment segment = MemorySegment.allocateNative(1, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(1L, SegmentScope.auto()); if (check) { checks.add(o -> { try { - assertEquals(o, segment.address()); + assertEquals(o, segment); } catch (Throwable ex) { throw new IllegalStateException(ex); } }); } - return segment.address(); + return segment; } else if (layout instanceof ValueLayout) { if (isIntegral(layout)) { if (check) { @@ -426,7 +418,7 @@ static Object makeArg(MemoryLayout layout, List> checks, boolea static void initStruct(MemorySegment str, GroupLayout g, List> checks, boolean check) throws ReflectiveOperationException { for (MemoryLayout l : g.memberLayouts()) { - if (l.isPadding()) continue; + if (l instanceof PaddingLayout) continue; VarHandle accessor = g.varHandle(MemoryLayout.PathElement.groupElement(l.name().get())); List> fieldsCheck = new ArrayList<>(); Object value = makeArg(l, fieldsCheck, check); @@ -447,19 +439,17 @@ static void initStruct(MemorySegment str, GroupLayout g, List> } } - static Class carrier(MemoryLayout layout, boolean param) { + static Class carrier(MemoryLayout layout) { if (layout instanceof GroupLayout) { return MemorySegment.class; - } if (isPointer(layout)) { - return param ? Addressable.class : MemoryAddress.class; - } else if (layout instanceof ValueLayout valueLayout) { + } if (layout instanceof ValueLayout valueLayout) { return valueLayout.carrier(); } else { throw new IllegalStateException("Unexpected layout: " + layout); } } - MethodHandle downcallHandle(Linker abi, Addressable symbol, SegmentAllocator allocator, FunctionDescriptor descriptor) { + MethodHandle downcallHandle(Linker abi, MemorySegment symbol, SegmentAllocator allocator, FunctionDescriptor descriptor) { MethodHandle mh = abi.downcallHandle(symbol, descriptor); if (descriptor.returnLayout().isPresent() && descriptor.returnLayout().get() instanceof GroupLayout) { mh = mh.bindTo(allocator); diff --git a/test/jdk/java/foreign/LibraryLookupTest.java b/test/jdk/java/foreign/LibraryLookupTest.java index 9a7f321807e..b5108b5a63e 100644 --- a/test/jdk/java/foreign/LibraryLookupTest.java +++ b/test/jdk/java/foreign/LibraryLookupTest.java @@ -23,11 +23,11 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.nio.file.Path; @@ -51,12 +51,12 @@ public class LibraryLookupTest { @Test void testLoadLibraryConfined() { - try (MemorySession session0 = MemorySession.openConfined()) { - callFunc(loadLibrary(session0)); - try (MemorySession session1 = MemorySession.openConfined()) { - callFunc(loadLibrary(session1)); - try (MemorySession session2 = MemorySession.openConfined()) { - callFunc(loadLibrary(session2)); + try (Arena arena0 = Arena.openConfined()) { + callFunc(loadLibrary(arena0.scope())); + try (Arena arena1 = Arena.openConfined()) { + callFunc(loadLibrary(arena1.scope())); + try (Arena arena2 = Arena.openConfined()) { + callFunc(loadLibrary(arena2.scope())); } } } @@ -64,21 +64,21 @@ void testLoadLibraryConfined() { @Test(expectedExceptions = IllegalStateException.class) void testLoadLibraryConfinedClosed() { - Addressable addr; - try (MemorySession session = MemorySession.openConfined()) { - addr = loadLibrary(session); + MemorySegment addr; + try (Arena arena = Arena.openConfined()) { + addr = loadLibrary(arena.scope()); } callFunc(addr); } - private static Addressable loadLibrary(MemorySession session) { + private static MemorySegment loadLibrary(SegmentScope session) { SymbolLookup lib = SymbolLookup.libraryLookup(LIB_PATH, session); - MemorySegment addr = lib.lookup("inc").get(); - assertEquals(addr.session(), session); + MemorySegment addr = lib.find("inc").get(); + assertEquals(addr.scope(), session); return addr; } - private static void callFunc(Addressable addr) { + private static void callFunc(MemorySegment addr) { try { INC.invokeExact(addr); } catch (IllegalStateException ex) { @@ -94,12 +94,12 @@ private static void callFunc(Addressable addr) { @Test(expectedExceptions = IllegalArgumentException.class) void testBadLibraryLookupName() { - SymbolLookup.libraryLookup("nonExistent", MemorySession.global()); + SymbolLookup.libraryLookup("nonExistent", SegmentScope.global()); } @Test(expectedExceptions = IllegalArgumentException.class) void testBadLibraryLookupPath() { - SymbolLookup.libraryLookup(Path.of("nonExistent"), MemorySession.global()); + SymbolLookup.libraryLookup(Path.of("nonExistent"), SegmentScope.global()); } @Test @@ -116,8 +116,8 @@ static class LibraryLoadAndAccess implements Runnable { @Override public void run() { for (int i = 0 ; i < ITERATIONS ; i++) { - try (MemorySession session = MemorySession.openConfined()) { - callFunc(loadLibrary(session)); + try (Arena arena = Arena.openConfined()) { + callFunc(loadLibrary(arena.scope())); } } } @@ -125,15 +125,15 @@ public void run() { @Test void testLoadLibrarySharedClosed() throws Throwable { - MemorySession session = MemorySession.openShared(); - Addressable addr = loadLibrary(session); + Arena arena = Arena.openShared(); + MemorySegment addr = loadLibrary(arena.scope()); ExecutorService accessExecutor = Executors.newCachedThreadPool(); for (int i = 0; i < NUM_ACCESSORS ; i++) { accessExecutor.execute(new LibraryAccess(addr)); } while (true) { try { - session.close(); + arena.close(); break; } catch (IllegalStateException ex) { // wait for addressable parameter to be released @@ -146,9 +146,9 @@ void testLoadLibrarySharedClosed() throws Throwable { static class LibraryAccess implements Runnable { - final Addressable addr; + final MemorySegment addr; - LibraryAccess(Addressable addr) { + LibraryAccess(MemorySegment addr) { this.addr = addr; } diff --git a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java new file mode 100644 index 00000000000..49d4f7d4f69 --- /dev/null +++ b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020, 2022, 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 + * @enablePreview + * @run testng/othervm MemoryLayoutPrincipalTotalityTest + */ + +import org.testng.annotations.*; + +import java.lang.foreign.*; + +import static java.lang.foreign.ValueLayout.*; +import static org.testng.Assert.*; + +public class MemoryLayoutPrincipalTotalityTest extends NativeTestHelper { + + // The tests in this class is mostly there to ensure compile-time pattern matching totality. + + @Test + public void testBasicTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + int v0 = switch (memoryLayout) { + case MemoryLayout ml -> 1; + }; + assertEquals(v0, 1); + } + + @Test + public void testMLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v1 = switch (memoryLayout) { + case GroupLayout gl -> 0; + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case ValueLayout vl -> 1; + }; + assertEquals(v1, 1); + } + + @Test + public void testMLGLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v2 = switch (memoryLayout) { + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case ValueLayout vl -> 1; + case StructLayout sl -> 0; // leaf + case UnionLayout ul -> 0; // leaf + }; + assertEquals(v2, 1); + } + + @Test + public void testMLGLVLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v3 = switch (memoryLayout) { + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case StructLayout sl -> 0; // leaf + case UnionLayout ul -> 0; // leaf + case OfAddress oa -> 0; // leaf + case OfBoolean ob -> 0; // leaf + case OfByte ob -> 0; // leaf + case OfChar oc -> 0; // leaf + case OfDouble od -> 0; // leaf + case OfFloat of -> 0; // leaf + case OfInt oi -> 1; // leaf + case OfLong ol -> 0; // leaf + case OfShort os -> 0; // leaf + }; + assertEquals(v3, 1); + } + + @Test + public void testMLVLRemovedTotality() { + MemoryLayout memoryLayout = javaIntMemoryLayout(); + var v4 = switch (memoryLayout) { + case GroupLayout gl -> 0; + case PaddingLayout pl -> 0; // leaf + case SequenceLayout sl -> 0; // leaf + case OfAddress oa -> 0; // leaf + case OfBoolean ob -> 0; // leaf + case OfByte ob -> 0; // leaf + case OfChar oc -> 0; // leaf + case OfDouble od -> 0; // leaf + case OfFloat of -> 0; // leaf + case OfInt oi -> 1; // leaf + case OfLong ol -> 0; // leaf + case OfShort os -> 0; // leaf + }; + assertEquals(v4, 1); + } + + private static MemoryLayout javaIntMemoryLayout() { + return JAVA_INT; + } + +} diff --git a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java new file mode 100644 index 00000000000..9abccdaf9f8 --- /dev/null +++ b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2020, 2022, 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 + * @enablePreview + * @run testng/othervm MemoryLayoutTypeRetentionTest + */ + +import org.testng.annotations.*; + +import java.lang.foreign.*; +import java.nio.ByteOrder; + +import static java.lang.foreign.ValueLayout.*; +import static org.testng.Assert.*; + +public class MemoryLayoutTypeRetentionTest extends NativeTestHelper { + + // These tests check both compile-time and runtime properties. + // withName() et al. should return the same type as the original object. + + private static final String NAME = "a"; + private static final long BIT_ALIGNMENT = 64; + private static final ByteOrder BYTE_ORDER = ByteOrder.LITTLE_ENDIAN; + + @Test + public void testOfBoolean() { + OfBoolean v = JAVA_BOOLEAN + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfByte() { + OfByte v = JAVA_BYTE + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfShort() { + OfShort v = JAVA_SHORT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfInt() { + OfInt v = JAVA_INT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfChar() { + OfChar v = JAVA_CHAR + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfLong() { + OfLong v = JAVA_LONG + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfFloat() { + OfFloat v = JAVA_FLOAT + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfDouble() { + OfDouble v = JAVA_DOUBLE + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + } + + @Test + public void testOfAddress() { + OfAddress v = ADDRESS + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME) + .withOrder(BYTE_ORDER); + check(v); + assertFalse(v.isUnbounded()); + OfAddress v2 = v.asUnbounded(); + assertTrue(v2.isUnbounded()); + } + + @Test + public void testPaddingLayout() { + PaddingLayout v = MemoryLayout.paddingLayout(8) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testGroupLayout() { + GroupLayout v = MemoryLayout.structLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testStructLayout() { + StructLayout v = MemoryLayout.structLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + @Test + public void testUnionLayout() { + UnionLayout v = MemoryLayout.unionLayout(JAVA_INT, JAVA_LONG) + .withBitAlignment(BIT_ALIGNMENT) + .withName(NAME); + check(v); + } + + public void check(ValueLayout v) { + check((MemoryLayout) v); + assertEquals(v.order(), BYTE_ORDER); + } + + public void check(MemoryLayout v) { + assertEquals(v.name().orElseThrow(), NAME); + assertEquals(v.bitAlignment(), BIT_ALIGNMENT); + assertEquals(v.byteSize() * 8, v.bitSize()); + } + +} diff --git a/test/jdk/java/foreign/NativeTestHelper.java b/test/jdk/java/foreign/NativeTestHelper.java index e4fa9cc6be3..2d48f2e386c 100644 --- a/test/jdk/java/foreign/NativeTestHelper.java +++ b/test/jdk/java/foreign/NativeTestHelper.java @@ -22,18 +22,21 @@ * */ -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; public class NativeTestHelper { + public static final boolean IS_WINDOWS = System.getProperty("os.name").startsWith("Windows"); + public static boolean isIntegral(MemoryLayout layout) { return layout instanceof ValueLayout valueLayout && isIntegral(valueLayout.carrier()); } @@ -44,7 +47,7 @@ static boolean isIntegral(Class clazz) { } public static boolean isPointer(MemoryLayout layout) { - return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemoryAddress.class; + return layout instanceof ValueLayout valueLayout && valueLayout.carrier() == MemorySegment.class; } // the constants below are useful aliases for C types. The type/carrier association is only valid for 64-bit platforms. @@ -81,17 +84,17 @@ public static boolean isPointer(MemoryLayout layout) { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64); + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.withBitAlignment(64).asUnbounded(); - private static Linker LINKER = Linker.nativeLinker(); + private static final Linker LINKER = Linker.nativeLinker(); private static final MethodHandle FREE = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); + LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(C_POINTER)); private static final MethodHandle MALLOC = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(C_POINTER, C_LONG_LONG)); - public static void freeMemory(Addressable address) { + public static void freeMemory(MemorySegment address) { try { FREE.invokeExact(address); } catch (Throwable ex) { @@ -99,15 +102,28 @@ public static void freeMemory(Addressable address) { } } - public static MemoryAddress allocateMemory(long size) { + public static MemorySegment allocateMemory(long size) { try { - return (MemoryAddress)MALLOC.invokeExact(size); + return (MemorySegment) MALLOC.invokeExact(size); } catch (Throwable ex) { throw new IllegalStateException(ex); } } - public static Addressable findNativeOrThrow(String name) { - return SymbolLookup.loaderLookup().lookup(name).orElseThrow(); + public static MemorySegment findNativeOrThrow(String name) { + return SymbolLookup.loaderLookup().find(name).orElseThrow(); + } + + public static MethodHandle downcallHandle(String symbol, FunctionDescriptor desc, Linker.Option... options) { + return LINKER.downcallHandle(findNativeOrThrow(symbol), desc, options); + } + + public static MemorySegment upcallStub(Class holder, String name, FunctionDescriptor descriptor) { + try { + MethodHandle target = MethodHandles.lookup().findStatic(holder, name, descriptor.toMethodType()); + return LINKER.upcallStub(target, descriptor, SegmentScope.auto()); + } catch (ReflectiveOperationException e) { + throw new RuntimeException(e); + } } } diff --git a/test/jdk/java/foreign/SafeFunctionAccessTest.java b/test/jdk/java/foreign/SafeFunctionAccessTest.java index f638814c4f9..5873afb2308 100644 --- a/test/jdk/java/foreign/SafeFunctionAccessTest.java +++ b/test/jdk/java/foreign/SafeFunctionAccessTest.java @@ -28,18 +28,20 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED SafeFunctionAccessTest */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; import java.lang.foreign.VaList; +import java.util.stream.Stream; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -56,10 +58,10 @@ public class SafeFunctionAccessTest extends NativeTestHelper { @Test(expectedExceptions = IllegalStateException.class) public void testClosedStruct() throws Throwable { MemorySegment segment; - try (MemorySession session = MemorySession.openConfined()) { - segment = MemorySegment.allocateNative(POINT, session); + try (Arena arena = Arena.openConfined()) { + segment = arena.allocate(POINT); } - assertFalse(segment.session().isAlive()); + assertFalse(segment.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("struct_func"), FunctionDescriptor.ofVoid(POINT)); @@ -72,33 +74,39 @@ public void testClosedStructAddr_6() throws Throwable { MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func_6"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER, C_POINTER)); + record Allocation(Arena drop, MemorySegment segment) { + static Allocation of(MemoryLayout layout) { + Arena arena = Arena.openShared(); + return new Allocation(arena, arena.allocate(layout)); + } + } for (int i = 0 ; i < 6 ; i++) { - MemorySegment[] segments = new MemorySegment[]{ - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()), - MemorySegment.allocateNative(POINT, MemorySession.openShared()) + Allocation[] allocations = new Allocation[]{ + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT), + Allocation.of(POINT) }; // check liveness - segments[i].session().close(); + allocations[i].drop().close(); for (int j = 0 ; j < 6 ; j++) { if (i == j) { - assertFalse(segments[j].session().isAlive()); + assertFalse(allocations[j].drop().scope().isAlive()); } else { - assertTrue(segments[j].session().isAlive()); + assertTrue(allocations[j].drop().scope().isAlive()); } } try { - handle.invokeWithArguments(segments); + handle.invokeWithArguments(Stream.of(allocations).map(Allocation::segment).toArray()); fail(); } catch (IllegalStateException ex) { assertTrue(ex.getMessage().contains("Already closed")); } for (int j = 0 ; j < 6 ; j++) { if (i != j) { - segments[j].session().close(); // should succeed! + allocations[j].drop().close(); // should succeed! } } } @@ -107,30 +115,30 @@ public void testClosedStructAddr_6() throws Throwable { @Test(expectedExceptions = IllegalStateException.class) public void testClosedVaList() throws Throwable { VaList list; - try (MemorySession session = MemorySession.openConfined()) { - list = VaList.make(b -> b.addVarg(C_INT, 42), session); + try (Arena arena = Arena.openConfined()) { + list = VaList.make(b -> b.addVarg(C_INT, 42), arena.scope()); } - assertFalse(list.session().isAlive()); + assertFalse(list.segment().scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func"), FunctionDescriptor.ofVoid(C_POINTER)); - handle.invokeExact((Addressable)list); + handle.invokeExact(list.segment()); } @Test(expectedExceptions = IllegalStateException.class) public void testClosedUpcall() throws Throwable { MemorySegment upcall; - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); - upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), session); + upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), arena.scope()); } - assertFalse(upcall.session().isAlive()); + assertFalse(upcall.scope().isAlive()); MethodHandle handle = Linker.nativeLinker().downcallHandle( findNativeOrThrow("addr_func"), FunctionDescriptor.ofVoid(C_POINTER)); - handle.invokeExact((Addressable)upcall); + handle.invokeExact(upcall); } static void dummy() { } @@ -141,9 +149,9 @@ public void testClosedVaListCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { - VaList list = VaList.make(b -> b.addVarg(C_INT, 42), session); - handle.invoke(list, sessionChecker(session)); + try (Arena arena = Arena.openConfined()) { + VaList list = VaList.make(b -> b.addVarg(C_INT, 42), arena.scope()); + handle.invokeExact(list.segment(), sessionChecker(arena)); } } @@ -153,9 +161,9 @@ public void testClosedStructCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(POINT, session); - handle.invoke(segment, sessionChecker(session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(POINT); + handle.invokeExact(segment, sessionChecker(arena)); } } @@ -165,27 +173,27 @@ public void testClosedUpcallCallback() throws Throwable { findNativeOrThrow("addr_func_cb"), FunctionDescriptor.ofVoid(C_POINTER, C_POINTER)); - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle dummy = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "dummy", MethodType.methodType(void.class)); - MemorySegment upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), session); - handle.invoke(upcall, sessionChecker(session)); + MemorySegment upcall = Linker.nativeLinker().upcallStub(dummy, FunctionDescriptor.ofVoid(), arena.scope()); + handle.invokeExact(upcall, sessionChecker(arena)); } } - MemorySegment sessionChecker(MemorySession session) { + MemorySegment sessionChecker(Arena arena) { try { MethodHandle handle = MethodHandles.lookup().findStatic(SafeFunctionAccessTest.class, "checkSession", - MethodType.methodType(void.class, MemorySession.class)); - handle = handle.bindTo(session); - return Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), MemorySession.openImplicit()); + MethodType.methodType(void.class, Arena.class)); + handle = handle.bindTo(arena); + return Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), SegmentScope.auto()); } catch (Throwable ex) { throw new AssertionError(ex); } } - static void checkSession(MemorySession session) { + static void checkSession(Arena arena) { try { - session.close(); + arena.close(); fail("Session closed unexpectedly!"); } catch (IllegalStateException ex) { assertTrue(ex.getMessage().contains("acquired")); //if acquired, fine diff --git a/test/jdk/java/foreign/StdLibTest.java b/test/jdk/java/foreign/StdLibTest.java index 98bf9f50703..05c4faac992 100644 --- a/test/jdk/java/foreign/StdLibTest.java +++ b/test/jdk/java/foreign/StdLibTest.java @@ -152,37 +152,35 @@ void test_vprintf(List args) throws Throwable { static class StdLibHelper { - final static MethodHandle strcat = abi.downcallHandle(abi.defaultLookup().lookup("strcat").get(), - FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)) - .asType(MethodType.methodType(MemoryAddress.class, MemorySegment.class, MemorySegment.class)); // exact signature match + final static MethodHandle strcat = abi.downcallHandle(abi.defaultLookup().find("strcat").get(), + FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER)); - - final static MethodHandle strcmp = abi.downcallHandle(abi.defaultLookup().lookup("strcmp").get(), + final static MethodHandle strcmp = abi.downcallHandle(abi.defaultLookup().find("strcmp").get(), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static MethodHandle puts = abi.downcallHandle(abi.defaultLookup().lookup("puts").get(), + final static MethodHandle puts = abi.downcallHandle(abi.defaultLookup().find("puts").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle strlen = abi.downcallHandle(abi.defaultLookup().lookup("strlen").get(), + final static MethodHandle strlen = abi.downcallHandle(abi.defaultLookup().find("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); - final static MethodHandle gmtime = abi.downcallHandle(abi.defaultLookup().lookup("gmtime").get(), + final static MethodHandle gmtime = abi.downcallHandle(abi.defaultLookup().find("gmtime").get(), FunctionDescriptor.of(C_POINTER, C_POINTER)); - final static MethodHandle qsort = abi.downcallHandle(abi.defaultLookup().lookup("qsort").get(), + final static MethodHandle qsort = abi.downcallHandle(abi.defaultLookup().find("qsort").get(), FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER)); final static FunctionDescriptor qsortComparFunction = FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER); final static MethodHandle qsortCompar; - final static MethodHandle rand = abi.downcallHandle(abi.defaultLookup().lookup("rand").get(), + final static MethodHandle rand = abi.downcallHandle(abi.defaultLookup().find("rand").get(), FunctionDescriptor.of(C_INT)); - final static MethodHandle vprintf = abi.downcallHandle(abi.defaultLookup().lookup("vprintf").get(), + final static MethodHandle vprintf = abi.downcallHandle(abi.defaultLookup().find("vprintf").get(), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER)); - final static Addressable printfAddr = abi.defaultLookup().lookup("printf").get(); + final static MemorySegment printfAddr = abi.defaultLookup().find("printf").get(); final static FunctionDescriptor printfBase = FunctionDescriptor.of(C_INT, C_POINTER); @@ -190,48 +188,48 @@ static class StdLibHelper { try { //qsort upcall handle qsortCompar = MethodHandles.lookup().findStatic(StdLibTest.StdLibHelper.class, "qsortCompare", - Linker.upcallType(qsortComparFunction)); + qsortComparFunction.toMethodType()); } catch (ReflectiveOperationException ex) { throw new IllegalStateException(ex); } } String strcat(String s1, String s2) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment buf = session.allocate(s1.length() + s2.length() + 1); + try (var arena = Arena.openConfined()) { + MemorySegment buf = arena.allocate(s1.length() + s2.length() + 1); buf.setUtf8String(0, s1); - MemorySegment other = session.allocateUtf8String(s2); - return ((MemoryAddress)strcat.invokeExact(buf, other)).getUtf8String(0); + MemorySegment other = arena.allocateUtf8String(s2); + return ((MemorySegment)strcat.invokeExact(buf, other)).getUtf8String(0); } } int strcmp(String s1, String s2) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment ns1 = session.allocateUtf8String(s1); - MemorySegment ns2 = session.allocateUtf8String(s2); - return (int)strcmp.invoke(ns1, ns2); + try (var arena = Arena.openConfined()) { + MemorySegment ns1 = arena.allocateUtf8String(s1); + MemorySegment ns2 = arena.allocateUtf8String(s2); + return (int)strcmp.invokeExact(ns1, ns2); } } int puts(String msg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = session.allocateUtf8String(msg); - return (int)puts.invoke(s); + try (var arena = Arena.openConfined()) { + MemorySegment s = arena.allocateUtf8String(msg); + return (int)puts.invokeExact(s); } } int strlen(String msg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = session.allocateUtf8String(msg); - return (int)strlen.invoke(s); + try (var arena = Arena.openConfined()) { + MemorySegment s = arena.allocateUtf8String(msg); + return (int)strlen.invokeExact(s); } } Tm gmtime(long arg) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment time = session.allocate(8); + try (var arena = Arena.openConfined()) { + MemorySegment time = arena.allocate(8); time.set(C_LONG_LONG, 0, arg); - return new Tm((MemoryAddress)gmtime.invoke(time)); + return new Tm((MemorySegment)gmtime.invokeExact(time)); } } @@ -242,8 +240,8 @@ static class Tm { static final long SIZE = 56; - Tm(MemoryAddress addr) { - this.base = MemorySegment.ofAddress(addr, SIZE, MemorySession.global()); + Tm(MemorySegment addr) { + this.base = addr.asSlice(0, SIZE); } int sec() { @@ -277,20 +275,20 @@ boolean isdst() { int[] qsort(int[] arr) throws Throwable { //init native array - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArr = session.allocateArray(C_INT, arr); + try (var arena = Arena.openConfined()) { + MemorySegment nativeArr = arena.allocateArray(C_INT, arr); //call qsort - Addressable qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, session); + MemorySegment qsortUpcallStub = abi.upcallStub(qsortCompar, qsortComparFunction, arena.scope()); - qsort.invoke(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); + qsort.invokeExact(nativeArr, (long)arr.length, C_INT.byteSize(), qsortUpcallStub); //convert back to Java array return nativeArr.toArray(C_INT); } } - static int qsortCompare(MemoryAddress addr1, MemoryAddress addr2) { + static int qsortCompare(MemorySegment addr1, MemorySegment addr2) { return addr1.get(C_INT, 0) - addr2.get(C_INT, 0); } @@ -300,32 +298,34 @@ int rand() throws Throwable { } int printf(String format, List args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment formatStr = session.allocateUtf8String(format); - return (int)specializedPrintf(args).invoke(formatStr, - args.stream().map(a -> a.nativeValue(session)).toArray()); + try (var arena = Arena.openConfined()) { + MemorySegment formatStr = arena.allocateUtf8String(format); + return (int)specializedPrintf(args).invokeExact(formatStr, + args.stream().map(a -> a.nativeValue(arena)).toArray()); } } int vprintf(String format, List args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment formatStr = session.allocateUtf8String(format); - VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, session)), session); - return (int)vprintf.invoke(formatStr, vaList); + try (var arena = Arena.openConfined()) { + MemorySegment formatStr = arena.allocateUtf8String(format); + VaList vaList = VaList.make(b -> args.forEach(a -> a.accept(b, arena)), arena.scope()); + return (int)vprintf.invokeExact(formatStr, vaList.segment()); } } private MethodHandle specializedPrintf(List args) { //method type - MethodType mt = MethodType.methodType(int.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(int.class, MemorySegment.class); FunctionDescriptor fd = printfBase; List variadicLayouts = new ArrayList<>(args.size()); for (PrintfArg arg : args) { mt = mt.appendParameterTypes(arg.carrier); variadicLayouts.add(arg.layout); } + Linker.Option varargIndex = Linker.Option.firstVariadicArg(fd.argumentLayouts().size()); MethodHandle mh = abi.downcallHandle(printfAddr, - fd.asVariadic(variadicLayouts.toArray(new MemoryLayout[args.size()]))); + fd.appendArgumentLayouts(variadicLayouts.toArray(new MemoryLayout[args.size()])), + varargIndex); return mh.asSpreader(1, Object[].class, args.size()); } } @@ -384,26 +384,24 @@ public static Object[][] printfArgs() { .toArray(Object[][]::new); } - enum PrintfArg implements BiConsumer { + enum PrintfArg implements BiConsumer { - INTEGRAL(int.class, C_INT, "%d", session -> 42, 42, VaList.Builder::addVarg), - STRING(MemoryAddress.class, C_POINTER, "%s", session -> { - var segment = MemorySegment.allocateNative(4, session); - segment.setUtf8String(0, "str"); - return segment.address(); + INTEGRAL(int.class, C_INT, "%d", arena -> 42, 42, VaList.Builder::addVarg), + STRING(MemorySegment.class, C_POINTER, "%s", arena -> { + return arena.allocateUtf8String("str"); }, "str", VaList.Builder::addVarg), - CHAR(byte.class, C_CHAR, "%c", session -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)), - DOUBLE(double.class, C_DOUBLE, "%.4f", session ->1.2345d, 1.2345d, VaList.Builder::addVarg); + CHAR(byte.class, C_CHAR, "%c", arena -> (byte) 'h', 'h', (builder, layout, value) -> builder.addVarg(C_INT, (int)value)), + DOUBLE(double.class, C_DOUBLE, "%.4f", arena ->1.2345d, 1.2345d, VaList.Builder::addVarg); final Class carrier; final ValueLayout layout; final String format; - final Function nativeValueFactory; + final Function nativeValueFactory; final Object javaValue; @SuppressWarnings("rawtypes") final VaListBuilderCall builderCall; - PrintfArg(Class carrier, L layout, String format, Function nativeValueFactory, Object javaValue, VaListBuilderCall builderCall) { + PrintfArg(Class carrier, L layout, String format, Function nativeValueFactory, Object javaValue, VaListBuilderCall builderCall) { this.carrier = carrier; this.layout = layout; this.format = format; @@ -414,16 +412,16 @@ PrintfArg(Class carrier, L layout, String format, @Override @SuppressWarnings("unchecked") - public void accept(VaList.Builder builder, MemorySession session) { - builderCall.build(builder, layout, nativeValueFactory.apply(session)); + public void accept(VaList.Builder builder, Arena arena) { + builderCall.build(builder, layout, nativeValueFactory.apply(arena)); } interface VaListBuilderCall { void build(VaList.Builder builder, L layout, V value); } - public Object nativeValue(MemorySession session) { - return nativeValueFactory.apply(session); + public Object nativeValue(Arena arena) { + return nativeValueFactory.apply(arena); } } diff --git a/test/jdk/java/foreign/TestAdaptVarHandles.java b/test/jdk/java/foreign/TestAdaptVarHandles.java index c16701991c6..de74ed8c6b2 100644 --- a/test/jdk/java/foreign/TestAdaptVarHandles.java +++ b/test/jdk/java/foreign/TestAdaptVarHandles.java @@ -31,8 +31,9 @@ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestAdaptVarHandles */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.*; import static org.testng.Assert.*; @@ -93,7 +94,7 @@ public class TestAdaptVarHandles { @Test public void testFilterValue() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, S2I, I2S); i2SHandle.set(segment, "1"); @@ -112,7 +113,7 @@ public void testFilterValue() throws Throwable { @Test public void testFilterValueComposite() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); MethodHandle CTX_S2I = MethodHandles.dropArguments(S2I, 0, String.class, String.class); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, CTX_S2I, CTX_I2S); @@ -133,7 +134,7 @@ public void testFilterValueComposite() throws Throwable { @Test public void testFilterValueLoose() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle = layout.varHandle(); VarHandle i2SHandle = MethodHandles.filterValue(intHandle, O2I, I2O); i2SHandle.set(segment, "1"); @@ -190,8 +191,8 @@ public void testBadFilterUnboxException() { public void testBadFilterBoxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I, I2S_EX); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, arena.scope()); vh.set(seg, "42"); String x = (String) vh.get(seg); // should throw } @@ -201,8 +202,8 @@ public void testBadFilterBoxHandleException() { public void testBadFilterUnboxHandleException() { VarHandle intHandle = ValueLayout.JAVA_INT.varHandle(); VarHandle vh = MethodHandles.filterValue(intHandle, S2I_EX, I2S); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.allocateNative(ValueLayout.JAVA_INT, arena.scope()); vh.set(seg, "42"); // should throw } } @@ -210,7 +211,7 @@ public void testBadFilterUnboxHandleException() { @Test public void testFilterCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_longIndex = MethodHandles.filterCoordinates(intHandleIndexed, 0, BASE_ADDR, S2L); intHandle_longIndex.set(segment, "0", 1); int oldValue = (int)intHandle_longIndex.getAndAdd(segment, "0", 42); @@ -253,7 +254,7 @@ public void testBadFilterCoordinatesTooManyFilters() { @Test public void testInsertCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_longIndex = MethodHandles.insertCoordinates(intHandleIndexed, 0, segment, 0L); intHandle_longIndex.set(1); int oldValue = (int)intHandle_longIndex.getAndAdd(42); @@ -291,7 +292,7 @@ public void testBadInsertCoordinatesTooManyValues() { @Test public void testPermuteCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_swap = MethodHandles.permuteCoordinates(intHandleIndexed, List.of(long.class, MemorySegment.class), 1, 0); intHandle_swap.set(0L, segment, 1); @@ -330,7 +331,7 @@ public void testBadPermuteCoordinatesIndexTooSmall() { @Test public void testCollectCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_sum = MethodHandles.collectCoordinates(intHandleIndexed, 1, SUM_OFFSETS); intHandle_sum.set(segment, -2L, 2L, 1); int oldValue = (int)intHandle_sum.getAndAdd(segment, -2L, 2L, 42); @@ -373,7 +374,7 @@ public void testBadCollectCoordinatesWrongFilterException() { @Test public void testDropCoordinates() throws Throwable { ValueLayout layout = ValueLayout.JAVA_INT; - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); VarHandle intHandle_dummy = MethodHandles.dropCoordinates(intHandleIndexed, 1, float.class, String.class); intHandle_dummy.set(segment, 1f, "hello", 0L, 1); int oldValue = (int)intHandle_dummy.getAndAdd(segment, 1f, "hello", 0L, 42); diff --git a/test/jdk/java/foreign/TestArrays.java b/test/jdk/java/foreign/TestArrays.java index 978993e1fb1..e16dfb0d851 100644 --- a/test/jdk/java/foreign/TestArrays.java +++ b/test/jdk/java/foreign/TestArrays.java @@ -28,11 +28,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestArrays */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.invoke.VarHandle; @@ -108,7 +108,7 @@ static void checkBytes(MemorySegment base, SequenceLayout layout, Function init, Consumer checker, MemoryLayout layout) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); init.accept(segment); assertFalse(segment.isReadOnly()); checker.accept(segment); @@ -119,7 +119,7 @@ public void testArrays(Consumer init, Consumer che public void testTooBigForArray(MemoryLayout layout, Function arrayFactory) { MemoryLayout seq = MemoryLayout.sequenceLayout((Integer.MAX_VALUE * layout.byteSize()) + 1, layout); //do not really allocate here, as it's way too much memory - MemorySegment segment = MemorySegment.ofAddress(MemoryAddress.NULL, seq.byteSize(), MemorySession.global()); + MemorySegment segment = MemorySegment.ofAddress(0, seq.byteSize(), SegmentScope.global()); arrayFactory.apply(segment); } @@ -127,8 +127,8 @@ public void testTooBigForArray(MemoryLayout layout, Function arrayFactory) { if (layout.byteSize() == 1) throw new IllegalStateException(); //make it fail - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout.byteSize() + 1, layout.byteSize(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout.byteSize() + 1, layout.byteSize(), arena.scope()); arrayFactory.apply(segment); } } @@ -136,8 +136,9 @@ public void testBadSize(MemoryLayout layout, Function arr @Test(dataProvider = "elemLayouts", expectedExceptions = IllegalStateException.class) public void testArrayFromClosedSegment(MemoryLayout layout, Function arrayFactory) { - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openConfined()); - segment.session().close(); + Arena arena = Arena.openConfined(); + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); + arena.close(); arrayFactory.apply(segment); } diff --git a/test/jdk/java/foreign/TestByteBuffer.java b/test/jdk/java/foreign/TestByteBuffer.java index 998a3197548..4f13b9112e6 100644 --- a/test/jdk/java/foreign/TestByteBuffer.java +++ b/test/jdk/java/foreign/TestByteBuffer.java @@ -28,11 +28,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestByteBuffer */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout.PathElement; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.io.File; @@ -63,7 +63,6 @@ import java.nio.file.Path; import java.nio.file.StandardOpenOption; import java.util.ArrayList; -import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -186,8 +185,8 @@ static void checkBytes(MemorySegment base, SequenceLayout lay @Test public void testOffheap() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(tuples, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(tuples, arena.scope());; initTuples(segment, tuples.elementCount()); ByteBuffer bb = segment.asByteBuffer(); @@ -231,15 +230,15 @@ public void testChannel() throws Throwable { @Test public void testDefaultAccessModesMappedSegment() throws Throwable { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena.scope()); assertFalse(segment.isReadOnly()); } - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 8L, arena.scope()); assertTrue(segment.isReadOnly()); } } @@ -250,18 +249,18 @@ public void testMappedSegment() throws Throwable { f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { //write to channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, tuples.byteSize(), arena.scope()); initTuples(segment, tuples.elementCount()); segment.force(); } - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { //read from channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena.scope()); checkTuples(segment, segment.asByteBuffer(), tuples.elementCount()); } } @@ -272,11 +271,11 @@ public void testMappedSegmentOperations(MappedSegmentOp mappedBufferOp) throws T f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); - FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, session); + Arena arena = Arena.openConfined(); + try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 8L, arena.scope()); assertTrue(segment.isMapped()); - segment.session().close(); + arena.close(); mappedBufferOp.apply(segment); } } @@ -291,10 +290,10 @@ public void testMappedSegmentOffset() throws Throwable { // write one at a time for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { //write to channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, i, tuples.byteSize(), arena.scope()); initTuples(segment, 1); segment.force(); } @@ -302,10 +301,10 @@ public void testMappedSegmentOffset() throws Throwable { // check one at a time for (int i = 0 ; i < tuples.byteSize() ; i += tupleLayout.byteSize()) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { //read from channel - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, tuples.byteSize(), arena.scope()); checkTuples(segment, segment.asByteBuffer(), 1); } } @@ -323,9 +322,9 @@ public void testLargeMappedSegment() throws Throwable { f.createNewFile(); f.deleteOnExit(); - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, LARGE_SIZE, arena.scope()); segment.isLoaded(); segment.load(); segment.isLoaded(); @@ -361,8 +360,8 @@ static void checkByteArrayAlignment(MemoryLayout layout) { @Test(dataProvider = "bufferOps") public void testScopedBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { Buffer bb; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; bb = bufferFactory.apply(segment.asByteBuffer()); } //outside of session!! @@ -387,8 +386,8 @@ public void testScopedBuffer(Function bufferFactory, @NoInje @Test(dataProvider = "bufferHandleOps") public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { ByteBuffer bb; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; bb = segment.asByteBuffer(); for (Map.Entry e : varHandleMembers(bb, bufferHandle).entrySet()) { MethodHandle handle = e.getKey().bindTo(bufferHandle) @@ -421,12 +420,12 @@ public void testScopedBufferAndVarHandle(VarHandle bufferHandle) { @Test(dataProvider = "bufferOps") public void testDirectBuffer(Function bufferFactory, @NoInjection Method method, Object[] args) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(bytes, arena.scope());; Buffer bb = bufferFactory.apply(segment.asByteBuffer()); assertTrue(bb.isDirect()); DirectBuffer directBuffer = ((DirectBuffer)bb); - assertEquals(directBuffer.address(), segment.address().toRawLongValue()); + assertEquals(directBuffer.address(), segment.address()); assertTrue((directBuffer.attachment() == null) == (bb instanceof ByteBuffer)); assertTrue(directBuffer.cleaner() == null); } @@ -434,8 +433,8 @@ public void testDirectBuffer(Function bufferFactory, @NoInje @Test(dataProvider="resizeOps") public void testResizeOffheap(Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); checker.accept(segment); } @@ -472,8 +471,8 @@ public void testResizeRoundtripHeap(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); MemorySegment second = MemorySegment.ofBuffer(segment.asByteBuffer()); checker.accept(second); @@ -483,8 +482,8 @@ public void testResizeRoundtripNative(Consumer checker, Consumer< @Test(expectedExceptions = IllegalStateException.class) public void testBufferOnClosedSession() { MemorySegment leaked; - try (MemorySession session = MemorySession.openConfined()) { - leaked = MemorySegment.allocateNative(bytes, session); + try (Arena arena = Arena.openConfined()) { + leaked = MemorySegment.allocateNative(bytes, arena.scope());; } ByteBuffer byteBuffer = leaked.asByteBuffer(); // ok byteBuffer.get(); // should throw @@ -492,7 +491,7 @@ public void testBufferOnClosedSession() { @Test(expectedExceptions = IllegalStateException.class) public void testTooBigForByteBuffer() { - MemorySegment segment = MemorySegment.ofAddress(MemoryAddress.NULL, Integer.MAX_VALUE + 10L, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.ofAddress(0, Integer.MAX_VALUE + 10L, SegmentScope.auto()); segment.asByteBuffer(); } @@ -502,7 +501,7 @@ public void testBadMapNegativeSize() throws IOException { f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, -1L, SegmentScope.auto()); } } @@ -512,7 +511,7 @@ public void testBadMapNegativeOffset() throws IOException { f.createNewFile(); f.deleteOnExit(); try (FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, -1L, 1L, SegmentScope.auto()); } } @@ -524,9 +523,9 @@ public void testMapOffset() throws IOException { int SIZE = Byte.MAX_VALUE; - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, SIZE, arena.scope()); for (byte offset = 0; offset < SIZE; offset++) { segment.set(JAVA_BYTE, offset, offset); } @@ -534,9 +533,9 @@ public void testMapOffset() throws IOException { } for (int offset = 0 ; offset < SIZE ; offset++) { - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, offset, SIZE - offset, arena.scope()); assertEquals(segment.get(JAVA_BYTE, 0), offset); } } @@ -548,9 +547,9 @@ public void testMapZeroSize() throws IOException { f.createNewFile(); f.deleteOnExit(); //RW - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, arena.scope()); assertEquals(segment.byteSize(), 0); assertEquals(segment.isMapped(), true); assertFalse(segment.isReadOnly()); @@ -560,9 +559,9 @@ public void testMapZeroSize() throws IOException { segment.unload(); } //RO - try (MemorySession session = MemorySession.openConfined(); + try (Arena arena = Arena.openConfined(); FileChannel fileChannel = FileChannel.open(f.toPath(), StandardOpenOption.READ)) { - MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, session); + MemorySegment segment = fileChannel.map(FileChannel.MapMode.READ_ONLY, 0L, 0L, arena.scope()); assertEquals(segment.byteSize(), 0); assertEquals(segment.isMapped(), true); assertTrue(segment.isReadOnly()); @@ -577,7 +576,7 @@ public void testMapZeroSize() throws IOException { public void testMapCustomPath() throws IOException { Path path = Path.of(URI.create("jrt:/")); try (FileChannel fileChannel = FileChannel.open(path, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, MemorySession.openImplicit()); + fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 0L, SegmentScope.auto()); } } @@ -585,8 +584,8 @@ public void testMapCustomPath() throws IOException { public void testCopyHeapToNative(Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArray = MemorySegment.allocateNative(bytes, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment nativeArray = MemorySegment.allocateNative(bytes, 1, arena.scope());; MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); initializer.accept(heapArray); nativeArray.copyFrom(heapArray); @@ -598,8 +597,8 @@ public void testCopyHeapToNative(Consumer checker, Consumer checker, Consumer initializer, SequenceLayout seq) { checkByteArrayAlignment(seq.elementLayout()); int bytes = (int)seq.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment nativeArray = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment nativeArray = MemorySegment.allocateNative(seq, arena.scope());; MemorySegment heapArray = MemorySegment.ofArray(new byte[bytes]); initializer.accept(nativeArray); heapArray.copyFrom(nativeArray); @@ -670,8 +669,8 @@ public void bufferProperties(ByteBuffer bb, Predicate _unused) { @Test public void testRoundTripAccess() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment ms = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment ms = MemorySegment.allocateNative(4, 1, arena.scope());; MemorySegment msNoAccess = ms.asReadOnly(); MemorySegment msRoundTrip = MemorySegment.ofBuffer(msNoAccess.asByteBuffer()); assertEquals(msNoAccess.isReadOnly(), msRoundTrip.isReadOnly()); @@ -680,23 +679,23 @@ public void testRoundTripAccess() { @Test(expectedExceptions = IllegalStateException.class) public void testDeadAccessOnClosedBufferSegment() { - MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, MemorySession.openConfined()); + Arena arena = Arena.openConfined(); + MemorySegment s1 = MemorySegment.allocateNative(JAVA_INT, arena.scope()); MemorySegment s2 = MemorySegment.ofBuffer(s1.asByteBuffer()); // memory freed - s1.session().close(); + arena.close(); s2.set(JAVA_INT, 0, 10); // Dead access! } - @Test(dataProvider = "allSessions") - public void testIOOnSegmentBuffer(Supplier sessionSupplier) throws IOException { + @Test(dataProvider = "closeableArenas") + public void closeableArenas(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); - MemorySession session; try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE) ; - MemorySession scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment = MemorySegment.allocateNative(10, 1, session); + Arena arena = arenaSupplier.get()) { + MemorySegment segment = MemorySegment.allocateNative(10, 1, arena.scope());; for (int i = 0; i < 10; i++) { segment.set(JAVA_BYTE, i, (byte) i); } @@ -711,17 +710,18 @@ public void testIOOnSegmentBuffer(Supplier sessionSupplier) throw static final Class ISE = IllegalStateException.class; - @Test(dataProvider = "closeableSessions") - public void testIOOnClosedSegmentBuffer(Supplier sessionSupplier) throws IOException { + @Test(dataProvider = "closeableArenas") + public void testIOOnClosedSegmentBuffer(Supplier arenaSupplier) throws IOException { File tmp = File.createTempFile("tmp", "txt"); tmp.deleteOnExit(); + Arena arena = arenaSupplier.get(); try (FileChannel channel = FileChannel.open(tmp.toPath(), StandardOpenOption.READ, StandardOpenOption.WRITE)) { - MemorySegment segment = MemorySegment.allocateNative(10, sessionSupplier.get()); + MemorySegment segment = MemorySegment.allocateNative(10, arena.scope()); for (int i = 0; i < 10; i++) { segment.set(JAVA_BYTE, i, (byte) i); } ByteBuffer bb = segment.asByteBuffer(); - segment.session().close(); + arena.close(); assertThrows(ISE, () -> channel.read(bb)); assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})); assertThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)); @@ -733,8 +733,8 @@ public void testIOOnClosedSegmentBuffer(Supplier sessionSupplier) @Test public void buffersAndArraysFromSlices() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(16, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(16, arena.scope());; int newSize = 8; var slice = segment.asSlice(4, newSize); @@ -751,8 +751,8 @@ public void buffersAndArraysFromSlices() { @Test public void viewsFromSharedSegment() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(16, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(16, arena.scope());; var byteBuffer = segment.asByteBuffer(); byteBuffer.asReadOnlyBuffer(); byteBuffer.slice(0, 8); @@ -762,33 +762,20 @@ public void viewsFromSharedSegment() { @DataProvider(name = "segments") public static Object[][] segments() throws Throwable { return new Object[][] { - { (Supplier) () -> MemorySegment.allocateNative(16, MemorySession.openImplicit()) }, - { (Supplier) () -> MemorySegment.allocateNative(16, MemorySession.openConfined()) }, + { (Supplier) () -> MemorySegment.allocateNative(16, SegmentScope.auto()) }, + { (Supplier) () -> MemorySegment.allocateNative(16, Arena.openConfined().scope()) }, { (Supplier) () -> MemorySegment.ofArray(new byte[16]) } }; } - @DataProvider(name = "closeableSessions") - public static Object[][] closeableSessions() { + @DataProvider(name = "closeableArenas") + public static Object[][] closeableArenas() { return new Object[][] { - { (Supplier) () -> MemorySession.openShared() }, - { (Supplier) () -> MemorySession.openConfined() }, - { (Supplier) () -> MemorySession.openShared(Cleaner.create()) }, - { (Supplier) () -> MemorySession.openConfined(Cleaner.create()) }, + { (Supplier) Arena::openConfined }, + { (Supplier) Arena::openShared }, }; } - @DataProvider(name = "allSessions") - public static Object[][] allSessions() { - return Stream.of(new Object[][] { { (Supplier) MemorySession::global} }, closeableSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - static MemorySession closeableSessionOrNull(MemorySession session) { - return session.isCloseable() ? session : null; - } - @DataProvider(name = "bufferOps") public static Object[][] bufferOps() throws Throwable { List args = new ArrayList<>(); diff --git a/test/jdk/java/foreign/TestClassLoaderFindNative.java b/test/jdk/java/foreign/TestClassLoaderFindNative.java index d83ca5bea9b..b462180b135 100644 --- a/test/jdk/java/foreign/TestClassLoaderFindNative.java +++ b/test/jdk/java/foreign/TestClassLoaderFindNative.java @@ -29,7 +29,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; import org.testng.annotations.Test; @@ -49,20 +49,20 @@ public class TestClassLoaderFindNative { @Test public void testSimpleLookup() { - assertFalse(SymbolLookup.loaderLookup().lookup("f").isEmpty()); + assertFalse(SymbolLookup.loaderLookup().find("f").isEmpty()); } @Test public void testInvalidSymbolLookup() { - assertTrue(SymbolLookup.loaderLookup().lookup("nonExistent").isEmpty()); + assertTrue(SymbolLookup.loaderLookup().find("nonExistent").isEmpty()); } @Test public void testVariableSymbolLookup() { MemorySegment segment = MemorySegment.ofAddress( - SymbolLookup.loaderLookup().lookup("c").get().address(), + SymbolLookup.loaderLookup().find("c").get().address(), ValueLayout.JAVA_INT.byteSize(), - MemorySession.global()); + SegmentScope.global()); assertEquals(segment.get(JAVA_BYTE, 0), 42); } } diff --git a/test/jdk/java/foreign/TestDowncallBase.java b/test/jdk/java/foreign/TestDowncallBase.java index 3e992228a6a..14d8928afc8 100644 --- a/test/jdk/java/foreign/TestDowncallBase.java +++ b/test/jdk/java/foreign/TestDowncallBase.java @@ -22,9 +22,9 @@ * */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; import java.lang.foreign.SegmentAllocator; import java.lang.invoke.MethodHandle; @@ -36,7 +36,7 @@ public class TestDowncallBase extends CallGeneratorHelper { static Linker LINKER = Linker.nativeLinker(); - Object doCall(Addressable symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { + Object doCall(MemorySegment symbol, SegmentAllocator allocator, FunctionDescriptor descriptor, Object[] args) throws Throwable { MethodHandle mh = downcallHandle(LINKER, symbol, allocator, descriptor); Object res = mh.invokeWithArguments(args); return res; diff --git a/test/jdk/java/foreign/TestDowncallScope.java b/test/jdk/java/foreign/TestDowncallScope.java index 67e63273e0c..1d586274ff1 100644 --- a/test/jdk/java/foreign/TestDowncallScope.java +++ b/test/jdk/java/foreign/TestDowncallScope.java @@ -38,11 +38,10 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.util.ArrayList; import java.util.List; @@ -61,20 +60,20 @@ public void testDowncall(int count, String fName, CallGeneratorHelper.Ret ret, List paramTypes, List fields) throws Throwable { List> checks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); + MemorySegment addr = findNativeOrThrow(fName); FunctionDescriptor descriptor = function(ret, paramTypes, fields); Object[] args = makeArgs(paramTypes, fields, checks); - try (MemorySession session = MemorySession.openShared()) { + try (Arena arena = Arena.openShared()) { boolean needsScope = descriptor.returnLayout().map(GroupLayout.class::isInstance).orElse(false); SegmentAllocator allocator = needsScope ? - SegmentAllocator.newNativeArena(session) : + SegmentAllocator.nativeAllocator(arena.scope()) : THROWING_ALLOCATOR; Object res = doCall(addr, allocator, descriptor, args); if (ret == CallGeneratorHelper.Ret.NON_VOID) { checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).session(), session); + assertEquals(((MemorySegment)res).scope(), arena.scope()); } } } diff --git a/test/jdk/java/foreign/TestDowncallStack.java b/test/jdk/java/foreign/TestDowncallStack.java index abf7d32b968..1426604a931 100644 --- a/test/jdk/java/foreign/TestDowncallStack.java +++ b/test/jdk/java/foreign/TestDowncallStack.java @@ -34,11 +34,10 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.util.ArrayList; import java.util.List; @@ -57,20 +56,20 @@ public void testDowncallStack(int count, String fName, CallGeneratorHelper.Ret r List paramTypes, List fields) throws Throwable { List> checks = new ArrayList<>(); - Addressable addr = findNativeOrThrow("s" + fName); + MemorySegment addr = findNativeOrThrow("s" + fName); FunctionDescriptor descriptor = functionStack(ret, paramTypes, fields); Object[] args = makeArgsStack(paramTypes, fields, checks); - try (MemorySession session = MemorySession.openShared()) { + try (Arena arena = Arena.openShared()) { boolean needsScope = descriptor.returnLayout().map(GroupLayout.class::isInstance).orElse(false); SegmentAllocator allocator = needsScope ? - SegmentAllocator.newNativeArena(session) : + SegmentAllocator.nativeAllocator(arena.scope()) : THROWING_ALLOCATOR; Object res = doCall(addr, allocator, descriptor, args); if (ret == CallGeneratorHelper.Ret.NON_VOID) { checks.forEach(c -> c.accept(res)); if (needsScope) { // check that return struct has indeed been allocated in the native scope - assertEquals(((MemorySegment)res).session(), session); + assertEquals(((MemorySegment)res).scope(), arena.scope()); } } } diff --git a/test/jdk/java/foreign/TestFallbackLookup.java b/test/jdk/java/foreign/TestFallbackLookup.java index d129db228c5..71363590b9a 100644 --- a/test/jdk/java/foreign/TestFallbackLookup.java +++ b/test/jdk/java/foreign/TestFallbackLookup.java @@ -38,6 +38,6 @@ public class TestFallbackLookup { void testBadSystemLookupRequest() { // we request a Linker, forcing OS name to be "Windows". This should trigger an exception when // attempting to load a non-existent ucrtbase.dll. Make sure that no error is generated at this stage. - assertTrue(Linker.nativeLinker().defaultLookup().lookup("nonExistentSymbol").isEmpty()); + assertTrue(Linker.nativeLinker().defaultLookup().find("nonExistentSymbol").isEmpty()); } } diff --git a/test/jdk/java/foreign/TestFree.java b/test/jdk/java/foreign/TestFree.java index 2a5dcac2796..a61499a2194 100644 --- a/test/jdk/java/foreign/TestFree.java +++ b/test/jdk/java/foreign/TestFree.java @@ -30,25 +30,17 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestFree */ -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import static org.testng.Assert.assertEquals; public class TestFree extends NativeTestHelper { - private static MemorySegment asArray(MemoryAddress addr, MemoryLayout layout, int numElements) { - return MemorySegment.ofAddress(addr, numElements * layout.byteSize(), MemorySession.global()); - } - public void test() throws Throwable { String str = "hello world"; - MemoryAddress addr = allocateMemory(str.length() + 1); - MemorySegment seg = asArray(addr, C_CHAR, str.length() + 1); - seg.copyFrom(MemorySegment.ofArray(str.getBytes())); - seg.set(C_CHAR, str.length(), (byte)0); - assertEquals(str, seg.getUtf8String(0)); + MemorySegment addr = allocateMemory(str.length() + 1); + addr.copyFrom(MemorySegment.ofArray(str.getBytes())); + addr.set(C_CHAR, str.length(), (byte)0); + assertEquals(str, addr.getUtf8String(0)); freeMemory(addr); } } diff --git a/test/jdk/java/foreign/TestFunctionDescriptor.java b/test/jdk/java/foreign/TestFunctionDescriptor.java index 2438ce23c48..915c97ad507 100644 --- a/test/jdk/java/foreign/TestFunctionDescriptor.java +++ b/test/jdk/java/foreign/TestFunctionDescriptor.java @@ -31,6 +31,8 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodType; import java.util.List; import java.util.Optional; import org.testng.annotations.Test; @@ -98,10 +100,25 @@ public void testDropReturnLayout() { @Test public void testEquals() { FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, C_INT); - FunctionDescriptor fd_va1 = FunctionDescriptor.of(C_INT).asVariadic(C_INT, C_INT); - FunctionDescriptor fd_va2 = FunctionDescriptor.of(C_INT, C_INT).asVariadic(C_INT); assertEquals(fd, fd); - assertNotEquals(fd, fd_va1); - assertNotEquals(fd, fd_va2); + } + + @Test + public void testCarrierMethodType() { + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, + C_INT, + MemoryLayout.structLayout(C_INT, C_INT)); + MethodType cmt = fd.toMethodType(); + assertEquals(cmt, MethodType.methodType(int.class, int.class, MemorySegment.class)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testBadCarrierMethodType() { + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, + C_INT, + MemoryLayout.structLayout(C_INT, C_INT), + MemoryLayout.sequenceLayout(3, C_INT), + MemoryLayout.paddingLayout(32)); + fd.toMethodType(); // should throw } } diff --git a/test/jdk/java/foreign/TestHandshake.java b/test/jdk/java/foreign/TestHandshake.java index 8d33b5b64ce..519739cb1eb 100644 --- a/test/jdk/java/foreign/TestHandshake.java +++ b/test/jdk/java/foreign/TestHandshake.java @@ -32,8 +32,8 @@ * @run testng/othervm -XX:-TieredCompilation TestHandshake */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; @@ -67,8 +67,8 @@ public class TestHandshake { @Test(dataProvider = "accessors") public void testHandshake(String testName, AccessorFactory accessorFactory) throws InterruptedException { for (int it = 0 ; it < ITERATIONS ; it++) { - MemorySession session = MemorySession.openShared(); - MemorySegment segment = MemorySegment.allocateNative(SEGMENT_SIZE, 1, session); + Arena arena = Arena.openShared(); + MemorySegment segment = MemorySegment.allocateNative(SEGMENT_SIZE, 1, arena.scope()); System.out.println("ITERATION " + it); ExecutorService accessExecutor = Executors.newCachedThreadPool(); start.set(System.currentTimeMillis()); @@ -79,10 +79,10 @@ public void testHandshake(String testName, AccessorFactory accessorFactory) thro int delay = ThreadLocalRandom.current().nextInt(MAX_DELAY_MILLIS); System.out.println("Starting handshaker with delay set to " + delay + " millis"); Thread.sleep(delay); - accessExecutor.execute(new Handshaker(session)); + accessExecutor.execute(new Handshaker(arena)); accessExecutor.shutdown(); assertTrue(accessExecutor.awaitTermination(MAX_EXECUTOR_WAIT_SECONDS, TimeUnit.SECONDS)); - assertTrue(!segment.session().isAlive()); + assertTrue(!segment.scope().isAlive()); } } @@ -99,7 +99,7 @@ static abstract class AbstractSegmentAccessor implements Runnable { @Override public final void run() { start("\"Accessor #\" + id"); - outer: while (segment.session().isAlive()) { + outer: while (segment.scope().isAlive()) { try { doAccess(); } catch (IllegalStateException ex) { @@ -193,7 +193,7 @@ static class SegmentMismatchAccessor extends AbstractSegmentAccessor { SegmentMismatchAccessor(int id, MemorySegment segment) { super(id, segment); - this.copy = MemorySegment.allocateNative(SEGMENT_SIZE, 1, segment.session()); + this.copy = MemorySegment.allocateNative(SEGMENT_SIZE, 1, segment.scope()); copy.copyFrom(segment); copy.set(JAVA_BYTE, ThreadLocalRandom.current().nextInt(SEGMENT_SIZE), (byte)42); } @@ -238,10 +238,10 @@ public void doAccess() { static class Handshaker implements Runnable { - final MemorySession session; + final Arena arena; - Handshaker(MemorySession session) { - this.session = session; + Handshaker(Arena arena) { + this.arena = arena; } @Override @@ -249,7 +249,7 @@ public void run() { start("Handshaker"); while (true) { try { - session.close(); + arena.close(); break; } catch (IllegalStateException ex) { Thread.onSpinWait(); diff --git a/test/jdk/java/foreign/TestHeapAlignment.java b/test/jdk/java/foreign/TestHeapAlignment.java index 91a15453816..eff8dca9802 100644 --- a/test/jdk/java/foreign/TestHeapAlignment.java +++ b/test/jdk/java/foreign/TestHeapAlignment.java @@ -29,10 +29,9 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestHeapAlignment */ -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import java.util.ArrayList; import java.util.List; @@ -101,7 +100,7 @@ enum SegmentAndAlignment { HEAP_FLOAT(MemorySegment.ofArray(new float[2]), 4), HEAP_LONG(MemorySegment.ofArray(new long[1]), 8), HEAP_DOUBLE(MemorySegment.ofArray(new double[1]), 8), - NATIVE(MemorySegment.allocateNative(8, MemorySession.openImplicit()), -1); + NATIVE(MemorySegment.allocateNative(8, SegmentScope.auto()), -1); final MemorySegment segment; final int align; @@ -124,7 +123,7 @@ public static Object[][] layouts() { layouts.add(new Object[] { testCase.segment, testCase.align, 42f, new float[]{42}, JAVA_FLOAT_ALIGNED, (Function)MemorySegment::ofArray }); layouts.add(new Object[] { testCase.segment, testCase.align, 42L, new long[]{42}, JAVA_LONG_ALIGNED, (Function)MemorySegment::ofArray }); layouts.add(new Object[] { testCase.segment, testCase.align, 42d, new double[]{42}, JAVA_DOUBLE_ALIGNED, (Function)MemorySegment::ofArray }); - layouts.add(new Object[] { testCase.segment, testCase.align, MemoryAddress.ofLong(42), null, ADDRESS_ALIGNED, null }); + layouts.add(new Object[] { testCase.segment, testCase.align, MemorySegment.ofAddress(42), null, ADDRESS_ALIGNED, null }); } return layouts.toArray(new Object[0][]); } diff --git a/test/jdk/java/foreign/TestIllegalLink.java b/test/jdk/java/foreign/TestIllegalLink.java index 3219d150158..670ac641eb2 100644 --- a/test/jdk/java/foreign/TestIllegalLink.java +++ b/test/jdk/java/foreign/TestIllegalLink.java @@ -29,11 +29,12 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestIllegalLink */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; +import java.nio.ByteOrder; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -42,7 +43,7 @@ public class TestIllegalLink extends NativeTestHelper { - private static final Addressable DUMMY_TARGET = MemoryAddress.ofLong(1); + private static final MemorySegment DUMMY_TARGET = MemorySegment.ofAddress(1); private static final Linker ABI = Linker.nativeLinker(); @Test(dataProvider = "types") @@ -51,7 +52,8 @@ public void testTypeMismatch(FunctionDescriptor desc, String expectedExceptionMe ABI.downcallHandle(DUMMY_TARGET, desc); fail("Expected IllegalArgumentException was not thrown"); } catch (IllegalArgumentException e) { - assertTrue(e.getMessage().contains(expectedExceptionMessage)); + assertTrue(e.getMessage().contains(expectedExceptionMessage), + e.getMessage() + " != " + expectedExceptionMessage); } } @@ -59,12 +61,12 @@ public void testTypeMismatch(FunctionDescriptor desc, String expectedExceptionMe public static Object[][] types() { return new Object[][]{ { - FunctionDescriptor.of(MemoryLayout.paddingLayout(64)), - "Unsupported layout: x64" + FunctionDescriptor.of(MemoryLayout.paddingLayout(64)), + "Unsupported layout: x64" }, { - FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(64)), - "Unsupported layout: x64" + FunctionDescriptor.ofVoid(MemoryLayout.paddingLayout(64)), + "Unsupported layout: x64" }, { FunctionDescriptor.of(MemoryLayout.sequenceLayout(2, C_INT)), @@ -74,6 +76,42 @@ public static Object[][] types() { FunctionDescriptor.ofVoid(MemoryLayout.sequenceLayout(2, C_INT)), "Unsupported layout: [2:i32]" }, + { + FunctionDescriptor.ofVoid(C_INT.withBitAlignment(16)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(C_POINTER.withBitAlignment(16)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.valueLayout(char.class, ByteOrder.nativeOrder()).withBitAlignment(32)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + C_CHAR.withName("x").withBitAlignment(8), + C_SHORT.withName("y").withBitAlignment(8), + C_INT.withName("z").withBitAlignment(8) + ).withBitAlignment(8)), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + MemoryLayout.structLayout( + C_CHAR.withName("x").withBitAlignment(8), + C_SHORT.withName("y").withBitAlignment(8), + C_INT.withName("z").withBitAlignment(8) + ))), + "Layout bit alignment must be natural alignment" + }, + { + FunctionDescriptor.ofVoid(MemoryLayout.structLayout( + MemoryLayout.sequenceLayout( + C_INT.withBitAlignment(8) + ))), + "Layout bit alignment must be natural alignment" + }, }; } diff --git a/test/jdk/java/foreign/TestIntrinsics.java b/test/jdk/java/foreign/TestIntrinsics.java index 60ed3faf757..38c742015bb 100644 --- a/test/jdk/java/foreign/TestIntrinsics.java +++ b/test/jdk/java/foreign/TestIntrinsics.java @@ -32,18 +32,18 @@ * TestIntrinsics */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; -import java.lang.invoke.MethodType; import java.util.ArrayList; import java.util.List; import java.lang.foreign.MemoryLayout; import org.testng.annotations.*; +import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.invoke.MethodType.methodType; import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static org.testng.Assert.assertEquals; @@ -84,8 +84,7 @@ interface AddIdentity { } AddIdentity addIdentity = (name, carrier, layout, arg) -> { - Addressable ma = findNativeOrThrow(name); - MethodType mt = methodType(carrier, carrier); + MemorySegment ma = findNativeOrThrow(name); FunctionDescriptor fd = FunctionDescriptor.of(layout, layout); tests.add(abi.downcallHandle(ma, fd), arg, arg); @@ -93,8 +92,7 @@ interface AddIdentity { }; { // empty - Addressable ma = findNativeOrThrow("empty"); - MethodType mt = methodType(void.class); + MemorySegment ma = findNativeOrThrow("empty"); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); tests.add(abi.downcallHandle(ma, fd), null); } @@ -108,21 +106,18 @@ interface AddIdentity { addIdentity.add("identity_double", double.class, C_DOUBLE, 10D); { // identity_va - Addressable ma = findNativeOrThrow("identity_va"); - MethodType mt = methodType(int.class, int.class, double.class, int.class, float.class, long.class); - FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT).asVariadic(C_DOUBLE, C_INT, C_FLOAT, C_LONG_LONG); - tests.add(abi.downcallHandle(ma, fd), 1, 1, 10D, 2, 3F, 4L); + MemorySegment ma = findNativeOrThrow("identity_va"); + FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT, + C_DOUBLE, C_INT, C_FLOAT, C_LONG_LONG); + tests.add(abi.downcallHandle(ma, fd, firstVariadicArg(1)), 1, 1, 10D, 2, 3F, 4L); } { // high_arity - MethodType baseMT = methodType(void.class, int.class, double.class, long.class, float.class, byte.class, - short.class, char.class); FunctionDescriptor baseFD = FunctionDescriptor.ofVoid(C_INT, C_DOUBLE, C_LONG_LONG, C_FLOAT, C_CHAR, C_SHORT, JAVA_CHAR); Object[] args = {1, 10D, 2L, 3F, (byte) 0, (short) 13, 'a'}; for (int i = 0; i < args.length; i++) { - Addressable ma = findNativeOrThrow("invoke_high_arity" + i); - MethodType mt = baseMT.changeReturnType(baseMT.parameterType(i)); + MemorySegment ma = findNativeOrThrow("invoke_high_arity" + i); FunctionDescriptor fd = baseFD.changeReturnLayout(baseFD.argumentLayouts().get(i)); Object expected = args[i]; tests.add(abi.downcallHandle(ma, fd), expected, args); diff --git a/test/jdk/java/foreign/TestLargeSegmentCopy.java b/test/jdk/java/foreign/TestLargeSegmentCopy.java new file mode 100644 index 00000000000..0ed9b3971af --- /dev/null +++ b/test/jdk/java/foreign/TestLargeSegmentCopy.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @bug 8292851 + * @run testng/othervm -Xmx4G TestLargeSegmentCopy + */ + +import org.testng.annotations.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + +import static java.lang.foreign.ValueLayout.JAVA_LONG; + +public class TestLargeSegmentCopy { + + @Test + public void testLargeSegmentCopy() { + // Make sure the byte size is bigger than Integer.MAX_VALUE + final int longArrayLength = Integer.MAX_VALUE / Long.BYTES + 100; + final long[] array = new long[longArrayLength]; + + try (var arena = Arena.openConfined()) { + var segment = MemorySegment.allocateNative((long) longArrayLength * Long.BYTES, Long.SIZE, arena.scope()); + // Should not throw an exception or error + MemorySegment.copy(segment, JAVA_LONG, 0, array, 0, longArrayLength); + // Should not throw an exception or error + MemorySegment.copy(array,0, segment, JAVA_LONG, 0, longArrayLength); + } + + } + +} diff --git a/test/jdk/java/foreign/TestLayoutEquality.java b/test/jdk/java/foreign/TestLayoutEquality.java index 66c8a8e3fc8..e07638e5078 100644 --- a/test/jdk/java/foreign/TestLayoutEquality.java +++ b/test/jdk/java/foreign/TestLayoutEquality.java @@ -29,7 +29,7 @@ * @run testng TestLayoutEquality */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemoryLayout; import java.lang.foreign.ValueLayout; import jdk.internal.foreign.PlatformLayouts; import org.testng.annotations.DataProvider; @@ -39,24 +39,17 @@ import java.util.ArrayList; import java.util.List; -import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_LONG; -import static java.lang.foreign.ValueLayout.JAVA_SHORT; import static org.testng.Assert.*; public class TestLayoutEquality { @Test(dataProvider = "layoutConstants") public void testReconstructedEquality(ValueLayout layout) { - ValueLayout newLayout = valueLayoutForCarrier(layout.carrier()); + ValueLayout newLayout = MemoryLayout.valueLayout(layout.carrier(), layout.order()); newLayout = newLayout.withBitAlignment(layout.bitAlignment()); - newLayout = newLayout.withOrder(layout.order()); + if (layout instanceof ValueLayout.OfAddress addressLayout && addressLayout.isUnbounded()) { + newLayout = ((ValueLayout.OfAddress)newLayout).asUnbounded(); + } // properties should be equal assertEquals(newLayout.bitSize(), layout.bitSize()); @@ -84,28 +77,4 @@ private static void addLayoutConstants(List testValues, Class cl testValues.add((ValueLayout) f.get(null)); } } - - static ValueLayout valueLayoutForCarrier(Class carrier) { - if (carrier == boolean.class) { - return JAVA_BOOLEAN; - } else if (carrier == char.class) { - return JAVA_CHAR; - } else if (carrier == byte.class) { - return JAVA_BYTE; - } else if (carrier == short.class) { - return JAVA_SHORT; - } else if (carrier == int.class) { - return JAVA_INT; - } else if (carrier == long.class) { - return JAVA_LONG; - } else if (carrier == float.class) { - return JAVA_FLOAT; - } else if (carrier == double.class) { - return JAVA_DOUBLE; - } else if (carrier == MemoryAddress.class) { - return ADDRESS; - } else { - throw new UnsupportedOperationException(); - } - } } diff --git a/test/jdk/java/foreign/TestLayoutPaths.java b/test/jdk/java/foreign/TestLayoutPaths.java index d3daa3ec3ed..59663af8200 100644 --- a/test/jdk/java/foreign/TestLayoutPaths.java +++ b/test/jdk/java/foreign/TestLayoutPaths.java @@ -28,11 +28,11 @@ * @run testng TestLayoutPaths */ +import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; @@ -433,10 +433,10 @@ public void testSliceHandle(MemoryLayout layout, PathElement[] pathElements, lon MethodHandle sliceHandle = layout.sliceHandle(pathElements); sliceHandle = sliceHandle.asSpreader(long[].class, indexes.length); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); MemorySegment slice = (MemorySegment) sliceHandle.invokeExact(segment, indexes); - assertEquals(slice.address().toRawLongValue() - segment.address().toRawLongValue(), expectedBitOffset / 8); + assertEquals(slice.address() - segment.address(), expectedBitOffset / 8); assertEquals(slice.byteSize(), selected.byteSize()); } } @@ -468,8 +468,8 @@ public void testSliceHandleUOEInvalidOffsetLate() throws Throwable { return; } - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope()); try { sliceHandle.invokeExact(segment, 1); // should work diff --git a/test/jdk/java/foreign/TestLayouts.java b/test/jdk/java/foreign/TestLayouts.java index 843c88d5e36..e09eaab508a 100644 --- a/test/jdk/java/foreign/TestLayouts.java +++ b/test/jdk/java/foreign/TestLayouts.java @@ -52,8 +52,8 @@ public void testBadLayoutAlignment(MemoryLayout layout, long alignment) { @Test public void testIndexedSequencePath() { MemoryLayout seq = MemoryLayout.sequenceLayout(10, ValueLayout.JAVA_INT); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; VarHandle indexHandle = seq.varHandle(MemoryLayout.PathElement.sequenceElement()); // init segment for (int i = 0 ; i < 10 ; i++) { @@ -138,10 +138,15 @@ public void testSequenceBadCount() { @Test(dataProvider = "basicLayouts") public void testSequenceInferredCount(MemoryLayout layout) { - assertEquals(MemoryLayout.sequenceLayout(-1, layout), + assertEquals(MemoryLayout.sequenceLayout(layout), MemoryLayout.sequenceLayout(Long.MAX_VALUE / layout.bitSize(), layout)); } + public void testSequenceNegativeElementCount() { + assertThrows(IllegalArgumentException.class, // negative + () -> MemoryLayout.sequenceLayout(-1, JAVA_SHORT)); + } + @Test public void testSequenceOverflow() { assertThrows(IllegalArgumentException.class, // negative @@ -163,7 +168,7 @@ public void testStructOverflow() { @Test(dataProvider = "layoutKinds") public void testPadding(LayoutKind kind) { - assertEquals(kind == LayoutKind.PADDING, kind.layout.isPadding()); + assertEquals(kind == LayoutKind.PADDING, kind.layout instanceof PaddingLayout); } @Test(dataProvider="layoutsAndAlignments") diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java new file mode 100644 index 00000000000..8077e3ef841 --- /dev/null +++ b/test/jdk/java/foreign/TestLinker.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @run testng TestLinker + */ + +import org.testng.annotations.Test; + +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.invoke.MethodHandle; + +import static org.testng.Assert.assertNotSame; + +public class TestLinker extends NativeTestHelper { + + @Test + public void testLinkerOptionsCache() { + Linker linker = Linker.nativeLinker(); + FunctionDescriptor descriptor = FunctionDescriptor.ofVoid(C_INT, C_INT); + MethodHandle mh1 = linker.downcallHandle(descriptor); + MethodHandle mh2 = linker.downcallHandle(descriptor, Linker.Option.firstVariadicArg(1)); + // assert that these are 2 distinct link request. No caching allowed + assertNotSame(mh1, mh2); + } + +} diff --git a/test/jdk/java/foreign/TestMemoryAccess.java b/test/jdk/java/foreign/TestMemoryAccess.java index 1fa39a40fd8..7028635b682 100644 --- a/test/jdk/java/foreign/TestMemoryAccess.java +++ b/test/jdk/java/foreign/TestMemoryAccess.java @@ -30,12 +30,11 @@ * @run testng/othervm -Djava.lang.invoke.VarHandle.VAR_HANDLE_GUARDS=false -Djava.lang.invoke.VarHandle.VAR_HANDLE_IDENTITY_ADAPT=true -Xverify:all TestMemoryAccess */ +import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; @@ -92,8 +91,8 @@ public void testPaddedArrayAccessByIndexSeq(Function viewFactory, MemoryLayout layout, VarHandle handle, Checker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(layout, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(layout, arena.scope())); boolean isRO = segment.isReadOnly(); try { checker.check(handle, segment); @@ -124,8 +123,8 @@ private void testAccessInternal(Function viewFacto private void testArrayAccessInternal(Function viewFactory, SequenceLayout seq, VarHandle handle, ArrayChecker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, arena.scope())); boolean isRO = segment.isReadOnly(); try { for (int i = 0; i < seq.elementCount(); i++) { @@ -193,8 +192,8 @@ public void testPaddedMatrixAccessByIndexSeq(Function viewFactory, SequenceLayout seq, VarHandle handle, MatrixChecker checker) { MemorySegment outer_segment; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, session)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = viewFactory.apply(MemorySegment.allocateNative(seq, arena.scope())); boolean isRO = segment.isReadOnly(); try { for (int i = 0; i < seq.elementCount(); i++) { @@ -465,8 +464,8 @@ interface MatrixChecker { }; MatrixChecker ADDR = (handle, segment, r, c) -> { - handle.set(segment, r, c, MemoryAddress.ofLong(r + c)); - assertEquals(MemoryAddress.ofLong(r + c), (MemoryAddress)handle.get(segment, r, c)); + handle.set(segment, r, c, MemorySegment.ofAddress(r + c)); + assertEquals(MemorySegment.ofAddress(r + c), (MemorySegment) handle.get(segment, r, c)); }; MatrixChecker FLOAT = (handle, segment, r, c) -> { diff --git a/test/jdk/java/foreign/TestMemoryAccessInstance.java b/test/jdk/java/foreign/TestMemoryAccessInstance.java index c75aeb45978..d2a8ba14f9c 100644 --- a/test/jdk/java/foreign/TestMemoryAccessInstance.java +++ b/test/jdk/java/foreign/TestMemoryAccessInstance.java @@ -27,9 +27,8 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestMemoryAccessInstance */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.ValueLayout; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -80,8 +79,8 @@ interface BufferSetter { } void test() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(128, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(128, arena.scope());; ByteBuffer buffer = segment.asByteBuffer(); T t = transform.apply(segment); segmentSetter.set(t, layout, 8, value); @@ -93,8 +92,8 @@ void test() { @SuppressWarnings("unchecked") void testHyperAligned() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(64, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(64, arena.scope());; T t = transform.apply(segment); L alignedLayout = (L)layout.withBitAlignment(layout.byteSize() * 8 * 2); try { @@ -117,12 +116,6 @@ static Accessor ofSegment(L layo BufferGetter bufferGetter, BufferSetter bufferSetter) { return new Accessor<>(Function.identity(), layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); } - - static Accessor ofAddress(L layout, X value, - SegmentGetter segmentGetter, SegmentSetter segmentSetter, - BufferGetter bufferGetter, BufferSetter bufferSetter) { - return new Accessor<>(MemorySegment::address, layout, value, segmentGetter, segmentSetter, bufferGetter, bufferSetter); - } } @Test(dataProvider = "segmentAccessors") @@ -130,11 +123,6 @@ public void testSegmentAccess(String testName, Accessor accessor) { accessor.test(); } - @Test(dataProvider = "addressAccessors") - public void testAddressAccess(String testName, Accessor accessor) { - accessor.test(); - } - @Test(dataProvider = "segmentAccessors") public void testSegmentAccessHyper(String testName, Accessor accessor) { if (testName.contains("index")) { @@ -144,15 +132,6 @@ public void testSegmentAccessHyper(String testName, Accessor accessor) } } - @Test(dataProvider = "addressAccessors") - public void testAddressAccessHyper(String testName, Accessor accessor) { - if (testName.contains("index")) { - accessor.testHyperAligned(); - } else { - throw new SkipException("Skipping"); - } - } - static final ByteOrder NE = ByteOrder.nativeOrder(); @DataProvider(name = "segmentAccessors") @@ -187,20 +166,20 @@ static Object[][] segmentAccessors() { MemorySegment::get, MemorySegment::set, (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) }, - { "address", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + { "address", Accessor.ofSegment(ValueLayout.ADDRESS, MemorySegment.ofAddress(42), MemorySegment::get, MemorySegment::set, (bb, pos) -> { ByteBuffer nb = bb.order(NE); long addr = ValueLayout.ADDRESS.byteSize() == 8 ? nb.getLong(pos) : nb.getInt(pos); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, pos, v) -> { ByteBuffer nb = bb.order(NE); if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos, v.toRawLongValue()); + nb.putLong(pos, v.address()); } else { - nb.putInt(pos, (int)v.toRawLongValue()); + nb.putInt(pos, (int)v.address()); } }) }, @@ -225,112 +204,23 @@ static Object[][] segmentAccessors() { MemorySegment::getAtIndex, MemorySegment::setAtIndex, (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) }, - { "address/index", Accessor.ofSegment(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), + { "address/index", Accessor.ofSegment(ValueLayout.ADDRESS, MemorySegment.ofAddress(42), MemorySegment::getAtIndex, MemorySegment::setAtIndex, (bb, pos) -> { ByteBuffer nb = bb.order(NE); long addr = ValueLayout.ADDRESS.byteSize() == 8 ? nb.getLong(pos * 8) : nb.getInt(pos * 4); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, pos, v) -> { ByteBuffer nb = bb.order(NE); if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos * 8, v.toRawLongValue()); + nb.putLong(pos * 8, v.address()); } else { - nb.putInt(pos * 4, (int)v.toRawLongValue()); + nb.putInt(pos * 4, (int)v.address()); } }) }, }; } - - @DataProvider(name = "addressAccessors") - static Object[][] addressAccessors() { - return new Object[][]{ - - {"byte", Accessor.ofAddress(ValueLayout.JAVA_BYTE, (byte) 42, - MemoryAddress::get, MemoryAddress::set, - ByteBuffer::get, ByteBuffer::put) - }, - {"bool", Accessor.ofAddress(ValueLayout.JAVA_BOOLEAN, false, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.get(pos) != 0, (bb, pos, v) -> bb.put(pos, v ? (byte)1 : (byte)0)) - }, - {"char", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getChar(pos), (bb, pos, v) -> bb.order(NE).putChar(pos, v)) - }, - {"int", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getInt(pos), (bb, pos, v) -> bb.order(NE).putInt(pos, v)) - }, - {"float", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getFloat(pos), (bb, pos, v) -> bb.order(NE).putFloat(pos, v)) - }, - {"long", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getLong(pos), (bb, pos, v) -> bb.order(NE).putLong(pos, v)) - }, - {"double", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> bb.order(NE).getDouble(pos), (bb, pos, v) -> bb.order(NE).putDouble(pos, v)) - }, - { "address", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), - MemoryAddress::get, MemoryAddress::set, - (bb, pos) -> { - ByteBuffer nb = bb.order(NE); - long addr = ValueLayout.ADDRESS.byteSize() == 8 ? - nb.getLong(pos) : nb.getInt(pos); - return MemoryAddress.ofLong(addr); - }, - (bb, pos, v) -> { - ByteBuffer nb = bb.order(NE); - if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos, v.toRawLongValue()); - } else { - nb.putInt(pos, (int)v.toRawLongValue()); - } - }) - }, - {"char/index", Accessor.ofAddress(ValueLayout.JAVA_CHAR, (char) 42, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getChar(pos * 2), (bb, pos, v) -> bb.order(NE).putChar(pos * 2, v)) - }, - {"int/index", Accessor.ofAddress(ValueLayout.JAVA_INT, 42, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getInt(pos * 4), (bb, pos, v) -> bb.order(NE).putInt(pos * 4, v)) - }, - {"float/index", Accessor.ofAddress(ValueLayout.JAVA_FLOAT, 42f, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getFloat(pos * 4), (bb, pos, v) -> bb.order(NE).putFloat(pos * 4, v)) - }, - {"long/index", Accessor.ofAddress(ValueLayout.JAVA_LONG, 42L, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getLong(pos * 8), (bb, pos, v) -> bb.order(NE).putLong(pos * 8, v)) - }, - {"double/index", Accessor.ofAddress(ValueLayout.JAVA_DOUBLE, 42d, - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> bb.order(NE).getDouble(pos * 8), (bb, pos, v) -> bb.order(NE).putDouble(pos * 8, v)) - }, - { "address/index", Accessor.ofAddress(ValueLayout.ADDRESS, MemoryAddress.ofLong(42), - MemoryAddress::getAtIndex, MemoryAddress::setAtIndex, - (bb, pos) -> { - ByteBuffer nb = bb.order(NE); - long addr = ValueLayout.ADDRESS.byteSize() == 8 ? - nb.getLong(pos * 8) : nb.getInt(pos * 4); - return MemoryAddress.ofLong(addr); - }, - (bb, pos, v) -> { - ByteBuffer nb = bb.order(NE); - if (ValueLayout.ADDRESS.byteSize() == 8) { - nb.putLong(pos * 8, v.toRawLongValue()); - } else { - nb.putInt(pos * 4, (int)v.toRawLongValue()); - } - }) - } - }; - } } diff --git a/test/jdk/java/foreign/TestMemoryAlignment.java b/test/jdk/java/foreign/TestMemoryAlignment.java index 225557d18f7..cc92085422b 100644 --- a/test/jdk/java/foreign/TestMemoryAlignment.java +++ b/test/jdk/java/foreign/TestMemoryAlignment.java @@ -27,11 +27,11 @@ * @run testng TestMemoryAlignment */ +import java.lang.foreign.Arena; import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; @@ -52,8 +52,8 @@ public void testAlignedAccess(long align) { ValueLayout aligned = layout.withBitAlignment(align); assertEquals(aligned.bitAlignment(), align); //unreasonable alignment here, to make sure access throws VarHandle vh = aligned.varHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(aligned, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(aligned, arena.scope());; vh.set(segment, -42); int val = (int)vh.get(segment); assertEquals(val, -42); @@ -70,8 +70,8 @@ public void testUnalignedAccess(long align) { MemoryLayout alignedGroup = MemoryLayout.structLayout(MemoryLayout.paddingLayout(8), aligned); assertEquals(alignedGroup.bitAlignment(), align); VarHandle vh = aligned.varHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(alignedGroup, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(alignedGroup, arena.scope());; vh.set(segment.asSlice(1L), -42); assertEquals(align, 8); //this is the only case where access is aligned } catch (IllegalArgumentException ex) { @@ -97,8 +97,8 @@ public void testUnalignedSequence(long align) { SequenceLayout layout = MemoryLayout.sequenceLayout(5, ValueLayout.JAVA_INT.withOrder(ByteOrder.BIG_ENDIAN).withBitAlignment(align)); try { VarHandle vh = layout.varHandle(PathElement.sequenceElement()); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope());; for (long i = 0 ; i < 5 ; i++) { vh.set(segment, i, -42); } @@ -121,8 +121,8 @@ public void testPackedAccess() { VarHandle vh_c = g.varHandle(PathElement.groupElement("a")); VarHandle vh_s = g.varHandle(PathElement.groupElement("b")); VarHandle vh_i = g.varHandle(PathElement.groupElement("c")); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(g, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(g, arena.scope());; vh_c.set(segment, Byte.MIN_VALUE); assertEquals(vh_c.get(segment), Byte.MIN_VALUE); vh_s.set(segment, Short.MIN_VALUE); diff --git a/test/jdk/java/foreign/TestMemoryDereference.java b/test/jdk/java/foreign/TestMemoryDereference.java index d6d5af5f949..13dd26ce749 100644 --- a/test/jdk/java/foreign/TestMemoryDereference.java +++ b/test/jdk/java/foreign/TestMemoryDereference.java @@ -27,7 +27,6 @@ * @run testng TestMemoryDereference */ -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import java.nio.ByteBuffer; @@ -36,14 +35,7 @@ import java.lang.foreign.ValueLayout; import org.testng.annotations.*; -import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static java.lang.foreign.ValueLayout.*; import static org.testng.Assert.*; public class TestMemoryDereference { @@ -98,14 +90,6 @@ Accessor of(Z value, } } - // unaligned constants - public final static ValueLayout.OfShort JAVA_SHORT_UNALIGNED = JAVA_SHORT.withBitAlignment(8); - public final static ValueLayout.OfChar JAVA_CHAR_UNALIGNED = JAVA_CHAR.withBitAlignment(8); - public final static ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - public final static ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - public final static ValueLayout.OfDouble JAVA_DOUBLE_UNALIGNED = JAVA_DOUBLE.withBitAlignment(8); - public final static ValueLayout.OfAddress ADDRESS_UNALIGNED = ADDRESS.withBitAlignment(8); - @Test(dataProvider = "accessors") public void testMemoryAccess(String testName, Accessor accessor) { accessor.test(); @@ -204,20 +188,20 @@ static Object[][] accessors() { (s, x) -> s.set(JAVA_DOUBLE_UNALIGNED.withOrder(ByteOrder.BIG_ENDIAN), 8, x), (bb) -> bb.order(BE).getDouble(8), (bb, v) -> bb.order(BE).putDouble(8, v)) }, - { "address/offset", new Accessor<>(MemoryAddress.ofLong(42), + { "address/offset", new Accessor<>(MemorySegment.ofAddress(42), s -> s.get(ADDRESS_UNALIGNED, 8), (s, x) -> s.set(ADDRESS_UNALIGNED, 8, x), (bb) -> { ByteBuffer nb = bb.order(NE); long addr = ADDRESS_UNALIGNED.byteSize() == 8 ? nb.getLong(8) : nb.getInt(8); - return MemoryAddress.ofLong(addr); + return MemorySegment.ofAddress(addr); }, (bb, v) -> { ByteBuffer nb = bb.order(NE); if (ADDRESS_UNALIGNED.byteSize() == 8) { - nb.putLong(8, v.toRawLongValue()); + nb.putLong(8, v.address()); } else { - nb.putInt(8, (int)v.toRawLongValue()); + nb.putInt(8, (int)v.address()); } }) }, diff --git a/test/jdk/java/foreign/TestMemorySession.java b/test/jdk/java/foreign/TestMemorySession.java index ff206255cc4..6501978f725 100644 --- a/test/jdk/java/foreign/TestMemorySession.java +++ b/test/jdk/java/foreign/TestMemorySession.java @@ -28,13 +28,11 @@ * @run testng/othervm TestMemorySession */ -import java.lang.ref.Cleaner; +import java.lang.foreign.Arena; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import jdk.internal.foreign.MemorySessionImpl; -import jdk.internal.ref.CleanerFactory; - import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import static org.testng.Assert.*; @@ -43,57 +41,39 @@ import java.util.List; import java.util.concurrent.atomic.AtomicInteger; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import java.util.function.Supplier; -import java.util.function.UnaryOperator; import java.util.stream.IntStream; public class TestMemorySession { final static int N_THREADS = 100; - @Test(dataProvider = "cleaners") - public void testConfined(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test + public void testConfined() { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); - MemorySession session = cleaner != null ? - MemorySession.openConfined(cleaner) : - MemorySession.openConfined(); - session = sessionFunc.apply(session); + Arena arena = Arena.openConfined(); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; - session.addCloseAction(() -> acc.addAndGet(delta)); + addCloseAction(arena.scope(), () -> acc.addAndGet(delta)); } assertEquals(acc.get(), 0); - if (cleaner == null) { - session.close(); - assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); - } else { - session = null; - int expected = IntStream.range(0, N_THREADS).sum(); - while (acc.get() != expected) { - kickGC(); - } - } + arena.close(); + assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } - @Test(dataProvider = "cleaners") - public void testSharedSingleThread(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test(dataProvider = "sharedSessions") + public void testSharedSingleThread(SessionSupplier sessionSupplier) { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); - MemorySession session = cleaner != null ? - MemorySession.openShared(cleaner) : - MemorySession.openShared(); - session = sessionFunc.apply(session); + SegmentScope session = sessionSupplier.get(); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; - session.addCloseAction(() -> acc.addAndGet(delta)); + addCloseAction(session, () -> acc.addAndGet(delta)); } assertEquals(acc.get(), 0); - if (cleaner == null) { - session.close(); + if (!SessionSupplier.isImplicit(session)) { + SessionSupplier.close(session); assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } else { session = null; @@ -104,21 +84,17 @@ public void testSharedSingleThread(Supplier cleanerSupplier, UnaryOpera } } - @Test(dataProvider = "cleaners") - public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperator sessionFunc) { + @Test(dataProvider = "sharedSessions") + public void testSharedMultiThread(SessionSupplier sessionSupplier) { AtomicInteger acc = new AtomicInteger(); - Cleaner cleaner = cleanerSupplier.get(); List threads = new ArrayList<>(); - MemorySession session = cleaner != null ? - MemorySession.openShared(cleaner) : - MemorySession.openShared(); - session = sessionFunc.apply(session); - AtomicReference sessionRef = new AtomicReference<>(session); + SegmentScope session = sessionSupplier.get(); + AtomicReference sessionRef = new AtomicReference<>(session); for (int i = 0 ; i < N_THREADS ; i++) { int delta = i; Thread thread = new Thread(() -> { try { - sessionRef.get().addCloseAction(() -> { + addCloseAction(sessionRef.get(), () -> { acc.addAndGet(delta); }); } catch (IllegalStateException ex) { @@ -133,10 +109,10 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat // if no cleaner, close - not all segments might have been added to the session! // if cleaner, don't unset the session - after all, the session is kept alive by threads - if (cleaner == null) { + if (!SessionSupplier.isImplicit(session)) { while (true) { try { - session.close(); + SessionSupplier.close(session); break; } catch (IllegalStateException ise) { // session is acquired (by add) - wait some more @@ -152,7 +128,7 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat } }); - if (cleaner == null) { + if (!SessionSupplier.isImplicit(session)) { assertEquals(acc.get(), IntStream.range(0, N_THREADS).sum()); } else { session = null; @@ -166,22 +142,22 @@ public void testSharedMultiThread(Supplier cleanerSupplier, UnaryOperat @Test public void testLockSingleThread() { - MemorySession session = MemorySession.openConfined(); - List handles = new ArrayList<>(); + Arena arena = Arena.openConfined(); + List handles = new ArrayList<>(); for (int i = 0 ; i < N_THREADS ; i++) { - MemorySession handle = MemorySession.openConfined(); - keepAlive(handle, session); + Arena handle = Arena.openConfined(); + keepAlive(handle.scope(), arena.scope()); handles.add(handle); } while (true) { try { - session.close(); + arena.close(); assertEquals(handles.size(), 0); break; } catch (IllegalStateException ex) { assertTrue(handles.size() > 0); - MemorySession handle = handles.remove(0); + Arena handle = handles.remove(0); handle.close(); } } @@ -189,16 +165,15 @@ public void testLockSingleThread() { @Test public void testLockSharedMultiThread() { - MemorySession session = MemorySession.openShared(); + Arena arena = Arena.openShared(); AtomicInteger lockCount = new AtomicInteger(); for (int i = 0 ; i < N_THREADS ; i++) { new Thread(() -> { - try (MemorySession handle = MemorySession.openConfined()) { - keepAlive(handle, session); + try (Arena handle = Arena.openConfined()) { + keepAlive(handle.scope(), arena.scope()); lockCount.incrementAndGet(); waitSomeTime(); lockCount.decrementAndGet(); - handle.close(); } catch (IllegalStateException ex) { // might be already closed - do nothing } @@ -207,7 +182,7 @@ public void testLockSharedMultiThread() { while (true) { try { - session.close(); + arena.close(); assertEquals(lockCount.get(), 0); break; } catch (IllegalStateException ex) { @@ -218,19 +193,19 @@ public void testLockSharedMultiThread() { @Test public void testCloseEmptyConfinedSession() { - MemorySession.openConfined().close(); + Arena.openConfined().close(); } @Test public void testCloseEmptySharedSession() { - MemorySession.openShared().close(); + Arena.openShared().close(); } @Test public void testCloseConfinedLock() { - MemorySession session = MemorySession.openConfined(); - MemorySession handle = MemorySession.openConfined(); - keepAlive(handle, session); + Arena arena = Arena.openConfined(); + Arena handle = Arena.openConfined(); + keepAlive(handle.scope(), arena.scope()); AtomicReference failure = new AtomicReference<>(); Thread t = new Thread(() -> { try { @@ -249,34 +224,33 @@ public void testCloseConfinedLock() { } } - @Test(dataProvider = "sessions") - public void testSessionAcquires(Supplier sessionFactory) { - MemorySession session = sessionFactory.get(); + @Test(dataProvider = "allSessions") + public void testSessionAcquires(SessionSupplier sessionSupplier) { + SegmentScope session = sessionSupplier.get(); acquireRecursive(session, 5); - if (session.isCloseable()) { - session.close(); - } + if (!SessionSupplier.isImplicit(session)) + SessionSupplier.close(session); } - private void acquireRecursive(MemorySession session, int acquireCount) { - try (MemorySession handle = MemorySession.openConfined()) { - keepAlive(handle, session); + private void acquireRecursive(SegmentScope session, int acquireCount) { + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), session); if (acquireCount > 0) { // recursive acquire acquireRecursive(session, acquireCount - 1); } - if (session.isCloseable()) { - assertThrows(IllegalStateException.class, session::close); + if (!SessionSupplier.isImplicit(session)) { + assertThrows(IllegalStateException.class, () -> SessionSupplier.close(session)); } } } @Test public void testConfinedSessionWithImplicitDependency() { - MemorySession root = MemorySession.openConfined(); + Arena root = Arena.openConfined(); // Create many implicit sessions which depend on 'root', and let them become unreachable. for (int i = 0; i < N_THREADS; i++) { - keepAlive(MemorySession.openConfined(Cleaner.create()), root); + keepAlive(SegmentScope.auto(), root.scope()); } // Now let's keep trying to close 'root' until we succeed. This is trickier than it seems: cleanup action // might be called from another thread (the Cleaner thread), so that the confined session lock count is updated racily. @@ -288,8 +262,8 @@ public void testConfinedSessionWithImplicitDependency() { } catch (IllegalStateException ex) { kickGC(); for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread - try (MemorySession session = MemorySession.openConfined()) { - keepAlive(session, root); + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), root.scope()); // dummy } } @@ -300,19 +274,19 @@ public void testConfinedSessionWithImplicitDependency() { @Test public void testConfinedSessionWithSharedDependency() { - MemorySession root = MemorySession.openConfined(); + Arena root = Arena.openConfined(); List threads = new ArrayList<>(); // Create many implicit sessions which depend on 'root', and let them become unreachable. for (int i = 0; i < N_THREADS; i++) { - MemorySession session = MemorySession.openShared(); // create session inside same thread! - keepAlive(session, root); - Thread t = new Thread(session::close); // close from another thread! + Arena arena = Arena.openShared(); // create session inside same thread! + keepAlive(arena.scope(), root.scope()); + Thread t = new Thread(arena::close); // close from another thread! threads.add(t); t.start(); } for (int i = 0 ; i < N_THREADS ; i++) { // add more races from current thread - try (MemorySession session = MemorySession.openConfined()) { - keepAlive(session, root); + try (Arena arena = Arena.openConfined()) { + keepAlive(arena.scope(), root.scope()); // dummy } } @@ -345,33 +319,57 @@ private void kickGC() { } @DataProvider - static Object[][] cleaners() { + static Object[][] drops() { return new Object[][] { - { (Supplier)() -> null, UnaryOperator.identity() }, - { (Supplier)Cleaner::create, UnaryOperator.identity() }, - { (Supplier)CleanerFactory::cleaner, UnaryOperator.identity() }, - { (Supplier)Cleaner::create, (UnaryOperator)MemorySession::asNonCloseable }, - { (Supplier)CleanerFactory::cleaner, (UnaryOperator)MemorySession::asNonCloseable } + { (Supplier) Arena::openConfined}, + { (Supplier) Arena::openShared}, }; } - @DataProvider - static Object[][] sessions() { + private void keepAlive(SegmentScope child, SegmentScope parent) { + MemorySessionImpl parentImpl = (MemorySessionImpl) parent; + parentImpl.acquire0(); + addCloseAction(child, parentImpl::release0); + } + + private void addCloseAction(SegmentScope session, Runnable action) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + sessionImpl.addCloseAction(action); + } + + interface SessionSupplier extends Supplier { + + static void close(SegmentScope session) { + ((MemorySessionImpl)session).close(); + } + + static boolean isImplicit(SegmentScope session) { + return !((MemorySessionImpl)session).isCloseable(); + } + + static SessionSupplier ofImplicit() { + return SegmentScope::auto; + } + + static SessionSupplier ofArena(Supplier arenaSupplier) { + return () -> arenaSupplier.get().scope(); + } + } + + @DataProvider(name = "sharedSessions") + static Object[][] sharedSessions() { return new Object[][] { - { (Supplier) MemorySession::openConfined}, - { (Supplier) MemorySession::openShared}, - { (Supplier) MemorySession::openImplicit}, - { (Supplier) MemorySession::global}, - { (Supplier) () -> MemorySession.openConfined().asNonCloseable() }, - { (Supplier) () -> MemorySession.openShared().asNonCloseable() }, - { (Supplier) () -> MemorySession.openImplicit().asNonCloseable() }, - { (Supplier) () -> MemorySession.global().asNonCloseable()}, + { SessionSupplier.ofArena(Arena::openShared) }, + { SessionSupplier.ofImplicit() }, }; } - private void keepAlive(MemorySession child, MemorySession parent) { - MemorySessionImpl parentImpl = MemorySessionImpl.toSessionImpl(parent); - parentImpl.acquire0(); - child.addCloseAction(parentImpl::release0); + @DataProvider(name = "allSessions") + static Object[][] allSessions() { + return new Object[][] { + { SessionSupplier.ofArena(Arena::openConfined) }, + { SessionSupplier.ofArena(Arena::openShared) }, + { SessionSupplier.ofImplicit() }, + }; } } diff --git a/test/jdk/java/foreign/TestMismatch.java b/test/jdk/java/foreign/TestMismatch.java index acdf2046d31..e7a381b9ce5 100644 --- a/test/jdk/java/foreign/TestMismatch.java +++ b/test/jdk/java/foreign/TestMismatch.java @@ -27,8 +27,8 @@ * @run testng TestMismatch */ -import java.lang.foreign.MemorySession; -import java.lang.invoke.VarHandle; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; @@ -36,6 +36,7 @@ import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.util.function.IntFunction; +import java.util.stream.Stream; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -45,16 +46,44 @@ public class TestMismatch { - final static VarHandle BYTE_HANDLE = ValueLayout.JAVA_BYTE.varHandle(); - // stores a increasing sequence of values into the memory of the given segment static MemorySegment initializeSegment(MemorySegment segment) { for (int i = 0 ; i < segment.byteSize() ; i++) { - BYTE_HANDLE.set(segment.asSlice(i), (byte)i); + segment.set(ValueLayout.JAVA_BYTE, i, (byte)i); } return segment; } + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcFromOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, -1, 0, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstFromOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, -1, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcToOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, -1, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstToOffset(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, 0, -1); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeSrcLength(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 3, 2, s2, 0, 0); + } + + @Test(dataProvider = "slices", expectedExceptions = IndexOutOfBoundsException.class) + public void testNegativeDstLength(MemorySegment s1, MemorySegment s2) { + MemorySegment.mismatch(s1, 0, 0, s2, 3, 2); + } + @Test(dataProvider = "slices") public void testSameValues(MemorySegment ss1, MemorySegment ss2) { out.format("testSameValues s1:%s, s2:%s\n", ss1, ss2); @@ -74,6 +103,26 @@ public void testSameValues(MemorySegment ss1, MemorySegment ss2) { } } + @Test(dataProvider = "slicesStatic") + public void testSameValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { + out.format("testSameValuesStatic s1:%s, s2:%s\n", ss1, ss2); + MemorySegment s1 = initializeSegment(ss1.toSlice()); + MemorySegment s2 = initializeSegment(ss2.toSlice()); + + for (long i = ss2.offset ; i < ss2.size ; i++) { + long bytes = i - ss2.offset; + long expected = (bytes == ss1.size) ? + -1 : Long.min(ss1.size, bytes); + assertEquals(MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, i), expected); + } + for (long i = ss1.offset ; i < ss1.size ; i++) { + long bytes = i - ss1.offset; + long expected = (bytes == ss2.size) ? + -1 : Long.min(ss2.size, bytes); + assertEquals(MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, i), expected); + } + } + @Test(dataProvider = "slices") public void testDifferentValues(MemorySegment s1, MemorySegment s2) { out.format("testDifferentValues s1:%s, s2:%s\n", s1, s2); @@ -82,7 +131,7 @@ public void testDifferentValues(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= 0; i--) { long expectedMismatchOffset = i; - BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF); + s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); if (s1.byteSize() == s2.byteSize()) { assertEquals(s1.mismatch(s2), expectedMismatchOffset); @@ -99,12 +148,32 @@ public void testDifferentValues(MemorySegment s1, MemorySegment s2) { } } + @Test(dataProvider = "slicesStatic") + public void testDifferentValuesStatic(SliceOffsetAndSize ss1, SliceOffsetAndSize ss2) { + out.format("testDifferentValues s1:%s, s2:%s\n", ss1, ss2); + + for (long i = ss2.size - 1 ; i >= 0; i--) { + if (i >= ss1.size) continue; + initializeSegment(ss1.toSlice()); + initializeSegment(ss2.toSlice()); + long expectedMismatchOffset = i; + ss2.toSlice().set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); + + for (long j = expectedMismatchOffset + 1 ; j < ss2.size ; j++) { + assertEquals(MemorySegment.mismatch(ss1.segment, ss1.offset, ss1.endOffset(), ss2.segment, ss2.offset, j + ss2.offset), expectedMismatchOffset); + } + for (long j = expectedMismatchOffset + 1 ; j < ss1.size ; j++) { + assertEquals(MemorySegment.mismatch(ss2.segment, ss2.offset, ss2.endOffset(), ss1.segment, ss1.offset, j + ss1.offset), expectedMismatchOffset); + } + } + } + @Test public void testEmpty() { var s1 = MemorySegment.ofArray(new byte[0]); assertEquals(s1.mismatch(s1), -1); - try (MemorySession session = MemorySession.openConfined()) { - var nativeSegment = MemorySegment.allocateNative(4, 4, session); + try (Arena arena = Arena.openConfined()) { + var nativeSegment = MemorySegment.allocateNative(4, 4, arena.scope());; var s2 = nativeSegment.asSlice(0, 0); assertEquals(s1.mismatch(s2), -1); assertEquals(s2.mismatch(s1), -1); @@ -115,9 +184,9 @@ public void testEmpty() { public void testLarge() { // skip if not on 64 bits if (ValueLayout.ADDRESS.byteSize() > 32) { - try (MemorySession session = MemorySession.openConfined()) { - var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, session); - var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, session); + try (Arena arena = Arena.openConfined()) { + var s1 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, arena.scope());; + var s2 = MemorySegment.allocateNative((long) Integer.MAX_VALUE + 10L, 8, arena.scope());; assertEquals(s1.mismatch(s1), -1); assertEquals(s1.mismatch(s2), -1); assertEquals(s2.mismatch(s1), -1); @@ -133,15 +202,20 @@ private void testLargeAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { var s3 = s1.asSlice(0, i); var s4 = s2.asSlice(0, i); + // instance assertEquals(s3.mismatch(s3), -1); assertEquals(s3.mismatch(s4), -1); assertEquals(s4.mismatch(s3), -1); + // static + assertEquals(MemorySegment.mismatch(s1, 0, s1.byteSize(), s1, 0, i), -1); + assertEquals(MemorySegment.mismatch(s2, 0, s1.byteSize(), s1, 0, i), -1); + assertEquals(MemorySegment.mismatch(s1, 0, s1.byteSize(), s2, 0, i), -1); } } private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment s2) { for (long i = s2.byteSize() -1 ; i >= Integer.MAX_VALUE - 10L; i--) { - BYTE_HANDLE.set(s2.asSlice(i), (byte) 0xFF); + s2.set(ValueLayout.JAVA_BYTE, i, (byte) 0xFF); long expectedMismatchOffset = i; assertEquals(s1.mismatch(s2), expectedMismatchOffset); assertEquals(s2.mismatch(s1), expectedMismatchOffset); @@ -154,9 +228,9 @@ private void testLargeMismatchAcrossMaxBoundary(MemorySegment s1, MemorySegment @Test public void testClosed() { MemorySegment s1, s2; - try (MemorySession session = MemorySession.openConfined()) { - s1 = MemorySegment.allocateNative(4, 1, session); - s2 = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + s1 = MemorySegment.allocateNative(4, 1, arena.scope());; + s2 = MemorySegment.allocateNative(4, 1, arena.scope());; } assertThrows(ISE, () -> s1.mismatch(s1)); assertThrows(ISE, () -> s1.mismatch(s2)); @@ -165,8 +239,8 @@ public void testClosed() { @Test public void testThreadAccess() throws Exception { - try (MemorySession session = MemorySession.openConfined()) { - var segment = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openConfined()) { + var segment = MemorySegment.allocateNative(4, 1, arena.scope());; { AtomicReference exception = new AtomicReference<>(); Runnable action = () -> { @@ -207,7 +281,7 @@ public void testThreadAccess() throws Exception { } enum SegmentKind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openImplicit())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; @@ -221,30 +295,48 @@ MemorySegment makeSegment(int elems) { } } - @DataProvider(name = "slices") - static Object[][] slices() { + record SliceOffsetAndSize(MemorySegment segment, long offset, long size) { + MemorySegment toSlice() { + return segment.asSlice(offset, size); + } + long endOffset() { + return offset + size; + } + }; + + @DataProvider(name = "slicesStatic") + static Object[][] slicesStatic() { int[] sizes = { 16, 8, 1 }; - List aSlices = new ArrayList<>(); - List bSlices = new ArrayList<>(); - for (List slices : List.of(aSlices, bSlices)) { + List aSliceOffsetAndSizes = new ArrayList<>(); + List bSliceOffsetAndSizes = new ArrayList<>(); + for (List slices : List.of(aSliceOffsetAndSizes, bSliceOffsetAndSizes)) { for (SegmentKind kind : SegmentKind.values()) { MemorySegment segment = kind.makeSegment(16); //compute all slices for (int size : sizes) { for (int index = 0 ; index < 16 ; index += size) { - MemorySegment slice = segment.asSlice(index, size); - slices.add(slice); + slices.add(new SliceOffsetAndSize(segment, index, size)); } } } } - assert aSlices.size() == bSlices.size(); - Object[][] sliceArray = new Object[aSlices.size() * bSlices.size()][]; - for (int i = 0 ; i < aSlices.size() ; i++) { - for (int j = 0 ; j < bSlices.size() ; j++) { - sliceArray[i * aSlices.size() + j] = new Object[] { aSlices.get(i), bSlices.get(j) }; + assert aSliceOffsetAndSizes.size() == bSliceOffsetAndSizes.size(); + Object[][] sliceArray = new Object[aSliceOffsetAndSizes.size() * bSliceOffsetAndSizes.size()][]; + for (int i = 0 ; i < aSliceOffsetAndSizes.size() ; i++) { + for (int j = 0 ; j < bSliceOffsetAndSizes.size() ; j++) { + sliceArray[i * aSliceOffsetAndSizes.size() + j] = new Object[] { aSliceOffsetAndSizes.get(i), bSliceOffsetAndSizes.get(j) }; } } return sliceArray; } + + @DataProvider(name = "slices") + static Object[][] slices() { + Object[][] slicesStatic = slicesStatic(); + return Stream.of(slicesStatic) + .map(arr -> new Object[]{ + ((SliceOffsetAndSize) arr[0]).toSlice(), + ((SliceOffsetAndSize) arr[1]).toSlice() + }).toArray(Object[][]::new); + } } diff --git a/test/jdk/java/foreign/TestNULLAddress.java b/test/jdk/java/foreign/TestNULLAddress.java index 93d9fe7ab6b..803b5d7fed5 100644 --- a/test/jdk/java/foreign/TestNULLAddress.java +++ b/test/jdk/java/foreign/TestNULLAddress.java @@ -32,20 +32,27 @@ import org.testng.annotations.Test; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SymbolLookup; +import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; +import static org.testng.Assert.*; + public class TestNULLAddress { + static { + System.loadLibrary("Null"); + } + static final Linker LINKER = Linker.nativeLinker(); @Test(expectedExceptions = IllegalArgumentException.class) public void testNULLLinking() { LINKER.downcallHandle( - MemoryAddress.NULL, + MemorySegment.NULL, FunctionDescriptor.ofVoid()); } @@ -53,16 +60,22 @@ public void testNULLLinking() { public void testNULLVirtual() throws Throwable { MethodHandle mh = LINKER.downcallHandle( FunctionDescriptor.ofVoid()); - mh.invokeExact((Addressable)MemoryAddress.NULL); + mh.invokeExact(MemorySegment.NULL); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLgetString() { - MemoryAddress.NULL.getUtf8String(0); + @Test + public void testNULLReturn_unbounded() throws Throwable { + MethodHandle mh = LINKER.downcallHandle(SymbolLookup.loaderLookup().find("get_null").get(), + FunctionDescriptor.of(ValueLayout.ADDRESS.asUnbounded())); + MemorySegment ret = (MemorySegment)mh.invokeExact(); + assertTrue(ret.equals(MemorySegment.NULL)); } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testNULLsetString() { - MemoryAddress.NULL.setUtf8String(0, "hello"); + @Test + public void testNULLReturn_plain() throws Throwable { + MethodHandle mh = LINKER.downcallHandle(SymbolLookup.loaderLookup().find("get_null").get(), + FunctionDescriptor.of(ValueLayout.ADDRESS)); + MemorySegment ret = (MemorySegment)mh.invokeExact(); + assertTrue(ret.equals(MemorySegment.NULL)); } } diff --git a/test/jdk/java/foreign/TestNative.java b/test/jdk/java/foreign/TestNative.java index 4f6aa24a3e4..672d6d7db2e 100644 --- a/test/jdk/java/foreign/TestNative.java +++ b/test/jdk/java/foreign/TestNative.java @@ -29,11 +29,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestNative */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemoryLayout.PathElement; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; import org.testng.annotations.DataProvider; @@ -112,7 +112,7 @@ static void checkBytes(MemorySegment base, SequenceLayout lay for (long i = 0 ; i < nelems ; i++) { Object handleValue = handleExtractor.apply(base, i); Object bufferValue = nativeBufferExtractor.apply(z, (int)i); - Object rawValue = nativeRawExtractor.apply(base.address().toRawLongValue(), (int)i); + Object rawValue = nativeRawExtractor.apply(base.address(), (int)i); if (handleValue instanceof Number) { assertEquals(((Number)handleValue).longValue(), i); assertEquals(((Number)bufferValue).longValue(), i); @@ -145,8 +145,8 @@ static void checkBytes(MemorySegment base, SequenceLayout lay @Test(dataProvider="nativeAccessOps") public void testNativeAccess(Consumer checker, Consumer initializer, SequenceLayout seq) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(seq, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(seq, arena.scope());; initializer.accept(segment); checker.accept(segment); } @@ -155,8 +155,8 @@ public void testNativeAccess(Consumer checker, Consumer bufferFunction, int elemSize) { int capacity = (int)doubles.byteSize(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(doubles, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(doubles, arena.scope());; ByteBuffer bb = segment.asByteBuffer(); Buffer buf = bufferFunction.apply(bb); int expected = capacity / elemSize; @@ -167,30 +167,30 @@ public void testNativeCapacity(Function bufferFunction, int @Test public void testDefaultAccessModes() { - MemoryAddress addr = allocateMemory(12); - try (MemorySession session = MemorySession.openConfined()) { - session.addCloseAction(() -> freeMemory(addr)); - MemorySegment mallocSegment = MemorySegment.ofAddress(addr, 12, session); + MemorySegment addr = allocateMemory(12); + try (Arena arena = Arena.openConfined()) { + MemorySegment mallocSegment = MemorySegment.ofAddress(addr.address(), 12, + arena.scope(), () -> freeMemory(addr)); assertFalse(mallocSegment.isReadOnly()); } } @Test public void testMallocSegment() { - MemoryAddress addr = allocateMemory(12); + MemorySegment addr = allocateMemory(12); MemorySegment mallocSegment = null; - try (MemorySession session = MemorySession.openConfined()) { - session.addCloseAction(() -> freeMemory(addr)); - mallocSegment = MemorySegment.ofAddress(addr, 12, session); + try (Arena arena = Arena.openConfined()) { + mallocSegment = MemorySegment.ofAddress(addr.address(), 12, + arena.scope(), () -> freeMemory(addr)); assertEquals(mallocSegment.byteSize(), 12); //free here } - assertTrue(!mallocSegment.session().isAlive()); + assertTrue(!mallocSegment.scope().isAlive()); } @Test public void testAddressAccess() { - MemoryAddress addr = allocateMemory(4); + MemorySegment addr = allocateMemory(4); addr.set(JAVA_INT, 0, 42); assertEquals(addr.get(JAVA_INT, 0), 42); freeMemory(addr); @@ -198,9 +198,9 @@ public void testAddressAccess() { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadResize() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(4, 1, session); - MemorySegment.ofAddress(segment.address(), -1, MemorySession.global()); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(4, 1, arena.scope());; + MemorySegment.ofAddress(segment.address(), -1, SegmentScope.global()); } } diff --git a/test/jdk/java/foreign/TestNulls.java b/test/jdk/java/foreign/TestNulls.java index 3c79d4cff6d..c72b5fefd61 100644 --- a/test/jdk/java/foreign/TestNulls.java +++ b/test/jdk/java/foreign/TestNulls.java @@ -32,12 +32,14 @@ */ import java.lang.foreign.*; + import jdk.internal.ref.CleanerFactory; import org.testng.annotations.DataProvider; import org.testng.annotations.NoInjection; import org.testng.annotations.Test; import java.lang.constant.Constable; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -79,8 +81,8 @@ public class TestNulls { static final Class[] CLASSES = new Class[] { + Arena.class, MemorySegment.class, - MemoryAddress.class, MemoryLayout.class, MemoryLayout.PathElement.class, SequenceLayout.class, @@ -95,19 +97,19 @@ public class TestNulls { ValueLayout.OfDouble.class, ValueLayout.OfAddress.class, GroupLayout.class, - Addressable.class, Linker.class, VaList.class, VaList.Builder.class, FunctionDescriptor.class, SegmentAllocator.class, - MemorySession.class, + SegmentScope.class, SymbolLookup.class }; static final Set EXCLUDE_LIST = Set.of( - "java.lang.foreign.MemorySession/openConfined(java.lang.ref.Cleaner)/0/0", - "java.lang.foreign.MemorySession/openShared(java.lang.ref.Cleaner)/0/0", + "java.lang.foreign.MemorySegment/ofAddress(long,long,java.lang.foreign.SegmentScope,java.lang.Runnable)/3/0", + "java.lang.foreign.MemorySegment.MemorySession/openConfined(java.lang.ref.Cleaner)/0/0", + "java.lang.foreign.MemorySegment.MemorySession/openShared(java.lang.ref.Cleaner)/0/0", "java.lang.foreign.MemoryLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "java.lang.foreign.SequenceLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", "java.lang.foreign.ValueLayout/withAttribute(java.lang.String,java.lang.constant.Constable)/1/0", @@ -162,8 +164,6 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(Charset.class, Charset.defaultCharset()); addDefaultMapping(Consumer.class, x -> {}); addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); - addDefaultMapping(MemoryAddress.class, MemoryAddress.ofLong(1)); - addDefaultMapping(Addressable.class, MemoryAddress.ofLong(1)); addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(ValueLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(ValueLayout.OfAddress.class, ValueLayout.ADDRESS); @@ -183,7 +183,8 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(Linker.class, Linker.nativeLinker()); addDefaultMapping(VaList.class, VaListHelper.vaList); addDefaultMapping(VaList.Builder.class, VaListHelper.vaListBuilder); - addDefaultMapping(MemorySession.class, MemorySession.openShared()); + addDefaultMapping(Arena.class, Arena.openConfined()); + addDefaultMapping(SegmentScope.class, SegmentScope.auto()); addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); addDefaultMapping(Supplier.class, () -> null); addDefaultMapping(ClassLoader.class, TestNulls.class.getClassLoader()); @@ -198,7 +199,7 @@ static class VaListHelper { vaList = VaList.make(b -> { builderRef.set(b); b.addVarg(JAVA_LONG, 42L); - }, MemorySession.openImplicit()); + }, SegmentScope.auto()); vaListBuilder = builderRef.get(); } } diff --git a/test/jdk/java/foreign/TestOfBufferIssue.java b/test/jdk/java/foreign/TestOfBufferIssue.java new file mode 100644 index 00000000000..df8d62ccf20 --- /dev/null +++ b/test/jdk/java/foreign/TestOfBufferIssue.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, 2022, 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. + * + */ + +import org.testng.annotations.*; + +import java.lang.foreign.MemorySegment; +import java.nio.CharBuffer; + +import static org.testng.Assert.*; + +/* + * @test + * @bug 8294621 + * @summary test that StringCharBuffer is not accepted by MemorySegment::ofBuffer + * @enablePreview + * @run testng TestOfBufferIssue + */ + +public class TestOfBufferIssue { + + @Test + public void ensure8294621Fixed() { + try { + final CharBuffer cb = CharBuffer.wrap("Hello"); + MemorySegment src2 = MemorySegment.ofBuffer(cb); + fail("A StringCharBuffer is not allowed as an argument."); + } catch (IllegalArgumentException iae) { + // Ignored. Happy path + } + } + +} diff --git a/test/jdk/java/foreign/TestScopedOperations.java b/test/jdk/java/foreign/TestScopedOperations.java index fa15e48ce0a..986703a02a5 100644 --- a/test/jdk/java/foreign/TestScopedOperations.java +++ b/test/jdk/java/foreign/TestScopedOperations.java @@ -28,13 +28,14 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED TestScopedOperations */ -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.VaList; import java.lang.foreign.ValueLayout; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -73,9 +74,9 @@ public class TestScopedOperations { @Test(dataProvider = "scopedOperations") public void testOpAfterClose(String name, ScopedOperation scopedOperation) { - MemorySession session = MemorySession.openConfined(); - Z obj = scopedOperation.apply(session); - session.close(); + Arena arena = Arena.openConfined(); + Z obj = scopedOperation.apply(arena.scope()); + arena.close(); try { scopedOperation.accept(obj); fail(); @@ -86,8 +87,8 @@ public void testOpAfterClose(String name, ScopedOperation scopedOperation @Test(dataProvider = "scopedOperations") public void testOpOutsideConfinement(String name, ScopedOperation scopedOperation) { - try (MemorySession session = MemorySession.openConfined()) { - Z obj = scopedOperation.apply(session); + try (Arena arena = Arena.openConfined()) { + Z obj = scopedOperation.apply(arena.scope()); AtomicReference failed = new AtomicReference<>(); Thread t = new Thread(() -> { try { @@ -110,9 +111,7 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO static { // session operations - ScopedOperation.ofScope(session -> session.addCloseAction(() -> { - }), "MemorySession::addCloseAction"); - ScopedOperation.ofScope(session -> MemorySegment.allocateNative(100, session), "MemorySegment::allocateNative"); + ScopedOperation.ofScope(session -> MemorySegment.allocateNative(100, session), "MemorySession::allocate");; ScopedOperation.ofScope(session -> { try (FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 10L, session); @@ -121,16 +120,13 @@ public void testOpOutsideConfinement(String name, ScopedOperation scopedO } }, "FileChannel::map"); ScopedOperation.ofScope(session -> VaList.make(b -> b.addVarg(JAVA_INT, 42), session), "VaList::make"); - ScopedOperation.ofScope(session -> VaList.ofAddress(MemoryAddress.ofLong(42), session), "VaList::make"); - ScopedOperation.ofScope(SegmentAllocator::newNativeArena, "SegmentAllocator::arenaAllocator"); + ScopedOperation.ofScope(session -> VaList.ofAddress(42, session), "VaList::make"); // segment operations ScopedOperation.ofSegment(s -> s.toArray(JAVA_BYTE), "MemorySegment::toArray(BYTE)"); - ScopedOperation.ofSegment(MemorySegment::address, "MemorySegment::address"); ScopedOperation.ofSegment(s -> s.copyFrom(s), "MemorySegment::copyFrom"); ScopedOperation.ofSegment(s -> s.mismatch(s), "MemorySegment::mismatch"); ScopedOperation.ofSegment(s -> s.fill((byte) 0), "MemorySegment::fill"); // valist operations - ScopedOperation.ofVaList(VaList::address, "VaList::address"); ScopedOperation.ofVaList(VaList::copy, "VaList::copy"); ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.ADDRESS), "VaList::nextVarg/address"); ScopedOperation.ofVaList(list -> list.nextVarg(ValueLayout.JAVA_INT), "VaList::nextVarg/int"); @@ -165,13 +161,13 @@ static Object[][] scopedOperations() { return scopedOperations.stream().map(op -> new Object[] { op.name, op }).toArray(Object[][]::new); } - static class ScopedOperation implements Consumer, Function { + static class ScopedOperation implements Consumer, Function { - final Function factory; + final Function factory; final Consumer operation; final String name; - private ScopedOperation(Function factory, Consumer operation, String name) { + private ScopedOperation(Function factory, Consumer operation, String name) { this.factory = factory; this.operation = operation; this.name = name; @@ -183,15 +179,15 @@ public void accept(X obj) { } @Override - public X apply(MemorySession session) { + public X apply(SegmentScope session) { return factory.apply(session); } - static void of(Function factory, Consumer consumer, String name) { + static void of(Function factory, Consumer consumer, String name) { scopedOperations.add(new ScopedOperation<>(factory, consumer, name)); } - static void ofScope(Consumer scopeConsumer, String name) { + static void ofScope(Consumer scopeConsumer, String name) { scopedOperations.add(new ScopedOperation<>(Function.identity(), scopeConsumer, name)); } @@ -228,7 +224,7 @@ enum SegmentFactory { throw new AssertionError(ex); } }), - UNSAFE(session -> MemorySegment.ofAddress(MemoryAddress.NULL, 10, session)); + UNSAFE(session -> MemorySegment.ofAddress(0, 10, session)); static { try { @@ -240,20 +236,19 @@ enum SegmentFactory { } } - final Function segmentFactory; + final Function segmentFactory; - SegmentFactory(Function segmentFactory) { + SegmentFactory(Function segmentFactory) { this.segmentFactory = segmentFactory; } } enum AllocatorFactory { - ARENA_BOUNDED(session -> SegmentAllocator.newNativeArena(1000, session)), - ARENA_UNBOUNDED(SegmentAllocator::newNativeArena); + NATIVE_ALLOCATOR(SegmentAllocator::nativeAllocator); - final Function allocatorFactory; + final Function allocatorFactory; - AllocatorFactory(Function allocatorFactory) { + AllocatorFactory(Function allocatorFactory) { this.allocatorFactory = allocatorFactory; } } diff --git a/test/jdk/java/foreign/TestSegmentAllocators.java b/test/jdk/java/foreign/TestSegmentAllocators.java index a5cca846dc5..94dd265563e 100644 --- a/test/jdk/java/foreign/TestSegmentAllocators.java +++ b/test/jdk/java/foreign/TestSegmentAllocators.java @@ -32,6 +32,7 @@ import org.testng.annotations.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.VarHandle; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -46,8 +47,6 @@ import java.util.concurrent.atomic.AtomicInteger; import java.util.function.BiFunction; import java.util.function.Function; -import java.util.stream.IntStream; -import java.util.stream.LongStream; import static org.testng.Assert.*; @@ -69,13 +68,13 @@ public void testAllocation(Z value, AllocationFactory for (L alignedLayout : layouts) { List addressList = new ArrayList<>(); int elems = ELEMS / ((int)alignedLayout.byteAlignment() / (int)layout.byteAlignment()); - MemorySession[] sessions = { - MemorySession.openConfined(), - MemorySession.openShared() + Arena[] arenas = { + Arena.openConfined(), + Arena.openShared() }; - for (MemorySession session : sessions) { - try (session) { - SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, session); + for (Arena arena : arenas) { + try (arena) { + SegmentAllocator allocator = allocationFactory.allocator(alignedLayout.byteSize() * ELEMS, arena); for (int i = 0; i < elems; i++) { MemorySegment address = allocationFunction.allocate(allocator, alignedLayout, value); assertEquals(address.byteSize(), alignedLayout.byteSize()); @@ -87,16 +86,14 @@ public void testAllocation(Z value, AllocationFactory try { allocationFunction.allocate(allocator, alignedLayout, value); assertFalse(isBound); - } catch (OutOfMemoryError ex) { + } catch (IndexOutOfBoundsException ex) { //failure is expected if bound assertTrue(isBound); } } - if (allocationFactory != AllocationFactory.IMPLICIT_ALLOCATOR) { - // addresses should be invalid now - for (MemorySegment address : addressList) { - assertFalse(address.session().isAlive()); - } + // addresses should be invalid now + for (MemorySegment address : addressList) { + assertFalse(address.scope().isAlive()); } } } @@ -106,40 +103,27 @@ public void testAllocation(Z value, AllocationFactory @Test public void testBigAllocationInUnboundedSession() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + try (Arena arena = Arena.openConfined()) { for (int i = 8 ; i < SIZE_256M ; i *= 8) { + SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(i * 2 + 1)); MemorySegment address = allocator.allocate(i, i); //check size assertEquals(address.byteSize(), i); //check alignment - assertEquals(address.address().toRawLongValue() % i, 0); + assertEquals(address.address() % i, 0); } } } @Test public void testTooBigForBoundedArena() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(10, session); - assertThrows(OutOfMemoryError.class, () -> allocator.allocate(12)); - allocator.allocate(5); // ok - } - } - - @Test - public void testBiggerThanBlockForBoundedArena() { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(4 * 1024 * 2, session); - allocator.allocate(4 * 1024 + 1); // should be ok + try (Arena arena = Arena.openConfined()) { + SegmentAllocator allocator = SegmentAllocator.slicingAllocator(arena.allocate(10)); + assertThrows(IndexOutOfBoundsException.class, () -> allocator.allocate(12)); + allocator.allocate(5); } } - @Test(expectedExceptions = IllegalArgumentException.class) - public void testBadUnboundedArenaSize() { - SegmentAllocator.newNativeArena( -1, MemorySession.global()); - } - @Test(dataProvider = "allocators", expectedExceptions = IllegalArgumentException.class) public void testBadAllocationSize(SegmentAllocator allocator) { allocator.allocate(-1); @@ -167,8 +151,9 @@ public void testBadAllocationArrayNegSize(SegmentAllocator allocator) { @Test(expectedExceptions = OutOfMemoryError.class) public void testBadArenaNullReturn() { - SegmentAllocator segmentAllocator = SegmentAllocator.newNativeArena(MemorySession.openImplicit()); - segmentAllocator.allocate(Long.MAX_VALUE, 2); + try (Arena arena = Arena.openConfined()) { + arena.allocate(Long.MAX_VALUE, 2); + } } @Test @@ -176,7 +161,7 @@ public void testArrayAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { + public MemorySegment allocate(long bytesSize, long byteAlignment) { return null; } @@ -201,8 +186,9 @@ public void testStringAllocateDelegation() { AtomicInteger calls = new AtomicInteger(); SegmentAllocator allocator = new SegmentAllocator() { @Override - public MemorySegment allocate(long bytesSize, long bytesAlignment) { - return MemorySegment.allocateNative(bytesSize, bytesAlignment, MemorySession.openImplicit()); + + public MemorySegment allocate(long byteSize, long byteAlignment) { + return MemorySegment.allocateNative(byteSize, byteAlignment, SegmentScope.auto()); } @Override @@ -219,13 +205,13 @@ public MemorySegment allocate(long size) { @Test(dataProvider = "arrayAllocations") public void testArray(AllocationFactory allocationFactory, ValueLayout layout, AllocationFunction allocationFunction, ToArrayHelper arrayHelper) { Z arr = arrayHelper.array(); - MemorySession[] sessions = { - MemorySession.openConfined(), - MemorySession.openShared() + Arena[] arenas = { + Arena.openConfined(), + Arena.openShared() }; - for (MemorySession session : sessions) { - try (session) { - SegmentAllocator allocator = allocationFactory.allocator(100, session); + for (Arena arena : arenas) { + try (arena) { + SegmentAllocator allocator = allocationFactory.allocator(100, arena); MemorySegment address = allocationFunction.allocate(allocator, layout, arr); Z found = arrayHelper.toArray(address, layout); assertEquals(found, arr); @@ -259,7 +245,7 @@ static Object[][] scalarAllocations() { scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); - scalarAllocations.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); @@ -282,7 +268,7 @@ static Object[][] scalarAllocations() { scalarAllocations.add(new Object[] { 42d, factory, ValueLayout.JAVA_DOUBLE.withOrder(ByteOrder.LITTLE_ENDIAN), (AllocationFunction.OfDouble) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); - scalarAllocations.add(new Object[] { MemoryAddress.ofLong(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), + scalarAllocations.add(new Object[] { MemorySegment.ofAddress(42), factory, ValueLayout.ADDRESS.withOrder(ByteOrder.BIG_ENDIAN), (AllocationFunction.OfAddress) SegmentAllocator::allocate, (Function)l -> l.varHandle() }); } @@ -350,7 +336,7 @@ interface OfInt extends AllocationFunction { } interface OfFloat extends AllocationFunction { } interface OfLong extends AllocationFunction { } interface OfDouble extends AllocationFunction { } - interface OfAddress extends AllocationFunction { } + interface OfAddress extends AllocationFunction { } interface OfByteArray extends AllocationFunction { } interface OfCharArray extends AllocationFunction { } @@ -362,21 +348,19 @@ interface OfDoubleArray extends AllocationFunction SegmentAllocator.newNativeArena(session)), - NATIVE_ALLOCATOR(false, (size, session) -> session), - IMPLICIT_ALLOCATOR(false, (size, session) -> SegmentAllocator.implicitAllocator()); + SLICING(true, (size, drop) -> SegmentAllocator.slicingAllocator(MemorySegment.allocateNative(size, drop.scope()))), + NATIVE_ALLOCATOR(false, (size, drop) -> SegmentAllocator.nativeAllocator(drop.scope())); private final boolean isBound; - private final BiFunction factory; + private final BiFunction factory; - AllocationFactory(boolean isBound, BiFunction factory) { + AllocationFactory(boolean isBound, BiFunction factory) { this.isBound = isBound; this.factory = factory; } - SegmentAllocator allocator(long size, MemorySession session) { - return factory.apply(size, session); + SegmentAllocator allocator(long size, Arena arena) { + return factory.apply(size, arena); } public boolean isBound() { @@ -492,42 +476,13 @@ public double[] toArray(MemorySegment segment, ValueLayout layout) { return found; } }; - - ToArrayHelper toAddressArray = new ToArrayHelper<>() { - @Override - public MemoryAddress[] array() { - return switch ((int) ValueLayout.ADDRESS.byteSize()) { - case 4 -> wrap(toIntArray.array()); - case 8 -> wrap(toLongArray.array()); - default -> throw new IllegalStateException("Cannot get here"); - }; - } - - @Override - public MemoryAddress[] toArray(MemorySegment segment, ValueLayout layout) { - return switch ((int)layout.byteSize()) { - case 4 -> wrap(toIntArray.toArray(segment, layout)); - case 8 -> wrap(toLongArray.toArray(segment, layout)); - default -> throw new IllegalStateException("Cannot get here"); - }; - } - - private MemoryAddress[] wrap(int[] ints) { - return IntStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new); - } - - private MemoryAddress[] wrap(long[] ints) { - return LongStream.of(ints).mapToObj(MemoryAddress::ofLong).toArray(MemoryAddress[]::new); - } - }; } @DataProvider(name = "allocators") static Object[][] allocators() { return new Object[][] { - { SegmentAllocator.implicitAllocator() }, - { SegmentAllocator.newNativeArena(MemorySession.global()) }, - { SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(10, MemorySession.global())) }, + { SegmentAllocator.nativeAllocator(SegmentScope.global()) }, + { SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(10, SegmentScope.global())) }, }; } } diff --git a/test/jdk/java/foreign/TestSegmentCopy.java b/test/jdk/java/foreign/TestSegmentCopy.java index 0a3de9a2476..c82d4e5ded8 100644 --- a/test/jdk/java/foreign/TestSegmentCopy.java +++ b/test/jdk/java/foreign/TestSegmentCopy.java @@ -29,7 +29,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandles; import java.lang.invoke.VarHandle; @@ -144,7 +144,7 @@ void check(SegmentSlice slice, int index, int val) { static class SegmentSlice { enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openImplicit())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; diff --git a/test/jdk/java/foreign/TestSegmentOffset.java b/test/jdk/java/foreign/TestSegmentOffset.java index bb4263b66d9..f3adcb67c89 100644 --- a/test/jdk/java/foreign/TestSegmentOffset.java +++ b/test/jdk/java/foreign/TestSegmentOffset.java @@ -28,9 +28,11 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; + +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; import java.util.function.IntFunction; @@ -79,7 +81,7 @@ public void testOffset(SegmentSlice s1, SegmentSlice s2) { static class SegmentSlice { enum Kind { - NATIVE(i -> MemorySegment.allocateNative(i, MemorySession.openConfined())), + NATIVE(i -> MemorySegment.allocateNative(i, SegmentScope.auto())), ARRAY(i -> MemorySegment.ofArray(new byte[i])); final IntFunction segmentFactory; diff --git a/test/jdk/java/foreign/TestSegmentOverlap.java b/test/jdk/java/foreign/TestSegmentOverlap.java index 1c08240dbde..bb0e07da817 100644 --- a/test/jdk/java/foreign/TestSegmentOverlap.java +++ b/test/jdk/java/foreign/TestSegmentOverlap.java @@ -29,6 +29,7 @@ import java.io.File; import java.io.IOException; +import java.lang.foreign.SegmentScope; import java.nio.channels.FileChannel; import java.nio.file.Files; import java.nio.file.Path; @@ -36,7 +37,7 @@ import java.util.List; import java.util.function.Supplier; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.Test; import org.testng.annotations.DataProvider; import static java.lang.System.out; @@ -61,10 +62,10 @@ public class TestSegmentOverlap { @DataProvider(name = "segmentFactories") public Object[][] segmentFactories() { List> l = List.of( - () -> MemorySegment.allocateNative(16, MemorySession.openConfined()), + () -> MemorySegment.allocateNative(16, SegmentScope.auto()), () -> { try (FileChannel fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE)) { - return fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 16L, MemorySession.openConfined()); + return fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, 16L, SegmentScope.auto()); } catch (IOException e) { throw new RuntimeException(e); } @@ -98,10 +99,10 @@ public void testIdentical(Supplier segmentSupplier) { var s2 = s1.asReadOnly(); out.format("testIdentical s1:%s, s2:%s\n", s1, s2); assertEquals(s1.asOverlappingSlice(s2).get().byteSize(), s1.byteSize()); - assertEquals(s1.asOverlappingSlice(s2).get().session(), s1.session()); + assertEquals(s1.asOverlappingSlice(s2).get().scope(), s1.scope()); assertEquals(s2.asOverlappingSlice(s1).get().byteSize(), s2.byteSize()); - assertEquals(s2.asOverlappingSlice(s1).get().session(), s2.session()); + assertEquals(s2.asOverlappingSlice(s1).get().scope(), s2.scope()); if (s1.isNative()) { assertEquals(s1.asOverlappingSlice(s2).get().address(), s1.address()); @@ -117,13 +118,13 @@ public void testSlices(Supplier segmentSupplier) { MemorySegment slice = s1.asSlice(offset); out.format("testSlices s1:%s, s2:%s, slice:%s, offset:%d\n", s1, s2, slice, offset); assertEquals(s1.asOverlappingSlice(slice).get().byteSize(), s1.byteSize() - offset); - assertEquals(s1.asOverlappingSlice(slice).get().session(), s1.session()); + assertEquals(s1.asOverlappingSlice(slice).get().scope(), s1.scope()); assertEquals(slice.asOverlappingSlice(s1).get().byteSize(), slice.byteSize()); - assertEquals(slice.asOverlappingSlice(s1).get().session(), slice.session()); + assertEquals(slice.asOverlappingSlice(s1).get().scope(), slice.scope()); if (s1.isNative()) { - assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address().addOffset(offset)); + assertEquals(s1.asOverlappingSlice(slice).get().address(), s1.address() + offset); assertEquals(slice.asOverlappingSlice(s1).get().address(), slice.address()); } assertTrue(s2.asOverlappingSlice(slice).isEmpty()); @@ -131,7 +132,7 @@ public void testSlices(Supplier segmentSupplier) { } enum OtherSegmentFactory { - NATIVE(() -> MemorySegment.allocateNative(16, MemorySession.openConfined())), + NATIVE(() -> MemorySegment.allocateNative(16, SegmentScope.auto())), HEAP(() -> MemorySegment.ofArray(new byte[]{16})); final Supplier factory; diff --git a/test/jdk/java/foreign/TestSegments.java b/test/jdk/java/foreign/TestSegments.java index 113c5039acd..3363a61134a 100644 --- a/test/jdk/java/foreign/TestSegments.java +++ b/test/jdk/java/foreign/TestSegments.java @@ -28,9 +28,10 @@ * @run testng/othervm -Xmx4G -XX:MaxDirectMemorySize=1M --enable-native-access=ALL-UNNAMED TestSegments */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -39,7 +40,6 @@ import java.nio.ByteBuffer; import java.util.List; import java.util.concurrent.atomic.AtomicReference; -import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; @@ -50,43 +50,44 @@ public class TestSegments { @Test(dataProvider = "badSizeAndAlignments", expectedExceptions = IllegalArgumentException.class) public void testBadAllocateAlign(long size, long align) { - MemorySegment.allocateNative(size, align, MemorySession.openImplicit()); + MemorySegment.allocateNative(size, align, SegmentScope.auto()); } @Test public void testZeroLengthNativeSegment() { - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { + SegmentScope session = arena.scope(); var segment = MemorySegment.allocateNative(0, session); assertEquals(segment.byteSize(), 0); MemoryLayout seq = MemoryLayout.sequenceLayout(0, JAVA_INT); segment = MemorySegment.allocateNative(seq, session); assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % seq.byteAlignment(), 0); + assertEquals(segment.address() % seq.byteAlignment(), 0); segment = MemorySegment.allocateNative(0, 4, session); assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % 4, 0); - segment = MemorySegment.ofAddress(segment.address(), 0, session); - assertEquals(segment.byteSize(), 0); - assertEquals(segment.address().toRawLongValue() % 4, 0); + assertEquals(segment.address() % 4, 0); + MemorySegment rawAddress = MemorySegment.ofAddress(segment.address(), 0, session); + assertEquals(rawAddress.byteSize(), 0); + assertEquals(rawAddress.address() % 4, 0); } } @Test(expectedExceptions = { OutOfMemoryError.class, IllegalArgumentException.class }) public void testAllocateTooBig() { - MemorySegment.allocateNative(Long.MAX_VALUE, MemorySession.openImplicit()); + MemorySegment.allocateNative(Long.MAX_VALUE, SegmentScope.auto()); } @Test(expectedExceptions = OutOfMemoryError.class) public void testNativeAllocationTooBig() { - MemorySegment segment = MemorySegment.allocateNative(1024 * 1024 * 8 * 2, MemorySession.openImplicit()); // 2M + MemorySegment segment = MemorySegment.allocateNative(1024L * 1024 * 8 * 2, SegmentScope.auto()); // 2M } @Test public void testNativeSegmentIsZeroed() { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(1000, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(1000, 1, arena.scope()); for (long i = 0 ; i < segment.byteSize() ; i++) { assertEquals(0, (byte)byteHandle.get(segment, i)); } @@ -96,8 +97,8 @@ public void testNativeSegmentIsZeroed() { @Test public void testSlices() { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(10, 1, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(10, 1, arena.scope()); //init for (byte i = 0 ; i < segment.byteSize() ; i++) { byteHandle.set(segment, (long)i, i); @@ -116,15 +117,14 @@ public void testSlices() { @Test public void testEqualsOffHeap() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(100, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); assertEquals(segment, segment.asReadOnly()); assertEquals(segment, segment.asSlice(0, 100)); assertNotEquals(segment, segment.asSlice(10, 90)); - assertNotEquals(segment, segment.asSlice(0, 90)); - assertEquals(segment, MemorySegment.ofAddress(segment.address(), 100, session.asNonCloseable())); - assertNotEquals(segment, MemorySegment.ofAddress(segment.address(), 100, MemorySession.global())); - MemorySegment segment2 = MemorySegment.allocateNative(100, session); + assertEquals(segment, segment.asSlice(0, 90)); + assertEquals(segment, MemorySegment.ofAddress(segment.address(), 100, SegmentScope.global())); + MemorySegment segment2 = MemorySegment.allocateNative(100, arena.scope()); assertNotEquals(segment, segment2); } } @@ -135,29 +135,48 @@ public void testEqualsOnHeap() { assertEquals(segment, segment.asReadOnly()); assertEquals(segment, segment.asSlice(0, 100)); assertNotEquals(segment, segment.asSlice(10, 90)); - assertNotEquals(segment, segment.asSlice(0, 90)); + assertEquals(segment, segment.asSlice(0, 90)); MemorySegment segment2 = MemorySegment.ofArray(new byte[100]); assertNotEquals(segment, segment2); } + @Test + public void testHashCodeOffHeap() { + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); + assertEquals(segment.hashCode(), segment.asReadOnly().hashCode()); + assertEquals(segment.hashCode(), segment.asSlice(0, 100).hashCode()); + assertEquals(segment.hashCode(), segment.asSlice(0, 90).hashCode()); + assertEquals(segment.hashCode(), MemorySegment.ofAddress(segment.address(), 100, SegmentScope.global()).hashCode()); + } + } + + @Test + public void testHashCodeOnHeap() { + MemorySegment segment = MemorySegment.ofArray(new byte[100]); + assertEquals(segment.hashCode(), segment.asReadOnly().hashCode()); + assertEquals(segment.hashCode(), segment.asSlice(0, 100).hashCode()); + assertEquals(segment.hashCode(), segment.asSlice(0, 90).hashCode()); + } + @Test(expectedExceptions = IndexOutOfBoundsException.class) public void testSmallSegmentMax() { - long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when casted to int - MemorySegment memorySegment = MemorySegment.allocateNative(10, MemorySession.openImplicit()); + long offset = (long)Integer.MAX_VALUE + (long)Integer.MAX_VALUE + 2L + 6L; // overflows to 6 when cast to int + MemorySegment memorySegment = MemorySegment.allocateNative(10, SegmentScope.auto()); memorySegment.get(JAVA_INT, offset); } @Test(expectedExceptions = IndexOutOfBoundsException.class) public void testSmallSegmentMin() { - long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when casted to int - MemorySegment memorySegment = MemorySegment.allocateNative(10, MemorySession.openImplicit()); + long offset = ((long)Integer.MIN_VALUE * 2L) + 6L; // underflows to 6 when cast to int + MemorySegment memorySegment = MemorySegment.allocateNative(10L, SegmentScope.auto()); memorySegment.get(JAVA_INT, offset); } @Test public void testSegmentOOBMessage() { try { - var segment = MemorySegment.allocateNative(10, MemorySession.global()); + var segment = MemorySegment.allocateNative(10, SegmentScope.global()); segment.getAtIndex(ValueLayout.JAVA_INT, 2); } catch (IndexOutOfBoundsException ex) { assertTrue(ex.getMessage().contains("Out of bound access")); @@ -170,13 +189,6 @@ public void testSegmentOOBMessage() { public void testAccessModesOfFactories(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); assertFalse(segment.isReadOnly()); - tryClose(segment); - } - - static void tryClose(MemorySegment segment) { - if (segment.session().isCloseable()) { - segment.session().close(); - } } @DataProvider(name = "segmentFactories") @@ -189,45 +201,17 @@ public Object[][] segmentFactories() { () -> MemorySegment.ofArray(new int[] { 1, 2, 3, 4 }), () -> MemorySegment.ofArray(new long[] { 1l, 2l, 3l, 4l } ), () -> MemorySegment.ofArray(new short[] { 1, 2, 3, 4 } ), - () -> MemorySegment.allocateNative(4, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, 8, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(JAVA_INT, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(4, 8, MemorySession.openImplicit()), - () -> MemorySegment.allocateNative(JAVA_INT, MemorySession.openImplicit()) + () -> MemorySegment.allocateNative(4L, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, 8, SegmentScope.auto()), + () -> MemorySegment.allocateNative(JAVA_INT, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, SegmentScope.auto()), + () -> MemorySegment.allocateNative(4L, 8, SegmentScope.auto()), + () -> MemorySegment.allocateNative(JAVA_INT, SegmentScope.auto()) ); return l.stream().map(s -> new Object[] { s }).toArray(Object[][]::new); } - static class SegmentFactory { - final MemorySession session; - final Function segmentFunc; - - SegmentFactory(MemorySession session, Function segmentFunc) { - this.session = session; - this.segmentFunc = segmentFunc; - } - - public void tryClose() { - if (session.isCloseable()) { - session.close(); - } - } - - public MemorySegment segment() { - return segmentFunc.apply(session); - } - - static SegmentFactory ofArray(Supplier segmentSupplier) { - return new SegmentFactory(MemorySession.global(), (_ignored) -> segmentSupplier.get()); - } - - static SegmentFactory ofImplicitSession(Function segmentFunc) { - return new SegmentFactory(MemorySession.openImplicit(), segmentFunc); - } - } - @Test(dataProvider = "segmentFactories") public void testFill(Supplier segmentSupplier) { VarHandle byteHandle = ValueLayout.JAVA_BYTE.arrayElementVarHandle(); @@ -250,41 +234,19 @@ public void testFill(Supplier segmentSupplier) { assertEquals((byte) byteHandle.get(segment, l), (byte) ~value); } assertEquals((byte) byteHandle.get(segment, segment.byteSize() - 1L), value); - tryClose(segment); - } - } - - @Test(dataProvider = "segmentFactories") - public void testFillClosed(Supplier segmentSupplier) { - MemorySegment segment = segmentSupplier.get(); - tryClose(segment); - if (!segment.session().isAlive()) { - try { - segment.fill((byte) 0xFF); - fail(); - } catch (IllegalStateException ex) { - assertTrue(true); - } } } @Test(dataProvider = "segmentFactories") public void testNativeSegments(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); - try { - segment.address(); - assertTrue(segment.isNative()); - } catch (UnsupportedOperationException exception) { - assertFalse(segment.isNative()); - } - tryClose(segment); + assertEquals(segment.isNative(), !segment.array().isPresent()); } @Test(dataProvider = "segmentFactories", expectedExceptions = UnsupportedOperationException.class) public void testFillIllegalAccessMode(Supplier segmentSupplier) { MemorySegment segment = segmentSupplier.get(); segment.asReadOnly().fill((byte) 0xFF); - tryClose(segment); } @Test(dataProvider = "segmentFactories") @@ -302,7 +264,7 @@ public void testFillThread(Supplier segmentSupplier) throws Excep thread.start(); thread.join(); - if (segment.session().ownerThread() != null) { + if (segment.scope().isAccessibleBy(Thread.currentThread())) { RuntimeException e = exception.get(); if (!(e instanceof IllegalStateException)) { throw e; @@ -310,7 +272,6 @@ public void testFillThread(Supplier segmentSupplier) throws Excep } else { assertNull(exception.get()); } - tryClose(segment); } @Test @@ -321,22 +282,11 @@ public void testFillEmpty() { } @Test(dataProvider = "heapFactories") - public void testBigHeapSegments(IntFunction heapSegmentFactory, int factor) { - int bigSize = (Integer.MAX_VALUE / factor) + 1; - MemorySegment segment = heapSegmentFactory.apply(bigSize); - assertTrue(segment.byteSize() > 0); - } - - @Test - public void testSegmentAccessorWithWrappedLifetime() { - MemorySession session = MemorySession.openConfined(); - MemorySession publicSession = session.asNonCloseable(); - assertEquals(session, publicSession); - MemorySegment segment = publicSession.allocate(100); - assertThrows(UnsupportedOperationException.class, publicSession::close); - assertThrows(UnsupportedOperationException.class, segment.session()::close); - session.close(); - assertFalse(publicSession.isAlive()); + public void testVirtualizedBaseAddress(IntFunction heapSegmentFactory, int factor) { + MemorySegment segment = heapSegmentFactory.apply(10); + assertEquals(segment.address(), 0); // base address should be zero (no leaking of impl details) + MemorySegment end = segment.asSlice(segment.byteSize(), 0); + assertEquals(end.address(), segment.byteSize()); // end address should be equal to segment byte size } @DataProvider(name = "badSizeAndAlignments") @@ -351,6 +301,7 @@ public Object[][] sizesAndAlignments() { @DataProvider(name = "heapFactories") public Object[][] heapFactories() { return new Object[][] { + { (IntFunction) size -> MemorySegment.ofArray(new byte[size]), 1 }, { (IntFunction) size -> MemorySegment.ofArray(new char[size]), 2 }, { (IntFunction) size -> MemorySegment.ofArray(new short[size]), 2 }, { (IntFunction) size -> MemorySegment.ofArray(new int[size]), 4 }, diff --git a/test/jdk/java/foreign/TestSharedAccess.java b/test/jdk/java/foreign/TestSharedAccess.java index e711d06e0c0..5c88b35a078 100644 --- a/test/jdk/java/foreign/TestSharedAccess.java +++ b/test/jdk/java/foreign/TestSharedAccess.java @@ -37,6 +37,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicInteger; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -48,8 +49,8 @@ public class TestSharedAccess { @Test public void testShared() throws Throwable { SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); - try (MemorySession session = MemorySession.openShared()) { - MemorySegment s = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openShared()) { + MemorySegment s = MemorySegment.allocateNative(layout, arena.scope());; for (int i = 0 ; i < layout.elementCount() ; i++) { setInt(s.asSlice(i * 4), 42); } @@ -93,12 +94,12 @@ public void testShared() throws Throwable { @Test public void testSharedUnsafe() throws Throwable { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment s = MemorySegment.allocateNative(4, 1, session); + try (Arena arena = Arena.openShared()) { + MemorySegment s = MemorySegment.allocateNative(4, 1, arena.scope());; setInt(s, 42); assertEquals(getInt(s), 42); List threads = new ArrayList<>(); - MemorySegment sharedSegment = MemorySegment.ofAddress(s.address(), s.byteSize(), session); + MemorySegment sharedSegment = MemorySegment.ofAddress(s.address(), s.byteSize(), arena.scope()); for (int i = 0 ; i < 1000 ; i++) { threads.add(new Thread(() -> { assertEquals(getInt(sharedSegment), 42); @@ -120,8 +121,8 @@ public void testOutsideConfinementThread() throws Throwable { CountDownLatch a = new CountDownLatch(1); CountDownLatch b = new CountDownLatch(1); CompletableFuture r; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment s1 = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT), arena.scope());; r = CompletableFuture.runAsync(() -> { try { ByteBuffer bb = s1.asByteBuffer(); diff --git a/test/jdk/java/foreign/TestSlices.java b/test/jdk/java/foreign/TestSlices.java index 76ce186d408..9cceaee9b75 100644 --- a/test/jdk/java/foreign/TestSlices.java +++ b/test/jdk/java/foreign/TestSlices.java @@ -22,9 +22,9 @@ * */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; @@ -46,8 +46,8 @@ public class TestSlices { @Test(dataProvider = "slices") public void testSlices(VarHandle handle, int lo, int hi, int[] values) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(LAYOUT, arena.scope());; //init for (long i = 0 ; i < 2 ; i++) { for (long j = 0 ; j < 5 ; j++) { @@ -61,8 +61,8 @@ public void testSlices(VarHandle handle, int lo, int hi, int[] values) { @Test(dataProvider = "slices") public void testSliceBadIndex(VarHandle handle, int lo, int hi, int[] values) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(LAYOUT, arena.scope());; assertThrows(() -> handle.get(segment, lo, 0)); assertThrows(() -> handle.get(segment, 0, hi)); } diff --git a/test/jdk/java/foreign/TestSpliterator.java b/test/jdk/java/foreign/TestSpliterator.java index e933706fd02..574c184522f 100644 --- a/test/jdk/java/foreign/TestSpliterator.java +++ b/test/jdk/java/foreign/TestSpliterator.java @@ -27,9 +27,10 @@ * @run testng TestSpliterator */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SequenceLayout; import java.lang.invoke.VarHandle; @@ -42,6 +43,7 @@ import java.util.stream.LongStream; import java.lang.foreign.ValueLayout; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -57,8 +59,8 @@ public void testSum(int size, int threshold) { SequenceLayout layout = MemoryLayout.sequenceLayout(size, ValueLayout.JAVA_INT); //setup - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = MemorySegment.allocateNative(layout, arena.scope());; for (int i = 0; i < layout.elementCount(); i++) { INT_HANDLE.set(segment, (long) i, i); } @@ -84,7 +86,7 @@ public void testSumSameThread() { SequenceLayout layout = MemoryLayout.sequenceLayout(1024, ValueLayout.JAVA_INT); //setup - MemorySegment segment = MemorySegment.allocateNative(layout, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(layout, SegmentScope.auto()); for (int i = 0; i < layout.elementCount(); i++) { INT_HANDLE.set(segment, (long) i, i); } @@ -99,37 +101,58 @@ public void testSumSameThread() { @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).spliterator(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(2, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeTooBig() { - MemorySegment.ofArray(new byte[2]).elements(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(2, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).spliterator(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeNotMultiple() { - MemorySegment.ofArray(new byte[7]).elements(ValueLayout.JAVA_INT); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); + } + + @Test + public void testSpliteratorElementSizeMultipleButNotPowerOfTwo() { + MemorySegment.allocateNative(12, SegmentScope.auto()) + .spliterator(ValueLayout.JAVA_INT); + } + + @Test + public void testStreamElementSizeMultipleButNotPowerOfTwo() { + MemorySegment.allocateNative(12, SegmentScope.auto()) + .elements(ValueLayout.JAVA_INT); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadSpliteratorElementSizeZero() { - MemorySegment.ofArray(new byte[7]).spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .spliterator(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testBadStreamElementSizeZero() { - MemorySegment.ofArray(new byte[7]).elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); + MemorySegment.allocateNative(7, SegmentScope.auto()) + .elements(MemoryLayout.sequenceLayout(0, ValueLayout.JAVA_INT)); } @Test(expectedExceptions = IllegalArgumentException.class) public void testHyperAligned() { - MemorySegment.ofArray(new byte[8]).elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(64))); + MemorySegment segment = MemorySegment.allocateNative(8, SegmentScope.auto()); + // compute an alignment constraint (in bytes) which exceed that of the native segment + long bigByteAlign = Long.lowestOneBit(segment.address()) << 1; + segment.elements(MemoryLayout.sequenceLayout(2, ValueLayout.JAVA_INT.withBitAlignment(bigByteAlign * 8))); } static long sumSingle(long acc, MemorySegment segment) { diff --git a/test/jdk/java/foreign/TestStringEncoding.java b/test/jdk/java/foreign/TestStringEncoding.java index c595e671c5b..ae86e7d4ca5 100644 --- a/test/jdk/java/foreign/TestStringEncoding.java +++ b/test/jdk/java/foreign/TestStringEncoding.java @@ -22,9 +22,9 @@ * */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; + import org.testng.annotations.*; import static org.testng.Assert.*; @@ -39,9 +39,8 @@ public class TestStringEncoding { @Test(dataProvider = "strings") public void testStrings(String testString, int expectedByteLength) { - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(expectedByteLength, session); - MemorySegment text = allocator.allocateUtf8String(testString); + try (Arena arena = Arena.openConfined()) { + MemorySegment text = arena.allocateUtf8String(testString); assertEquals(text.byteSize(), expectedByteLength); diff --git a/test/jdk/java/foreign/TestTypeAccess.java b/test/jdk/java/foreign/TestTypeAccess.java index 2739881b191..e84af14aa05 100644 --- a/test/jdk/java/foreign/TestTypeAccess.java +++ b/test/jdk/java/foreign/TestTypeAccess.java @@ -28,8 +28,8 @@ * @run testng TestTypeAccess */ +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.ValueLayout; import org.testng.annotations.*; @@ -53,33 +53,33 @@ public void testMemoryCoordinatePrimitive() { @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressValueGetAsString() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - String address = (String)ADDR_HANDLE.get(s.address()); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + String address = (String)ADDR_HANDLE.get(s); } } @Test(expectedExceptions=ClassCastException.class) public void testMemoryAddressValueSetAsString() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - ADDR_HANDLE.set(s.address(), "string"); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + ADDR_HANDLE.set(s, "string"); } } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryAddressValueGetAsPrimitive() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - int address = (int)ADDR_HANDLE.get(s.address()); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + int address = (int)ADDR_HANDLE.get(s); } } @Test(expectedExceptions=WrongMethodTypeException.class) public void testMemoryAddressValueSetAsPrimitive() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment s = MemorySegment.allocateNative(8, 8, session); - ADDR_HANDLE.set(s.address(), 1); + try (Arena arena = Arena.openConfined()) { + MemorySegment s = MemorySegment.allocateNative(8, 8, arena.scope());; + ADDR_HANDLE.set(s, 1); } } diff --git a/test/jdk/java/foreign/TestUnsupportedLinker.java b/test/jdk/java/foreign/TestUnsupportedLinker.java index 8d223919b97..d16ba1646b2 100644 --- a/test/jdk/java/foreign/TestUnsupportedLinker.java +++ b/test/jdk/java/foreign/TestUnsupportedLinker.java @@ -29,8 +29,7 @@ */ import java.lang.foreign.Linker; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import java.lang.foreign.ValueLayout; @@ -50,11 +49,11 @@ public void testEmptyVaList() { @Test(expectedExceptions = UnsupportedOperationException.class) public void testNonEmptyVaList() { - VaList.make(builder -> builder.addVarg(ValueLayout.JAVA_INT, 42), MemorySession.openImplicit()); + VaList.make(builder -> builder.addVarg(ValueLayout.JAVA_INT, 42), SegmentScope.auto()); } @Test(expectedExceptions = UnsupportedOperationException.class) public void testUnsafeVaList() { - VaList.ofAddress(MemoryAddress.NULL, MemorySession.openImplicit()); + VaList.ofAddress(0L, SegmentScope.auto()); } } diff --git a/test/jdk/java/foreign/TestUpcallAsync.java b/test/jdk/java/foreign/TestUpcallAsync.java index 64573029588..4463bc0475c 100644 --- a/test/jdk/java/foreign/TestUpcallAsync.java +++ b/test/jdk/java/foreign/TestUpcallAsync.java @@ -33,15 +33,15 @@ * TestUpcallAsync */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.GroupLayout; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; + import org.testng.annotations.Test; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.util.ArrayList; @@ -61,24 +61,24 @@ public class TestUpcallAsync extends TestUpcallBase { public void testUpcallsAsync(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); - try (MemorySession session = MemorySession.openShared()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); + MemorySegment addr = findNativeOrThrow(fName); + try (Arena arena = Arena.openShared()) { FunctionDescriptor descriptor = function(ret, paramTypes, fields); - MethodHandle mh = downcallHandle(ABI, addr, allocator, descriptor); - Object[] args = makeArgs(MemorySession.openImplicit(), ret, paramTypes, fields, returnChecks, argChecks); + MethodHandle mh = downcallHandle(ABI, addr, arena, descriptor); + Object[] args = makeArgs(SegmentScope.auto(), ret, paramTypes, fields, returnChecks, argChecks); mh = mh.asSpreader(Object[].class, args.length); mh = MethodHandles.insertArguments(mh, 0, (Object) args); FunctionDescriptor callbackDesc = descriptor.returnLayout() .map(FunctionDescriptor::of) .orElse(FunctionDescriptor.ofVoid()); - Addressable callback = ABI.upcallStub(mh.asType(Linker.upcallType(callbackDesc)), callbackDesc, session); + MemorySegment callback = ABI.upcallStub(mh, callbackDesc, arena.scope()); MethodHandle invoker = asyncInvoker(ret, ret == Ret.VOID ? null : paramTypes.get(0), fields); - Object res = invoker.type().returnType() == MemorySegment.class - ? invoker.invoke(allocator, callback) + Object res = (descriptor.returnLayout().isPresent() && + descriptor.returnLayout().get() instanceof GroupLayout) + ? invoker.invoke(arena.scope(), callback) : invoker.invoke(callback); argChecks.forEach(c -> c.accept(args)); if (ret == Ret.NON_VOID) { @@ -102,7 +102,7 @@ private MethodHandle asyncInvoker(Ret ret, ParamType returnType, List { - Addressable invokerSymbol = findNativeOrThrow(symbol); + MemorySegment invokerSymbol = findNativeOrThrow(symbol); MemoryLayout returnLayout = returnType.layout(fields); FunctionDescriptor desc = FunctionDescriptor.of(returnLayout, C_POINTER); diff --git a/test/jdk/java/foreign/TestUpcallBase.java b/test/jdk/java/foreign/TestUpcallBase.java index a9b750d8219..85da103a801 100644 --- a/test/jdk/java/foreign/TestUpcallBase.java +++ b/test/jdk/java/foreign/TestUpcallBase.java @@ -22,10 +22,10 @@ * */ -import java.lang.foreign.Addressable; +import java.lang.foreign.GroupLayout; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; @@ -34,6 +34,7 @@ import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; @@ -54,17 +55,17 @@ public abstract class TestUpcallBase extends CallGeneratorHelper { try { DUMMY = MethodHandles.lookup().findStatic(TestUpcallBase.class, "dummy", MethodType.methodType(void.class)); PASS_AND_SAVE = MethodHandles.lookup().findStatic(TestUpcallBase.class, "passAndSave", - MethodType.methodType(Object.class, Object[].class, AtomicReference.class, int.class)); + MethodType.methodType(Object.class, Object[].class, AtomicReference.class, int.class, List.class)); } catch (Throwable ex) { throw new IllegalStateException(ex); } } - private static Addressable DUMMY_STUB; + private static MemorySegment DUMMY_STUB; @BeforeClass void setup() { - DUMMY_STUB = ABI.upcallStub(DUMMY, FunctionDescriptor.ofVoid(), MemorySession.openImplicit()); + DUMMY_STUB = ABI.upcallStub(DUMMY, FunctionDescriptor.ofVoid(), SegmentScope.auto()); } static FunctionDescriptor function(Ret ret, List params, List fields) { @@ -80,11 +81,11 @@ static FunctionDescriptor function(Ret ret, List params, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { + static Object[] makeArgs(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { return makeArgs(session, ret, params, fields, checks, argChecks, List.of()); } - static Object[] makeArgs(MemorySession session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) throws ReflectiveOperationException { + static Object[] makeArgs(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) throws ReflectiveOperationException { Object[] args = new Object[prefix.size() + params.size() + 1]; int argNum = 0; for (MemoryLayout layout : prefix) { @@ -97,27 +98,32 @@ static Object[] makeArgs(MemorySession session, Ret ret, List params, return args; } - static Addressable makeCallback(MemorySession session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) { + static MemorySegment makeCallback(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks, List prefix) { if (params.isEmpty()) { return DUMMY_STUB; } AtomicReference box = new AtomicReference<>(); - MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box, prefix.size()); + List layouts = new ArrayList<>(); + layouts.addAll(prefix); + for (int i = 0 ; i < params.size() ; i++) { + layouts.add(params.get(i).layout(fields)); + } + MethodHandle mh = insertArguments(PASS_AND_SAVE, 1, box, prefix.size(), layouts); mh = mh.asCollector(Object[].class, prefix.size() + params.size()); for(int i = 0; i < prefix.size(); i++) { - mh = mh.asType(mh.type().changeParameterType(i, carrier(prefix.get(i), false))); + mh = mh.asType(mh.type().changeParameterType(i, carrier(prefix.get(i)))); } for (int i = 0; i < params.size(); i++) { ParamType pt = params.get(i); MemoryLayout layout = pt.layout(fields); - Class carrier = carrier(layout, false); + Class carrier = carrier(layout); mh = mh.asType(mh.type().changeParameterType(prefix.size() + i, carrier)); final int finalI = prefix.size() + i; - if (carrier == MemorySegment.class) { + if (layout instanceof GroupLayout) { argChecks.add(o -> assertStructEquals((MemorySegment) box.get()[finalI], (MemorySegment) o[finalI], layout)); } else { argChecks.add(o -> assertEquals(box.get()[finalI], o[finalI])); @@ -126,9 +132,8 @@ static Addressable makeCallback(MemorySession session, Ret ret, List ParamType firstParam = params.get(0); MemoryLayout firstlayout = firstParam.layout(fields); - Class firstCarrier = carrier(firstlayout, true); - - if (firstCarrier == MemorySegment.class) { + Class firstCarrier = carrier(firstlayout); + if (firstlayout instanceof GroupLayout) { checks.add(o -> assertStructEquals((MemorySegment) box.get()[prefix.size()], (MemorySegment) o, firstlayout)); } else { checks.add(o -> assertEquals(o, box.get()[prefix.size()])); @@ -143,11 +148,11 @@ static Addressable makeCallback(MemorySession session, Ret ret, List return ABI.upcallStub(mh, func, session); } - static Object passAndSave(Object[] o, AtomicReference ref, int retArg) { + static Object passAndSave(Object[] o, AtomicReference ref, int retArg, List layouts) { for (int i = 0; i < o.length; i++) { - if (o[i] instanceof MemorySegment) { + if (layouts.get(i) instanceof GroupLayout) { MemorySegment ms = (MemorySegment) o[i]; - MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), MemorySession.openImplicit()); + MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), SegmentScope.auto()); copy.copyFrom(ms); o[i] = copy; } diff --git a/test/jdk/java/foreign/TestUpcallException.java b/test/jdk/java/foreign/TestUpcallException.java index c27fde54dc0..d9dc32bacb2 100644 --- a/test/jdk/java/foreign/TestUpcallException.java +++ b/test/jdk/java/foreign/TestUpcallException.java @@ -33,71 +33,26 @@ * TestUpcallException */ -import jdk.test.lib.Utils; +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.io.BufferedReader; import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.nio.file.Paths; -import java.util.List; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotEquals; -import static org.testng.Assert.assertTrue; +public class TestUpcallException extends UpcallTestHelper { -public class TestUpcallException { - - @Test - public void testExceptionInterpreted() throws InterruptedException, IOException { - run(/* useSpec = */ false, /* isVoid = */ true); - run(/* useSpec = */ false, /* isVoid = */ false); - } - - @Test - public void testExceptionSpecialized() throws IOException, InterruptedException { - run(/* useSpec = */ true, /* isVoid = */ true); - run(/* useSpec = */ true, /* isVoid = */ false); - } - - private void run(boolean useSpec, boolean isVoid) throws IOException, InterruptedException { - Process process = new ProcessBuilder() - .command( - Paths.get(Utils.TEST_JDK) - .resolve("bin") - .resolve("java") - .toAbsolutePath() - .toString(), - "--enable-preview", - "--enable-native-access=ALL-UNNAMED", - "-Djava.library.path=" + System.getProperty("java.library.path"), - "-Djdk.internal.foreign.ProgrammableUpcallHandler.USE_SPEC=" + useSpec, - "-cp", Utils.TEST_CLASS_PATH, - "ThrowingUpcall", - isVoid ? "void" : "non-void") - .start(); - - int result = process.waitFor(); - assertNotEquals(result, 0); - - List outLines = linesFromStream(process.getInputStream()); - outLines.forEach(System.out::println); - List errLines = linesFromStream(process.getErrorStream()); - errLines.forEach(System.err::println); - - // Exception message would be found in stack trace - String shouldInclude = "Testing upcall exceptions"; - assertTrue(linesContain(errLines, shouldInclude), "Did not find '" + shouldInclude + "' in stderr"); - } - - private boolean linesContain(List errLines, String shouldInclude) { - return errLines.stream().anyMatch(line -> line.contains(shouldInclude)); + @Test(dataProvider = "cases") + public void testException(boolean useSpec, boolean isVoid) throws InterruptedException, IOException { + runInNewProcess(ThrowingUpcall.class, useSpec, isVoid ? "void" : "") + .assertStdErrContains("Testing upcall exceptions"); } - private static List linesFromStream(InputStream stream) throws IOException { - try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { - return reader.lines().toList(); - } + @DataProvider + public static Object[][] cases() { + return new Object[][]{ + { false, true, }, + { false, false, }, + { true, true, }, + { true, false, } + }; } } diff --git a/test/jdk/java/foreign/TestUpcallHighArity.java b/test/jdk/java/foreign/TestUpcallHighArity.java index f36da3bb948..54e34fa2f9c 100644 --- a/test/jdk/java/foreign/TestUpcallHighArity.java +++ b/test/jdk/java/foreign/TestUpcallHighArity.java @@ -33,16 +33,17 @@ * TestUpcallHighArity */ -import java.lang.foreign.Addressable; -import java.lang.foreign.Linker; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.GroupLayout; +import java.lang.foreign.Linker; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.DataProvider; import org.testng.annotations.Test; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; @@ -76,17 +77,17 @@ public class TestUpcallHighArity extends CallGeneratorHelper { S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER) ); MH_passAndSave = MethodHandles.lookup().findStatic(TestUpcallHighArity.class, "passAndSave", - MethodType.methodType(void.class, Object[].class, AtomicReference.class)); + MethodType.methodType(void.class, Object[].class, AtomicReference.class, List.class)); } catch (ReflectiveOperationException e) { throw new InternalError(e); } } - static void passAndSave(Object[] o, AtomicReference ref) { + static void passAndSave(Object[] o, AtomicReference ref, List layouts) { for (int i = 0; i < o.length; i++) { - if (o[i] instanceof MemorySegment) { + if (layouts.get(i) instanceof GroupLayout) { MemorySegment ms = (MemorySegment) o[i]; - MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), MemorySession.openImplicit()); + MemorySegment copy = MemorySegment.allocateNative(ms.byteSize(), SegmentScope.auto()); copy.copyFrom(ms); o[i] = copy; } @@ -98,11 +99,11 @@ static void passAndSave(Object[] o, AtomicReference ref) { public void testUpcall(MethodHandle downcall, MethodType upcallType, FunctionDescriptor upcallDescriptor) throws Throwable { AtomicReference capturedArgs = new AtomicReference<>(); - MethodHandle target = MethodHandles.insertArguments(MH_passAndSave, 1, capturedArgs) + MethodHandle target = MethodHandles.insertArguments(MH_passAndSave, 1, capturedArgs, upcallDescriptor.argumentLayouts()) .asCollector(Object[].class, upcallType.parameterCount()) .asType(upcallType); - try (MemorySession session = MemorySession.openConfined()) { - Addressable upcallStub = LINKER.upcallStub(target, upcallDescriptor, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment upcallStub = LINKER.upcallStub(target, upcallDescriptor, arena.scope()); Object[] args = new Object[upcallType.parameterCount() + 1]; args[0] = upcallStub; List argLayouts = upcallDescriptor.argumentLayouts(); @@ -114,7 +115,7 @@ public void testUpcall(MethodHandle downcall, MethodType upcallType, Object[] capturedArgsArr = capturedArgs.get(); for (int i = 0; i < capturedArgsArr.length; i++) { - if (upcallType.parameterType(i) == MemorySegment.class) { + if (upcallDescriptor.argumentLayouts().get(i) instanceof GroupLayout) { assertStructEquals((MemorySegment) capturedArgsArr[i], (MemorySegment) args[i + 1], argLayouts.get(i)); } else { assertEquals(capturedArgsArr[i], args[i + 1], "For index " + i); @@ -128,10 +129,10 @@ public static Object[][] args() { return new Object[][]{ { MH_do_upcall, MethodType.methodType(void.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class), + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class), FunctionDescriptor.ofVoid( S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, S_PDI_LAYOUT, C_INT, C_DOUBLE, C_POINTER, diff --git a/test/jdk/java/foreign/TestUpcallScope.java b/test/jdk/java/foreign/TestUpcallScope.java index e5bb77c6af2..f59e9c0d427 100644 --- a/test/jdk/java/foreign/TestUpcallScope.java +++ b/test/jdk/java/foreign/TestUpcallScope.java @@ -32,9 +32,9 @@ * TestUpcallScope */ -import java.lang.foreign.Addressable; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -52,11 +52,10 @@ public class TestUpcallScope extends TestUpcallBase { public void testUpcalls(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow(fName); - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MethodHandle mh = downcallHandle(ABI, addr, allocator, function(ret, paramTypes, fields)); - Object[] args = makeArgs(session, ret, paramTypes, fields, returnChecks, argChecks); + MemorySegment addr = findNativeOrThrow(fName); + try (Arena arena = Arena.openConfined()) { + MethodHandle mh = downcallHandle(ABI, addr, arena, function(ret, paramTypes, fields)); + Object[] args = makeArgs(arena.scope(), ret, paramTypes, fields, returnChecks, argChecks); Object[] callArgs = args; Object res = mh.invokeWithArguments(callArgs); argChecks.forEach(c -> c.accept(args)); diff --git a/test/jdk/java/foreign/TestUpcallStack.java b/test/jdk/java/foreign/TestUpcallStack.java index 9454d77a996..5df32ec2af6 100644 --- a/test/jdk/java/foreign/TestUpcallStack.java +++ b/test/jdk/java/foreign/TestUpcallStack.java @@ -32,10 +32,11 @@ * TestUpcallStack */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; -import java.lang.foreign.SegmentAllocator; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -53,11 +54,10 @@ public class TestUpcallStack extends TestUpcallBase { public void testUpcallsStack(int count, String fName, Ret ret, List paramTypes, List fields) throws Throwable { List> returnChecks = new ArrayList<>(); List> argChecks = new ArrayList<>(); - Addressable addr = findNativeOrThrow("s" + fName); - try (MemorySession session = MemorySession.openConfined()) { - SegmentAllocator allocator = SegmentAllocator.newNativeArena(session); - MethodHandle mh = downcallHandle(ABI, addr, allocator, functionStack(ret, paramTypes, fields)); - Object[] args = makeArgsStack(session, ret, paramTypes, fields, returnChecks, argChecks); + MemorySegment addr = findNativeOrThrow("s" + fName); + try (Arena arena = Arena.openConfined()) { + MethodHandle mh = downcallHandle(ABI, addr, arena, functionStack(ret, paramTypes, fields)); + Object[] args = makeArgsStack(arena.scope(), ret, paramTypes, fields, returnChecks, argChecks); Object[] callArgs = args; Object res = mh.invokeWithArguments(callArgs); argChecks.forEach(c -> c.accept(args)); @@ -71,7 +71,7 @@ static FunctionDescriptor functionStack(Ret ret, List params, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { + static Object[] makeArgsStack(SegmentScope session, Ret ret, List params, List fields, List> checks, List> argChecks) throws ReflectiveOperationException { return makeArgs(session, ret, params, fields, checks, argChecks, STACK_PREFIX_LAYOUTS); } diff --git a/test/jdk/java/foreign/TestUpcallStructScope.java b/test/jdk/java/foreign/TestUpcallStructScope.java index ca2cab17d58..680893cd57f 100644 --- a/test/jdk/java/foreign/TestUpcallStructScope.java +++ b/test/jdk/java/foreign/TestUpcallStructScope.java @@ -37,12 +37,12 @@ * TestUpcallStructScope */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.Test; import java.lang.invoke.MethodHandle; @@ -89,14 +89,14 @@ public void testUpcall() throws Throwable { AtomicReference capturedSegment = new AtomicReference<>(); MethodHandle target = methodHandle(capturedSegment::set); FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(S_PDI_LAYOUT); - try (MemorySession session = MemorySession.openConfined()) { - Addressable upcallStub = LINKER.upcallStub(target, upcallDesc, session); - MemorySegment argSegment = MemorySegment.allocateNative(S_PDI_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment upcallStub = LINKER.upcallStub(target, upcallDesc, arena.scope()); + MemorySegment argSegment = MemorySegment.allocateNative(S_PDI_LAYOUT, arena.scope());; MH_do_upcall.invoke(upcallStub, argSegment); } MemorySegment captured = capturedSegment.get(); - assertFalse(captured.session().isAlive()); + assertFalse(captured.scope().isAlive()); } } diff --git a/test/jdk/java/foreign/TestValueLayouts.java b/test/jdk/java/foreign/TestValueLayouts.java new file mode 100644 index 00000000000..56019f907a8 --- /dev/null +++ b/test/jdk/java/foreign/TestValueLayouts.java @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2019, 2022, 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 + * @enablePreview + * @modules java.base/jdk.internal.misc + * @run testng TestValueLayouts + */ + +import org.testng.annotations.*; + +import java.lang.foreign.*; +import java.nio.ByteOrder; +import jdk.internal.misc.Unsafe; + +import static java.lang.foreign.ValueLayout.*; +import static org.testng.Assert.*; + +public class TestValueLayouts { + + @Test + public void testByte() { + testAligned(JAVA_BYTE, byte.class, Byte.SIZE); + } + + @Test + public void testBoolean() { + testAligned(JAVA_BOOLEAN, boolean.class, Byte.SIZE); + } + + @Test + public void testShort() { + testAligned(JAVA_SHORT, short.class, Short.SIZE); + } + + @Test + public void testShortUnaligned() { + testUnaligned(JAVA_SHORT_UNALIGNED, short.class, Short.SIZE); + } + + @Test + public void testInt() { + testAligned(JAVA_INT, int.class, Integer.SIZE); + } + + @Test + public void testIntUnaligned() { + testUnaligned(JAVA_INT_UNALIGNED, int.class, Integer.SIZE); + } + + @Test + public void testLong() { + testAligned(JAVA_LONG, long.class, Long.SIZE); + } + + @Test + public void testLongUnaligned() { + testUnaligned(JAVA_LONG_UNALIGNED, long.class, Long.SIZE); + } + + @Test + public void testFloat() { + testAligned(JAVA_FLOAT, float.class, Float.SIZE); + } + + @Test + public void testFloatUnaligned() { + testUnaligned(JAVA_FLOAT_UNALIGNED, float.class, Float.SIZE); + } + + @Test + public void testDouble() { + testAligned(JAVA_DOUBLE, double.class, Double.SIZE); + } + + @Test + public void testDoubleUnaligned() { + testUnaligned(JAVA_DOUBLE_UNALIGNED, double.class, Double.SIZE); + } + + @Test + public void testChar() { + testAligned(JAVA_CHAR, char.class, Character.SIZE); + } + + @Test + public void testCharUnaligned() { + testUnaligned(JAVA_CHAR_UNALIGNED, char.class, Character.SIZE); + } + + @Test + public void testAddress() { + testAligned(ADDRESS, MemorySegment.class, Unsafe.ADDRESS_SIZE * 8L); + } + + @Test + public void testAddressUnaligned() { + testUnaligned(ADDRESS_UNALIGNED, MemorySegment.class, Unsafe.ADDRESS_SIZE * 8L); + } + + void testAligned(ValueLayout layout, + Class carrier, + long bitSize) { + test(layout, carrier, bitSize, bitSize); + } + + void testUnaligned(ValueLayout layout, + Class carrier, + long bitSize) { + test(layout, carrier, bitSize, Byte.SIZE); + } + + void test(ValueLayout layout, + Class carrier, + long bitSize, + long bitAlignment) { + assertEquals(layout.carrier(), carrier); + assertEquals(layout.bitSize(), bitSize); + assertEquals(layout.order(), ByteOrder.nativeOrder()); + assertEquals(layout.bitAlignment(), bitAlignment); + assertTrue(layout.name().isEmpty()); + assertEquals(layout.byteSize(), layout.bitSize() / 8); + assertEquals(layout.byteAlignment(), layout.bitAlignment() / 8); + + } + +} diff --git a/test/jdk/java/foreign/TestVarArgs.java b/test/jdk/java/foreign/TestVarArgs.java index bd485bc0c0e..90ad9842d3d 100644 --- a/test/jdk/java/foreign/TestVarArgs.java +++ b/test/jdk/java/foreign/TestVarArgs.java @@ -29,13 +29,11 @@ * @run testng/othervm --enable-native-access=ALL-UNNAMED -Dgenerator.sample.factor=17 TestVarArgs */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import org.testng.annotations.Test; @@ -59,26 +57,26 @@ public class TestVarArgs extends CallGeneratorHelper { System.loadLibrary("VarArgs"); try { MH_CHECK = MethodHandles.lookup().findStatic(TestVarArgs.class, "check", - MethodType.methodType(void.class, int.class, MemoryAddress.class, List.class)); + MethodType.methodType(void.class, int.class, MemorySegment.class, List.class)); } catch (ReflectiveOperationException e) { throw new ExceptionInInitializerError(e); } } - static final Addressable VARARGS_ADDR = findNativeOrThrow("varargs"); + static final MemorySegment VARARGS_ADDR = findNativeOrThrow("varargs"); @Test(dataProvider = "functions") public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff List paramTypes, List fields) throws Throwable { List args = makeArgs(paramTypes, fields); - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { MethodHandle checker = MethodHandles.insertArguments(MH_CHECK, 2, args); - MemorySegment writeBack = LINKER.upcallStub(checker, FunctionDescriptor.ofVoid(C_INT, C_POINTER), session); - MemorySegment callInfo = MemorySegment.allocateNative(CallInfo.LAYOUT, session); - MemorySegment argIDs = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(args.size(), C_INT), session); + MemorySegment writeBack = LINKER.upcallStub(checker, FunctionDescriptor.ofVoid(C_INT, C_POINTER), arena.scope()); + MemorySegment callInfo = MemorySegment.allocateNative(CallInfo.LAYOUT, arena.scope());; + MemorySegment argIDs = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(args.size(), C_INT), arena.scope());; - MemoryAddress callInfoPtr = callInfo.address(); + MemorySegment callInfoPtr = callInfo; CallInfo.writeback(callInfo, writeBack); CallInfo.argIDs(callInfo, argIDs); @@ -91,10 +89,11 @@ public void testVarArgs(int count, String fName, Ret ret, // ignore this stuff argLayouts.add(C_POINTER); // call info argLayouts.add(C_INT); // size - FunctionDescriptor desc = FunctionDescriptor.ofVoid(argLayouts.toArray(MemoryLayout[]::new)) - .asVariadic(args.stream().map(a -> a.layout).toArray(MemoryLayout[]::new)); + FunctionDescriptor baseDesc = FunctionDescriptor.ofVoid(argLayouts.toArray(MemoryLayout[]::new)); + Linker.Option varargIndex = Linker.Option.firstVariadicArg(baseDesc.argumentLayouts().size()); + FunctionDescriptor desc = baseDesc.appendArgumentLayouts(args.stream().map(a -> a.layout).toArray(MemoryLayout[]::new)); - MethodHandle downcallHandle = LINKER.downcallHandle(VARARGS_ADDR, desc); + MethodHandle downcallHandle = LINKER.downcallHandle(VARARGS_ADDR, desc, varargIndex); List argValues = new ArrayList<>(); argValues.add(callInfoPtr); // call info @@ -121,13 +120,13 @@ private static List makeArgs(List paramTypes, List args) { + private static void check(int index, MemorySegment ptr, List args) { Arg varArg = args.get(index); MemoryLayout layout = varArg.layout; MethodHandle getter = varArg.getter; List> checks = varArg.checks; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.ofAddress(ptr, layout.byteSize(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = MemorySegment.ofAddress(ptr.address(), layout.byteSize(), arena.scope()); Object obj = getter.invoke(seg); checks.forEach(check -> check.accept(obj)); } catch (Throwable e) { @@ -143,11 +142,11 @@ private static class CallInfo { static final VarHandle VH_writeback = LAYOUT.varHandle(groupElement("writeback")); static final VarHandle VH_argIDs = LAYOUT.varHandle(groupElement("argIDs")); - static void writeback(MemorySegment seg, Addressable addr) { - VH_writeback.set(seg, addr.address()); + static void writeback(MemorySegment seg, MemorySegment addr) { + VH_writeback.set(seg, addr); } - static void argIDs(MemorySegment seg, Addressable addr) { - VH_argIDs.set(seg, addr.address()); + static void argIDs(MemorySegment seg, MemorySegment addr) { + VH_argIDs.set(seg, addr); } } diff --git a/test/jdk/java/foreign/TestVarHandleCombinators.java b/test/jdk/java/foreign/TestVarHandleCombinators.java index e09d6292098..28b05d02d62 100644 --- a/test/jdk/java/foreign/TestVarHandleCombinators.java +++ b/test/jdk/java/foreign/TestVarHandleCombinators.java @@ -28,7 +28,8 @@ * @run testng TestVarHandleCombinators */ -import java.lang.foreign.MemorySession; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import org.testng.annotations.Test; @@ -65,7 +66,7 @@ public void testUnalignedElement() { public void testAlign() { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_BYTE.withBitAlignment(16)); - MemorySegment segment = MemorySegment.allocateNative(1, 2, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(1L, 2, SegmentScope.auto()); vh.set(segment, 0L, (byte) 10); // fine, memory region is aligned assertEquals((byte) vh.get(segment, 0L), (byte) 10); } @@ -101,8 +102,8 @@ public void testNestedSequenceAccess() { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(ValueLayout.JAVA_INT.withBitAlignment(32)); int count = 0; - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(inner_size * outer_size * 8, 4, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = MemorySegment.allocateNative(inner_size * outer_size * 8, 4, arena.scope());; for (long i = 0; i < outer_size; i++) { for (long j = 0; j < inner_size; j++) { vh.set(segment, i * 40 + j * 8, count); diff --git a/test/jdk/java/foreign/ThrowingUpcall.java b/test/jdk/java/foreign/ThrowingUpcall.java index 40ea4e51a70..70d2aba66ec 100644 --- a/test/jdk/java/foreign/ThrowingUpcall.java +++ b/test/jdk/java/foreign/ThrowingUpcall.java @@ -21,10 +21,10 @@ * questions. */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; @@ -72,8 +72,8 @@ public static void testVoid() throws Throwable { MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(void.class)); handle = MethodHandles.insertArguments(invoker, 0, handle); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.ofVoid(), arena.scope()); downcallVoid.invoke(stub); // should call Shutdown.exit(1); } @@ -85,8 +85,8 @@ public static void testNonVoid() throws Throwable { MethodHandle invoker = MethodHandles.exactInvoker(MethodType.methodType(int.class, int.class)); handle = MethodHandles.insertArguments(invoker, 0, handle); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.of(C_INT, C_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = Linker.nativeLinker().upcallStub(handle, FunctionDescriptor.of(C_INT, C_INT), arena.scope()); downcallNonVoid.invoke(42, stub); // should call Shutdown.exit(1); } diff --git a/test/jdk/java/foreign/UpcallTestHelper.java b/test/jdk/java/foreign/UpcallTestHelper.java new file mode 100644 index 00000000000..fa4ff862d51 --- /dev/null +++ b/test/jdk/java/foreign/UpcallTestHelper.java @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2022, 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. + */ + +import jdk.test.lib.Utils; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.testng.Assert.assertNotEquals; +import static org.testng.Assert.assertTrue; + +public class UpcallTestHelper extends NativeTestHelper { + public record Output(List stdout, List stderr) { + private static void assertContains(List lines, String shouldInclude) { + assertTrue(lines.stream().anyMatch(line -> line.contains(shouldInclude)), + "Did not find '" + shouldInclude + "' in stderr"); + } + + public void assertStdErrContains(String shouldInclude) { + assertContains(stderr, shouldInclude); + } + } + + public Output runInNewProcess(Class target, boolean useSpec, String... programArgs) throws IOException, InterruptedException { + assert !target.isArray(); + + List command = new ArrayList<>(List.of( + Paths.get(Utils.TEST_JDK) + .resolve("bin") + .resolve("java") + .toAbsolutePath() + .toString(), + "--enable-preview", + "--enable-native-access=ALL-UNNAMED", + "-Djava.library.path=" + System.getProperty("java.library.path"), + "-Djdk.internal.foreign.ProgrammableUpcallHandler.USE_SPEC=" + useSpec, + "-cp", Utils.TEST_CLASS_PATH, + target.getName() + )); + command.addAll(Arrays.asList(programArgs)); + Process process = new ProcessBuilder() + .command(command) + .start(); + + int result = process.waitFor(); + assertNotEquals(result, 0); + + List outLines = linesFromStream(process.getInputStream()); + outLines.forEach(System.out::println); + List errLines = linesFromStream(process.getErrorStream()); + errLines.forEach(System.err::println); + + return new Output(outLines, errLines); + } + + private static List linesFromStream(InputStream stream) throws IOException { + try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { + return reader.lines().toList(); + } + } +} diff --git a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java index a2c49e50432..c4c8670e8bd 100644 --- a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java @@ -32,23 +32,24 @@ * @run testng TestAarch64CallArranger */ -import java.lang.foreign.Addressable; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.aarch64.CallArranger; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.invoke.MethodType; +import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.AArch64.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; + import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @@ -61,13 +62,13 @@ public void testEmpty() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) } + { unboxAddress(), vmStore(r9, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -85,13 +86,13 @@ public void testInteger() { C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(r2, int.class) }, @@ -115,13 +116,13 @@ public void testTwoIntTwoFloat() { C_INT, C_INT, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -137,13 +138,13 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, expectedBindings }); @@ -165,7 +166,7 @@ public static Object[][] structs() { // struct s { int32_t a, b; double c; int32_t d }; { struct2, new Binding[] { copy(struct2), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r0, long.class) }}, // struct s { int32_t a[2]; float b[2] }; @@ -197,21 +198,21 @@ public void testMultipleStructs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct1, struct2, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { copy(struct1), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r0, long.class) }, { copy(struct2), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r1, long.class) }, { vmStore(r2, int.class) } @@ -228,13 +229,13 @@ public void testReturnStruct1() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class)); + assertTrue(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { unboxAddress(), vmStore(r8, long.class) @@ -252,14 +253,14 @@ public void testReturnStruct2() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r10, long.class) }, - { unboxAddress(Addressable.class), vmStore(r9, long.class) } + { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r9, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{ @@ -281,14 +282,14 @@ public void testStructHFA1() { FunctionDescriptor fd = FunctionDescriptor.of(hfa, C_FLOAT, C_INT, hfa); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r10, long.class) }, - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { vmStore(v0, float.class) }, { vmStore(r0, int.class) }, { @@ -319,13 +320,13 @@ public void testStructHFA3() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct, struct, struct); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { dup(), bufferLoad(0, float.class), @@ -373,22 +374,22 @@ public void testStructStackSpill() { struct, struct, C_INT, C_INT, C_INT, C_INT, C_INT, C_INT, struct, C_INT); CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(r0, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(r1, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, + { copy(struct), unboxAddress(), vmStore(r0, long.class) }, + { copy(struct), unboxAddress(), vmStore(r1, long.class) }, { vmStore(r2, int.class) }, { vmStore(r3, int.class) }, { vmStore(r4, int.class) }, { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(0), long.class) }, { vmStore(stackStorage(1), int.class) }, }); @@ -398,18 +399,18 @@ public void testStructStackSpill() { @Test public void testVarArgsInRegs() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); - FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(1))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -421,18 +422,18 @@ public void testVarArgsInRegs() { @Test public void testVarArgsOnStack() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); - FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_FLOAT); + FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(1))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); // The two variadic arguments should be allocated on the stack checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(r9, long.class) }, { vmStore(r0, int.class) }, { vmStore(stackStorage(0), int.class) }, { vmStore(stackStorage(1), float.class) }, diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index 1e8da4fd456..01066b550ae 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -34,7 +34,6 @@ */ import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; @@ -43,13 +42,13 @@ import org.testng.annotations.DataProvider; import org.testng.annotations.Test; -import java.lang.foreign.Addressable; import java.lang.invoke.MethodType; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.SysV.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; + import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertTrue; @@ -62,19 +61,19 @@ public void testEmpty() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rax, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -90,13 +89,13 @@ public void testNestedStructs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, int.class), vmStore(rsi, int.class)}, { vmStore(rax, long.class) }, @@ -104,7 +103,7 @@ public void testNestedStructs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -121,13 +120,13 @@ public void testNestedUnion() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, long.class), vmStore(rsi, long.class)}, { vmStore(rax, long.class) }, @@ -135,7 +134,7 @@ public void testNestedUnion() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -151,13 +150,13 @@ public void testNestedStructsUnaligned() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), bufferLoad(8, long.class), vmStore(stackStorage(1), long.class)}, { vmStore(rax, long.class) }, @@ -165,7 +164,7 @@ public void testNestedStructsUnaligned() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -181,13 +180,13 @@ public void testNestedUnionUnaligned() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(POINT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), bufferLoad(8, int.class), vmStore(stackStorage(1), int.class)}, { vmStore(rax, long.class) }, @@ -195,7 +194,7 @@ public void testNestedUnionUnaligned() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -206,13 +205,13 @@ public void testIntegerRegs() { C_INT, C_INT, C_INT, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { vmStore(rdx, int.class) }, @@ -224,7 +223,7 @@ public void testIntegerRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -237,13 +236,13 @@ public void testDoubleRegs() { C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -257,7 +256,7 @@ public void testDoubleRegs() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 8); + assertEquals(bindings.nVectorArgs(), 8); } @Test @@ -272,13 +271,13 @@ public void testMixed() { C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rdi, long.class) }, { vmStore(rsi, long.class) }, { vmStore(rdx, long.class) }, @@ -302,7 +301,7 @@ public void testMixed() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 8); + assertEquals(bindings.nVectorArgs(), 8); } /** @@ -329,13 +328,13 @@ public void testAbiExample() { C_INT, C_INT, struct, C_INT, C_INT, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { @@ -355,7 +354,7 @@ public void testAbiExample() { checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 3); + assertEquals(bindings.nVectorArgs(), 3); } /** @@ -368,24 +367,24 @@ public void testAbiExample() { */ @Test public void testMemoryAddress() { - MethodType mt = MethodType.methodType(void.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test(dataProvider = "structs") @@ -394,20 +393,20 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, expectedBindings, { vmStore(rax, long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @@ -453,14 +452,14 @@ public void testReturnRegisterStruct() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.appendParameterTypes(long.class).insertParameterTypes(0, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(MemorySegment.class), vmStore(r11, long.class) }, - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r11, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rax, long.class) } }); @@ -474,7 +473,7 @@ public void testReturnRegisterStruct() { bufferStore(8, long.class) }); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -485,20 +484,20 @@ public void testIMR() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class, long.class)); + assertTrue(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class, long.class)); assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) } }); checkReturnBindings(callingSequence, new Binding[] {}); - assertEquals(bindings.nVectorArgs, 0); + assertEquals(bindings.nVectorArgs(), 0); } @Test @@ -509,8 +508,8 @@ public void testFloatStructsUpcall() { FunctionDescriptor fd = FunctionDescriptor.of(struct, struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, true); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); assertEquals(callingSequence.calleeMethodType(), mt); assertEquals(callingSequence.functionDesc(), fd); @@ -522,7 +521,7 @@ public void testFloatStructsUpcall() { bufferLoad(0, float.class), vmStore(xmm0, float.class) }); - assertEquals(bindings.nVectorArgs, 1); + assertEquals(bindings.nVectorArgs(), 1); } } diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index 0c72d950709..2deedfa10e6 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -34,22 +34,23 @@ */ import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.Addressable; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.x64.windows.CallArranger; import org.testng.annotations.Test; import java.lang.invoke.MethodType; +import static java.lang.foreign.Linker.Option.firstVariadicArg; import static java.lang.foreign.ValueLayout.ADDRESS; import static jdk.internal.foreign.PlatformLayouts.Win64.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.Binding.copy; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; + import static org.testng.Assert.*; public class TestWindowsCallArranger extends CallArrangerTestBase { @@ -60,13 +61,13 @@ public void testEmpty() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) } + { unboxAddress(), vmStore(r10, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); } @@ -77,13 +78,13 @@ public void testIntegerRegs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { vmStore(r8, int.class) }, @@ -99,13 +100,13 @@ public void testDoubleRegs() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -123,13 +124,13 @@ public void testMixed() { C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT, C_LONG_LONG, C_LONG_LONG, C_FLOAT, C_FLOAT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rcx, long.class) }, { vmStore(rdx, long.class) }, { vmStore(xmm2, float.class) }, @@ -154,18 +155,18 @@ public void testAbiExample() { C_DOUBLE, C_DOUBLE, C_DOUBLE, C_INT, C_INT, C_INT); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { copy(structLayout), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(r8, long.class) }, { vmStore(r9, int.class) }, @@ -186,18 +187,18 @@ public void testAbiExampleVarargs() { MethodType mt = MethodType.methodType(void.class, int.class, double.class, int.class, double.class, double.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( - C_INT, C_DOUBLE).asVariadic(C_INT, C_DOUBLE, C_DOUBLE); + C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid( ADDRESS, C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); + CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(2))); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fdExpected); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { vmStore(rcx, int.class) }, { vmStore(xmm1, double.class) }, { vmStore(r8, int.class) }, @@ -225,13 +226,13 @@ public void testStructRegister() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { bufferLoad(0, long.class), vmStore(rcx, long.class) } }); @@ -255,16 +256,16 @@ public void testStructReference() { FunctionDescriptor fd = FunctionDescriptor.ofVoid(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { copy(struct), - unboxAddress(MemorySegment.class), + unboxAddress(), vmStore(rcx, long.class) } }); @@ -282,17 +283,17 @@ public void testStructReference() { */ @Test public void testMemoryAddress() { - MethodType mt = MethodType.methodType(void.class, MemoryAddress.class); + MethodType mt = MethodType.methodType(void.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -307,13 +308,13 @@ public void testReturnRegisterStruct() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, }); checkReturnBindings(callingSequence, @@ -331,13 +332,13 @@ public void testIMR() { FunctionDescriptor fd = FunctionDescriptor.of(struct); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertTrue(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, Addressable.class, MemoryAddress.class)); + assertTrue(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), MethodType.methodType(void.class, MemorySegment.class, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -349,10 +350,10 @@ public void testStackStruct() { MemoryLayout struct = MemoryLayout.structLayout(C_POINTER, C_DOUBLE, C_INT); MethodType mt = MethodType.methodType(void.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class, - MemorySegment.class, int.class, double.class, MemoryAddress.class); + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class, + MemorySegment.class, int.class, double.class, MemorySegment.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid( struct, C_INT, C_DOUBLE, C_POINTER, struct, C_INT, C_DOUBLE, C_POINTER, @@ -360,26 +361,26 @@ public void testStackStruct() { struct, C_INT, C_DOUBLE, C_POINTER); CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false); - assertFalse(bindings.isInMemoryReturn); - CallingSequence callingSequence = bindings.callingSequence; - assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, Addressable.class)); + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(Addressable.class), vmStore(r10, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(rcx, long.class) }, + { unboxAddress(), vmStore(r10, long.class) }, + { copy(struct), unboxAddress(), vmStore(rcx, long.class) }, { vmStore(rdx, int.class) }, { vmStore(xmm2, double.class) }, { unboxAddress(), vmStore(r9, long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(0), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(0), long.class) }, { vmStore(stackStorage(1), int.class) }, { vmStore(stackStorage(2), double.class) }, { unboxAddress(), vmStore(stackStorage(3), long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(4), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(4), long.class) }, { vmStore(stackStorage(5), int.class) }, { vmStore(stackStorage(6), double.class) }, { unboxAddress(), vmStore(stackStorage(7), long.class) }, - { copy(struct), unboxAddress(MemorySegment.class), vmStore(stackStorage(8), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(8), long.class) }, { vmStore(stackStorage(9), int.class) }, { vmStore(stackStorage(10), double.class) }, { unboxAddress(), vmStore(stackStorage(11), long.class) }, diff --git a/test/jdk/java/foreign/channels/AbstractChannelsTest.java b/test/jdk/java/foreign/channels/AbstractChannelsTest.java index 1fae62d353e..d3c96bba986 100644 --- a/test/jdk/java/foreign/channels/AbstractChannelsTest.java +++ b/test/jdk/java/foreign/channels/AbstractChannelsTest.java @@ -22,8 +22,9 @@ */ import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Random; @@ -51,11 +52,6 @@ interface ThrowingConsumer { void accept(T action) throws X; } - static MemorySession closeableSessionOrNull(MemorySession session) { - return (session.isCloseable()) ? - session : null; - } - static long remaining(ByteBuffer[] buffers) { return Arrays.stream(buffers).mapToLong(ByteBuffer::remaining).sum(); } @@ -72,7 +68,7 @@ static ByteBuffer[] clear(ByteBuffer[] buffers) { static final Random RANDOM = RandomFactory.getRandom(); - static ByteBuffer segmentBufferOfSize(MemorySession session, int size) { + static ByteBuffer segmentBufferOfSize(SegmentScope session, int size) { var segment = MemorySegment.allocateNative(size, 1, session); for (int i = 0; i < size; i++) { segment.set(JAVA_BYTE, i, ((byte)RANDOM.nextInt())); @@ -80,7 +76,7 @@ static ByteBuffer segmentBufferOfSize(MemorySession session, int size) { return segment.asByteBuffer(); } - static ByteBuffer[] segmentBuffersOfSize(int len, MemorySession session, int size) { + static ByteBuffer[] segmentBuffersOfSize(int len, SegmentScope session, int size) { ByteBuffer[] bufs = new ByteBuffer[len]; for (int i = 0; i < len; i++) bufs[i] = segmentBufferOfSize(session, size); @@ -92,7 +88,7 @@ static ByteBuffer[] segmentBuffersOfSize(int len, MemorySession session, int siz * where heap can be from the global session or session-less, and direct are * associated with the given session. */ - static ByteBuffer[] mixedBuffersOfSize(int len, MemorySession session, int size) { + static ByteBuffer[] mixedBuffersOfSize(int len, SegmentScope session, int size) { ByteBuffer[] bufs; boolean atLeastOneSessionBuffer = false; do { @@ -125,75 +121,50 @@ static void assertCauses(Throwable ex, Class... exceptions) } } - @DataProvider(name = "confinedSessions") - public static Object[][] confinedSessions() { + @DataProvider(name = "confinedArenas") + public static Object[][] confinedArenas() { return new Object[][] { - { SessionSupplier.NEW_CONFINED }, + { ArenaSupplier.NEW_CONFINED }, }; } - @DataProvider(name = "sharedSessions") - public static Object[][] sharedSessions() { - return new Object[][] { - { SessionSupplier.NEW_SHARED }, - }; - } - - @DataProvider(name = "closeableSessions") - public static Object[][] closeableSessions() { - return Stream.of(sharedSessions(), confinedSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - @DataProvider(name = "implicitSessions") - public static Object[][] implicitSessions() { + @DataProvider(name = "sharedArenas") + public static Object[][] sharedArenas() { return new Object[][] { - { SessionSupplier.GLOBAL }, + { ArenaSupplier.NEW_SHARED }, }; } - @DataProvider(name = "sharedAndImplicitSessions") - public static Object[][] sharedAndImplicitSessions() { - return Stream.of(sharedSessions(), implicitSessions()) - .flatMap(Arrays::stream) - .toArray(Object[][]::new); - } - - @DataProvider(name = "allSessions") - public static Object[][] allSessions() { - return Stream.of(implicitSessions(), closeableSessions()) + @DataProvider(name = "closeableArenas") + public static Object[][] closeableArenas() { + return Stream.of(sharedArenas(), confinedArenas()) .flatMap(Arrays::stream) .toArray(Object[][]::new); } - @DataProvider(name = "sharedSessionsAndTimeouts") - public static Object[][] sharedSessionsAndTimeouts() { + @DataProvider(name = "sharedArenasAndTimeouts") + public static Object[][] sharedArenasAndTimeouts() { return new Object[][] { - { SessionSupplier.NEW_SHARED , 0 }, - { SessionSupplier.NEW_SHARED , 30 }, + { ArenaSupplier.NEW_SHARED , 0 }, + { ArenaSupplier.NEW_SHARED , 30 }, }; } - static class SessionSupplier implements Supplier { + static class ArenaSupplier implements Supplier { - static final Supplier NEW_CONFINED = - new SessionSupplier(MemorySession::openConfined, "newConfinedSession()"); - static final Supplier NEW_SHARED = - new SessionSupplier(MemorySession::openShared, "newSharedSession()"); - static final Supplier NEW_IMPLICIT = - new SessionSupplier(MemorySession::openImplicit, "newImplicitSession()"); - static final Supplier GLOBAL = - new SessionSupplier(MemorySession::global, "globalSession()"); + static final Supplier NEW_CONFINED = + new ArenaSupplier(Arena::openConfined, "confined arena"); + static final Supplier NEW_SHARED = + new ArenaSupplier(Arena::openShared, "shared arena"); - private final Supplier supplier; + private final Supplier supplier; private final String str; - private SessionSupplier(Supplier supplier, String str) { + private ArenaSupplier(Supplier supplier, String str) { this.supplier = supplier; this.str = str; } @Override public String toString() { return str; } - @Override public MemorySession get() { return supplier.get(); } + @Override public Arena get() { return supplier.get(); } } } diff --git a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java index 9278c7748a7..3091514cc58 100644 --- a/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestAsyncSocketChannels.java @@ -33,8 +33,8 @@ */ import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.StandardSocketOptions; @@ -67,15 +67,15 @@ public class TestAsyncSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; /** Tests that confined sessions are not supported. */ - @Test(dataProvider = "confinedSessions") - public void testWithConfined(Supplier sessionSupplier) + @Test(dataProvider = "confinedArenas") + public void testWithConfined(Supplier arenaSupplier) throws Throwable { try (var channel = AsynchronousSocketChannel.open(); var server = AsynchronousServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); var bb = segment.asByteBuffer(); var bba = new ByteBuffer[] { bb }; List> ioOps = List.of( @@ -100,17 +100,17 @@ public void testWithConfined(Supplier sessionSupplier) } /** Tests that I/O with a closed session throws a suitable exception. */ - @Test(dataProvider = "sharedSessionsAndTimeouts") - public void testIOWithClosedSharedSession(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testIOWithClosedSharedSession(Supplier arenaSupplier, int timeout) throws Exception { try (var channel = AsynchronousSocketChannel.open(); var server = AsynchronousServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = sessionSupplier.get(); - ByteBuffer bb = segmentBufferOfSize(session, 64); - ByteBuffer[] buffers = segmentBuffersOfSize(8, session, 32); - ((MemorySession)session).close(); + Arena drop = arenaSupplier.get(); + ByteBuffer bb = segmentBufferOfSize(drop.scope(), 64); + ByteBuffer[] buffers = segmentBuffersOfSize(8, drop.scope(), 32); + drop.close(); { assertCauses(expectThrows(EE, () -> connectedChannel.read(bb).get()), IOE, ISE); } @@ -151,17 +151,17 @@ public void testIOWithClosedSharedSession(Supplier sessionSupplie } /** Tests basic I/O operations work with views over implicit and shared sessions. */ - @Test(dataProvider = "sharedAndImplicitSessions") - public void testBasicIOWithSupportedSession(Supplier sessionSupplier) + @Test(dataProvider = "sharedArenas") + public void testBasicIOWithSupportedSession(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment1 = MemorySegment.allocateNative(10, 1, session); - MemorySegment segment2 = MemorySegment.allocateNative(10, 1, session); + var scp = drop = arenaSupplier.get()) { + MemorySegment segment1 = MemorySegment.allocateNative(10, 1, drop.scope()); + MemorySegment segment2 = MemorySegment.allocateNative(10, 1, drop.scope()); for (int i = 0; i < 10; i++) { segment1.set(JAVA_BYTE, i, (byte) i); } @@ -184,8 +184,8 @@ public void testBasicIOWithSupportedSession(Supplier sessionSuppl assertEquals(bb2.flip(), ByteBuffer.wrap(new byte[]{0, 1, 2, 3, 4, 5, 6, 7, 8, 9})); } { // Gathering/Scattering variants - var writeBuffers = mixedBuffersOfSize(16, session, 32); - var readBuffers = mixedBuffersOfSize(16, session, 32); + var writeBuffers = mixedBuffersOfSize(16, drop.scope(), 32); + var readBuffers = mixedBuffersOfSize(16, drop.scope(), 32); long expectedCount = remaining(writeBuffers); var writeHandler = new TestHandler(); asc1.write(writeBuffers, 0, 16, 30L, SECONDS, null, writeHandler); @@ -199,15 +199,15 @@ public void testBasicIOWithSupportedSession(Supplier sessionSuppl } /** Tests that a session is not closeable when there is an outstanding read operation. */ - @Test(dataProvider = "sharedSessionsAndTimeouts") - public void testCloseWithOutstandingRead(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testCloseWithOutstandingRead(Supplier arenaSupplier, int timeout) throws Throwable { try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); var bb = segment.asByteBuffer(); var bba = new ByteBuffer[] { bb }; List> readOps = List.of( @@ -221,28 +221,28 @@ public void testCloseWithOutstandingRead(Supplier sessionSupplier var handler = new TestHandler(); ioOp.accept(handler); assertFalse(handler.isDone()); - assertTrue(session.isAlive()); - assertMessage(expectThrows(ISE, () -> session.close()), "Session is acquired by"); + assertTrue(drop.scope().isAlive()); + assertMessage(expectThrows(ISE, () -> drop.close()), "Session is acquired by"); // write to allow the blocking read complete, which will // in turn unlock the session and allow it to be closed. asc2.write(ByteBuffer.wrap(new byte[] { 0x01 })).get(); handler.await().assertCompleteWith(1L); - assertTrue(session.isAlive()); + assertTrue(drop.scope().isAlive()); } } } /** Tests that a session is not closeable when there is an outstanding write operation. */ // Note: limited scenarios are checked, given the 5 sec sleep! - @Test(dataProvider = "sharedSessionsAndTimeouts") - public void testCloseWithOutstandingWrite(Supplier sessionSupplier, int timeout) + @Test(dataProvider = "sharedArenasAndTimeouts") + public void testCloseWithOutstandingWrite(Supplier arenaSupplier, int timeout) throws Throwable { try (var asc1 = AsynchronousSocketChannel.open(); var assc = AsynchronousServerSocketChannel.open(); var asc2 = connectChannels(assc, asc1); - var session = closeableSessionOrNull(sessionSupplier.get())) { + var drop = arenaSupplier.get()) { // number of bytes written final AtomicLong bytesWritten = new AtomicLong(0); @@ -252,7 +252,7 @@ public void testCloseWithOutstandingWrite(Supplier sessionSupplie // write until socket buffer is full so as to create the conditions // for when a write does not complete immediately - var bba = segmentBuffersOfSize(32, session, 128); + var bba = segmentBuffersOfSize(32, drop.scope(), 128); TestHandler handler; outstandingWriteOps.getAndIncrement(); asc1.write(bba, 0, bba.length, timeout, SECONDS, null, @@ -261,7 +261,7 @@ public void completed(Long result, Void att) { super.completed(result, att); bytesWritten.addAndGet(result); if (continueWriting.get()) { - var bba = segmentBuffersOfSize(32, session, 128); + var bba = segmentBuffersOfSize(32, drop.scope(), 128); outstandingWriteOps.getAndIncrement(); asc1.write(bba, 0, bba.length, timeout, SECONDS, null, this); } @@ -271,8 +271,8 @@ public void completed(Long result, Void att) { // give time for socket buffer to fill up. awaitNoFurtherWrites(bytesWritten); - assertMessage(expectThrows(ISE, () -> session.close()), "Session is acquired by"); - assertTrue(session.isAlive()); + assertMessage(expectThrows(ISE, () -> drop.close()), "Session is acquired by"); + assertTrue(drop.scope().isAlive()); // signal handler to stop further writing continueWriting.set(false); @@ -280,7 +280,7 @@ public void completed(Long result, Void att) { // read to allow the outstanding write complete, which will // in turn unlock the session and allow it to be closed. readNBytes(asc2, bytesWritten.get()); - assertTrue(session.isAlive()); + assertTrue(drop.scope().isAlive()); awaitOutstandingWrites(outstandingWriteOps); handler.await(); } diff --git a/test/jdk/java/foreign/channels/TestSocketChannels.java b/test/jdk/java/foreign/channels/TestSocketChannels.java index 4b4aa91c886..98cc84e0bf7 100644 --- a/test/jdk/java/foreign/channels/TestSocketChannels.java +++ b/test/jdk/java/foreign/channels/TestSocketChannels.java @@ -30,6 +30,7 @@ * @run testng/othervm TestSocketChannels */ +import java.lang.foreign.Arena; import java.net.InetAddress; import java.net.InetSocketAddress; import java.nio.ByteBuffer; @@ -42,7 +43,7 @@ import java.util.stream.Stream; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.testng.annotations.*; import static java.lang.foreign.ValueLayout.JAVA_BYTE; @@ -56,16 +57,16 @@ public class TestSocketChannels extends AbstractChannelsTest { static final Class ISE = IllegalStateException.class; static final Class WTE = WrongThreadException.class; - @Test(dataProvider = "closeableSessions") - public void testBasicIOWithClosedSegment(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIOWithClosedSegment(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = sessionSupplier.get(); - ByteBuffer bb = segmentBufferOfSize(session, 16); - ((MemorySession)session).close(); + Arena drop = arenaSupplier.get(); + ByteBuffer bb = segmentBufferOfSize(drop.scope(), 16); + drop.close(); assertMessage(expectThrows(ISE, () -> channel.read(bb)), "Already closed"); assertMessage(expectThrows(ISE, () -> channel.read(new ByteBuffer[] {bb})), "Already closed"); assertMessage(expectThrows(ISE, () -> channel.read(new ByteBuffer[] {bb}, 0, 1)), "Already closed"); @@ -75,16 +76,16 @@ public void testBasicIOWithClosedSegment(Supplier sessionSupplier } } - @Test(dataProvider = "closeableSessions") - public void testScatterGatherWithClosedSegment(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testScatterGatherWithClosedSegment(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connectedChannel = connectChannels(server, channel)) { - MemorySession session = (MemorySession)sessionSupplier.get(); - ByteBuffer[] buffers = segmentBuffersOfSize(8, session, 16); - session.close(); + Arena drop = arenaSupplier.get(); + ByteBuffer[] buffers = segmentBuffersOfSize(8, drop.scope(), 16); + drop.close(); assertMessage(expectThrows(ISE, () -> channel.write(buffers)), "Already closed"); assertMessage(expectThrows(ISE, () -> channel.read(buffers)), "Already closed"); assertMessage(expectThrows(ISE, () -> channel.write(buffers, 0 ,8)), "Already closed"); @@ -92,17 +93,17 @@ public void testScatterGatherWithClosedSegment(Supplier sessionSu } } - @Test(dataProvider = "allSessions") - public void testBasicIO(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIO(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - MemorySegment segment1 = MemorySegment.allocateNative(10, 1, session); - MemorySegment segment2 = MemorySegment.allocateNative(10, 1, session); + var scp = drop = arenaSupplier.get()) { + MemorySegment segment1 = MemorySegment.allocateNative(10, 1, drop.scope()); + MemorySegment segment2 = MemorySegment.allocateNative(10, 1, drop.scope()); for (int i = 0; i < 10; i++) { segment1.set(JAVA_BYTE, i, (byte) i); } @@ -132,15 +133,15 @@ public void testBasicHeapIOWithGlobalSession() throws Exception { } } - @Test(dataProvider = "confinedSessions") - public void testIOOnConfinedFromAnotherThread(Supplier sessionSupplier) + @Test(dataProvider = "confinedArenas") + public void testIOOnConfinedFromAnotherThread(Supplier arenaSupplier) throws Exception { try (var channel = SocketChannel.open(); var server = ServerSocketChannel.open(); var connected = connectChannels(server, channel); - var session = closeableSessionOrNull(sessionSupplier.get())) { - var segment = MemorySegment.allocateNative(10, 1, session); + var drop = arenaSupplier.get()) { + var segment = MemorySegment.allocateNative(10, 1, drop.scope()); ByteBuffer bb = segment.asByteBuffer(); List ioOps = List.of( () -> channel.write(bb), @@ -161,17 +162,17 @@ public void testIOOnConfinedFromAnotherThread(Supplier sessionSup } } - @Test(dataProvider = "allSessions") - public void testScatterGatherIO(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testScatterGatherIO(Supplier arenaSupplier) throws Exception { - MemorySession session; + Arena drop; try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var scp = closeableSessionOrNull(session = sessionSupplier.get())) { - var writeBuffers = mixedBuffersOfSize(32, session, 64); - var readBuffers = mixedBuffersOfSize(32, session, 64); + var scp = drop = arenaSupplier.get()) { + var writeBuffers = mixedBuffersOfSize(32, drop.scope(), 64); + var readBuffers = mixedBuffersOfSize(32, drop.scope(), 64); long expectedCount = remaining(writeBuffers); assertEquals(writeNBytes(sc1, writeBuffers, 0, 32, expectedCount), expectedCount); assertEquals(readNBytes(sc2, readBuffers, 0, 32, expectedCount), expectedCount); @@ -179,19 +180,19 @@ public void testScatterGatherIO(Supplier sessionSupplier) } } - @Test(dataProvider = "closeableSessions") - public void testBasicIOWithDifferentSessions(Supplier sessionSupplier) + @Test(dataProvider = "closeableArenas") + public void testBasicIOWithDifferentSessions(Supplier arenaSupplier) throws Exception { try (var sc1 = SocketChannel.open(); var ssc = ServerSocketChannel.open(); var sc2 = connectChannels(ssc, sc1); - var session1 = closeableSessionOrNull(sessionSupplier.get()); - var session2 = closeableSessionOrNull(sessionSupplier.get())) { - var writeBuffers = Stream.of(mixedBuffersOfSize(16, session1, 64), mixedBuffersOfSize(16, session2, 64)) + var drop1 = arenaSupplier.get(); + var drop2 = arenaSupplier.get()) { + var writeBuffers = Stream.of(mixedBuffersOfSize(16, drop1.scope(), 64), mixedBuffersOfSize(16, drop2.scope(), 64)) .flatMap(Arrays::stream) .toArray(ByteBuffer[]::new); - var readBuffers = Stream.of(mixedBuffersOfSize(16, session1, 64), mixedBuffersOfSize(16, session2, 64)) + var readBuffers = Stream.of(mixedBuffersOfSize(16, drop1.scope(), 64), mixedBuffersOfSize(16, drop2.scope(), 64)) .flatMap(Arrays::stream) .toArray(ByteBuffer[]::new); diff --git a/test/jdk/java/foreign/dontrelease/TestDontRelease.java b/test/jdk/java/foreign/dontrelease/TestDontRelease.java new file mode 100644 index 00000000000..1d8ca974c90 --- /dev/null +++ b/test/jdk/java/foreign/dontrelease/TestDontRelease.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestDontRelease + */ + +import org.testng.annotations.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static org.testng.Assert.assertTrue; + +public class TestDontRelease extends NativeTestHelper { + + static { + System.loadLibrary("DontRelease"); + } + + @Test + public void testDontRelease() { + MethodHandle handle = downcallHandle("test_ptr", FunctionDescriptor.ofVoid(ADDRESS)); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(JAVA_INT); + arena.scope().whileAlive(() -> { + Thread t = new Thread(() -> { + try { + // acquire of the segment should fail here, + // due to wrong thread + handle.invokeExact(segment); + } catch (Throwable e) { + // catch the exception. + assertTrue(e instanceof WrongThreadException); + assertTrue(e.getMessage().matches(".*Attempted access outside owning thread.*")); + } + }); + t.start(); + try { + t.join(); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + + // the downcall above should not have called release on the session + // so doing it here should succeed without error + }); + } + } +} + diff --git a/test/jdk/java/foreign/dontrelease/libDontRelease.c b/test/jdk/java/foreign/dontrelease/libDontRelease.c new file mode 100644 index 00000000000..c7a8f743083 --- /dev/null +++ b/test/jdk/java/foreign/dontrelease/libDontRelease.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void test_ptr(void* ptr) {} diff --git a/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java b/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java new file mode 100644 index 00000000000..c76cdfdbe86 --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/NativeAccessDynamicMain.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.nio.file.Path; +import java.nio.file.Paths; +import java.lang.Module; +import java.lang.ModuleLayer; +import java.lang.module.ModuleFinder; +import java.lang.module.ModuleReference; +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; +import java.util.stream.Collectors; + +// This class creates a dynamic module layer and loads the +// panama_module in it. enableNativeAccess on that dynamic +// module is called depending on the command line option. +// +// Usage: +// java --enable-native-access=ALL-UNNAMED NativeAccessDynamicMain [main-args] +public class NativeAccessDynamicMain { + public static void main(String[] args) throws Exception { + String modulePath = args[0]; + String moduleAndClsName = args[1]; + boolean enableNativeAccess = Boolean.parseBoolean(args[2]); + String[] mainArgs = args.length > 2? Arrays.copyOfRange(args, 3, args.length) : new String[0]; + + int idx = moduleAndClsName.indexOf('/'); + String moduleName = moduleAndClsName.substring(0, idx); + String className = moduleAndClsName.substring(idx+1); + + Path[] paths = Stream.of(modulePath.split(File.pathSeparator)) + .map(Paths::get) + .toArray(Path[]::new); + ModuleFinder mf = ModuleFinder.of(paths); + var mrefs = mf.findAll(); + if (mrefs.isEmpty()) { + throw new RuntimeException("No modules module path: " + modulePath); + } + + var rootMods = mrefs.stream(). + map(mr->mr.descriptor().name()). + collect(Collectors.toSet()); + + ModuleLayer boot = ModuleLayer.boot(); + var conf = boot.configuration(). + resolve(mf, ModuleFinder.of(), rootMods); + String firstMod = rootMods.iterator().next(); + URLClassLoader cl = new URLClassLoader(new URL[] { paths[0].toFile().toURL() }); + ModuleLayer.Controller controller = boot.defineModulesWithOneLoader(conf, List.of(boot), cl); + ModuleLayer layer = controller.layer(); + Module mod = layer.findModule(firstMod).get(); + + // conditionally grant native access to the dynamic module created + if (enableNativeAccess) { + controller.enableNativeAccess(mod); + } + Class mainCls = Class.forName(mod, className); + var main = mainCls.getMethod("main", String[].class); + main.invoke(null, (Object)mainArgs); + } +} diff --git a/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java new file mode 100644 index 00000000000..6be989ec1ac --- /dev/null +++ b/test/jdk/java/foreign/enablenativeaccess/TestEnableNativeAccessDynamic.java @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @requires !vm.musl + * + * @library /test/lib + * @build TestEnableNativeAccessDynamic + * panama_module/* + NativeAccessDynamicMain + * @run testng/othervm/timeout=180 TestEnableNativeAccessDynamic + * @summary Test for dynamically setting --enable-native-access flag for a module + */ + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Stream; + +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class TestEnableNativeAccessDynamic { + + static final String MODULE_PATH = System.getProperty("jdk.module.path"); + + static final String PANAMA_MAIN = "panama_module/org.openjdk.foreigntest.PanamaMainDirect"; + static final String PANAMA_REFLECTION = "panama_module/org.openjdk.foreigntest.PanamaMainReflection"; + static final String PANAMA_INVOKE = "panama_module/org.openjdk.foreigntest.PanamaMainInvoke"; + static final String PANAMA_JNI = "panama_module/org.openjdk.foreigntest.PanamaMainJNI"; + + /** + * Represents the expected result of a test. + */ + static final class Result { + private final boolean success; + private final List expectedOutput = new ArrayList<>(); + private final List notExpectedOutput = new ArrayList<>(); + + Result(boolean success) { + this.success = success; + } + + Result expect(String msg) { + expectedOutput.add(msg); + return this; + } + + Result doNotExpect(String msg) { + notExpectedOutput.add(msg); + return this; + } + + boolean shouldSucceed() { + return success; + } + + Stream expectedOutput() { + return expectedOutput.stream(); + } + + Stream notExpectedOutput() { + return notExpectedOutput.stream(); + } + + @Override + public String toString() { + String s = (success) ? "success" : "failure"; + for (String msg : expectedOutput) { + s += "/" + msg; + } + return s; + } + } + + static Result success() { + return new Result(true); + } + + static Result successNoWarning() { + return success().doNotExpect("WARNING"); + } + + static Result failWithError(String expectedOutput) { + return new Result(false).expect(expectedOutput); + } + + @DataProvider(name = "succeedCases") + public Object[][] succeedCases() { + return new Object[][] { + { "panama_enable_native_access", PANAMA_MAIN, successNoWarning() }, + { "panama_enable_native_access_reflection", PANAMA_REFLECTION, successNoWarning() }, + { "panama_enable_native_access_invoke", PANAMA_INVOKE, successNoWarning() }, + }; + } + + @DataProvider(name = "failureCases") + public Object[][] failureCases() { + String errMsg = "Illegal native access from: module panama_module"; + return new Object[][] { + { "panama_enable_native_access_fail", PANAMA_MAIN, failWithError(errMsg) }, + { "panama_enable_native_access_fail_reflection", PANAMA_REFLECTION, failWithError(errMsg) }, + { "panama_enable_native_access_fail_invoke", PANAMA_INVOKE, failWithError(errMsg) }, + }; + } + + /** + * Checks an expected result with the output captured by the given + * OutputAnalyzer. + */ + void checkResult(Result expectedResult, OutputAnalyzer outputAnalyzer) { + expectedResult.expectedOutput().forEach(outputAnalyzer::shouldContain); + expectedResult.notExpectedOutput().forEach(outputAnalyzer::shouldNotContain); + int exitValue = outputAnalyzer.getExitValue(); + if (expectedResult.shouldSucceed()) { + assertTrue(exitValue == 0); + } else { + assertTrue(exitValue != 0); + } + } + + /** + * Runs the test to execute the given test action. The VM is run with the + * given VM options and the output checked to see that it matches the + * expected result. + */ + OutputAnalyzer run(String action, String moduleAndCls, boolean enableNativeAccess, + Result expectedResult, boolean panamaModuleInBootLayer) throws Exception + { + List list = new ArrayList<>(); + list.add("--enable-preview"); + if (panamaModuleInBootLayer) { + list.addAll(List.of("-p", MODULE_PATH)); + list.add("--add-modules=panama_module"); + list.add("--enable-native-access=panama_module"); + } else { + list.add("--enable-native-access=ALL-UNNAMED"); + } + list.addAll(List.of("NativeAccessDynamicMain", MODULE_PATH, + moduleAndCls, Boolean.toString(enableNativeAccess), action)); + String[] opts = list.toArray(String[]::new); + OutputAnalyzer outputAnalyzer = ProcessTools + .executeTestJava(opts) + .outputTo(System.out) + .errorTo(System.out); + checkResult(expectedResult, outputAnalyzer); + return outputAnalyzer; + } + + @Test(dataProvider = "succeedCases") + public void testSucceed(String action, String moduleAndCls, + Result expectedResult) throws Exception { + run(action, moduleAndCls, true, expectedResult, false); + } + + @Test(dataProvider = "failureCases") + public void testFailures(String action, String moduleAndCls, + Result expectedResult) throws Exception { + run(action, moduleAndCls, false, expectedResult, false); + } + + // make sure that having a same named module in boot layer with native access + // does not influence same named dynamic module. + @Test(dataProvider = "failureCases") + public void testFailuresWithPanamaModuleInBootLayer(String action, String moduleAndCls, + Result expectedResult) throws Exception { + run(action, moduleAndCls, false, expectedResult, true); + } +} diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java index e042a773fda..3743ac73835 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainDirect.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; public class PanamaMainDirect { public static void main(String[] args) { @@ -39,7 +40,7 @@ public static void testDirectAccessCLinker() { public static void testDirectAccessMemorySegment() { System.out.println("Trying to get MemorySegment"); - MemorySegment.ofAddress(MemoryAddress.NULL, 4000, MemorySession.global()); + MemorySegment.ofAddress(0, 4000, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java index b50ebe9ca80..0d4d7bb4bb0 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainInvoke.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.invoke.*; public class PanamaMainInvoke { @@ -43,8 +44,8 @@ public static void testInvokenativeLinker() throws Throwable { public static void testInvokeMemorySegment() throws Throwable { System.out.println("Trying to get MemorySegment"); var mh = MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", - MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, MemorySession.class)); - var seg = (MemorySegment)mh.invokeExact(MemoryAddress.NULL, 4000L, MemorySession.global()); + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)); + var seg = (MemorySegment)mh.invokeExact(0L, 4000L, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java index 7a8eab027e9..68aebc73ab5 100644 --- a/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java +++ b/test/jdk/java/foreign/enablenativeaccess/panama_module/org/openjdk/foreigntest/PanamaMainReflection.java @@ -24,6 +24,7 @@ package org.openjdk.foreigntest; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.reflect.Method; public class PanamaMainReflection { @@ -41,8 +42,8 @@ public static void testReflectionnativeLinker() throws Throwable { public static void testReflectionMemorySegment() throws Throwable { System.out.println("Trying to get MemorySegment"); - Method method = MemorySegment.class.getDeclaredMethod("ofAddress", MemoryAddress.class, long.class, MemorySession.class); - method.invoke(null, MemoryAddress.NULL, 4000L, MemorySession.global()); + Method method = MemorySegment.class.getDeclaredMethod("ofAddress", long.class, long.class, SegmentScope.class); + method.invoke(null, 0L, 4000L, SegmentScope.global()); System.out.println("Got MemorySegment"); } } diff --git a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java index 319fcde6600..090a57bcc7b 100644 --- a/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java +++ b/test/jdk/java/foreign/handles/invoker_module/handle/invoker/MethodHandleInvoker.java @@ -23,13 +23,11 @@ package handle.invoker; -import java.lang.foreign.Addressable; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.SymbolLookup; import java.lang.foreign.ValueLayout; @@ -71,11 +69,10 @@ static void addDefaultMapping(Class carrier, Z value) { addDefaultMapping(MethodHandle.class, MethodHandles.identity(int.class)); addDefaultMapping(Charset.class, Charset.defaultCharset()); addDefaultMapping(MethodType.class, MethodType.methodType(void.class)); - addDefaultMapping(MemoryAddress.class, MemoryAddress.NULL); - addDefaultMapping(Addressable.class, MemoryAddress.NULL); + addDefaultMapping(MemorySegment.class, MemorySegment.NULL); addDefaultMapping(MemoryLayout.class, ValueLayout.JAVA_INT); addDefaultMapping(FunctionDescriptor.class, FunctionDescriptor.ofVoid()); - addDefaultMapping(MemorySession.class, MemorySession.openImplicit()); + addDefaultMapping(SegmentScope.class, SegmentScope.auto()); addDefaultMapping(SegmentAllocator.class, SegmentAllocator.prefixAllocator(MemorySegment.ofArray(new byte[10]))); addDefaultMapping(ValueLayout.OfByte.class, ValueLayout.JAVA_BYTE); addDefaultMapping(ValueLayout.OfBoolean.class, ValueLayout.JAVA_BOOLEAN); diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java index f3f5c6238e9..6bd7121c651 100644 --- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java +++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java @@ -23,19 +23,15 @@ package handle.lookup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.Linker; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodHandles; import java.lang.invoke.MethodType; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SymbolLookup; -import java.lang.foreign.VaList; -import java.lang.foreign.ValueLayout; import java.nio.file.Path; @@ -54,120 +50,15 @@ static Object[][] restrictedMethods() { return new Object[][]{ { MethodHandles.lookup().findStatic(Linker.class, "nativeLinker", MethodType.methodType(Linker.class)), "Linker::nativeLinker" }, - { MethodHandles.lookup().findStatic(VaList.class, "ofAddress", - MethodType.methodType(VaList.class, MemoryAddress.class, MemorySession.class)), - "VaList::ofAddress/1" }, { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", - MethodType.methodType(MemorySegment.class, MemoryAddress.class, long.class, MemorySession.class)), - "MemorySegment::ofAddress" }, + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)), + "MemorySegment::ofAddressNative" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", - MethodType.methodType(SymbolLookup.class, String.class, MemorySession.class)), + MethodType.methodType(SymbolLookup.class, String.class, SegmentScope.class)), "SymbolLookup::libraryLookup(String)" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", - MethodType.methodType(SymbolLookup.class, Path.class, MemorySession.class)), + MethodType.methodType(SymbolLookup.class, Path.class, SegmentScope.class)), "SymbolLookup::libraryLookup(Path)" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getUtf8String", - MethodType.methodType(String.class, long.class)), - "MemoryAddress::getUtf8String" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setUtf8String", - MethodType.methodType(void.class, long.class, String.class)), - "MemoryAddress::setUtf8String" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(byte.class, ValueLayout.OfByte.class, long.class)), - "MemoryAddress::get/byte" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(boolean.class, ValueLayout.OfBoolean.class, long.class)), - "MemoryAddress::get/boolean" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(char.class, ValueLayout.OfChar.class, long.class)), - "MemoryAddress::get/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(short.class, ValueLayout.OfShort.class, long.class)), - "MemoryAddress::get/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(int.class, ValueLayout.OfInt.class, long.class)), - "MemoryAddress::get/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(float.class, ValueLayout.OfFloat.class, long.class)), - "MemoryAddress::get/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(long.class, ValueLayout.OfLong.class, long.class)), - "MemoryAddress::get/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(double.class, ValueLayout.OfDouble.class, long.class)), - "MemoryAddress::get/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "get", - MethodType.methodType(MemoryAddress.class, ValueLayout.OfAddress.class, long.class)), - "MemoryAddress::get/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfByte.class, long.class, byte.class)), - "MemoryAddress::set/byte" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfBoolean.class, long.class, boolean.class)), - "MemoryAddress::set/boolean" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfChar.class, long.class, char.class)), - "MemoryAddress::set/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfShort.class, long.class, short.class)), - "MemoryAddress::set/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfInt.class, long.class, int.class)), - "MemoryAddress::set/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfFloat.class, long.class, float.class)), - "MemoryAddress::set/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfLong.class, long.class, long.class)), - "MemoryAddress::set/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfDouble.class, long.class, double.class)), - "MemoryAddress::set/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "set", - MethodType.methodType(void.class, ValueLayout.OfAddress.class, long.class, Addressable.class)), - "MemoryAddress::set/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(char.class, ValueLayout.OfChar.class, long.class)), - "MemoryAddress::getAtIndex/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(short.class, ValueLayout.OfShort.class, long.class)), - "MemoryAddress::getAtIndex/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(int.class, ValueLayout.OfInt.class, long.class)), - "MemoryAddress::getAtIndex/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(float.class, ValueLayout.OfFloat.class, long.class)), - "MemoryAddress::getAtIndex/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(long.class, ValueLayout.OfLong.class, long.class)), - "MemoryAddress::getAtIndex/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(double.class, ValueLayout.OfDouble.class, long.class)), - "MemoryAddress::getAtIndex/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "getAtIndex", - MethodType.methodType(MemoryAddress.class, ValueLayout.OfAddress.class, long.class)), - "MemoryAddress::getAtIndex/address" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfChar.class, long.class, char.class)), - "MemoryAddress::setAtIndex/char" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfShort.class, long.class, short.class)), - "MemoryAddress::setAtIndex/short" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfInt.class, long.class, int.class)), - "MemoryAddress::setAtIndex/int" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfFloat.class, long.class, float.class)), - "MemoryAddress::setAtIndex/float" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfLong.class, long.class, long.class)), - "MemoryAddress::set/long" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfDouble.class, long.class, double.class)), - "MemoryAddress::set/double" }, - { MethodHandles.lookup().findVirtual(MemoryAddress.class, "setAtIndex", - MethodType.methodType(void.class, ValueLayout.OfAddress.class, long.class, Addressable.class)), - "MemoryAddress::set/address" }, }; } catch (Throwable ex) { throw new ExceptionInInitializerError((ex)); diff --git a/test/jdk/java/foreign/libNull.c b/test/jdk/java/foreign/libNull.c new file mode 100644 index 00000000000..52ea8493f21 --- /dev/null +++ b/test/jdk/java/foreign/libNull.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2021, 2022, 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +#include + +EXPORT void* get_null() { return NULL; } diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java index aff471cc241..b6a4b82616b 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookup.java @@ -42,11 +42,11 @@ public static void main(String[] args) throws ReflectiveOperationException { ClassLoader loader1 = newClassLoader("lookup"); Class lookup = loader1.loadClass("lookup.Lookup"); Method fooSymbol = lookup.getDeclaredMethod("fooSymbol"); - Addressable foo = (Addressable)fooSymbol.invoke(null); + MemorySegment foo = (MemorySegment) fooSymbol.invoke(null); ClassLoader loader2 = newClassLoader("invoker"); Class invoker = loader2.loadClass("invoker.Invoker"); - Method invoke = invoker.getDeclaredMethod("invoke", Addressable.class); + Method invoke = invoker.getDeclaredMethod("invoke", MemorySegment.class); invoke.invoke(null, foo); loader1 = null; diff --git a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java index 1d981722fc0..f5d0a8073a5 100644 --- a/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java +++ b/test/jdk/java/foreign/loaderLookup/TestLoaderLookupJNI.java @@ -42,10 +42,10 @@ public class TestLoaderLookupJNI { @Test void testLoaderLookupJNI() { SymbolLookup loaderLookup = SymbolLookup.loaderLookup(); - assertTrue(loaderLookup.lookup("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); + assertTrue(loaderLookup.find("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); // now try calling via JNI loaderLookup = loaderLookup0(); // lookup backed by application loader, so can see same symbols - assertTrue(loaderLookup.lookup("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); + assertTrue(loaderLookup.find("Java_TestLoaderLookupJNI_loaderLookup0").isPresent()); } static native SymbolLookup loaderLookup0(); diff --git a/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java index eb188719a98..06bf9eac4a8 100644 --- a/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java +++ b/test/jdk/java/foreign/loaderLookup/invoker/Invoker.java @@ -26,7 +26,7 @@ import java.lang.foreign.*; public class Invoker { - public static void invoke(Addressable symbol) throws Throwable { + public static void invoke(MemorySegment symbol) throws Throwable { var linker = Linker.nativeLinker(); var handle = linker.downcallHandle(symbol, FunctionDescriptor.ofVoid()); handle.invokeExact(); diff --git a/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java index 00946f75c20..6efa9e0ac09 100644 --- a/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java +++ b/test/jdk/java/foreign/loaderLookup/lookup/Lookup.java @@ -23,7 +23,7 @@ package lookup; -import java.lang.foreign.Addressable; +import java.lang.foreign.MemorySegment; import java.lang.foreign.SymbolLookup; public class Lookup { @@ -31,7 +31,7 @@ public class Lookup { System.loadLibrary("Foo"); } - public static Addressable fooSymbol() { - return SymbolLookup.loaderLookup().lookup("foo").get(); + public static MemorySegment fooSymbol() { + return SymbolLookup.loaderLookup().find("foo").get(); } } diff --git a/test/jdk/java/foreign/normalize/TestNormalize.java b/test/jdk/java/foreign/normalize/TestNormalize.java new file mode 100644 index 00000000000..0ba8ef6d36f --- /dev/null +++ b/test/jdk/java/foreign/normalize/TestNormalize.java @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @library ../ + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm + * --enable-native-access=ALL-UNNAMED + * -Xbatch + * -XX:CompileCommand=dontinline,TestNormalize::doCall* + * TestNormalize + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +import static java.lang.foreign.ValueLayout.ADDRESS; +import static java.lang.foreign.ValueLayout.JAVA_BOOLEAN; +import static java.lang.foreign.ValueLayout.JAVA_BYTE; +import static java.lang.foreign.ValueLayout.JAVA_CHAR; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_SHORT; +import static org.testng.Assert.assertEquals; + +// test normalization of smaller than int primitive types +public class TestNormalize extends NativeTestHelper { + + private static final Linker LINKER = Linker.nativeLinker(); + private static final MethodHandle SAVE_BOOLEAN_AS_INT; + private static final MethodHandle SAVE_BYTE_AS_INT; + private static final MethodHandle SAVE_SHORT_AS_INT; + private static final MethodHandle SAVE_CHAR_AS_INT; + + private static final MethodHandle BOOLEAN_TO_INT; + private static final MethodHandle BYTE_TO_INT; + private static final MethodHandle SHORT_TO_INT; + private static final MethodHandle CHAR_TO_INT; + + private static final MethodHandle NATIVE_BOOLEAN_TO_INT; + + private static final int BOOLEAN_HOB_MASK = ~0b1; + private static final int BYTE_HOB_MASK = ~0xFF; + private static final int SHORT_HOB_MASK = ~0xFFFF; + private static final int CHAR_HOB_MASK = ~0xFFFF; + + private static final MethodHandle SAVE_BOOLEAN; + + static { + System.loadLibrary("Normalize"); + + try { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + SAVE_BOOLEAN_AS_INT = lookup.findStatic(TestNormalize.class, "saveBooleanAsInt", MethodType.methodType(void.class, boolean.class, int[].class)); + SAVE_BYTE_AS_INT = lookup.findStatic(TestNormalize.class, "saveByteAsInt", MethodType.methodType(void.class, byte.class, int[].class)); + SAVE_SHORT_AS_INT = lookup.findStatic(TestNormalize.class, "saveShortAsInt", MethodType.methodType(void.class, short.class, int[].class)); + SAVE_CHAR_AS_INT = lookup.findStatic(TestNormalize.class, "saveCharAsInt", MethodType.methodType(void.class, char.class, int[].class)); + + BOOLEAN_TO_INT = lookup.findStatic(TestNormalize.class, "booleanToInt", MethodType.methodType(int.class, boolean.class)); + BYTE_TO_INT = lookup.findStatic(TestNormalize.class, "byteToInt", MethodType.methodType(int.class, byte.class)); + SHORT_TO_INT = lookup.findStatic(TestNormalize.class, "shortToInt", MethodType.methodType(int.class, short.class)); + CHAR_TO_INT = lookup.findStatic(TestNormalize.class, "charToInt", MethodType.methodType(int.class, char.class)); + + NATIVE_BOOLEAN_TO_INT = LINKER.downcallHandle(findNativeOrThrow("int_identity"), FunctionDescriptor.of(JAVA_INT, JAVA_BOOLEAN)); + + SAVE_BOOLEAN = lookup.findStatic(TestNormalize.class, "saveBoolean", MethodType.methodType(void.class, boolean.class, boolean[].class)); + } catch (ReflectiveOperationException e) { + throw new ExceptionInInitializerError(e); + } + } + + // The idea of this test is that we pass a 'dirty' int value down to native code, and then receive it back + // as the argument to an upcall, as well as the result of the downcall, but with a sub-int type (boolean, byte, short, char). + // When we do either of those, argument normalization should take place, so that the resulting value is sane (1). + // After that we convert the value back to int again, the JVM can/will skip value normalization here. + // We then check the high order bits of the resulting int. If argument normalization took place at (1), they should all be 0. + @Test(dataProvider = "cases") + public void testNormalize(ValueLayout layout, int testValue, int hobMask, MethodHandle toInt, MethodHandle saver) throws Throwable { + // use actual type as parameter type to test upcall arg normalization + FunctionDescriptor upcallDesc = FunctionDescriptor.ofVoid(layout); + // use actual type as return type to test downcall return normalization + FunctionDescriptor downcallDesc = FunctionDescriptor.of(layout, ADDRESS, JAVA_INT); + + MemorySegment target = findNativeOrThrow("test"); + MethodHandle downcallHandle = LINKER.downcallHandle(target, downcallDesc); + downcallHandle = MethodHandles.filterReturnValue(downcallHandle, toInt); + + try (Arena arena = Arena.openConfined()) { + int[] box = new int[1]; + saver = MethodHandles.insertArguments(saver, 1, box); + MemorySegment upcallStub = LINKER.upcallStub(saver, upcallDesc, arena.scope()); + int dirtyValue = testValue | hobMask; // set all bits that should not be set + + // test after JIT as well + for (int i = 0; i < 20_000; i++) { + doCall(downcallHandle, upcallStub, box, dirtyValue, hobMask); + } + } + } + + private static void doCall(MethodHandle downcallHandle, MemorySegment upcallStub, + int[] box, int dirtyValue, int hobMask) throws Throwable { + int result = (int) downcallHandle.invokeExact(upcallStub, dirtyValue); + assertEquals(box[0] & hobMask, 0); // check normalized upcall arg + assertEquals(result & hobMask, 0); // check normalized downcall return value + } + + public static void saveBooleanAsInt(boolean b, int[] box) { + box[0] = booleanToInt(b); + } + public static void saveByteAsInt(byte b, int[] box) { + box[0] = byteToInt(b); + } + public static void saveShortAsInt(short s, int[] box) { + box[0] = shortToInt(s); + } + public static void saveCharAsInt(char c, int[] box) { + box[0] = charToInt(c); + } + + public static int booleanToInt(boolean b) { + try { + return (int) NATIVE_BOOLEAN_TO_INT.invokeExact(b); // FIXME do in pure Java? + } catch (Throwable e) { + throw new RuntimeException(e); + } + } + public static int byteToInt(byte b) { + return b; + } + public static int charToInt(char c) { + return c; + } + public static int shortToInt(short s) { + return s; + } + + @DataProvider + public static Object[][] cases() { + return new Object[][] { + { JAVA_BOOLEAN, booleanToInt(true), BOOLEAN_HOB_MASK, BOOLEAN_TO_INT, SAVE_BOOLEAN_AS_INT }, + { JAVA_BYTE, byteToInt((byte) 42), BYTE_HOB_MASK, BYTE_TO_INT, SAVE_BYTE_AS_INT }, + { JAVA_SHORT, shortToInt((short) 42), SHORT_HOB_MASK, SHORT_TO_INT, SAVE_SHORT_AS_INT }, + { JAVA_CHAR, charToInt('a'), CHAR_HOB_MASK, CHAR_TO_INT, SAVE_CHAR_AS_INT } + }; + } + + // test which int values are considered true and false + // we currently convert any int with a non-zero first byte to true, otherwise false. + @Test(dataProvider = "bools") + public void testBool(int testValue, boolean expected) throws Throwable { + MemorySegment addr = findNativeOrThrow("test"); + MethodHandle target = LINKER.downcallHandle(addr, FunctionDescriptor.of(JAVA_BOOLEAN, ADDRESS, JAVA_INT)); + + boolean[] box = new boolean[1]; + MethodHandle upcallTarget = MethodHandles.insertArguments(SAVE_BOOLEAN, 1, box); + + try (Arena arena = Arena.openConfined()) { + MemorySegment callback = LINKER.upcallStub(upcallTarget, FunctionDescriptor.ofVoid(JAVA_BOOLEAN), arena.scope()); + boolean result = (boolean) target.invokeExact(callback, testValue); + assertEquals(box[0], expected); + assertEquals(result, expected); + } + } + + private static void saveBoolean(boolean b, boolean[] box) { + box[0] = b; + } + + @DataProvider + public static Object[][] bools() { + return new Object[][]{ + { 0b10, true }, // zero least significant bit, but non-zero first byte + { 0b1_0000_0000, false } // zero first byte + }; + } +} diff --git a/test/jdk/java/foreign/normalize/libNormalize.c b/test/jdk/java/foreign/normalize/libNormalize.c new file mode 100644 index 00000000000..4a21551278f --- /dev/null +++ b/test/jdk/java/foreign/normalize/libNormalize.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2022, 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +// we use 'int' here to make sure the native code doesn't touch any of the bits +// the important part is that our Java code performs argument normalization +EXPORT int test(void (*cb)(int), int x) { + cb(x); // check upcall arg normalization + return x; // check return value normalization +} + +EXPORT int int_identity(int x) { + return x; +} diff --git a/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java new file mode 100644 index 00000000000..9a745113e3f --- /dev/null +++ b/test/jdk/java/foreign/passheapsegment/TestPassHeapSegment.java @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestPassHeapSegment + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.io.IOException; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; +import java.lang.invoke.MethodHandle; + +import static java.lang.foreign.ValueLayout.ADDRESS; + +public class TestPassHeapSegment extends UpcallTestHelper { + + static { + System.loadLibrary("PassHeapSegment"); + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Heap segment not allowed.*") + public void testNoHeapArgs() throws Throwable { + MethodHandle handle = downcallHandle("test_args", FunctionDescriptor.ofVoid(ADDRESS)); + MemorySegment segment = MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); + handle.invoke(segment); // should throw + } + + @Test(dataProvider = "specs") + public void testNoHeapReturns(boolean spec) throws IOException, InterruptedException { + runInNewProcess(Runner.class, spec).assertStdErrContains("Heap segment not allowed"); + } + + public static class Runner { + + static { + System.loadLibrary("PassHeapSegment"); + } + + public static void main(String[] args) throws Throwable { + MethodHandle handle = downcallHandle("test_return", FunctionDescriptor.ofVoid(ADDRESS)); + MemorySegment upcallStub = upcallStub(Runner.class, "target", FunctionDescriptor.of(ADDRESS)); + handle.invoke(upcallStub); + } + + public static MemorySegment target() { + return MemorySegment.ofArray(new byte[]{ 0, 1, 2 }); // should throw + } + } + + @DataProvider + public static Object[][] specs() { + return new Object[][]{ + { true }, + { false } + }; + } +} + diff --git a/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c b/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c new file mode 100644 index 00000000000..fdb1981ac65 --- /dev/null +++ b/test/jdk/java/foreign/passheapsegment/libPassHeapSegment.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2022, 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. + */ + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void test_args(void* ptr) {} + +EXPORT void test_return(void* (*cb)(void)) { + cb(); +} diff --git a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java index 643bf3d9317..c9b3582d4d0 100644 --- a/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestAsyncStackWalk.java @@ -78,15 +78,14 @@ * TestAsyncStackWalk */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; -import java.lang.foreign.MemorySession; import jdk.test.whitebox.WhiteBox; import static java.lang.invoke.MethodHandles.lookup; @@ -116,17 +115,16 @@ public class TestAsyncStackWalk extends NativeTestHelper { static boolean didStackWalk; public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), session); - MemoryAddress stubAddress = stub.address(); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), arena.scope()); invocations = 0; didStackWalk = false; - payload(stubAddress); + payload(stub); assertTrue(didStackWalk); } } - static void payload(MemoryAddress cb) throws Throwable { + static void payload(MemorySegment cb) throws Throwable { MH_asyncStackWalk.invoke(cb); } diff --git a/test/jdk/java/foreign/stackwalk/TestStackWalk.java b/test/jdk/java/foreign/stackwalk/TestStackWalk.java index 23b56c5e219..9b3679c9f35 100644 --- a/test/jdk/java/foreign/stackwalk/TestStackWalk.java +++ b/test/jdk/java/foreign/stackwalk/TestStackWalk.java @@ -78,11 +78,10 @@ * TestStackWalk */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -115,20 +114,19 @@ public class TestStackWalk extends NativeTestHelper { static boolean armed; public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), session); - MemoryAddress stubAddress = stub.address(); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(), arena.scope()); armed = false; for (int i = 0; i < 20_000; i++) { - payload(stubAddress); // warmup + payload(stub); // warmup } armed = true; - payload(stubAddress); // test + payload(stub); // test } } - static void payload(MemoryAddress cb) throws Throwable { + static void payload(MemorySegment cb) throws Throwable { MH_foo.invoke(cb); Reference.reachabilityFence(cb); // keep oop alive across call } diff --git a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java index 4d82eb677fe..a0f36c479fc 100644 --- a/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java +++ b/test/jdk/java/foreign/upcalldeopt/TestUpcallDeopt.java @@ -40,10 +40,10 @@ * TestUpcallDeopt */ -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -79,8 +79,8 @@ public class TestUpcallDeopt extends NativeTestHelper { // we need to deoptimize through an uncommon trap in the callee of the optimized upcall stub // that is created when calling upcallStub below public static void main(String[] args) throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT), session); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = linker.upcallStub(MH_m, FunctionDescriptor.ofVoid(C_INT, C_INT, C_INT, C_INT), arena.scope()); armed = false; for (int i = 0; i < 20_000; i++) { payload(stub); // warmup @@ -91,8 +91,8 @@ public static void main(String[] args) throws Throwable { } } - static void payload(Addressable cb) throws Throwable { - MH_foo.invokeExact((Addressable) cb, 0, 1, 2, 3); + static void payload(MemorySegment cb) throws Throwable { + MH_foo.invokeExact(cb, 0, 1, 2, 3); Reference.reachabilityFence(cb); // keep oop alive across call } diff --git a/test/jdk/java/foreign/valist/VaListTest.java b/test/jdk/java/foreign/valist/VaListTest.java index e8846490e25..9c8ce23b5ee 100644 --- a/test/jdk/java/foreign/valist/VaListTest.java +++ b/test/jdk/java/foreign/valist/VaListTest.java @@ -40,6 +40,7 @@ */ import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; import java.lang.foreign.VaList; import jdk.internal.foreign.abi.aarch64.linux.LinuxAArch64Linker; import jdk.internal.foreign.abi.aarch64.macos.MacOsAArch64Linker; @@ -63,13 +64,9 @@ import static java.lang.foreign.MemoryLayout.PathElement.groupElement; import static java.lang.foreign.ValueLayout.ADDRESS; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_CHAR; import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; import static java.lang.foreign.ValueLayout.JAVA_INT; import static java.lang.foreign.ValueLayout.JAVA_LONG; -import static java.lang.foreign.ValueLayout.JAVA_SHORT; import static jdk.internal.foreign.PlatformLayouts.*; import static org.testng.Assert.*; @@ -80,11 +77,13 @@ public class VaListTest extends NativeTestHelper { System.loadLibrary("VaList"); } - private static final MethodHandle ADDRESS_TO_VALIST; + private static final MethodHandle VALIST_TO_ADDRESS; + private static final MethodHandle SEGMENT_TO_VALIST; static { try { - ADDRESS_TO_VALIST = MethodHandles.lookup().findStatic(VaList.class, "ofAddress", MethodType.methodType(VaList.class, MemoryAddress.class, MemorySession.class)); + VALIST_TO_ADDRESS = MethodHandles.lookup().findVirtual(VaList.class, "segment", MethodType.methodType(MemorySegment.class)); + SEGMENT_TO_VALIST = MethodHandles.lookup().findStatic(VaListTest.class, "segmentToValist", MethodType.methodType(VaList.class, MemorySegment.class)); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } @@ -113,7 +112,7 @@ private static MethodHandle link(String symbol, FunctionDescriptor fd) { } private static MethodHandle linkVaList(String symbol, FunctionDescriptor fd) { - return linkInternal(symbol, fd); + return MethodHandles.filterArguments(linkInternal(symbol, fd), fd.argumentLayouts().size() - 1, VALIST_TO_ADDRESS); } @@ -128,25 +127,25 @@ private static MethodHandle linkVaListCB(String symbol) { } private static final Function, VaList> winVaListFactory - = actions -> Windowsx64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> Windowsx64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> sysvVaListFactory - = actions -> SysVx64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> SysVx64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> linuxAArch64VaListFactory - = actions -> LinuxAArch64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> LinuxAArch64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> macAArch64VaListFactory - = actions -> MacOsAArch64Linker.newVaList(actions, MemorySession.openImplicit()); + = actions -> MacOsAArch64Linker.newVaList(actions, SegmentScope.auto()); private static final Function, VaList> platformVaListFactory - = (builder) -> VaList.make(builder, MemorySession.openConfined()); + = (builder) -> VaList.make(builder, SegmentScope.auto()); - private static final BiFunction, MemorySession, VaList> winVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> winVaListScopedFactory = Windowsx64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> sysvVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> sysvVaListScopedFactory = SysVx64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> linuxAArch64VaListScopedFactory + private static final BiFunction, SegmentScope, VaList> linuxAArch64VaListScopedFactory = LinuxAArch64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> macAArch64VaListScopedFactory + private static final BiFunction, SegmentScope, VaList> macAArch64VaListScopedFactory = MacOsAArch64Linker::newVaList; - private static final BiFunction, MemorySession, VaList> platformVaListScopedFactory + private static final BiFunction, SegmentScope, VaList> platformVaListScopedFactory = VaList::make; @DataProvider @@ -170,9 +169,9 @@ public void testIntSum(Function, VaList> vaListFactory, BiFunction sumInts, ValueLayout.OfInt intLayout) { VaList vaList = vaListFactory.apply(b -> - b.addVarg(intLayout, 10) - .addVarg(intLayout, 15) - .addVarg(intLayout, 20)); + b.addVarg(intLayout, 10) + .addVarg(intLayout, 15) + .addVarg(intLayout, 20)); int x = sumInts.apply(3, vaList); assertEquals(x, 45); } @@ -198,9 +197,9 @@ public void testDoubleSum(Function, VaList> vaListFacto BiFunction sumDoubles, ValueLayout.OfDouble doubleLayout) { VaList vaList = vaListFactory.apply(b -> - b.addVarg(doubleLayout, 3.0D) - .addVarg(doubleLayout, 4.0D) - .addVarg(doubleLayout, 5.0D)); + b.addVarg(doubleLayout, 3.0D) + .addVarg(doubleLayout, 4.0D) + .addVarg(doubleLayout, 5.0D)); double x = sumDoubles.apply(3, vaList); assertEquals(x, 12.0D); } @@ -210,7 +209,7 @@ public void testDoubleSum(Function, VaList> vaListFacto public static Object[][] pointers() { Function> getIntJavaFact = layout -> list -> { - MemoryAddress ma = list.nextVarg(layout); + MemorySegment ma = list.nextVarg(layout); return ma.get(JAVA_INT, 0); }; Function getIntNative = MethodHandleProxies.asInterfaceInstance(Function.class, MH_getInt); @@ -224,13 +223,13 @@ public static Object[][] pointers() { } @Test(dataProvider = "pointers") - public void testVaListMemoryAddress(Function, VaList> vaListFactory, + public void testVaListMemorySegment(Function, VaList> vaListFactory, Function getFromPointer, ValueLayout.OfAddress pointerLayout) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment msInt = MemorySegment.allocateNative(JAVA_INT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment msInt = MemorySegment.allocateNative(JAVA_INT, arena.scope());; msInt.set(JAVA_INT, 0, 10); - VaList vaList = vaListFactory.apply(b -> b.addVarg(pointerLayout, msInt.address())); + VaList vaList = vaListFactory.apply(b -> b.addVarg(pointerLayout, msInt)); int x = getFromPointer.apply(vaList); assertEquals(x, 10); } @@ -246,7 +245,7 @@ public static Object[][] structs() { TriFunction> sumStructJavaFact = (pointLayout, VH_Point_x, VH_Point_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(pointLayout, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(pointLayout, SegmentScope.auto()); list.nextVarg(pointLayout, SegmentAllocator.prefixAllocator(struct)); int x = (int) VH_Point_x.get(struct); int y = (int) VH_Point_y.get(struct); @@ -282,8 +281,8 @@ public static Object[][] structs() { public void testStruct(Function, VaList> vaListFactory, Function sumStruct, GroupLayout Point_LAYOUT, VarHandle VH_Point_x, VarHandle VH_Point_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, arena.scope());; VH_Point_x.set(struct, 5); VH_Point_y.set(struct, 10); @@ -299,7 +298,7 @@ public static Object[][] bigStructs() { TriFunction> sumStructJavaFact = (BigPoint_LAYOUT, VH_BigPoint_x, VH_BigPoint_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); list.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_BigPoint_x.get(struct); long y = (long) VH_BigPoint_y.get(struct); @@ -335,8 +334,8 @@ public static Object[][] bigStructs() { public void testBigStruct(Function, VaList> vaListFactory, Function sumBigStruct, GroupLayout BigPoint_LAYOUT, VarHandle VH_BigPoint_x, VarHandle VH_BigPoint_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, arena.scope());; VH_BigPoint_x.set(struct, 5); VH_BigPoint_y.set(struct, 10); @@ -352,7 +351,7 @@ public static Object[][] floatStructs() { TriFunction> sumStructJavaFact = (FloatPoint_LAYOUT, VH_FloatPoint_x, VH_FloatPoint_y) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, SegmentScope.auto()); list.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); float x = (float) VH_FloatPoint_x.get(struct); float y = (float) VH_FloatPoint_y.get(struct); @@ -389,8 +388,8 @@ public void testFloatStruct(Function, VaList> vaListFac Function sumFloatStruct, GroupLayout FloatPoint_LAYOUT, VarHandle VH_FloatPoint_x, VarHandle VH_FloatPoint_y) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, arena.scope());; VH_FloatPoint_x.set(struct, 1.234f); VH_FloatPoint_y.set(struct, 3.142f); @@ -410,7 +409,7 @@ public static Object[][] hugeStructs() { QuadFunc> sumStructJavaFact = (HugePoint_LAYOUT, VH_HugePoint_x, VH_HugePoint_y, VH_HugePoint_z) -> list -> { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, SegmentScope.auto()); list.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); long x = (long) VH_HugePoint_x.get(struct); long y = (long) VH_HugePoint_y.get(struct); @@ -453,8 +452,8 @@ public void testHugeStruct(Function, VaList> vaListFact VarHandle VH_HugePoint_x, VarHandle VH_HugePoint_y, VarHandle VH_HugePoint_z) { // On AArch64 a struct needs to be larger than 16 bytes to be // passed by reference. - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, arena.scope());; VH_HugePoint_x.set(struct, 1); VH_HugePoint_y.set(struct, 2); VH_HugePoint_z.set(struct, 3); @@ -486,7 +485,7 @@ public static Object[][] sumStack() { }; SumStackFunc sumStackNative = (longSum, doubleSum, list) -> { try { - MH_sumStack.invoke(longSum, doubleSum, list); + MH_sumStack.invokeExact(longSum, doubleSum, list); } catch (Throwable ex) { throw new AssertionError(ex); } @@ -505,9 +504,9 @@ public void testStack(Function, VaList> vaListFactory, SumStackFunc sumStack, ValueLayout.OfLong longLayout, ValueLayout.OfDouble doubleLayout) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment longSum = MemorySegment.allocateNative(longLayout, session); - MemorySegment doubleSum = MemorySegment.allocateNative(doubleLayout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment longSum = MemorySegment.allocateNative(longLayout, arena.scope());; + MemorySegment doubleSum = MemorySegment.allocateNative(doubleLayout, arena.scope());; longSum.set(JAVA_LONG, 0, 0L); doubleSum.set(JAVA_DOUBLE, 0, 0D); @@ -533,9 +532,9 @@ public void testStack(Function, VaList> vaListFactory, @Test(dataProvider = "upcalls") public void testUpcall(MethodHandle target, MethodHandle callback) throws Throwable { FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_POINTER); - try (MemorySession session = MemorySession.openConfined()) { - Addressable stub = abi.upcallStub(callback, desc, session); - target.invoke(stub); + try (Arena arena = Arena.openConfined()) { + MemorySegment stub = abi.upcallStub(callback, desc, arena.scope()); + target.invokeExact(stub); } } @@ -570,18 +569,18 @@ public static Object[][] sumIntsScoped() { } @Test(dataProvider = "sumIntsScoped") - public void testScopedVaList(BiFunction, MemorySession, VaList> vaListFactory, + public void testScopedVaList(BiFunction, SegmentScope, VaList> vaListFactory, BiFunction sumInts, ValueLayout.OfInt intLayout) { VaList listLeaked; - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); int x = sumInts.apply(2, list); assertEquals(x, 12); listLeaked = list; } - assertFalse(listLeaked.session().isAlive()); + assertFalse(listLeaked.segment().scope().isAlive()); } @Test(dataProvider = "structs") @@ -589,21 +588,21 @@ public void testScopeMSRead(Function, VaList> vaListFac Function sumStruct, // ignored GroupLayout Point_LAYOUT, VarHandle VH_Point_x, VarHandle VH_Point_y) { MemorySegment pointOut; - try (MemorySession session = MemorySession.openConfined()) { - try (MemorySession innerSession = MemorySession.openConfined()) { - MemorySegment pointIn = MemorySegment.allocateNative(Point_LAYOUT, innerSession); + try (Arena arena = Arena.openConfined()) { + try (Arena innerArena = Arena.openConfined()) { + MemorySegment pointIn = MemorySegment.allocateNative(Point_LAYOUT, innerArena.scope());; VH_Point_x.set(pointIn, 3); VH_Point_y.set(pointIn, 6); VaList list = vaListFactory.apply(b -> b.addVarg(Point_LAYOUT, pointIn)); - pointOut = MemorySegment.allocateNative(Point_LAYOUT, session); + pointOut = MemorySegment.allocateNative(Point_LAYOUT, arena.scope());; list.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(pointOut)); assertEquals((int) VH_Point_x.get(pointOut), 3); assertEquals((int) VH_Point_y.get(pointOut), 6); - assertTrue(pointOut.session().isAlive()); // after VaList freed + assertTrue(pointOut.scope().isAlive()); // after VaList freed } - assertTrue(pointOut.session().isAlive()); // after inner session freed + assertTrue(pointOut.scope().isAlive()); // after inner session freed } - assertFalse(pointOut.session().isAlive()); // after outer session freed + assertFalse(pointOut.scope().isAlive()); // after outer session freed } @DataProvider @@ -617,10 +616,10 @@ public Object[][] copy() { } @Test(dataProvider = "copy") - public void testCopy(BiFunction, MemorySession, VaList> vaListFactory, ValueLayout.OfInt intLayout) { - try (var session = MemorySession.openConfined()) { + public void testCopy(BiFunction, SegmentScope, VaList> vaListFactory, ValueLayout.OfInt intLayout) { + try (var arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); VaList copy = list.copy(); assertEquals(copy.nextVarg(intLayout), 4); assertEquals(copy.nextVarg(intLayout), 8); @@ -639,12 +638,12 @@ public void testCopy(BiFunction, MemorySession, VaList> @Test(dataProvider = "copy", expectedExceptions = IllegalStateException.class) - public void testCopyUnusableAfterOriginalClosed(BiFunction, MemorySession, VaList> vaListFactory, + public void testCopyUnusableAfterOriginalClosed(BiFunction, SegmentScope, VaList> vaListFactory, ValueLayout.OfInt intLayout) { VaList copy; - try (var session = MemorySession.openConfined()) { + try (var arena = Arena.openConfined()) { VaList list = vaListFactory.apply(b -> b.addVarg(intLayout, 4) - .addVarg(intLayout, 8), session); + .addVarg(intLayout, 8), arena.scope()); copy = list.copy(); } @@ -682,14 +681,14 @@ public static Object[][] upcalls() { return new Object[][]{ { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStruct"), VaListConsumer.mh(vaList -> { VaList copy = vaList.copy(); - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); @@ -703,7 +702,7 @@ public static Object[][] upcalls() { assertEquals((long) VH_BigPoint_y.get(struct), 16); })}, { linkVaListCB("upcallBigStructPlusScalar"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(BigPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_BigPoint_x.get(struct), 8); assertEquals((long) VH_BigPoint_y.get(struct), 16); @@ -715,28 +714,27 @@ public static Object[][] upcalls() { assertEquals(vaList.nextVarg(C_LONG_LONG), 42); })}, { linkVaListCB("upcallStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(Point_LAYOUT, SegmentScope.auto()); vaList.nextVarg(Point_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((int) VH_Point_x.get(struct), 5); assertEquals((int) VH_Point_y.get(struct), 10); })}, { linkVaListCB("upcallHugeStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(HugePoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(HugePoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((long) VH_HugePoint_x.get(struct), 1); assertEquals((long) VH_HugePoint_y.get(struct), 2); assertEquals((long) VH_HugePoint_z.get(struct), 3); })}, { linkVaListCB("upcallFloatStruct"), VaListConsumer.mh(vaList -> { - MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment struct = MemorySegment.allocateNative(FloatPoint_LAYOUT, SegmentScope.auto()); vaList.nextVarg(FloatPoint_LAYOUT, SegmentAllocator.prefixAllocator(struct)); assertEquals((float) VH_FloatPoint_x.get(struct), 1.0f); assertEquals((float) VH_FloatPoint_y.get(struct), 2.0f); })}, { linkVaListCB("upcallMemoryAddress"), VaListConsumer.mh(vaList -> { - MemoryAddress intPtr = vaList.nextVarg(C_POINTER); - MemorySegment ms = MemorySegment.ofAddress(intPtr, C_INT.byteSize(), MemorySession.global()); - int x = ms.get(JAVA_INT, 0); + MemorySegment intPtr = vaList.nextVarg(C_POINTER); + int x = intPtr.get(JAVA_INT, 0); assertEquals(x, 10); })}, { linkVaListCB("upcallDoubles"), VaListConsumer.mh(vaList -> { @@ -774,7 +772,7 @@ public static Object[][] upcalls() { assertEquals((float) vaList.nextVarg(C_DOUBLE), 13.0F); assertEquals(vaList.nextVarg(C_DOUBLE), 14.0D); - MemorySegment buffer = MemorySegment.allocateNative(BigPoint_LAYOUT, MemorySession.openImplicit()); + MemorySegment buffer = MemorySegment.allocateNative(BigPoint_LAYOUT, SegmentScope.auto()); SegmentAllocator bufferAllocator = SegmentAllocator.prefixAllocator(buffer); MemorySegment point = vaList.nextVarg(Point_LAYOUT, bufferAllocator); @@ -816,13 +814,17 @@ static MethodHandle mh(VaListConsumer instance) { MethodHandle handle = MethodHandles.lookup().findVirtual(VaListConsumer.class, "accept", MethodType.methodType(void.class, VaList.class)).bindTo(instance); return MethodHandles.filterArguments(handle, 0, - MethodHandles.insertArguments(ADDRESS_TO_VALIST, 1, MemorySession.openConfined())); + SEGMENT_TO_VALIST); } catch (ReflectiveOperationException e) { throw new InternalError(e); } } } + static VaList segmentToValist(MemorySegment segment) { + return VaList.ofAddress(segment.address(), SegmentScope.auto()); + } + @DataProvider public static Object[][] overflow() { List, VaList>> factories = List.of( @@ -868,7 +870,7 @@ private static void buildVaList(VaList.Builder builder, List conte } else if (layout instanceof ValueLayout.OfDouble ofDouble) { builder.addVarg(ofDouble, 1D); } else if (layout instanceof ValueLayout.OfAddress ofAddress) { - builder.addVarg(ofAddress, MemoryAddress.ofLong(1)); + builder.addVarg(ofAddress, MemorySegment.ofAddress(1)); } } } @@ -890,7 +892,7 @@ private static void nextVarg(VaList vaList, MemoryLayout layout) { } else if (layout instanceof ValueLayout.OfDouble ofDouble) { assertEquals(vaList.nextVarg(ofDouble), 1D); } else if (layout instanceof ValueLayout.OfAddress ofAddress) { - assertEquals(vaList.nextVarg(ofAddress), MemoryAddress.ofLong(1)); + assertEquals(vaList.nextVarg(ofAddress), MemorySegment.ofAddress(1)); } } diff --git a/test/jdk/java/foreign/virtual/TestVirtualCalls.java b/test/jdk/java/foreign/virtual/TestVirtualCalls.java index 7f0e7f1f1ff..eacccd4d893 100644 --- a/test/jdk/java/foreign/virtual/TestVirtualCalls.java +++ b/test/jdk/java/foreign/virtual/TestVirtualCalls.java @@ -31,10 +31,10 @@ * TestVirtualCalls */ -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.MemorySegment; import java.lang.invoke.MethodHandle; import org.testng.annotations.*; @@ -46,9 +46,9 @@ public class TestVirtualCalls extends NativeTestHelper { static final Linker abi = Linker.nativeLinker(); static final MethodHandle func; - static final Addressable funcA; - static final Addressable funcB; - static final Addressable funcC; + static final MemorySegment funcA; + static final MemorySegment funcB; + static final MemorySegment funcC; static { func = abi.downcallHandle( @@ -69,7 +69,7 @@ public void testVirtualCalls() throws Throwable { @Test(expectedExceptions = NullPointerException.class) public void testNullTarget() throws Throwable { - int x = (int) func.invokeExact((Addressable) null); + int x = (int) func.invokeExact((MemorySegment)null); } } diff --git a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java index ae5d5a6f2bf..5e676da446b 100644 --- a/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java +++ b/test/jdk/java/lang/Thread/jni/AttachCurrentThread/ImplicitAttach.java @@ -58,11 +58,11 @@ public static void main(String[] args) throws Throwable { .findStatic(ImplicitAttach.class, "callback", MethodType.methodType(void.class)); MemorySegment upcallStub = abi.upcallStub(callback, FunctionDescriptor.ofVoid(), - MemorySession.global()); + SegmentScope.global()); // void start_threads(int count, void *(*f)(void *)) SymbolLookup symbolLookup = SymbolLookup.loaderLookup(); - MemorySegment symbol = symbolLookup.lookup("start_threads").orElseThrow(); + MemorySegment symbol = symbolLookup.find("start_threads").orElseThrow(); FunctionDescriptor desc = FunctionDescriptor.ofVoid(C_INT, C_POINTER); MethodHandle start_threads = abi.downcallHandle(symbol, desc); diff --git a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java index fa29d2a85e2..261483c0ac2 100644 --- a/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java +++ b/test/jdk/java/lang/invoke/VarHandles/VarHandleTestExact.java @@ -46,9 +46,9 @@ * VarHandleTestExact */ +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import org.testng.SkipException; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -170,8 +170,8 @@ public void testExactBufferSet(Class arrayClass, Object testValue, SetBufferX @Test(dataProvider = "dataSetMemorySegment") public void testExactSegmentSet(Class carrier, Object testValue, SetSegmentX setter) { VarHandle vh = MethodHandles.memorySegmentViewVarHandle(MemoryLayout.valueLayout(carrier, ByteOrder.nativeOrder())); - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment seg = MemorySegment.allocateNative(8, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment seg = arena.allocate(8); doTest(vh, tvh -> tvh.set(seg, 0L, testValue), tvh -> setter.set(tvh, seg, 0L, testValue), diff --git a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java index 62a48b26b25..afd067605ae 100644 --- a/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java +++ b/test/jdk/java/nio/channels/FileChannel/LargeMapTest.java @@ -24,7 +24,7 @@ import jdk.test.lib.RandomFactory; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.io.IOException; import java.nio.ByteBuffer; @@ -78,7 +78,7 @@ public static void main(String[] args) throws IOException { try (FileChannel fc = FileChannel.open(p, READ, WRITE)) { MemorySegment mappedMemorySegment = fc.map(FileChannel.MapMode.READ_WRITE, 0, p.toFile().length(), - MemorySession.openImplicit()); + SegmentScope.auto()); MemorySegment target = mappedMemorySegment.asSlice(BASE, EXTRA); if (!target.asByteBuffer().equals(bb)) { throw new RuntimeException("Expected buffers to be equal"); diff --git a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java index 3a817cd9e28..b06af75c48d 100644 --- a/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java +++ b/test/jdk/java/nio/channels/FileChannel/MapToMemorySegmentTest.java @@ -30,8 +30,9 @@ import java.io.File; import java.io.IOException; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; @@ -61,21 +62,21 @@ public class MapToMemorySegmentTest { @Test(expectedExceptions = UnsupportedOperationException.class) public void testCustomFileChannel() throws IOException { - var session = MemorySession.openConfined(); + var arena = Arena.openConfined(); var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ); var fileChannel = new CustomFileChannel(fc); - try (session; fileChannel){ - fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, session); + try (arena; fileChannel){ + fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena.scope()); } } @Test public void testCustomFileChannelOverride() throws IOException { - var session = MemorySession.openConfined(); + var arena = Arena.openConfined(); var fc = FileChannel.open(tempPath, StandardOpenOption.WRITE, StandardOpenOption.READ); var fileChannel = new CustomFileChannelOverride(fc); - try (session; fileChannel){ - fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, session); + try (arena; fileChannel){ + fileChannel.map(FileChannel.MapMode.READ_WRITE, 1L, 10L, arena.scope()); } } @@ -160,10 +161,10 @@ static class CustomFileChannelOverride extends CustomFileChannel { public CustomFileChannelOverride(FileChannel fc) { super(fc); } @Override - public MemorySegment map(MapMode mode, long offset, long size, MemorySession session) + public MemorySegment map(MapMode mode, long offset, long size, SegmentScope scope) throws IOException, UnsupportedOperationException { - return fc.map(mode, offset, size, session); + return fc.map(mode, offset, size, scope); } } } diff --git a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java index 1e8ddae42bb..efe69ef3c36 100644 --- a/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java +++ b/test/jdk/java/util/stream/test/org/openjdk/tests/java/util/stream/SpliteratorTest.java @@ -22,8 +22,8 @@ */ package org.openjdk.tests.java.util.stream; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import org.testng.annotations.Test; @@ -65,8 +65,8 @@ public void testDoubleSpliterator(String name, Supplier su @Test(dataProvider = "SegmentSpliterator", dataProviderClass = SegmentTestDataProvider.class ) public void testSegmentSpliterator(String name, SequenceLayout layout, SpliteratorTestHelper.ContentAsserter contentAsserter) { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(layout, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(layout); SegmentTestDataProvider.initSegment(segment); SpliteratorTestHelper.testSpliterator(() -> segment.spliterator(layout), SegmentTestDataProvider::segmentCopier, contentAsserter); diff --git a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java index a664f65092b..8139931f41d 100644 --- a/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java +++ b/test/jdk/jdk/incubator/vector/AbstractVectorLoadStoreTest.java @@ -22,7 +22,7 @@ */ import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.Collection; @@ -36,25 +36,23 @@ public class AbstractVectorLoadStoreTest extends AbstractVectorTest { ByteOrder.BIG_ENDIAN, ByteOrder.LITTLE_ENDIAN); static final List> BYTE_BUFFER_GENERATORS = List.of( - withToString("HB:RW:NE", (int s) -> { - return ByteBuffer.allocate(s) - .order(ByteOrder.nativeOrder()); - }), - withToString("DB:RW:NE", (int s) -> { - return ByteBuffer.allocateDirect(s) - .order(ByteOrder.nativeOrder()); - }), - withToString("MS:RW:NE", (int s) -> { - return MemorySegment.allocateNative(s, MemorySession.openImplicit()) + withToString("HB:RW:NE", (int s) -> + ByteBuffer.allocate(s) + .order(ByteOrder.nativeOrder())), + withToString("DB:RW:NE", (int s) -> + ByteBuffer.allocateDirect(s) + .order(ByteOrder.nativeOrder())), + withToString("MS:RW:NE", (int s) -> + MemorySegment.allocateNative(s, SegmentScope.auto()) .asByteBuffer() - .order(ByteOrder.nativeOrder()); - }) + .order(ByteOrder.nativeOrder()) + ) ); static final List> MEMORY_SEGMENT_GENERATORS = List.of( - withToString("HMS", (int s) -> { - return MemorySegment.allocateNative(s, MemorySession.openImplicit()); - }), + withToString("HMS", (int s) -> + MemorySegment.allocateNative(s, SegmentScope.auto()) + ), withToString("DMS", (int s) -> { byte[] b = new byte[s]; return MemorySegment.ofArray(b); @@ -62,4 +60,3 @@ public class AbstractVectorLoadStoreTest extends AbstractVectorTest { ); } - diff --git a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java index 930c8ce791e..c588b03fb68 100644 --- a/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java index 0c52ddde4f3..0a60dc2742c 100644 --- a/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java index c9990cdf2ce..807a1647532 100644 --- a/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java index 10312b7cb5f..1274106caff 100644 --- a/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Byte64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java index a9042cb65f9..1d956bc339c 100644 --- a/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ByteMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ByteVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "byteByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "byteByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "byteByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Byte.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Byte.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java index 68dd22c966e..4ff63cf1fda 100644 --- a/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java index b6a3fe5fe61..ef3ab3d5b26 100644 --- a/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java index 99b44ada0aa..4a3a0bc4f8a 100644 --- a/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java index b69de8938a5..7d242995c1f 100644 --- a/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Double64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java index eb8d201bee5..137f7ba5791 100644 --- a/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/DoubleMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.DoubleVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "doubleByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "doubleByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Double.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Double.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java index 2efaf867c66..719b803b69b 100644 --- a/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java index 18baffa0e90..26f2f02883f 100644 --- a/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java index d1ba7a644de..53e75fa62c7 100644 --- a/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java index 83ecf751cb5..6ea43adfec4 100644 --- a/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Float64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java index 64148eaabdb..f67bf1e3267 100644 --- a/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/FloatMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.FloatVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "floatByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "floatByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "floatByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Float.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Float.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java index 7ddc9f6ee55..d6bf4dedc3e 100644 --- a/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java index 97b2e1ecc14..c2d0077a8cd 100644 --- a/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java index d6e3f18a2c5..e9b70d9c93b 100644 --- a/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java index b9157d93295..28633c1b345 100644 --- a/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Int64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java index 2891c0c142e..f128184026b 100644 --- a/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/IntMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.IntVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "intByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction f @Test(dataProvider = "intByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "intByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Integer.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Integer.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java index cebd1c4cb32..81b5ebd8fff 100644 --- a/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java index 2be1356e3bd..ca6d4d74243 100644 --- a/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java index 43cb1898573..5ad19715622 100644 --- a/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java index 48a3e94bbbb..1041d47d96c 100644 --- a/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Long64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java index e21cedfae09..e20d33d2026 100644 --- a/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/LongMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.LongVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "longByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "longByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "longByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Long.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Long.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java index 13b59c5ffbc..2a153318cae 100644 --- a/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short128VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java index ad2204cc822..407f5affdf4 100644 --- a/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short256VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java index fb04ca5779d..d32d6735030 100644 --- a/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short512VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java index 157a0638bdb..6ab8817b22d 100644 --- a/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/Short64VectorLoadStoreTests.java @@ -32,7 +32,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -479,8 +479,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -508,8 +508,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -572,8 +572,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -603,8 +603,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java index 1129f5cd83a..7fb1c43ba3b 100644 --- a/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java +++ b/test/jdk/jdk/incubator/vector/ShortMaxVectorLoadStoreTests.java @@ -33,7 +33,7 @@ // -- This file was mechanically generated: Do not edit! -- // import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorMask; @@ -486,8 +486,8 @@ static void loadStoreMemorySegment(IntFunction fa, @Test(dataProvider = "shortByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -515,8 +515,8 @@ static void loadMemorySegmentIOOBE(IntFunction fa, IntFunction @Test(dataProvider = "shortByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -579,8 +579,8 @@ static void loadStoreMemorySegmentMask(IntFunction fa, @Test(dataProvider = "shortByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); @@ -610,8 +610,8 @@ static void loadMemorySegmentMaskIOOBE(IntFunction fa, IntFunction fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, Short.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), Short.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/jdk/jdk/incubator/vector/gen-template.sh b/test/jdk/jdk/incubator/vector/gen-template.sh index 8c495bc4f96..8a009bb9fb9 100644 --- a/test/jdk/jdk/incubator/vector/gen-template.sh +++ b/test/jdk/jdk/incubator/vector/gen-template.sh @@ -223,6 +223,7 @@ function gen_op_tmpl { replace_variables $unit_filename $unit_output "$kernel" "$test" "$op" "$init" "$guard" "$masked" "$op_name" "$kernel_smoke" local gen_perf_tests=$generate_perf_tests + gen_perf_tests=true if [[ $template == *"-Broadcast-"* ]] || [[ $template == "Miscellaneous" ]] || [[ $template == *"Compare-Masked"* ]] || [[ $template == *"Compare-Broadcast"* ]]; then gen_perf_tests=false diff --git a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template index 7e27bfe96bf..ada362cee8f 100644 --- a/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template +++ b/test/jdk/jdk/incubator/vector/templates/X-LoadStoreTest.java.template @@ -37,7 +37,7 @@ #warn This file is preprocessed before being compiled import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.ValueLayout; import jdk.incubator.vector.$Type$Vector; import jdk.incubator.vector.VectorMask; @@ -499,8 +499,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteProviderForIOOBE") static void loadMemorySegmentIOOBE(IntFunction<$type$[]> fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -528,8 +528,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteProviderForIOOBE") static void storeMemorySegmentIOOBE(IntFunction<$type$[]> fa, IntFunction fi) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); int l = (int) a.byteSize(); int s = SPECIES.vectorByteSize(); @@ -592,8 +592,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteMaskProviderForIOOBE") static void loadMemorySegmentMaskIOOBE(IntFunction<$type$[]> fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask<$Boxtype$> vmask = VectorMask.fromValues(SPECIES, mask); @@ -623,8 +623,8 @@ public class $vectorteststype$ extends AbstractVectorLoadStoreTest { @Test(dataProvider = "$type$ByteMaskProviderForIOOBE") static void storeMemorySegmentMaskIOOBE(IntFunction<$type$[]> fa, IntFunction fi, IntFunction fm) { - MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, MemorySession.openImplicit())); - MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, MemorySession.openImplicit()); + MemorySegment a = toSegment(fa.apply(SPECIES.length()), i -> MemorySegment.allocateNative(i, $Boxtype$.SIZE, SegmentScope.auto())); + MemorySegment r = MemorySegment.allocateNative(a.byteSize(), $Boxtype$.SIZE, SegmentScope.auto()); boolean[] mask = fm.apply(SPECIES.length()); VectorMask<$Boxtype$> vmask = VectorMask.fromValues(SPECIES, mask); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java index a8fb7d9fc37..61b705e5b26 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkMismatchAcquire.java @@ -37,8 +37,8 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import java.util.function.Supplier; @@ -52,18 +52,17 @@ public class BulkMismatchAcquire { public enum SessionKind { - CONFINED(MemorySession::openConfined), - SHARED(MemorySession::openShared), - IMPLICIT(MemorySession::openImplicit); + CONFINED(Arena::openConfined), + SHARED(Arena::openShared); - final Supplier sessionFactory; + final Supplier arenaFactory; - SessionKind(Supplier sessionFactory) { - this.sessionFactory = sessionFactory; + SessionKind(Supplier arenaFactory) { + this.arenaFactory = arenaFactory; } - MemorySession makeSession() { - return sessionFactory.get(); + Arena makeArena() { + return arenaFactory.get(); } } @@ -73,7 +72,7 @@ MemorySession makeSession() { // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; - MemorySession session; + Arena arena; MemorySegment mismatchSegmentLarge1; MemorySegment mismatchSegmentLarge2; ByteBuffer mismatchBufferLarge1; @@ -85,15 +84,15 @@ MemorySession makeSession() { @Setup public void setup() { - session = sessionKind.makeSession(); - mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); - mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); + arena = sessionKind.makeArena(); + mismatchSegmentLarge1 = arena.allocate(SIZE_WITH_TAIL); + mismatchSegmentLarge2 = arena.allocate(SIZE_WITH_TAIL); mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); // mismatch at first byte - mismatchSegmentSmall1 = MemorySegment.allocateNative(7, session); - mismatchSegmentSmall2 = MemorySegment.allocateNative(7, session); + mismatchSegmentSmall1 = arena.allocate(7); + mismatchSegmentSmall2 = arena.allocate(7); mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); { @@ -117,9 +116,7 @@ public void setup() { @TearDown public void tearDown() { - if (session.isCloseable()) { - session.close(); - } + arena.close(); } @Benchmark @@ -132,7 +129,7 @@ public long mismatch_large_segment() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_large_segment_acquire() { long[] arr = new long[1]; - mismatchSegmentLarge1.session().whileAlive(() -> { + mismatchSegmentLarge1.scope().whileAlive(() -> { arr[0] = mismatchSegmentLarge1.mismatch(mismatchSegmentSmall2); }); return arr[0]; @@ -154,7 +151,7 @@ public long mismatch_small_segment() { @OutputTimeUnit(TimeUnit.NANOSECONDS) public long mismatch_small_segment_acquire() { long[] arr = new long[1]; - mismatchSegmentLarge1.session().whileAlive(() -> { + mismatchSegmentLarge1.scope().whileAlive(() -> { arr[0] = mismatchSegmentSmall1.mismatch(mismatchSegmentSmall2); }); return arr[0]; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java index cfb11d937e5..64ad5c4b377 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/BulkOps.java @@ -37,14 +37,15 @@ import org.openjdk.jmh.annotations.Warmup; import sun.misc.Unsafe; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; import java.nio.ByteBuffer; import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; import static java.lang.foreign.ValueLayout.JAVA_BYTE; import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_INT_UNALIGNED; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -60,10 +61,10 @@ public class BulkOps { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - final MemorySession session = MemorySession.openConfined(); + final Arena arena = Arena.openShared(); final long unsafe_addr = unsafe.allocateMemory(ALLOC_SIZE); - final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); final IntBuffer buffer = IntBuffer.allocate(ELEM_SIZE); final int[] ints = new int[ELEM_SIZE]; @@ -72,14 +73,14 @@ public class BulkOps { // large(ish) segments/buffers with same content, 0, for mismatch, non-multiple-of-8 sized static final int SIZE_WITH_TAIL = (1024 * 1024) + 7; - final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); - final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, session); + final MemorySegment mismatchSegmentLarge1 = MemorySegment.allocateNative(SIZE_WITH_TAIL, arena.scope()); + final MemorySegment mismatchSegmentLarge2 = MemorySegment.allocateNative(SIZE_WITH_TAIL, arena.scope());; final ByteBuffer mismatchBufferLarge1 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); final ByteBuffer mismatchBufferLarge2 = ByteBuffer.allocateDirect(SIZE_WITH_TAIL); // mismatch at first byte - final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, session); - final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, session); + final MemorySegment mismatchSegmentSmall1 = MemorySegment.allocateNative(7, arena.scope());; + final MemorySegment mismatchSegmentSmall2 = MemorySegment.allocateNative(7, arena.scope());; final ByteBuffer mismatchBufferSmall1 = ByteBuffer.allocateDirect(7); final ByteBuffer mismatchBufferSmall2 = ByteBuffer.allocateDirect(7); @@ -108,7 +109,7 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark @@ -138,20 +139,20 @@ public void segment_copy() { @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, ints.length); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, ints.length); } @Benchmark @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_small() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, 10); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, 10); } @Benchmark @CompilerControl(CompilerControl.Mode.DONT_INLINE) @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_small_dontinline() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, 10); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, 10); } @Benchmark @@ -176,7 +177,7 @@ public void buffer_copy() { @CompilerControl(CompilerControl.Mode.DONT_INLINE) @OutputTimeUnit(TimeUnit.NANOSECONDS) public void segment_copy_static_dontinline() { - MemorySegment.copy(ints, 0, segment, JAVA_BYTE, 0, ints.length); + MemorySegment.copy(ints, 0, segment, JAVA_INT_UNALIGNED, 0, ints.length); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java index 24cc10047d3..d88838905fd 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CLayouts.java @@ -23,10 +23,9 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.MemorySegment; import java.lang.foreign.ValueLayout; import java.lang.invoke.MethodHandle; @@ -67,17 +66,17 @@ public class CLayouts { /** * The {@code T*} native type. */ - public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS; + public static final ValueLayout.OfAddress C_POINTER = ValueLayout.ADDRESS.asUnbounded(); private static Linker LINKER = Linker.nativeLinker(); private static final MethodHandle FREE = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); + LINKER.defaultLookup().find("free").get(), FunctionDescriptor.ofVoid(ValueLayout.ADDRESS)); private static final MethodHandle MALLOC = LINKER.downcallHandle( - LINKER.defaultLookup().lookup("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS, ValueLayout.JAVA_LONG)); + LINKER.defaultLookup().find("malloc").get(), FunctionDescriptor.of(ValueLayout.ADDRESS.asUnbounded(), ValueLayout.JAVA_LONG)); - public static void freeMemory(Addressable address) { + public static void freeMemory(MemorySegment address) { try { FREE.invokeExact(address); } catch (Throwable ex) { @@ -85,9 +84,9 @@ public static void freeMemory(Addressable address) { } } - public static MemoryAddress allocateMemory(long size) { + public static MemorySegment allocateMemory(long size) { try { - return (MemoryAddress)MALLOC.invokeExact(size); + return (MemorySegment)MALLOC.invokeExact(size); } catch (Throwable ex) { throw new IllegalStateException(ex); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java index d87c48b56f5..e542276ccf6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadConstant.java @@ -22,8 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -87,53 +85,38 @@ public MemorySegment panama_identity_struct_shared_3() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_shared() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(confinedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(sharedPoint, sharedPoint, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(confinedPoint, confinedPoint, confinedPoint); } @Benchmark - public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)sharedPoint); + public MemorySegment panama_identity_memory_address_null() throws Throwable { + return (MemorySegment) identity_memory_address.invokeExact(MemorySegment.NULL); } @Benchmark - public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)confinedPoint); + public MemorySegment panama_identity_memory_address_null_3() throws Throwable { + return (MemorySegment) identity_memory_address_3.invokeExact(MemorySegment.NULL, MemorySegment.NULL, MemorySegment.NULL); } @Benchmark - public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3.invokeExact((Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_memory_address_null() throws Throwable { - return (MemoryAddress) identity_memory_address.invokeExact((Addressable)MemoryAddress.NULL); - } - - @Benchmark - public MemoryAddress panama_identity_memory_address_null_non_exact() throws Throwable { - return (MemoryAddress) identity_memory_address.invoke(MemoryAddress.NULL); + public MemorySegment panama_identity_memory_address_null_non_exact() throws Throwable { + return (MemorySegment) identity_memory_address.invoke(MemorySegment.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java index 32ff0ffdee1..bbbc0afbb0f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadHelper.java @@ -22,12 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; import java.lang.foreign.SymbolLookup; @@ -42,51 +42,51 @@ public class CallOverheadHelper extends CLayouts { static final MethodHandle func; static final MethodHandle func_v; - static Addressable func_addr; + static MemorySegment func_addr; static final MethodHandle identity; static final MethodHandle identity_v; - static Addressable identity_addr; + static MemorySegment identity_addr; static final MethodHandle identity_struct; static final MethodHandle identity_struct_v; - static Addressable identity_struct_addr; + static MemorySegment identity_struct_addr; static final MethodHandle identity_struct_3; static final MethodHandle identity_struct_3_v; - static Addressable identity_struct_3_addr; + static MemorySegment identity_struct_3_addr; static final MethodHandle identity_memory_address; static final MethodHandle identity_memory_address_v; - static Addressable identity_memory_address_addr; + static MemorySegment identity_memory_address_addr; static final MethodHandle identity_memory_address_3; static final MethodHandle identity_memory_address_3_v; - static Addressable identity_memory_address_3_addr; + static MemorySegment identity_memory_address_3_addr; static final MethodHandle args1; static final MethodHandle args1_v; - static Addressable args1_addr; + static MemorySegment args1_addr; static final MethodHandle args2; static final MethodHandle args2_v; - static Addressable args2_addr; + static MemorySegment args2_addr; static final MethodHandle args3; static final MethodHandle args3_v; - static Addressable args3_addr; + static MemorySegment args3_addr; static final MethodHandle args4; static final MethodHandle args4_v; - static Addressable args4_addr; + static MemorySegment args4_addr; static final MethodHandle args5; static final MethodHandle args5_v; - static Addressable args5_addr; + static MemorySegment args5_addr; static final MethodHandle args10; static final MethodHandle args10_v; - static Addressable args10_addr; + static MemorySegment args10_addr; static final MemoryLayout POINT_LAYOUT = MemoryLayout.structLayout( C_INT, C_INT ); - static final MemorySegment sharedPoint = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openShared()); - static final MemorySegment confinedPoint = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openConfined()); + static final MemorySegment sharedPoint = MemorySegment.allocateNative(POINT_LAYOUT, Arena.openShared().scope()); + static final MemorySegment confinedPoint = MemorySegment.allocateNative(POINT_LAYOUT, Arena.openConfined().scope()); - static final MemorySegment point = MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openImplicit()); + static final MemorySegment point = MemorySegment.allocateNative(POINT_LAYOUT, SegmentScope.auto()); - static final SegmentAllocator recycling_allocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(POINT_LAYOUT, MemorySession.openImplicit())); + static final SegmentAllocator recycling_allocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(POINT_LAYOUT, SegmentScope.auto())); static { System.loadLibrary("CallOverheadJNI"); @@ -94,64 +94,64 @@ public class CallOverheadHelper extends CLayouts { System.loadLibrary("CallOverhead"); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); { - func_addr = loaderLibs.lookup("func").orElseThrow(); + func_addr = loaderLibs.find("func").orElseThrow(); MethodType mt = MethodType.methodType(void.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(); func_v = abi.downcallHandle(fd); func = insertArguments(func_v, 0, func_addr); } { - identity_addr = loaderLibs.lookup("identity").orElseThrow(); + identity_addr = loaderLibs.find("identity").orElseThrow(); FunctionDescriptor fd = FunctionDescriptor.of(C_INT, C_INT); identity_v = abi.downcallHandle(fd); identity = insertArguments(identity_v, 0, identity_addr); } - identity_struct_addr = loaderLibs.lookup("identity_struct").orElseThrow(); + identity_struct_addr = loaderLibs.find("identity_struct").orElseThrow(); identity_struct_v = abi.downcallHandle( FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT)); identity_struct = insertArguments(identity_struct_v, 0, identity_struct_addr); - identity_struct_3_addr = loaderLibs.lookup("identity_struct_3").orElseThrow(); + identity_struct_3_addr = loaderLibs.find("identity_struct_3").orElseThrow(); identity_struct_3_v = abi.downcallHandle( FunctionDescriptor.of(POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT, POINT_LAYOUT)); identity_struct_3 = insertArguments(identity_struct_3_v, 0, identity_struct_3_addr); - identity_memory_address_addr = loaderLibs.lookup("identity_memory_address").orElseThrow(); + identity_memory_address_addr = loaderLibs.find("identity_memory_address").orElseThrow(); identity_memory_address_v = abi.downcallHandle( FunctionDescriptor.of(C_POINTER, C_POINTER)); identity_memory_address = insertArguments(identity_memory_address_v, 0, identity_memory_address_addr); - identity_memory_address_3_addr = loaderLibs.lookup("identity_memory_address_3").orElseThrow(); + identity_memory_address_3_addr = loaderLibs.find("identity_memory_address_3").orElseThrow(); identity_memory_address_3_v = abi.downcallHandle( FunctionDescriptor.of(C_POINTER, C_POINTER, C_POINTER, C_POINTER)); identity_memory_address_3 = insertArguments(identity_memory_address_3_v, 0, identity_memory_address_3_addr); - args1_addr = loaderLibs.lookup("args1").orElseThrow(); + args1_addr = loaderLibs.find("args1").orElseThrow(); args1_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG)); args1 = insertArguments(args1_v, 0, args1_addr); - args2_addr = loaderLibs.lookup("args2").orElseThrow(); + args2_addr = loaderLibs.find("args2").orElseThrow(); args2_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE)); args2 = insertArguments(args2_v, 0, args2_addr); - args3_addr = loaderLibs.lookup("args3").orElseThrow(); + args3_addr = loaderLibs.find("args3").orElseThrow(); args3_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args3 = insertArguments(args3_v, 0, args3_addr); - args4_addr = loaderLibs.lookup("args4").orElseThrow(); + args4_addr = loaderLibs.find("args4").orElseThrow(); args4_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); args4 = insertArguments(args4_v, 0, args4_addr); - args5_addr = loaderLibs.lookup("args5").orElseThrow(); + args5_addr = loaderLibs.find("args5").orElseThrow(); args5_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG)); args5 = insertArguments(args5_v, 0, args5_addr); - args10_addr = loaderLibs.lookup("args10").orElseThrow(); + args10_addr = loaderLibs.find("args10").orElseThrow(); args10_v = abi.downcallHandle( FunctionDescriptor.ofVoid(C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE, C_LONG_LONG, C_DOUBLE)); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java index 10fe5a9055b..de3b275e034 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/CallOverheadVirtual.java @@ -22,8 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -81,43 +79,23 @@ public MemorySegment panama_identity_struct_shared_3() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_shared() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)confinedPoint.address()); + public MemorySegment panama_identity_memory_address_confined() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, confinedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address(), (Addressable)sharedPoint.address()); + public MemorySegment panama_identity_memory_address_shared_3() throws Throwable { + return (MemorySegment) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, sharedPoint, sharedPoint, sharedPoint); } @Benchmark - public MemoryAddress panama_identity_memory_address_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address(), (Addressable)confinedPoint.address()); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_shared() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_struct_addr, (Addressable)confinedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_shared_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)sharedPoint, (Addressable)sharedPoint, (Addressable)sharedPoint); - } - - @Benchmark - public MemoryAddress panama_identity_struct_ref_confined_3() throws Throwable { - return (MemoryAddress) identity_memory_address_3_v.invokeExact(identity_struct_3_addr, (Addressable)confinedPoint, (Addressable)confinedPoint, (Addressable)confinedPoint); + public MemorySegment panama_identity_memory_address_confined_3() throws Throwable { + return (MemorySegment) identity_memory_address_3_v.invokeExact(identity_memory_address_3_addr, confinedPoint, confinedPoint, confinedPoint); } @Benchmark @@ -131,8 +109,8 @@ public MemorySegment panama_identity_struct() throws Throwable { } @Benchmark - public MemoryAddress panama_identity_memory_address_null() throws Throwable { - return (MemoryAddress) identity_memory_address_v.invokeExact(identity_memory_address_addr, (Addressable)MemoryAddress.NULL); + public MemorySegment panama_identity_memory_address_null() throws Throwable { + return (MemorySegment) identity_memory_address_v.invokeExact(identity_memory_address_addr, MemorySegment.NULL); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java index bc395a23105..56ebaad5410 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/JavaLayouts.java @@ -26,29 +26,15 @@ import java.lang.foreign.ValueLayout; import java.lang.invoke.VarHandle; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; -import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.*; /** * Some useful Java {@link ValueLayout} and associated {@link ValueLayout#arrayElementVarHandle(int...)} var handles. */ public class JavaLayouts { - static final ValueLayout.OfInt JAVA_INT_UNALIGNED = JAVA_INT.withBitAlignment(8); - - static final ValueLayout.OfFloat JAVA_FLOAT_UNALIGNED = JAVA_FLOAT.withBitAlignment(8); - - static final ValueLayout.OfLong JAVA_LONG_UNALIGNED = JAVA_LONG.withBitAlignment(8); static final VarHandle VH_INT_UNALIGNED = JAVA_INT_UNALIGNED.arrayElementVarHandle(); static final VarHandle VH_INT = JAVA_INT.arrayElementVarHandle(); - static final VarHandle VH_FLOAT_UNALIGNED = JAVA_FLOAT_UNALIGNED.arrayElementVarHandle(); - - static final VarHandle VH_FLOAT = JAVA_FLOAT.arrayElementVarHandle(); - - static final VarHandle VH_LONG_UNALIGNED = JAVA_LONG_UNALIGNED.arrayElementVarHandle(); - - static final VarHandle VH_LONG = JAVA_LONG.arrayElementVarHandle(); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java index 917370d2157..57b42a0e24a 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LinkUpcall.java @@ -35,7 +35,7 @@ import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; import java.util.concurrent.TimeUnit; @@ -64,7 +64,7 @@ public class LinkUpcall extends CLayouts { @Benchmark public MemorySegment link_blank() { - return LINKER.upcallStub(BLANK, BLANK_DESC, MemorySession.openImplicit()); + return LINKER.upcallStub(BLANK, BLANK_DESC, SegmentScope.auto()); } static void blank() {} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java index ded0d8ca09f..a01891894f7 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverConstant.java @@ -22,7 +22,6 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.MemorySession; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -37,11 +36,12 @@ import sun.misc.Unsafe; import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -69,7 +69,7 @@ public class LoopOverConstant extends JavaLayouts { //setup native memory segment - static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openImplicit()); + static final MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, SegmentScope.auto()); static { for (int i = 0; i < ELEM_SIZE; i++) { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java index c1598522516..05be20222fa 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNew.java @@ -22,10 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -42,7 +44,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -58,12 +60,12 @@ public class LoopOverNew extends JavaLayouts { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; static final MemoryLayout ALLOC_LAYOUT = MemoryLayout.sequenceLayout(ELEM_SIZE, JAVA_INT); - final MemorySession session = MemorySession.openConfined(); - final SegmentAllocator recyclingAlloc = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(ALLOC_LAYOUT, session)); + final Arena arena = Arena.openConfined(); + final SegmentAllocator recyclingAlloc = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(ALLOC_LAYOUT, arena.scope())); @TearDown public void tearDown() throws Throwable { - session.close(); + arena.close(); } @Benchmark @@ -77,8 +79,8 @@ public void unsafe_loop() { @Benchmark public void segment_loop_confined() { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocate(ALLOC_SIZE, 4); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -87,8 +89,8 @@ public void segment_loop_confined() { @Benchmark public void segment_loop_shared() { - try (MemorySession session = MemorySession.openShared()) { - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openShared()) { + MemorySegment segment = arena.allocate(ALLOC_SIZE, 4); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -133,7 +135,7 @@ public void buffer_loop_implicit() { @Benchmark public void segment_loop_implicit() { if (gcCount++ == 0) System.gc(); // GC when we overflow - MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + MemorySegment segment = MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java index 5793b427074..2fd596d8a36 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNewHeap.java @@ -40,7 +40,7 @@ import java.nio.IntBuffer; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java index a287b1120f6..c5b697b8ac8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstant.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -40,7 +41,7 @@ import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -55,6 +56,8 @@ public class LoopOverNonConstant extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + + Arena arena; MemorySegment segment; long unsafe_addr; @@ -66,7 +69,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(unsafe_addr + (i * CARRIER_SIZE) , i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -78,7 +82,7 @@ public void setup() { @TearDown public void tearDown() { - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); unsafe.freeMemory(unsafe_addr); } @@ -157,24 +161,6 @@ public int segment_loop_instance_unaligned() { return res; } - @Benchmark - public int segment_loop_instance_address() { - int sum = 0; - for (int i = 0; i < ELEM_SIZE; i++) { - sum += segment.address().get(JAVA_INT, i * CARRIER_SIZE); - } - return sum; - } - - @Benchmark - public int segment_loop_instance_address_index() { - int sum = 0; - for (int i = 0; i < ELEM_SIZE; i++) { - sum += segment.address().getAtIndex(JAVA_INT, i); - } - return sum; - } - @Benchmark public int segment_loop_slice() { int sum = 0; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java index 65f818c71b1..430a3b69d04 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantFP.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -56,7 +57,7 @@ public class LoopOverNonConstantFP { static final int CARRIER_SIZE = (int)JAVA_DOUBLE.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; - MemorySession session; + Arena arena; MemorySegment segmentIn, segmentOut; long unsafe_addrIn, unsafe_addrOut; ByteBuffer byteBufferIn, byteBufferOut; @@ -71,9 +72,9 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putDouble(unsafe_addrOut + (i * CARRIER_SIZE), i); } - session = MemorySession.openConfined(); - segmentIn = MemorySegment.allocateNative(ALLOC_SIZE, session); - segmentOut = MemorySegment.allocateNative(ALLOC_SIZE, session); + arena = Arena.openConfined(); + segmentIn = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); + segmentOut = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { segmentIn.setAtIndex(JAVA_DOUBLE, i, i); } @@ -92,7 +93,7 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + arena.close(); unsafe.invokeCleaner(byteBufferIn); unsafe.invokeCleaner(byteBufferOut); unsafe.freeMemory(unsafe_addrIn); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java index c49c050cbe8..386fe2691ea 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantHeap.java @@ -23,7 +23,7 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -37,14 +37,12 @@ import org.openjdk.jmh.annotations.Warmup; import sun.misc.Unsafe; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; -import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; -import static java.lang.foreign.ValueLayout.JAVA_FLOAT; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -78,7 +76,7 @@ public void setup() { MemorySegment intI = MemorySegment.ofArray(new int[ALLOC_SIZE]); MemorySegment intD = MemorySegment.ofArray(new double[ALLOC_SIZE]); MemorySegment intF = MemorySegment.ofArray(new float[ALLOC_SIZE]); - MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, MemorySession.openConfined()); + MemorySegment s = MemorySegment.allocateNative(ALLOC_SIZE, 1, SegmentScope.auto()); for (int i = 0; i < ALLOC_SIZE; i++) { intB.set(JAVA_BYTE, i, (byte)i); intI.setAtIndex(JAVA_INT, i, i); diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java index f208586eb97..0572223f84e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantMapped.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -47,7 +48,7 @@ import java.nio.file.StandardOpenOption; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -78,6 +79,7 @@ public class LoopOverNonConstantMapped extends JavaLayouts { } FileChannel fileChannel; + Arena arena; MemorySegment segment; long unsafe_addr; @@ -93,14 +95,15 @@ public void setup() throws IOException { ((MappedByteBuffer)byteBuffer).force(); } fileChannel = FileChannel.open(tempPath, StandardOpenOption.READ, StandardOpenOption.WRITE); - segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, ALLOC_SIZE, MemorySession.openConfined()); - unsafe_addr = segment.address().toRawLongValue(); + arena = Arena.openConfined(); + segment = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0L, ALLOC_SIZE, arena.scope()); + unsafe_addr = segment.address(); } @TearDown public void tearDown() throws IOException { fileChannel.close(); - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); } @@ -149,15 +152,6 @@ public int segment_loop_instance() { return res; } - @Benchmark - public int segment_loop_instance_address() { - int res = 0; - for (int i = 0; i < ELEM_SIZE; i ++) { - res += segment.address().get(JAVA_INT, i * CARRIER_SIZE); - } - return res; - } - @Benchmark public int segment_loop_slice() { int sum = 0; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java index dd61a3cf3b5..f3d47fed5d1 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverNonConstantShared.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -55,6 +56,7 @@ public class LoopOverNonConstantShared extends JavaLayouts { static final int ELEM_SIZE = 1_000_000; static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + Arena arena; MemorySegment segment; long unsafe_addr; @@ -66,7 +68,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(unsafe_addr + (i * CARRIER_SIZE) , i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -78,7 +81,7 @@ public void setup() { @TearDown public void tearDown() { - segment.session().close(); + arena.close(); unsafe.invokeCleaner(byteBuffer); unsafe.freeMemory(unsafe_addr); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java new file mode 100644 index 00000000000..2463856fbdf --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverOfAddress.java @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2020, 2022, 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.java.lang.foreign; + +import java.lang.foreign.MemorySegment; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.SegmentScope; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@State(org.openjdk.jmh.annotations.Scope.Thread) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = "--enable-preview") +public class LoopOverOfAddress extends JavaLayouts { + + static final int ITERATIONS = 1_000_000; + + @Benchmark + public long segment_loop_addr() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i % 100).address(); + } + return res; + } + + @Benchmark + public long segment_loop_addr_size() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i, i % 100).address(); + } + return res; + } + + @Benchmark + public long segment_loop_addr_size_session() { + long res = 0; + for (int i = 0; i < ITERATIONS; i++) { + res += MemorySegment.ofAddress(i, i % 100, SegmentScope.global()).address(); + } + return res; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java index 6ed7ab6bc29..425a1adce44 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverPollutedSegments.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -38,7 +39,7 @@ import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -55,7 +56,7 @@ public class LoopOverPollutedSegments extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; - MemorySession session; + Arena confinedArena, sharedArena; MemorySegment nativeSegment, nativeSharedSegment, heapSegmentBytes, heapSegmentFloats; byte[] arr; long addr; @@ -67,8 +68,10 @@ public void setup() { unsafe.putInt(addr + (i * 4), i); } arr = new byte[ALLOC_SIZE]; - nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session = MemorySession.openConfined()); - nativeSharedSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + confinedArena = Arena.openConfined(); + sharedArena = Arena.openShared(); + nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, confinedArena.scope()); + nativeSharedSegment = MemorySegment.allocateNative(ALLOC_SIZE, 4, sharedArena.scope()); heapSegmentBytes = MemorySegment.ofArray(new byte[ALLOC_SIZE]); heapSegmentFloats = MemorySegment.ofArray(new float[ELEM_SIZE]); @@ -92,7 +95,8 @@ public void setup() { @TearDown public void tearDown() { - session.close(); + confinedArena.close(); + sharedArena.close(); heapSegmentBytes = null; heapSegmentFloats = null; arr = null; diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java index 4c5e79c483a..23ac72d0e68 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/LoopOverSlice.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -56,19 +57,22 @@ public class LoopOverSlice { static final int CARRIER_SIZE = (int)JAVA_INT.byteSize(); static final int ALLOC_SIZE = ELEM_SIZE * CARRIER_SIZE; + Arena arena; MemorySegment nativeSegment, heapSegment; IntBuffer nativeBuffer, heapBuffer; @Setup public void setup() { - nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, MemorySession.openConfined()); + arena = Arena.openConfined(); + nativeSegment = MemorySegment.allocateNative(ALLOC_SIZE, arena.scope()); heapSegment = MemorySegment.ofArray(new int[ELEM_SIZE]); nativeBuffer = ByteBuffer.allocateDirect(ALLOC_SIZE).order(ByteOrder.LITTLE_ENDIAN).asIntBuffer(); heapBuffer = IntBuffer.wrap(new int[ELEM_SIZE]); } @TearDown - public void tearDown() { nativeSegment.session().close(); + public void tearDown() { + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java index e609da7fa7e..6df2fb0d6c1 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/MemorySessionClose.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -36,10 +37,9 @@ import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.util.ArrayList; import java.util.List; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; @BenchmarkMode(Mode.AverageTime) @@ -104,27 +104,27 @@ public void tearDown() throws Throwable { @Benchmark public MemorySegment confined_close() { - try (MemorySession session = MemorySession.openConfined()) { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openConfined()) { + return arena.allocate(ALLOC_SIZE, 4); } } @Benchmark public MemorySegment shared_close() { - try (MemorySession session = MemorySession.openShared()) { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, session); + try (Arena arena = Arena.openShared()) { + return arena.allocate(ALLOC_SIZE, 4); } } @Benchmark public MemorySegment implicit_close() { - return MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + return MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); } @Benchmark public MemorySegment implicit_close_systemgc() { if (gcCount++ == 0) System.gc(); // GC when we overflow - return MemorySegment.allocateNative(ALLOC_SIZE, 4, MemorySession.openImplicit()); + return MemorySegment.allocateNative(ALLOC_SIZE, 4, SegmentScope.auto()); } // keep diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java index 05128cedbb7..78575b3c45c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/ParallelSum.java @@ -23,10 +23,11 @@ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; -import java.lang.foreign.MemorySession; import java.lang.foreign.SequenceLayout; import java.lang.foreign.ValueLayout; + import sun.misc.Unsafe; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; @@ -68,6 +69,7 @@ public class ParallelSum extends JavaLayouts { static final Unsafe unsafe = Utils.unsafe; + Arena arena; MemorySegment segment; long address; @@ -77,7 +79,8 @@ public void setup() { for (int i = 0; i < ELEM_SIZE; i++) { unsafe.putInt(address + (i * CARRIER_SIZE), i); } - segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, MemorySession.openShared()); + arena = Arena.openShared(); + segment = MemorySegment.allocateNative(ALLOC_SIZE, CARRIER_SIZE, arena.scope()); for (int i = 0; i < ELEM_SIZE; i++) { VH_INT.set(segment, (long) i, i); } @@ -86,7 +89,7 @@ public void setup() { @TearDown public void tearDown() throws Throwable { unsafe.freeMemory(address); - segment.session().close(); + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java index d7abdb72885..6f4aa4c17b6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/PointerInvoke.java @@ -25,16 +25,14 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; -import org.openjdk.jmh.annotations.Setup; -import org.openjdk.jmh.annotations.Param; import org.openjdk.jmh.annotations.TearDown; import org.openjdk.jmh.annotations.Measurement; import org.openjdk.jmh.annotations.Mode; @@ -54,8 +52,8 @@ @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) public class PointerInvoke extends CLayouts { - MemorySession session = MemorySession.openConfined(); - MemorySegment segment = MemorySegment.allocateNative(100, session); + Arena arena = Arena.openConfined(); + MemorySegment segment = MemorySegment.allocateNative(100, arena.scope()); static { System.loadLibrary("Ptr"); @@ -66,35 +64,30 @@ public class PointerInvoke extends CLayouts { static { Linker abi = Linker.nativeLinker(); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); - F_LONG = abi.downcallHandle(loaderLibs.lookup("func_as_long").get(), + F_LONG = abi.downcallHandle(loaderLibs.find("func_as_long").get(), FunctionDescriptor.of(C_INT, C_LONG_LONG)); - F_PTR = abi.downcallHandle(loaderLibs.lookup("func_as_ptr").get(), + F_PTR = abi.downcallHandle(loaderLibs.find("func_as_ptr").get(), FunctionDescriptor.of(C_INT, C_POINTER)); } @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark public int panama_call_as_long() throws Throwable { - return (int)F_LONG.invokeExact(segment.address().toRawLongValue()); + return (int)F_LONG.invokeExact(segment.address()); } @Benchmark public int panama_call_as_address() throws Throwable { - return (int)F_PTR.invokeExact((Addressable)segment.address()); - } - - @Benchmark - public int panama_call_as_segment() throws Throwable { - return (int)F_PTR.invokeExact((Addressable)segment); + return (int)F_PTR.invokeExact(segment); } @Benchmark public int panama_call_as_new_segment() throws Throwable { - MemorySegment newSegment = MemorySegment.ofAddress(segment.address(), 100, session); - return (int)F_PTR.invokeExact((Addressable)newSegment); + MemorySegment newSegment = MemorySegment.ofAddress(segment.address(), 100, arena.scope()); + return (int)F_PTR.invokeExact(newSegment); } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java index 8fd2a64a34a..0b8b4e9708e 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/QSort.java @@ -22,13 +22,11 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -38,6 +36,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -56,17 +55,17 @@ public class QSort extends CLayouts { static final Linker abi = Linker.nativeLinker(); static final MethodHandle clib_qsort; - static final Addressable native_compar; - static final Addressable panama_upcall_compar; + static final MemorySegment native_compar; + static final MemorySegment panama_upcall_compar; static final long jni_upcall_compar; static final int[] INPUT = { 5, 3, 2, 7, 8, 12, 1, 7 }; static final MemorySegment INPUT_SEGMENT; - static Addressable qsort_addr = abi.defaultLookup().lookup("qsort").get(); + static MemorySegment qsort_addr = abi.defaultLookup().find("qsort").get(); static { - INPUT_SEGMENT = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(INPUT.length, JAVA_INT), MemorySession.global()); + INPUT_SEGMENT = MemorySegment.allocateNative(MemoryLayout.sequenceLayout(INPUT.length, JAVA_INT), SegmentScope.global()); INPUT_SEGMENT.copyFrom(MemorySegment.ofArray(INPUT)); System.loadLibrary("QSortJNI"); @@ -78,13 +77,13 @@ public class QSort extends CLayouts { FunctionDescriptor.ofVoid(C_POINTER, C_LONG_LONG, C_LONG_LONG, C_POINTER) ); System.loadLibrary("QSort"); - native_compar = SymbolLookup.loaderLookup().lookup("compar").orElseThrow(); + native_compar = SymbolLookup.loaderLookup().find("compar").orElseThrow(); panama_upcall_compar = abi.upcallStub( lookup().findStatic(QSort.class, "panama_upcall_compar", - MethodType.methodType(int.class, MemoryAddress.class, MemoryAddress.class)), + MethodType.methodType(int.class, MemorySegment.class, MemorySegment.class)), FunctionDescriptor.of(C_INT, C_POINTER, C_POINTER), - MemorySession.global() + SegmentScope.global() ); } catch (ReflectiveOperationException e) { throw new BootstrapMethodError(e); @@ -103,7 +102,7 @@ interface JNIComparator { @Benchmark public void native_qsort() throws Throwable { - clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)native_compar); + clib_qsort.invokeExact(INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), native_compar); } @Benchmark @@ -118,15 +117,11 @@ public void jni_upcall_qsort_naive() { @Benchmark public void panama_upcall_qsort() throws Throwable { - clib_qsort.invokeExact((Addressable)INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), (Addressable)panama_upcall_compar); - } - - private static int getIntAbsolute(MemoryAddress addr) { - return addr.get(JAVA_INT, 0); + clib_qsort.invokeExact(INPUT_SEGMENT, (long) INPUT.length, JAVA_INT.byteSize(), panama_upcall_compar); } - static int panama_upcall_compar(MemoryAddress e0, MemoryAddress e1) { - return Integer.compare(getIntAbsolute(e0), getIntAbsolute(e1)); + static int panama_upcall_compar(MemorySegment e0, MemorySegment e1) { + return Integer.compare(e0.get(JAVA_INT, 0), e1.get(JAVA_INT, 0)); } static int jni_upcall_compar(int j0, int j1) { diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java index 5ec95dce4f9..cd943a022f4 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/StrLenTest.java @@ -25,13 +25,13 @@ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SegmentAllocator; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,10 +57,10 @@ @Fork(value = 3, jvmArgsAppend = { "--enable-native-access=ALL-UNNAMED", "--enable-preview" }) public class StrLenTest extends CLayouts { - MemorySession session = MemorySession.openConfined(); + Arena arena = Arena.openConfined(); SegmentAllocator segmentAllocator; - SegmentAllocator arenaAllocator = SegmentAllocator.newNativeArena(session); + SegmentAllocator arenaAllocator = new RingAllocator(arena.scope()); @Param({"5", "20", "100"}) public int size; @@ -74,19 +74,19 @@ public class StrLenTest extends CLayouts { static { Linker abi = Linker.nativeLinker(); - STRLEN = abi.downcallHandle(abi.defaultLookup().lookup("strlen").get(), + STRLEN = abi.downcallHandle(abi.defaultLookup().find("strlen").get(), FunctionDescriptor.of(C_INT, C_POINTER)); } @Setup public void setup() { str = makeString(size); - segmentAllocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(size + 1, MemorySession.openConfined())); + segmentAllocator = SegmentAllocator.prefixAllocator(MemorySegment.allocateNative(size + 1, arena.scope())); } @TearDown public void tearDown() { - session.close(); + arena.close(); } @Benchmark @@ -96,36 +96,35 @@ public int jni_strlen() throws Throwable { @Benchmark public int panama_strlen() throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { - MemorySegment segment = MemorySegment.allocateNative(str.length() + 1, session); - segment.setUtf8String(0, str); - return (int)STRLEN.invokeExact((Addressable)segment); + try (Arena arena = Arena.openConfined()) { + MemorySegment segment = arena.allocateUtf8String(str); + return (int)STRLEN.invokeExact(segment); } } @Benchmark - public int panama_strlen_arena() throws Throwable { - return (int)STRLEN.invokeExact((Addressable)arenaAllocator.allocateUtf8String(str)); + public int panama_strlen_ring() throws Throwable { + return (int)STRLEN.invokeExact(arenaAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_prefix() throws Throwable { - return (int)STRLEN.invokeExact((Addressable)segmentAllocator.allocateUtf8String(str)); + return (int)STRLEN.invokeExact(segmentAllocator.allocateUtf8String(str)); } @Benchmark public int panama_strlen_unsafe() throws Throwable { - MemoryAddress address = makeStringUnsafe(str); - int res = (int) STRLEN.invokeExact((Addressable)address); + MemorySegment address = makeStringUnsafe(str); + int res = (int) STRLEN.invokeExact(address); freeMemory(address); return res; } - static MemoryAddress makeStringUnsafe(String s) { + static MemorySegment makeStringUnsafe(String s) { byte[] bytes = s.getBytes(); int len = bytes.length; - MemoryAddress address = allocateMemory(len + 1); - MemorySegment str = MemorySegment.ofAddress(address, len + 1, MemorySession.global()); + MemorySegment address = allocateMemory(len + 1); + MemorySegment str = address.asSlice(0, len + 1); str.copyFrom(MemorySegment.ofArray(bytes)); str.set(JAVA_BYTE, len, (byte)0); return address; @@ -143,4 +142,31 @@ static String makeString(int size) { """; return lorem.substring(0, size); } + + static class RingAllocator implements SegmentAllocator { + final MemorySegment segment; + SegmentAllocator current; + long rem; + + public RingAllocator(SegmentScope session) { + this.segment = MemorySegment.allocateNative(1024, session); + reset(); + } + + @Override + public MemorySegment allocate(long byteSize, long byteAlignment) { + if (rem < byteSize) { + reset(); + } + MemorySegment res = current.allocate(byteSize, byteAlignment); + long lastOffset = segment.segmentOffset(res) + res.byteSize(); + rem = segment.byteSize() - lastOffset; + return res; + } + + void reset() { + current = SegmentAllocator.slicingAllocator(segment); + rem = segment.byteSize(); + } + } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java index ec487cd75ad..c1ff656f780 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/TestLoadBytes.java @@ -24,7 +24,7 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.CompilerControl; @@ -37,6 +37,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; @@ -67,7 +68,7 @@ public void setup() { } srcBufferNative = ByteBuffer.allocateDirect(size); - srcSegmentImplicit = MemorySegment.allocateNative(size, MemorySession.openImplicit()); + srcSegmentImplicit = MemorySegment.allocateNative(size, SegmentScope.auto()); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java index 709b6aec9c5..5586aa866c6 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/UnrolledAccess.java @@ -24,6 +24,8 @@ package org.openjdk.bench.java.lang.foreign; import java.lang.foreign.*; +import java.lang.foreign.SegmentScope; +import java.lang.invoke.VarHandle; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; @@ -31,7 +33,7 @@ import sun.misc.Unsafe; import java.util.concurrent.TimeUnit; -import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static java.lang.foreign.ValueLayout.*; @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -43,6 +45,10 @@ public class UnrolledAccess extends JavaLayouts { static final Unsafe U = Utils.unsafe; + static final VarHandle VH_LONG_UNALIGNED = JAVA_LONG_UNALIGNED.arrayElementVarHandle(); + + static final VarHandle VH_LONG = JAVA_LONG.arrayElementVarHandle(); + final static int SIZE = 1024; @State(Scope.Benchmark) @@ -61,8 +67,8 @@ public Data() { this.outputArray = new double[SIZE]; this.inputAddress = U.allocateMemory(8 * SIZE); this.outputAddress = U.allocateMemory(8 * SIZE); - this.inputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(inputAddress), 8*SIZE, MemorySession.global()); - this.outputSegment = MemorySegment.ofAddress(MemoryAddress.ofLong(outputAddress), 8*SIZE, MemorySession.global()); + this.inputSegment = MemorySegment.ofAddress(inputAddress, 8*SIZE, SegmentScope.global()); + this.outputSegment = MemorySegment.ofAddress(outputAddress, 8*SIZE, SegmentScope.global()); } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java index f40c3c5916e..ed79a30b6e8 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/Upcalls.java @@ -22,10 +22,10 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.MemorySegment; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -35,6 +35,7 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; +import java.lang.foreign.SegmentScope; import java.lang.foreign.SymbolLookup; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -56,10 +57,10 @@ public class Upcalls extends CLayouts { static final MethodHandle args5; static final MethodHandle args10; - static final Addressable cb_blank; - static final Addressable cb_identity; - static final Addressable cb_args5; - static final Addressable cb_args10; + static final MemorySegment cb_blank; + static final MemorySegment cb_identity; + static final MemorySegment cb_args5; + static final MemorySegment cb_args10; static final long cb_blank_jni; static final long cb_identity_jni; @@ -122,15 +123,15 @@ public class Upcalls extends CLayouts { static MethodHandle linkFunc(String name, FunctionDescriptor baseDesc) { return abi.downcallHandle( - SymbolLookup.loaderLookup().lookup(name).orElseThrow(), + SymbolLookup.loaderLookup().find(name).orElseThrow(), baseDesc.appendArgumentLayouts(C_POINTER) ); } - static Addressable makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { + static MemorySegment makeCB(String name, MethodType mt, FunctionDescriptor fd) throws ReflectiveOperationException { return abi.upcallStub( lookup().findStatic(Upcalls.class, name, mt), - fd, MemorySession.global() + fd, SegmentScope.global() ); } @@ -147,7 +148,7 @@ public void jni_blank() throws Throwable { @Benchmark public void panama_blank() throws Throwable { - blank.invokeExact((Addressable)cb_blank); + blank.invokeExact(cb_blank); } @Benchmark @@ -167,17 +168,17 @@ public void jni_args10() throws Throwable { @Benchmark public int panama_identity() throws Throwable { - return (int) identity.invokeExact(10, (Addressable)cb_identity); + return (int) identity.invokeExact(10, cb_identity); } @Benchmark public void panama_args5() throws Throwable { - args5.invokeExact(1L, 2D, 3L, 4D, 5L, (Addressable)cb_args5); + args5.invokeExact(1L, 2D, 3L, 4D, 5L, cb_args5); } @Benchmark public void panama_args10() throws Throwable { - args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, (Addressable)cb_args10); + args10.invokeExact(1L, 2D, 3L, 4D, 5L, 6D, 7L, 8D, 9L, 10D, cb_args10); } static void blank() {} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java b/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java index 46815f565dd..a9205c22515 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/VaList.java @@ -22,10 +22,10 @@ */ package org.openjdk.bench.java.lang.foreign; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,9 +57,10 @@ public class VaList extends CLayouts { static { SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); - MH_ellipsis = linker.downcallHandle(loaderLibs.lookup("ellipsis").get(), - FunctionDescriptor.ofVoid(C_INT).asVariadic(C_INT, C_DOUBLE, C_LONG_LONG)); - MH_vaList = linker.downcallHandle(loaderLibs.lookup("vaList").get(), + MH_ellipsis = linker.downcallHandle(loaderLibs.find("ellipsis").get(), + FunctionDescriptor.ofVoid(C_INT, C_INT, C_DOUBLE, C_LONG_LONG), + Linker.Option.firstVariadicArg(1)); + MH_vaList = linker.downcallHandle(loaderLibs.find("vaList").get(), FunctionDescriptor.ofVoid(C_INT, C_POINTER)); } @@ -71,13 +72,13 @@ public void ellipsis() throws Throwable { @Benchmark public void vaList() throws Throwable { - try (MemorySession session = MemorySession.openConfined()) { + try (Arena arena = Arena.openConfined()) { java.lang.foreign.VaList vaList = java.lang.foreign.VaList.make(b -> b.addVarg(C_INT, 1) .addVarg(C_DOUBLE, 2D) - .addVarg(C_LONG_LONG, 3L), session); + .addVarg(C_LONG_LONG, 3L), arena.scope()); MH_vaList.invokeExact(3, - (Addressable)vaList); + vaList.segment()); } } } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java index 574bfdc27a8..e6501eae35f 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/VarHandleExact.java @@ -22,8 +22,9 @@ */ package org.openjdk.bench.java.lang.foreign; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Fork; @@ -57,16 +58,18 @@ public class VarHandleExact { exact = generic.withInvokeExactBehavior(); } + Arena arena; MemorySegment data; @Setup public void setup() { - data = MemorySegment.allocateNative(JAVA_INT, MemorySession.openConfined()); + arena = Arena.openConfined(); + data = MemorySegment.allocateNative(JAVA_INT, arena.scope()); } @TearDown public void tearDown() { - data.session().close(); + arena.close(); } @Benchmark diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java new file mode 100644 index 00000000000..159464db390 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/NativeType.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2021, 2022, 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.java.lang.foreign.pointers; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.ValueLayout; + +public sealed abstract class NativeType { + + public abstract MemoryLayout layout(); + + public non-sealed static abstract class OfInt extends NativeType { + public abstract ValueLayout.OfInt layout(); + } + public non-sealed static abstract class OfDouble extends NativeType { + public abstract ValueLayout.OfDouble layout(); + } + + private static final ValueLayout.OfAddress UNSAFE_ADDRESS = ValueLayout.ADDRESS.asUnbounded(); + + public final static class OfPointer extends NativeType { + public ValueLayout.OfAddress layout() { + return UNSAFE_ADDRESS; + } + } + + public non-sealed static abstract class OfStruct extends NativeType { + public abstract GroupLayout layout(); + public abstract X make(Pointer ptr); + } + + public static final OfInt C_INT = new OfInt<>() { + @Override + public ValueLayout.OfInt layout() { + return ValueLayout.JAVA_INT; + } + }; + + public static final OfDouble C_DOUBLE = new OfDouble<>() { + @Override + public ValueLayout.OfDouble layout() { + return ValueLayout.JAVA_DOUBLE; + } + }; + + @SuppressWarnings("unchecked") + final static OfPointer C_VOID_PTR = new OfPointer(); + + @SuppressWarnings("unchecked") + public static final OfPointer> C_INT_PTR = NativeType.C_VOID_PTR; + @SuppressWarnings("unchecked") + public static final OfPointer> C_DOUBLE_PTR = NativeType.C_VOID_PTR; + + + + @SuppressWarnings("unchecked") + public static OfPointer> ptr(NativeType type) { + return NativeType.C_VOID_PTR; + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java new file mode 100644 index 00000000000..223cdf66652 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Point.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, 2022, 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.java.lang.foreign.pointers; + +import java.lang.foreign.GroupLayout; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; + +public class Point extends Struct { + + Point(Pointer ptr) { + super(ptr); + } + + int x() { + return ptr.segment.get(NativeType.C_INT.layout(), 0); + } + int y() { + return ptr.segment.get(NativeType.C_INT.layout(), 4); + } + + static Point wrap(MemorySegment segment) { + return new Point(Pointer.wrap(TYPE, segment)); + } + + static final NativeType.OfStruct TYPE = new NativeType.OfStruct() { + static final GroupLayout LAYOUT = MemoryLayout.structLayout( + ValueLayout.JAVA_INT.withName("x"), + ValueLayout.JAVA_INT.withName("y")); + + @Override + public GroupLayout layout() { + return LAYOUT; + } + + @Override + public Point make(Pointer pointer) { + return new Point(pointer); + } + }; +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java new file mode 100644 index 00000000000..13a96a2ab59 --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Pointer.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021, 2022, 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.java.lang.foreign.pointers; + + +import java.lang.foreign.MemorySegment; +import java.lang.foreign.SegmentAllocator; + +public class Pointer { + + final MemorySegment segment; + + Pointer(MemorySegment segment) { + this.segment = segment; + } + + public > int get(Z type, long index) { + return segment.getAtIndex(type.layout(), index); + } + + public > double get(Z type, long index) { + return segment.getAtIndex(type.layout(), index); + } + + public > X get(Z type, long index) { + return type.make(addOffset(index * type.layout().byteSize())); + } + + public Pointer addOffset(long offset) { + return new Pointer<>(segment.asSlice(offset)); + } + + @SuppressWarnings("unchecked") + public > X get(Z type, long index) { + MemorySegment address = segment.getAtIndex(type.layout(), index); + return (X)new Pointer<>(address); + } + + @SuppressWarnings("unchecked") + public X get(NativeType type, long offset) { + if (type instanceof NativeType.OfInt intType) { + return (X) (Object) get(intType, offset); + } else if (type instanceof NativeType.OfDouble doubleType) { + return (X) (Object) get(doubleType, offset); + } else { + throw new UnsupportedOperationException(); + } + } + + public MemorySegment segment() { + return segment; + } + + public static Pointer allocate(NativeType type, SegmentAllocator allocator) { + MemorySegment segment = allocator.allocate(type.layout()); + return new Pointer<>(segment); + } + + public static Pointer allocate(NativeType type, long size, SegmentAllocator allocator) { + MemorySegment segment = allocator.allocateArray(type.layout(), size); + return new Pointer<>(segment); + } + + public static Pointer wrap(NativeType type, MemorySegment segment) { + return new Pointer<>(segment); + } +} diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java new file mode 100644 index 00000000000..1a1d196c2ae --- /dev/null +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/PointerBench.java @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, 2022, 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.java.lang.foreign.pointers; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.TearDown; +import org.openjdk.jmh.annotations.Warmup; + +import java.lang.foreign.Arena; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.ValueLayout; +import java.util.concurrent.TimeUnit; + +@BenchmarkMode(Mode.AverageTime) +@Warmup(iterations = 3, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) +@OutputTimeUnit(TimeUnit.MILLISECONDS) +@Fork(value = 3, jvmArgsAppend = "--enable-preview") +@State(Scope.Benchmark) +public class PointerBench { + + final Arena arena = Arena.openConfined(); + static final int ELEM_SIZE = 1_000_000; + Pointer intPointer = Pointer.allocate(NativeType.C_INT, ELEM_SIZE, arena); + Pointer> intPointerPointer = Pointer.allocate(NativeType.C_INT_PTR, ELEM_SIZE, arena); + Pointer pointPointer = Pointer.allocate(Point.TYPE, ELEM_SIZE, arena); + MemorySegment intSegment = intPointer.segment(); + MemorySegment intPointerSegment = intPointerPointer.segment(); + MemorySegment pointSegment = pointPointer.segment(); + + public static final ValueLayout.OfAddress UNSAFE_ADDRESS = ValueLayout.ADDRESS.asUnbounded(); + + @Setup + public void setup() { + for (int i = 0 ; i < ELEM_SIZE ; i++) { + intSegment.setAtIndex(ValueLayout.JAVA_INT, i, i); + intPointerSegment.setAtIndex(ValueLayout.ADDRESS, i, intSegment.asSlice(4 * i)); + pointSegment.setAtIndex(ValueLayout.JAVA_INT, (i * 2), i); + pointSegment.setAtIndex(ValueLayout.JAVA_INT, (i * 2) + 1, i); + } + } + + @TearDown + public void teardown() { + arena.close(); + } + + @Benchmark + public int testLoopPointerInt_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intPointer.get(NativeType.C_INT, i); + } + return sum; + } + + @Benchmark + public int testLoopPointerPointerInt_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intPointerPointer.get(NativeType.C_INT_PTR, i) + .get(NativeType.C_INT, 0); + } + return sum; + } + + @Benchmark + public int testLoopPointerPoint_ptr() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += pointPointer.get(Point.TYPE, i).x(); + } + return sum; + } + + @Benchmark + public int testLoopPointerInt_ptr_generic() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += genericGet(intPointer, NativeType.C_INT, i); + } + return sum; + } + + static Z genericGet(Pointer pz, NativeType type, long offset) { + return pz.get(type, offset); + } + + @Benchmark + public int testLoopPointerInt_segment() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += intSegment.getAtIndex(ValueLayout.JAVA_INT, i); + } + return sum; + } + + @Benchmark + public int testLoopPointerPointerInt_segment() { + int sum = 0; + for (long i = 0 ; i < ELEM_SIZE ; i++) { + var segment = intPointerSegment.getAtIndex(UNSAFE_ADDRESS, i); + sum += segment.get(ValueLayout.JAVA_INT, 0); + } + return sum; + } + + @Benchmark + public int testLoopPointerPoint_segment() { + int sum = 0; + for (int i = 0 ; i < ELEM_SIZE ; i++) { + sum += pointSegment.getAtIndex(ValueLayout.JAVA_INT, i * 2); + } + return sum; + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/Scoped.java b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java similarity index 67% rename from src/java.base/share/classes/jdk/internal/foreign/Scoped.java rename to test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java index d33557341f3..f9a0c05b377 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/Scoped.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/pointers/Struct.java @@ -4,9 +4,7 @@ * * 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. + * 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 @@ -23,16 +21,12 @@ * questions. */ -package jdk.internal.foreign; +package org.openjdk.bench.java.lang.foreign.pointers; -import jdk.internal.vm.annotation.ForceInline; +public abstract class Struct> { + protected final Pointer ptr; -import java.lang.foreign.MemorySession; - -public interface Scoped { - @ForceInline - default MemorySessionImpl sessionImpl() { - return MemorySessionImpl.toSessionImpl(session()); + public Struct(Pointer ptr) { + this.ptr = ptr; } - MemorySession session(); } diff --git a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java index 4f5fe751a98..1ed1d7a899c 100644 --- a/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java +++ b/test/micro/org/openjdk/bench/java/lang/foreign/points/support/PanamaPoint.java @@ -22,12 +22,12 @@ */ package org.openjdk.bench.java.lang.foreign.points.support; -import java.lang.foreign.Addressable; +import java.lang.foreign.Arena; import java.lang.foreign.Linker; import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import org.openjdk.bench.java.lang.foreign.CLayouts; import java.lang.foreign.SymbolLookup; @@ -53,19 +53,21 @@ public class PanamaPoint extends CLayouts implements AutoCloseable { System.loadLibrary("Point"); SymbolLookup loaderLibs = SymbolLookup.loaderLookup(); MH_distance = abi.downcallHandle( - loaderLibs.lookup("distance").get(), + loaderLibs.find("distance").get(), FunctionDescriptor.of(C_DOUBLE, LAYOUT, LAYOUT) ); MH_distance_ptrs = abi.downcallHandle( - loaderLibs.lookup("distance_ptrs").get(), + loaderLibs.find("distance_ptrs").get(), FunctionDescriptor.of(C_DOUBLE, C_POINTER, C_POINTER) ); } + Arena arena; private final MemorySegment segment; public PanamaPoint(int x, int y) { - this.segment = MemorySegment.allocateNative(LAYOUT, MemorySession.openConfined()); + this.arena = Arena.openConfined(); + this.segment = MemorySegment.allocateNative(LAYOUT, arena.scope()); setX(x); setY(y); } @@ -96,7 +98,7 @@ public double distanceTo(PanamaPoint other) { public double distanceToPtrs(PanamaPoint other) { try { - return (double) MH_distance_ptrs.invokeExact((Addressable)segment, (Addressable)other.segment); + return (double) MH_distance_ptrs.invokeExact(segment, other.segment); } catch (Throwable throwable) { throw new InternalError(throwable); } @@ -104,6 +106,6 @@ public double distanceToPtrs(PanamaPoint other) { @Override public void close() { - segment.session().close(); + arena.close(); } } diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java index a73beddfe87..4f6c4aa65f2 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/MemorySegmentVectorAccess.java @@ -26,7 +26,7 @@ package org.openjdk.bench.jdk.incubator.vector; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import jdk.incubator.vector.ByteVector; @@ -69,8 +69,8 @@ public class MemorySegmentVectorAccess { @Setup public void setup() { - nativeIn = MemorySegment.allocateNative(size, MemorySession.openImplicit()); - nativeOut = MemorySegment.allocateNative(size, MemorySession.openImplicit()); + nativeIn = MemorySegment.allocateNative(size, SegmentScope.auto()); + nativeOut = MemorySegment.allocateNative(size, SegmentScope.auto()); byteIn = new byte[size]; byteOut = new byte[size]; diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java index d28c860ebe0..62735fa3b00 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreBytes.java @@ -23,9 +23,9 @@ */ package org.openjdk.bench.jdk.incubator.vector; -import java.lang.foreign.MemoryAddress; +import java.lang.foreign.Arena; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; import jdk.incubator.vector.ByteVector; @@ -43,8 +43,6 @@ import org.openjdk.jmh.annotations.State; import org.openjdk.jmh.annotations.Warmup; -import static java.lang.foreign.ValueLayout.JAVA_BYTE; - @BenchmarkMode(Mode.AverageTime) @Warmup(iterations = 5, time = 500, timeUnit = TimeUnit.MILLISECONDS) @Measurement(iterations = 10, time = 500, timeUnit = TimeUnit.MILLISECONDS) @@ -70,18 +68,10 @@ public class TestLoadStoreBytes { private MemorySegment dstSegmentHeap; - - private MemorySession implicitScope; - private MemorySegment srcSegment; private MemorySegment dstSegment; - - private MemoryAddress srcAddress; - - private MemoryAddress dstAddress; - private byte[] a, b, c; @Setup @@ -95,12 +85,8 @@ public void setup() { srcSegmentHeap = MemorySegment.ofArray(new byte[size]); dstSegmentHeap = MemorySegment.ofArray(new byte[size]); - implicitScope = MemorySession.openImplicit(); - srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - - srcAddress = srcSegment.address(); - dstAddress = dstSegment.address(); + srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); + dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); a = new byte[size]; b = new byte[size]; @@ -177,9 +163,9 @@ public void segmentNativeImplicit() { @Benchmark public void segmentNativeConfined() { - try (final var session = MemorySession.openConfined()) { - final var srcSegmentConfined = MemorySegment.ofAddress(srcAddress, size, session); - final var dstSegmentConfined = MemorySegment.ofAddress(dstAddress, size, session); + try (final var arena = Arena.openConfined()) { + final var srcSegmentConfined = MemorySegment.ofAddress(srcSegment.address(), size, arena.scope()); + final var dstSegmentConfined = MemorySegment.ofAddress(dstSegment.address(), size, arena.scope()); for (long i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ByteVector.fromMemorySegment(SPECIES, srcSegmentConfined, i, ByteOrder.nativeOrder()); diff --git a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java index ef6f2bb4ed4..ecbe5889806 100644 --- a/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java +++ b/test/micro/org/openjdk/bench/jdk/incubator/vector/TestLoadStoreShorts.java @@ -23,12 +23,13 @@ */ package org.openjdk.bench.jdk.incubator.vector; +import java.lang.foreign.Arena; +import java.lang.foreign.SegmentScope; import java.nio.ByteOrder; import java.util.concurrent.TimeUnit; -import java.lang.foreign.MemoryAddress; import java.lang.foreign.MemorySegment; -import java.lang.foreign.MemorySession; + import jdk.incubator.vector.ShortVector; import jdk.incubator.vector.VectorOperators; import jdk.incubator.vector.VectorSpecies; @@ -71,18 +72,10 @@ public class TestLoadStoreShorts { private MemorySegment dstSegmentHeap; - - private MemorySession implicitScope; - private MemorySegment srcSegment; private MemorySegment dstSegment; - - private MemoryAddress srcAddress; - - private MemoryAddress dstAddress; - private short[] a, b, c; @Setup @@ -97,12 +90,8 @@ public void setup() { srcSegmentHeap = MemorySegment.ofArray(new byte[size]); dstSegmentHeap = MemorySegment.ofArray(new byte[size]); - implicitScope = MemorySession.openImplicit(); - srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), implicitScope); - - srcAddress = srcSegment.address(); - dstAddress = dstSegment.address(); + srcSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); + dstSegment = MemorySegment.allocateNative(size, SPECIES.vectorByteSize(), SegmentScope.auto()); this.longSize = longSize; @@ -172,9 +161,9 @@ public void segmentNativeImplicit() { @Benchmark public void segmentNativeConfined() { - try (final var session = MemorySession.openConfined()) { - final var srcSegmentConfined = MemorySegment.ofAddress(srcAddress, size, session); - final var dstSegmentConfined = MemorySegment.ofAddress(dstAddress, size, session); + try (final var arena = Arena.openConfined()) { + final var srcSegmentConfined = MemorySegment.ofAddress(srcSegment.address(), size, arena.scope()); + final var dstSegmentConfined = MemorySegment.ofAddress(dstSegment.address(), size, arena.scope()); for (long i = 0; i < SPECIES.loopBound(srcArray.length); i += SPECIES.length()) { var v = ShortVector.fromMemorySegment(SPECIES, srcSegmentConfined, i, ByteOrder.nativeOrder()); From 0452c39fecb7fa4962b00868cb20a50e5f7ab1a7 Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Mon, 5 Dec 2022 14:47:12 +0000 Subject: [PATCH 046/494] 8296477: Foreign linker implementation update following JEP 434 Co-authored-by: Jorn Vernee Co-authored-by: Nick Gasson Co-authored-by: Per Minborg Reviewed-by: rehn, mcimadamore, vlivanov --- .../cpu/aarch64/downcallLinker_aarch64.cpp | 125 +++++---- .../cpu/aarch64/foreignGlobals_aarch64.cpp | 206 +++++++++----- .../cpu/aarch64/foreignGlobals_aarch64.hpp | 4 +- src/hotspot/cpu/aarch64/register_aarch64.hpp | 16 +- .../cpu/aarch64/upcallLinker_aarch64.cpp | 42 +-- src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp | 86 ++++++ src/hotspot/cpu/arm/downcallLinker_arm.cpp | 8 +- src/hotspot/cpu/arm/foreignGlobals_arm.cpp | 14 +- src/hotspot/cpu/arm/vmstorage_arm.hpp | 52 ++++ src/hotspot/cpu/ppc/downcallLinker_ppc.cpp | 7 +- src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp | 13 +- src/hotspot/cpu/ppc/vmstorage_ppc.hpp | 52 ++++ .../cpu/riscv/downcallLinker_riscv.cpp | 7 +- .../cpu/riscv/foreignGlobals_riscv.cpp | 14 +- src/hotspot/cpu/riscv/vmstorage_riscv.hpp | 52 ++++ src/hotspot/cpu/s390/downcallLinker_s390.cpp | 8 +- src/hotspot/cpu/s390/foreignGlobals_s390.cpp | 14 +- src/hotspot/cpu/s390/vmstorage_s390.hpp | 52 ++++ src/hotspot/cpu/x86/downcallLinker_x86_32.cpp | 7 +- src/hotspot/cpu/x86/downcallLinker_x86_64.cpp | 136 ++++++---- src/hotspot/cpu/x86/foreignGlobals_x86.hpp | 4 +- src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp | 13 +- src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp | 185 +++++++------ src/hotspot/cpu/x86/register_x86.hpp | 16 +- src/hotspot/cpu/x86/upcallLinker_x86_64.cpp | 44 +-- src/hotspot/cpu/x86/vmstorage_x86.hpp | 100 +++++++ src/hotspot/cpu/zero/downcallLinker_zero.cpp | 7 +- src/hotspot/cpu/zero/foreignGlobals_zero.cpp | 13 +- src/hotspot/cpu/zero/vmstorage_zero.hpp | 53 ++++ src/hotspot/share/classfile/javaClasses.cpp | 48 ++-- src/hotspot/share/classfile/javaClasses.hpp | 18 +- src/hotspot/share/code/codeBlob.cpp | 1 + src/hotspot/share/code/codeBlob.hpp | 2 +- src/hotspot/share/prims/downcallLinker.cpp | 54 ++++ src/hotspot/share/prims/downcallLinker.hpp | 9 +- src/hotspot/share/prims/foreignGlobals.cpp | 183 ++++++++----- src/hotspot/share/prims/foreignGlobals.hpp | 78 ++++-- .../share/prims/foreignGlobals.inline.hpp | 8 +- src/hotspot/share/prims/nativeEntryPoint.cpp | 14 +- src/hotspot/share/prims/vmstorage.cpp | 30 +++ src/hotspot/share/prims/vmstorage.hpp | 100 +++++++ src/hotspot/share/runtime/globals.hpp | 3 - .../classes/java/lang/foreign/Linker.java | 74 ++++- .../internal/foreign/abi/ABIDescriptor.java | 15 +- .../internal/foreign/abi/AbstractLinker.java | 2 +- .../internal/foreign/abi/Architecture.java | 3 +- .../internal/foreign/abi/CallingSequence.java | 16 +- .../foreign/abi/CallingSequenceBuilder.java | 11 +- .../internal/foreign/abi/CapturableState.java | 70 +++++ .../internal/foreign/abi/DowncallLinker.java | 3 +- .../internal/foreign/abi/LinkerOptions.java | 65 ++++- .../foreign/abi/NativeEntryPoint.java | 30 ++- .../jdk/internal/foreign/abi/SharedUtils.java | 7 +- .../internal/foreign/abi/StubLocations.java | 36 +++ .../jdk/internal/foreign/abi/VMStorage.java | 61 ++--- .../abi/aarch64/AArch64Architecture.java | 171 ++++++------ .../foreign/abi/aarch64/CallArranger.java | 114 +++++--- .../foreign/abi/x64/X86_64Architecture.java | 155 ++++++----- .../foreign/abi/x64/sysv/CallArranger.java | 58 ++-- .../foreign/abi/x64/sysv/SysVx64Linker.java | 2 +- .../foreign/abi/x64/windows/CallArranger.java | 34 +-- test/jdk/ProblemList.txt | 4 +- .../MemoryLayoutPrincipalTotalityTest.java | 2 +- .../MemoryLayoutTypeRetentionTest.java | 2 +- .../java/foreign/TestLargeSegmentCopy.java | 1 + test/jdk/java/foreign/TestLinker.java | 25 ++ .../callarranger/CallArrangerTestBase.java | 7 +- .../callarranger/TestAarch64CallArranger.java | 253 ++++++++++++++++-- .../callarranger/TestSysVCallArranger.java | 69 ++--- .../callarranger/TestWindowsCallArranger.java | 80 +++--- .../TestCaptureCallState.java | 131 +++++++++ .../capturecallstate/libCaptureCallState.c | 122 +++++++++ 72 files changed, 2586 insertions(+), 935 deletions(-) create mode 100644 src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp create mode 100644 src/hotspot/cpu/arm/vmstorage_arm.hpp create mode 100644 src/hotspot/cpu/ppc/vmstorage_ppc.hpp create mode 100644 src/hotspot/cpu/riscv/vmstorage_riscv.hpp create mode 100644 src/hotspot/cpu/s390/vmstorage_s390.hpp create mode 100644 src/hotspot/cpu/x86/vmstorage_x86.hpp create mode 100644 src/hotspot/cpu/zero/vmstorage_zero.hpp create mode 100644 src/hotspot/share/prims/downcallLinker.cpp create mode 100644 src/hotspot/share/prims/vmstorage.cpp create mode 100644 src/hotspot/share/prims/vmstorage.hpp create mode 100644 src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java create mode 100644 src/java.base/share/classes/jdk/internal/foreign/abi/StubLocations.java create mode 100644 test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java create mode 100644 test/jdk/java/foreign/capturecallstate/libCaptureCallState.c diff --git a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp index 7a940a4b25a..9f740098e19 100644 --- a/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/downcallLinker_aarch64.cpp @@ -42,13 +42,14 @@ class DowncallStubGenerator : public StubCodeGenerator { BasicType _ret_bt; const ABIDescriptor& _abi; - const GrowableArray& _input_registers; - const GrowableArray& _output_registers; + const GrowableArray& _input_registers; + const GrowableArray& _output_registers; bool _needs_return_buffer; + int _captured_state_mask; int _frame_complete; - int _framesize; + int _frame_size_slots; OopMapSet* _oop_maps; public: DowncallStubGenerator(CodeBuffer* buffer, @@ -56,9 +57,10 @@ class DowncallStubGenerator : public StubCodeGenerator { int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) : StubCodeGenerator(buffer, PrintMethodHandleStubs), _signature(signature), _num_args(num_args), @@ -67,8 +69,9 @@ class DowncallStubGenerator : public StubCodeGenerator { _input_registers(input_registers), _output_registers(output_registers), _needs_return_buffer(needs_return_buffer), + _captured_state_mask(captured_state_mask), _frame_complete(0), - _framesize(0), + _frame_size_slots(0), _oop_maps(NULL) { } @@ -79,7 +82,7 @@ class DowncallStubGenerator : public StubCodeGenerator { } int framesize() const { - return (_framesize >> (LogBytesPerWord - LogBytesPerInt)); + return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt)); } OopMapSet* oop_maps() const { @@ -93,12 +96,15 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { - int locs_size = 64; + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { + int locs_size = 64; CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size); - DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer); + DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, + input_registers, output_registers, + needs_return_buffer, captured_state_mask); g.generate(); code.log_section_sizes("nep_invoker_blob"); @@ -137,10 +143,10 @@ void DowncallStubGenerator::generate() { Register tmp1 = r9; Register tmp2 = r10; - Register shuffle_reg = r19; + VMStorage shuffle_reg = as_VMStorage(r19); JavaCallingConvention in_conv; NativeCallingConvention out_conv(_input_registers); - ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); + ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg); #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; @@ -152,32 +158,36 @@ void DowncallStubGenerator::generate() { #endif int allocated_frame_size = 0; - if (_needs_return_buffer) { - allocated_frame_size += 8; // for address spill - } - allocated_frame_size += arg_shuffle.out_arg_stack_slots() < allocated_frame_size ? out_reg_spiller.spill_size_bytes() : allocated_frame_size; } - _framesize = align_up(framesize - + (allocated_frame_size >> LogBytesPerInt), 4); - assert(is_even(_framesize/2), "sp not 16-byte aligned"); + StubLocations locs; + locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch1); + if (_needs_return_buffer) { + locs.set_frame_data(StubLocations::RETURN_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; // for address spill + } + if (_captured_state_mask != 0) { + locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + + _frame_size_slots = align_up(framesize + (allocated_frame_size >> LogBytesPerInt), 4); + assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned"); _oop_maps = new OopMapSet(); address start = __ pc(); @@ -185,13 +195,13 @@ void DowncallStubGenerator::generate() { __ enter(); // lr and fp are already in place - __ sub(sp, rfp, ((unsigned)_framesize-4) << LogBytesPerInt); // prolog + __ sub(sp, rfp, ((unsigned)_frame_size_slots-4) << LogBytesPerInt); // prolog _frame_complete = __ pc() - start; address the_pc = __ pc(); __ set_last_Java_frame(sp, rfp, the_pc, tmp1); - OopMap* map = new OopMap(_framesize, 0); + OopMap* map = new OopMap(_frame_size_slots, 0); _oop_maps->add_gc_map(the_pc - start, map); // State transition @@ -200,27 +210,22 @@ void DowncallStubGenerator::generate() { __ stlrw(tmp1, tmp2); __ block_comment("{ argument shuffle"); - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes); - if (_needs_return_buffer) { - assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill"); - __ str(_abi._ret_buf_addr_reg, Address(sp, ret_buf_addr_sp_offset)); - } + arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs); __ block_comment("} argument shuffle"); - __ blr(_abi._target_addr_reg); + __ blr(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed rthread if (_needs_return_buffer) { - assert(ret_buf_addr_sp_offset != -1, "no return buffer addr spill"); - __ ldr(tmp1, Address(sp, ret_buf_addr_sp_offset)); + __ ldr(tmp1, Address(sp, locs.data_offset(StubLocations::RETURN_BUFFER))); int offset = 0; for (int i = 0; i < _output_registers.length(); i++) { - VMReg reg = _output_registers.at(i); - if (reg->is_Register()) { - __ str(reg->as_Register(), Address(tmp1, offset)); + VMStorage reg = _output_registers.at(i); + if (reg.type() == StorageType::INTEGER) { + __ str(as_Register(reg), Address(tmp1, offset)); offset += 8; - } else if(reg->is_FloatRegister()) { - __ strd(reg->as_FloatRegister(), Address(tmp1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ strd(as_FloatRegister(reg), Address(tmp1, offset)); offset += 16; } else { ShouldNotReachHere(); @@ -228,6 +233,28 @@ void DowncallStubGenerator::generate() { } } + ////////////////////////////////////////////////////////////////////////////// + + if (_captured_state_mask != 0) { + __ block_comment("{ save thread local"); + + if (should_save_return_value) { + out_reg_spiller.generate_spill(_masm, spill_offset); + } + + __ ldr(c_rarg0, Address(sp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movw(c_rarg1, _captured_state_mask); + __ rt_call(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state), tmp1); + + if (should_save_return_value) { + out_reg_spiller.generate_fill(_masm, spill_offset); + } + + __ block_comment("} save thread local"); + } + + ////////////////////////////////////////////////////////////////////////////// + __ mov(tmp1, _thread_in_native_trans); __ strw(tmp1, Address(rthread, JavaThread::thread_state_offset())); @@ -272,7 +299,7 @@ void DowncallStubGenerator::generate() { __ block_comment("{ L_safepoint_poll_slow_path"); __ bind(L_safepoint_poll_slow_path); - if (!_needs_return_buffer) { + if (should_save_return_value) { // Need to save the native result registers around any runtime calls. out_reg_spiller.generate_spill(_masm, spill_offset); } @@ -282,7 +309,7 @@ void DowncallStubGenerator::generate() { __ lea(tmp1, RuntimeAddress(CAST_FROM_FN_PTR(address, JavaThread::check_special_condition_for_native_trans))); __ blr(tmp1); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_offset); } @@ -294,13 +321,13 @@ void DowncallStubGenerator::generate() { __ block_comment("{ L_reguard"); __ bind(L_reguard); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_offset); } __ rt_call(CAST_FROM_FN_PTR(address, SharedRuntime::reguard_yellow_pages), tmp1); - if (!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_offset); } diff --git a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp index 6416703502e..e20c7e40601 100644 --- a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.cpp @@ -30,6 +30,7 @@ #include "oops/oopCast.inline.hpp" #include "prims/foreignGlobals.hpp" #include "prims/foreignGlobals.inline.hpp" +#include "prims/vmstorage.hpp" #include "utilities/formatBuffer.hpp" bool ABIDescriptor::is_volatile_reg(Register reg) const { @@ -42,112 +43,183 @@ bool ABIDescriptor::is_volatile_reg(FloatRegister reg) const { || _vector_additional_volatile_registers.contains(reg); } -static constexpr int INTEGER_TYPE = 0; -static constexpr int VECTOR_TYPE = 1; - const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { oop abi_oop = JNIHandles::resolve_non_null(jabi); ABIDescriptor abi; - constexpr Register (*to_Register)(int) = as_Register; objArrayOop inputStorage = jdk_internal_foreign_abi_ABIDescriptor::inputStorage(abi_oop); - parse_register_array(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, to_Register); - parse_register_array(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_FloatRegister); + parse_register_array(inputStorage, StorageType::INTEGER, abi._integer_argument_registers, as_Register); + parse_register_array(inputStorage, StorageType::VECTOR, abi._vector_argument_registers, as_FloatRegister); objArrayOop outputStorage = jdk_internal_foreign_abi_ABIDescriptor::outputStorage(abi_oop); - parse_register_array(outputStorage, INTEGER_TYPE, abi._integer_return_registers, to_Register); - parse_register_array(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_FloatRegister); + parse_register_array(outputStorage, StorageType::INTEGER, abi._integer_return_registers, as_Register); + parse_register_array(outputStorage, StorageType::VECTOR, abi._vector_return_registers, as_FloatRegister); objArrayOop volatileStorage = jdk_internal_foreign_abi_ABIDescriptor::volatileStorage(abi_oop); - parse_register_array(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, to_Register); - parse_register_array(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_FloatRegister); + parse_register_array(volatileStorage, StorageType::INTEGER, abi._integer_additional_volatile_registers, as_Register); + parse_register_array(volatileStorage, StorageType::VECTOR, abi._vector_additional_volatile_registers, as_FloatRegister); abi._stack_alignment_bytes = jdk_internal_foreign_abi_ABIDescriptor::stackAlignment(abi_oop); abi._shadow_space_bytes = jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(abi_oop); - abi._target_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(abi_oop))->as_Register(); - abi._ret_buf_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(abi_oop))->as_Register(); + abi._scratch1 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch1(abi_oop)); + abi._scratch2 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch2(abi_oop)); return abi; } -enum class RegType { - INTEGER = 0, - VECTOR = 1, - STACK = 3 -}; - -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - switch(static_cast(type)) { - case RegType::INTEGER: return ::as_Register(index)->as_VMReg(); - case RegType::VECTOR: return ::as_FloatRegister(index)->as_VMReg(); - case RegType::STACK: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); - } - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { - if (reg->is_Register()) { +int RegSpiller::pd_reg_size(VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { return 8; - } else if (reg->is_FloatRegister()) { + } else if (reg.type() == StorageType::VECTOR) { return 16; // Always spill/unspill Q registers } return 0; // stack and BAD } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->spill(reg->as_Register(), true, offset); - } else if (reg->is_FloatRegister()) { - masm->spill(reg->as_FloatRegister(), masm->Q, offset); +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->spill(as_Register(reg), true, offset); + } else if (reg.type() == StorageType::VECTOR) { + masm->spill(as_FloatRegister(reg), masm->Q, offset); } else { // stack and BAD } } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->unspill(reg->as_Register(), true, offset); - } else if (reg->is_FloatRegister()) { - masm->unspill(reg->as_FloatRegister(), masm->Q, offset); +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->unspill(as_Register(reg), true, offset); + } else if (reg.type() == StorageType::VECTOR) { + masm->unspill(as_FloatRegister(reg), masm->Q, offset); } else { // stack and BAD } } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { - assert(in_stk_bias == 0 && out_stk_bias == 0, "bias not implemented"); - Register tmp_reg = tmp->as_Register(); +static constexpr int RFP_BIAS = 16; // skip old rfp and lr + +static void move_reg64(MacroAssembler* masm, int out_stk_bias, + Register from_reg, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->mov(as_Register(to_reg), from_reg); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: { + Address dest(sp, to_reg.offset() + out_bias); + switch (to_reg.stack_size()) { + case 8: masm->str (from_reg, dest); break; + case 4: masm->strw(from_reg, dest); break; + case 2: masm->strh(from_reg, dest); break; + case 1: masm->strb(from_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +static void move_stack(MacroAssembler* masm, Register tmp_reg, int in_stk_bias, int out_stk_bias, + VMStorage from_reg, VMStorage to_reg) { + Address from_addr(rfp, RFP_BIAS + from_reg.offset() + in_stk_bias); + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + switch (from_reg.stack_size()) { + case 8: masm->ldr (as_Register(to_reg), from_addr); break; + case 4: masm->ldrw(as_Register(to_reg), from_addr); break; + case 2: masm->ldrh(as_Register(to_reg), from_addr); break; + case 1: masm->ldrb(as_Register(to_reg), from_addr); break; + default: ShouldNotReachHere(); + } + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == V128_MASK, "only moves to v128 registers supported"); + switch (from_reg.stack_size()) { + case 8: + masm->ldrd(as_FloatRegister(to_reg), from_addr); + break; + case 4: + masm->ldrs(as_FloatRegister(to_reg), from_addr); + break; + default: ShouldNotReachHere(); + } + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: { + switch (from_reg.stack_size()) { + case 8: masm->ldr (tmp_reg, from_addr); break; + case 4: masm->ldrw(tmp_reg, from_addr); break; + case 2: masm->ldrh(tmp_reg, from_addr); break; + case 1: masm->ldrb(tmp_reg, from_addr); break; + default: ShouldNotReachHere(); + } + Address dest(sp, to_reg.offset() + out_bias); + switch (to_reg.stack_size()) { + case 8: masm->str (tmp_reg, dest); break; + case 4: masm->strw(tmp_reg, dest); break; + case 2: masm->strh(tmp_reg, dest); break; + case 1: masm->strb(tmp_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +static void move_v128(MacroAssembler* masm, int out_stk_bias, + FloatRegister from_reg, VMStorage to_reg) { + switch (to_reg.type()) { + case StorageType::VECTOR: + assert(to_reg.segment_mask() == V128_MASK, "only moves to v128 registers supported"); + masm->fmovd(as_FloatRegister(to_reg), from_reg); + break; + case StorageType::STACK: { + Address dest(sp, to_reg.offset() + out_stk_bias); + switch (to_reg.stack_size()) { + case 8: masm->strd(from_reg, dest); break; + case 4: masm->strs(from_reg, dest); break; + default: ShouldNotReachHere(); + } + } break; + default: ShouldNotReachHere(); + } +} + +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { + Register tmp_reg = as_Register(tmp); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; - VMRegPair from_vmreg = move.from; - VMRegPair to_vmreg = move.to; - - masm->block_comment(err_msg("bt=%s", null_safe_string(type2name(arg_bt)))); - switch (arg_bt) { - case T_BOOLEAN: - case T_BYTE: - case T_SHORT: - case T_CHAR: - case T_INT: - masm->move32_64(from_vmreg, to_vmreg, tmp_reg); - break; + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; - case T_FLOAT: - masm->float_move(from_vmreg, to_vmreg, tmp_reg); - break; + // replace any placeholders + if (from_reg.type() == StorageType::PLACEHOLDER) { + from_reg = locs.get(from_reg); + } + if (to_reg.type() == StorageType::PLACEHOLDER) { + to_reg = locs.get(to_reg); + } - case T_DOUBLE: - masm->double_move(from_vmreg, to_vmreg, tmp_reg); + switch (from_reg.type()) { + case StorageType::INTEGER: + assert(from_reg.segment_mask() == REG64_MASK, "only 64-bit register supported"); + move_reg64(masm, out_stk_bias, as_Register(from_reg), to_reg); break; - - case T_LONG : - masm->long_move(from_vmreg, to_vmreg, tmp_reg); + case StorageType::VECTOR: + assert(from_reg.segment_mask() == V128_MASK, "only v128 register supported"); + move_v128(masm, out_stk_bias, as_FloatRegister(from_reg), to_reg); break; - - default: - fatal("found in upcall args: %s", type2name(arg_bt)); + case StorageType::STACK: + move_stack(masm, tmp_reg, in_stk_bias, out_stk_bias, from_reg, to_reg); + break; + default: ShouldNotReachHere(); } } } diff --git a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp index 4555b44f528..c4f11266871 100644 --- a/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/foreignGlobals_aarch64.hpp @@ -42,8 +42,8 @@ struct ABIDescriptor { int32_t _stack_alignment_bytes; int32_t _shadow_space_bytes; - Register _target_addr_reg; - Register _ret_buf_addr_reg; + VMStorage _scratch1; + VMStorage _scratch2; bool is_volatile_reg(Register reg) const; bool is_volatile_reg(FloatRegister reg) const; diff --git a/src/hotspot/cpu/aarch64/register_aarch64.hpp b/src/hotspot/cpu/aarch64/register_aarch64.hpp index 82f441cf765..f7ad44aa842 100644 --- a/src/hotspot/cpu/aarch64/register_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/register_aarch64.hpp @@ -52,9 +52,9 @@ class Register { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline Register successor() const; @@ -71,7 +71,7 @@ class Register { int operator==(const Register r) const { return _encoding == r._encoding; } int operator!=(const Register r) const { return _encoding != r._encoding; } - const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } + constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } }; extern Register::RegisterImpl all_RegisterImpls[Register::number_of_declared_registers + 1] INTERNAL_VISIBILITY; @@ -175,9 +175,9 @@ class FloatRegister { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline FloatRegister successor() const; @@ -192,7 +192,7 @@ class FloatRegister { int operator==(const FloatRegister r) const { return _encoding == r._encoding; } int operator!=(const FloatRegister r) const { return _encoding != r._encoding; } - const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; } + constexpr const FloatRegisterImpl* operator->() const { return FloatRegisterImpl::first() + _encoding; } }; extern FloatRegister::FloatRegisterImpl all_FloatRegisterImpls[FloatRegister::number_of_registers + 1] INTERNAL_VISIBILITY; diff --git a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp index a051a47417e..9856fbdbdc3 100644 --- a/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/upcallLinker_aarch64.cpp @@ -128,9 +128,10 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, Register shuffle_reg = r19; JavaCallingConvention out_conv; NativeCallingConvention in_conv(call_regs._arg_regs); - ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); - int stack_slots = SharedRuntime::out_preserve_stack_slots() + arg_shuffle.out_arg_stack_slots(); - int out_arg_area = align_up(stack_slots * VMRegImpl::stack_slot_size, StackAlignmentInBytes); + ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, as_VMStorage(shuffle_reg)); + int preserved_bytes = SharedRuntime::out_preserve_stack_slots() * VMRegImpl::stack_slot_size; + int stack_bytes = preserved_bytes + arg_shuffle.out_arg_bytes(); + int out_arg_area = align_up(stack_bytes , StackAlignmentInBytes); #ifndef PRODUCT LogTarget(Trace, foreign, upcall) lt; @@ -158,10 +159,14 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, int frame_data_offset = reg_save_area_offset + reg_save_area_size; int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData); + StubLocations locs; int ret_buf_offset = -1; if (needs_return_buffer) { ret_buf_offset = frame_bottom_offset; frame_bottom_offset += ret_buf_size; + // use a free register for shuffling code to pick up return + // buffer address from + locs.set(StubLocations::RETURN_BUFFER, abi._scratch1); } int frame_size = frame_bottom_offset; @@ -218,9 +223,9 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, arg_spilller.generate_fill(_masm, arg_save_area_offset); if (needs_return_buffer) { assert(ret_buf_offset != -1, "no return buffer allocated"); - __ lea(abi._ret_buf_addr_reg, Address(sp, ret_buf_offset)); + __ lea(as_Register(locs.get(StubLocations::RETURN_BUFFER)), Address(sp, ret_buf_offset)); } - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), abi._shadow_space_bytes, 0); + arg_shuffle.generate(_masm, as_VMStorage(shuffle_reg), abi._shadow_space_bytes, 0, locs); __ block_comment("} argument shuffle"); __ block_comment("{ receiver "); @@ -239,7 +244,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, if (!needs_return_buffer) { #ifdef ASSERT if (call_regs._ret_regs.length() == 1) { // 0 or 1 - VMReg j_expected_result_reg; + VMStorage j_expected_result_reg; switch (ret_type) { case T_BOOLEAN: case T_BYTE: @@ -247,19 +252,18 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, case T_CHAR: case T_INT: case T_LONG: - j_expected_result_reg = r0->as_VMReg(); + j_expected_result_reg = as_VMStorage(r0); break; case T_FLOAT: case T_DOUBLE: - j_expected_result_reg = v0->as_VMReg(); + j_expected_result_reg = as_VMStorage(v0); break; default: fatal("unexpected return type: %s", type2name(ret_type)); } // No need to move for now, since CallArranger can pick a return type // that goes in the same reg for both CCs. But, at least assert they are the same - assert(call_regs._ret_regs.at(0) == j_expected_result_reg, - "unexpected result register: %s != %s", call_regs._ret_regs.at(0)->name(), j_expected_result_reg->name()); + assert(call_regs._ret_regs.at(0) == j_expected_result_reg, "unexpected result register"); } #endif } else { @@ -267,12 +271,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, __ lea(rscratch1, Address(sp, ret_buf_offset)); int offset = 0; for (int i = 0; i < call_regs._ret_regs.length(); i++) { - VMReg reg = call_regs._ret_regs.at(i); - if (reg->is_Register()) { - __ ldr(reg->as_Register(), Address(rscratch1, offset)); + VMStorage reg = call_regs._ret_regs.at(i); + if (reg.type() == StorageType::INTEGER) { + __ ldr(as_Register(reg), Address(rscratch1, offset)); offset += 8; - } else if (reg->is_FloatRegister()) { - __ ldrd(reg->as_FloatRegister(), Address(rscratch1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ ldrd(as_FloatRegister(reg), Address(rscratch1, offset)); offset += 16; // needs to match VECTOR_REG_SIZE in AArch64Architecture (Java) } else { ShouldNotReachHere(); @@ -328,9 +332,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, receiver, in_ByteSize(frame_data_offset)); - if (TraceOptimizedUpcallStubs) { - blob->print_on(tty); +#ifndef PRODUCT + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + blob->print_on(&ls); } +#endif return blob->code_begin(); } diff --git a/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp b/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp new file mode 100644 index 00000000000..7c6d34c802f --- /dev/null +++ b/src/hotspot/cpu/aarch64/vmstorage_aarch64.hpp @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2022, 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 CPU_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP +#define CPU_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP + +#include + +#include "asm/register.hpp" + +// keep in sync with jdk/internal/foreign/abi/aarch64/AArch64Architecture +enum class StorageType : int8_t { + INTEGER = 0, + VECTOR = 1, + STACK = 2, + PLACEHOLDER = 3, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return type == StorageType::INTEGER || type == StorageType::VECTOR; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +constexpr uint16_t REG64_MASK = 0b0000000000000001; +constexpr uint16_t V128_MASK = 0b0000000000000001; + +inline Register as_Register(VMStorage vms) { + assert(vms.type() == StorageType::INTEGER, "not the right type"); + return ::as_Register(vms.index()); +} + +inline FloatRegister as_FloatRegister(VMStorage vms) { + assert(vms.type() == StorageType::VECTOR, "not the right type"); + return ::as_FloatRegister(vms.index()); +} + +constexpr inline VMStorage as_VMStorage(Register reg) { + return VMStorage::reg_storage(StorageType::INTEGER, REG64_MASK, reg->encoding()); +} + +constexpr inline VMStorage as_VMStorage(FloatRegister reg) { + return VMStorage::reg_storage(StorageType::VECTOR, V128_MASK, reg->encoding()); +} + +inline VMStorage as_VMStorage(VMReg reg) { + if (reg->is_Register()) { + return as_VMStorage(reg->as_Register()); + } else if (reg->is_FloatRegister()) { + return as_VMStorage(reg->as_FloatRegister()); + } else if (reg->is_stack()) { + return VMStorage::stack_storage(reg); + } else if (!reg->is_valid()) { + return VMStorage::invalid(); + } + + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_AARCH64_VMSTORAGE_AARCH64_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/arm/downcallLinker_arm.cpp b/src/hotspot/cpu/arm/downcallLinker_arm.cpp index af69f2a58a6..37b6f43ac14 100644 --- a/src/hotspot/cpu/arm/downcallLinker_arm.cpp +++ b/src/hotspot/cpu/arm/downcallLinker_arm.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/arm/foreignGlobals_arm.cpp b/src/hotspot/cpu/arm/foreignGlobals_arm.cpp index 918e89f3ee6..5438cbe5cd6 100644 --- a/src/hotspot/cpu/arm/foreignGlobals_arm.cpp +++ b/src/hotspot/cpu/arm/foreignGlobals_arm.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,24 +34,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/arm/vmstorage_arm.hpp b/src/hotspot/cpu/arm/vmstorage_arm.hpp new file mode 100644 index 00000000000..fda9ceac0a6 --- /dev/null +++ b/src/hotspot/cpu/arm/vmstorage_arm.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 CPU_ARM_VMSTORAGE_ARM_INLINE_HPP +#define CPU_ARM_VMSTORAGE_ARM_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_ARM_VMSTORAGE_ARM_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp index 86afc73e286..13679cf6669 100644 --- a/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp +++ b/src/hotspot/cpu/ppc/downcallLinker_ppc.cpp @@ -30,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp b/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp index 53eb53ec7cb..b685023656d 100644 --- a/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp +++ b/src/hotspot/cpu/ppc/foreignGlobals_ppc.cpp @@ -35,24 +35,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/ppc/vmstorage_ppc.hpp b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp new file mode 100644 index 00000000000..46efafebe0c --- /dev/null +++ b/src/hotspot/cpu/ppc/vmstorage_ppc.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 CPU_PPC_VMSTORAGE_PPC_INLINE_HPP +#define CPU_PPC_VMSTORAGE_PPC_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_PPC_VMSTORAGE_PPC_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp index 9bd1f8002db..7d757e75180 100644 --- a/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp +++ b/src/hotspot/cpu/riscv/downcallLinker_riscv.cpp @@ -31,9 +31,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp b/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp index a239ed40df3..aefbb56a491 100644 --- a/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp +++ b/src/hotspot/cpu/riscv/foreignGlobals_riscv.cpp @@ -35,25 +35,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } - diff --git a/src/hotspot/cpu/riscv/vmstorage_riscv.hpp b/src/hotspot/cpu/riscv/vmstorage_riscv.hpp new file mode 100644 index 00000000000..93940376229 --- /dev/null +++ b/src/hotspot/cpu/riscv/vmstorage_riscv.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 CPU_RISCV_VMSTORAGE_RISCV_INLINE_HPP +#define CPU_RISCV_VMSTORAGE_RISCV_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_RISCV_VMSTORAGE_RISCV_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/s390/downcallLinker_s390.cpp b/src/hotspot/cpu/s390/downcallLinker_s390.cpp index af69f2a58a6..37b6f43ac14 100644 --- a/src/hotspot/cpu/s390/downcallLinker_s390.cpp +++ b/src/hotspot/cpu/s390/downcallLinker_s390.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -29,9 +30,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp index 918e89f3ee6..5438cbe5cd6 100644 --- a/src/hotspot/cpu/s390/foreignGlobals_s390.cpp +++ b/src/hotspot/cpu/s390/foreignGlobals_s390.cpp @@ -1,4 +1,5 @@ /* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, Red Hat, Inc. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,24 +34,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/s390/vmstorage_s390.hpp b/src/hotspot/cpu/s390/vmstorage_s390.hpp new file mode 100644 index 00000000000..702e57efb94 --- /dev/null +++ b/src/hotspot/cpu/s390/vmstorage_s390.hpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 CPU_S390_VMSTORAGE_S390_INLINE_HPP +#define CPU_S390_VMSTORAGE_S390_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_S390_VMSTORAGE_S390_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp index 3fc43c5031e..3f1241970f2 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_32.cpp @@ -28,9 +28,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp index b7da306ad75..9637057b6ab 100644 --- a/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/downcallLinker_x86_64.cpp @@ -41,13 +41,14 @@ class DowncallStubGenerator : public StubCodeGenerator { BasicType _ret_bt; const ABIDescriptor& _abi; - const GrowableArray& _input_registers; - const GrowableArray& _output_registers; + const GrowableArray& _input_registers; + const GrowableArray& _output_registers; bool _needs_return_buffer; + int _captured_state_mask; int _frame_complete; - int _framesize; + int _frame_size_slots; OopMapSet* _oop_maps; public: DowncallStubGenerator(CodeBuffer* buffer, @@ -55,9 +56,10 @@ class DowncallStubGenerator : public StubCodeGenerator { int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) : StubCodeGenerator(buffer, PrintMethodHandleStubs), _signature(signature), _num_args(num_args), @@ -66,8 +68,9 @@ class DowncallStubGenerator : public StubCodeGenerator { _input_registers(input_registers), _output_registers(output_registers), _needs_return_buffer(needs_return_buffer), + _captured_state_mask(captured_state_mask), _frame_complete(0), - _framesize(0), + _frame_size_slots(0), _oop_maps(NULL) { } @@ -77,8 +80,8 @@ class DowncallStubGenerator : public StubCodeGenerator { return _frame_complete; } - int framesize() const { - return (_framesize >> (LogBytesPerWord - LogBytesPerInt)); + int framesize() const { // frame size in 64-bit words + return (_frame_size_slots >> (LogBytesPerWord - LogBytesPerInt)); } OopMapSet* oop_maps() const { @@ -92,12 +95,15 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { - int locs_size = 64; + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { + int locs_size = 64; CodeBuffer code("nep_invoker_blob", native_invoker_code_size, locs_size); - DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, input_registers, output_registers, needs_return_buffer); + DowncallStubGenerator g(&code, signature, num_args, ret_bt, abi, + input_registers, output_registers, + needs_return_buffer, captured_state_mask); g.generate(); code.log_section_sizes("nep_invoker_blob"); @@ -133,10 +139,10 @@ void DowncallStubGenerator::generate() { // out arg area (e.g. for stack args) }; - Register shufffle_reg = rbx; + VMStorage shuffle_reg = as_VMStorage(rbx); JavaCallingConvention in_conv; NativeCallingConvention out_conv(_input_registers); - ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shufffle_reg->as_VMReg()); + ArgumentShuffle arg_shuffle(_signature, _num_args, _signature, _num_args, &in_conv, &out_conv, shuffle_reg); #ifndef PRODUCT LogTarget(Trace, foreign, downcall) lt; @@ -149,34 +155,38 @@ void DowncallStubGenerator::generate() { // in bytes int allocated_frame_size = 0; - if (_needs_return_buffer) { - allocated_frame_size += 8; // store address - } - allocated_frame_size += arg_shuffle.out_arg_stack_slots() << LogBytesPerInt; allocated_frame_size += _abi._shadow_space_bytes; + allocated_frame_size += arg_shuffle.out_arg_bytes(); - int ret_buf_addr_rsp_offset = -1; - if (_needs_return_buffer) { - // the above - ret_buf_addr_rsp_offset = allocated_frame_size - 8; - } - - // when we don't use a return buffer we need to spill the return value around our slowpath calls - // when we use a return buffer case this SHOULD be unused. + // when we don't use a return buffer we need to spill the return value around our slow path calls + bool should_save_return_value = !_needs_return_buffer; RegSpiller out_reg_spiller(_output_registers); int spill_rsp_offset = -1; - if (!_needs_return_buffer) { + if (should_save_return_value) { spill_rsp_offset = 0; - // spill area can be shared with the above, so we take the max of the 2 + // spill area can be shared with shadow space and out args, + // since they are only used before the call, + // and spill area is only used after. allocated_frame_size = out_reg_spiller.spill_size_bytes() > allocated_frame_size ? out_reg_spiller.spill_size_bytes() : allocated_frame_size; } + + StubLocations locs; + locs.set(StubLocations::TARGET_ADDRESS, _abi._scratch1); + if (_needs_return_buffer) { + locs.set_frame_data(StubLocations::RETURN_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + if (_captured_state_mask != 0) { + locs.set_frame_data(StubLocations::CAPTURED_STATE_BUFFER, allocated_frame_size); + allocated_frame_size += BytesPerWord; + } + allocated_frame_size = align_up(allocated_frame_size, 16); - // _framesize is in 32-bit stack slots: - _framesize += framesize_base + (allocated_frame_size >> LogBytesPerInt); - assert(is_even(_framesize/2), "sp not 16-byte aligned"); + _frame_size_slots += framesize_base + (allocated_frame_size >> LogBytesPerInt); + assert(is_even(_frame_size_slots/2), "sp not 16-byte aligned"); _oop_maps = new OopMapSet(); address start = __ pc(); @@ -192,7 +202,7 @@ void DowncallStubGenerator::generate() { __ block_comment("{ thread java2native"); __ set_last_Java_frame(rsp, rbp, (address)the_pc, rscratch1); - OopMap* map = new OopMap(_framesize, 0); + OopMap* map = new OopMap(_frame_size_slots, 0); _oop_maps->add_gc_map(the_pc - start, map); // State transition @@ -200,28 +210,22 @@ void DowncallStubGenerator::generate() { __ block_comment("} thread java2native"); __ block_comment("{ argument shuffle"); - arg_shuffle.generate(_masm, shufffle_reg->as_VMReg(), 0, _abi._shadow_space_bytes); - if (_needs_return_buffer) { - // spill our return buffer address - assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill"); - __ movptr(Address(rsp, ret_buf_addr_rsp_offset), _abi._ret_buf_addr_reg); - } + arg_shuffle.generate(_masm, shuffle_reg, 0, _abi._shadow_space_bytes, locs); __ block_comment("} argument shuffle"); - __ call(_abi._target_addr_reg); + __ call(as_Register(locs.get(StubLocations::TARGET_ADDRESS))); // this call is assumed not to have killed r15_thread if (_needs_return_buffer) { - assert(ret_buf_addr_rsp_offset != -1, "no return buffer addr spill"); - __ movptr(rscratch1, Address(rsp, ret_buf_addr_rsp_offset)); + __ movptr(rscratch1, Address(rsp, locs.data_offset(StubLocations::RETURN_BUFFER))); int offset = 0; for (int i = 0; i < _output_registers.length(); i++) { - VMReg reg = _output_registers.at(i); - if (reg->is_Register()) { - __ movptr(Address(rscratch1, offset), reg->as_Register()); + VMStorage reg = _output_registers.at(i); + if (reg.type() == StorageType::INTEGER) { + __ movptr(Address(rscratch1, offset), as_Register(reg)); offset += 8; - } else if (reg->is_XMMRegister()) { - __ movdqu(Address(rscratch1, offset), reg->as_XMMRegister()); + } else if (reg.type() == StorageType::VECTOR) { + __ movdqu(Address(rscratch1, offset), as_XMMRegister(reg)); offset += 16; } else { ShouldNotReachHere(); @@ -229,6 +233,34 @@ void DowncallStubGenerator::generate() { } } + ////////////////////////////////////////////////////////////////////////////// + + if (_captured_state_mask != 0) { + __ block_comment("{ save thread local"); + __ vzeroupper(); + + if (should_save_return_value) { + out_reg_spiller.generate_spill(_masm, spill_rsp_offset); + } + + __ movptr(c_rarg0, Address(rsp, locs.data_offset(StubLocations::CAPTURED_STATE_BUFFER))); + __ movl(c_rarg1, _captured_state_mask); + __ mov(r12, rsp); // remember sp + __ subptr(rsp, frame::arg_reg_save_area_bytes); // windows + __ andptr(rsp, -16); // align stack as required by ABI + __ call(RuntimeAddress(CAST_FROM_FN_PTR(address, DowncallLinker::capture_state))); + __ mov(rsp, r12); // restore sp + __ reinit_heapbase(); + + if (should_save_return_value) { + out_reg_spiller.generate_fill(_masm, spill_rsp_offset); + } + + __ block_comment("} save thread local"); + } + + ////////////////////////////////////////////////////////////////////////////// + __ block_comment("{ thread native2java"); __ restore_cpu_control_state_after_jni(rscratch1); @@ -272,7 +304,7 @@ void DowncallStubGenerator::generate() { __ bind(L_safepoint_poll_slow_path); __ vzeroupper(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_rsp_offset); } @@ -284,7 +316,7 @@ void DowncallStubGenerator::generate() { __ mov(rsp, r12); // restore sp __ reinit_heapbase(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_rsp_offset); } @@ -297,7 +329,7 @@ void DowncallStubGenerator::generate() { __ bind(L_reguard); __ vzeroupper(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_spill(_masm, spill_rsp_offset); } @@ -308,7 +340,7 @@ void DowncallStubGenerator::generate() { __ mov(rsp, r12); // restore sp __ reinit_heapbase(); - if(!_needs_return_buffer) { + if (should_save_return_value) { out_reg_spiller.generate_fill(_masm, spill_rsp_offset); } diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86.hpp b/src/hotspot/cpu/x86/foreignGlobals_x86.hpp index 160aa468539..19999a416ea 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86.hpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86.hpp @@ -40,8 +40,8 @@ struct ABIDescriptor { int32_t _stack_alignment_bytes; int32_t _shadow_space_bytes; - Register _target_addr_reg; - Register _ret_buf_addr_reg; + VMStorage _scratch1; + VMStorage _scratch2; bool is_volatile_reg(Register reg) const; bool is_volatile_reg(XMMRegister reg) const; diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp b/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp index e196727674d..8a31955f4d1 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86_32.cpp @@ -33,24 +33,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp b/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp index 3b3d5ff00df..74afbe4fd61 100644 --- a/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp +++ b/src/hotspot/cpu/x86/foreignGlobals_x86_64.cpp @@ -40,123 +40,154 @@ bool ABIDescriptor::is_volatile_reg(XMMRegister reg) const { || _vector_additional_volatile_registers.contains(reg); } -static constexpr int INTEGER_TYPE = 0; -static constexpr int VECTOR_TYPE = 1; -static constexpr int X87_TYPE = 2; - const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { oop abi_oop = JNIHandles::resolve_non_null(jabi); ABIDescriptor abi; objArrayOop inputStorage = jdk_internal_foreign_abi_ABIDescriptor::inputStorage(abi_oop); - parse_register_array(inputStorage, INTEGER_TYPE, abi._integer_argument_registers, as_Register); - parse_register_array(inputStorage, VECTOR_TYPE, abi._vector_argument_registers, as_XMMRegister); + parse_register_array(inputStorage, StorageType::INTEGER, abi._integer_argument_registers, as_Register); + parse_register_array(inputStorage, StorageType::VECTOR, abi._vector_argument_registers, as_XMMRegister); objArrayOop outputStorage = jdk_internal_foreign_abi_ABIDescriptor::outputStorage(abi_oop); - parse_register_array(outputStorage, INTEGER_TYPE, abi._integer_return_registers, as_Register); - parse_register_array(outputStorage, VECTOR_TYPE, abi._vector_return_registers, as_XMMRegister); - objArrayOop subarray = oop_cast(outputStorage->obj_at(X87_TYPE)); + parse_register_array(outputStorage, StorageType::INTEGER, abi._integer_return_registers, as_Register); + parse_register_array(outputStorage, StorageType::VECTOR, abi._vector_return_registers, as_XMMRegister); + objArrayOop subarray = oop_cast(outputStorage->obj_at((int) StorageType::X87)); abi._X87_return_registers_noof = subarray->length(); objArrayOop volatileStorage = jdk_internal_foreign_abi_ABIDescriptor::volatileStorage(abi_oop); - parse_register_array(volatileStorage, INTEGER_TYPE, abi._integer_additional_volatile_registers, as_Register); - parse_register_array(volatileStorage, VECTOR_TYPE, abi._vector_additional_volatile_registers, as_XMMRegister); + parse_register_array(volatileStorage, StorageType::INTEGER, abi._integer_additional_volatile_registers, as_Register); + parse_register_array(volatileStorage, StorageType::VECTOR, abi._vector_additional_volatile_registers, as_XMMRegister); abi._stack_alignment_bytes = jdk_internal_foreign_abi_ABIDescriptor::stackAlignment(abi_oop); abi._shadow_space_bytes = jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(abi_oop); - abi._target_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(abi_oop))->as_Register(); - abi._ret_buf_addr_reg = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(abi_oop))->as_Register(); + abi._scratch1 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch1(abi_oop)); + abi._scratch2 = parse_vmstorage(jdk_internal_foreign_abi_ABIDescriptor::scratch2(abi_oop)); return abi; } -enum class RegType { - INTEGER = 0, - VECTOR = 1, - X87 = 2, - STACK = 3 -}; - -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - switch(static_cast(type)) { - case RegType::INTEGER: return ::as_Register(index)->as_VMReg(); - case RegType::VECTOR: return ::as_XMMRegister(index)->as_VMReg(); - case RegType::STACK: return VMRegImpl::stack2reg(index LP64_ONLY(* 2)); // numbering on x64 goes per 64-bits - case RegType::X87: break; - } - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { - if (reg->is_Register()) { +int RegSpiller::pd_reg_size(VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { return 8; - } else if (reg->is_XMMRegister()) { + } else if (reg.type() == StorageType::VECTOR) { return 16; } return 0; // stack and BAD } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->movptr(Address(rsp, offset), reg->as_Register()); - } else if (reg->is_XMMRegister()) { - masm->movdqu(Address(rsp, offset), reg->as_XMMRegister()); +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->movptr(Address(rsp, offset), as_Register(reg)); + } else if (reg.type() == StorageType::VECTOR) { + masm->movdqu(Address(rsp, offset), as_XMMRegister(reg)); } else { // stack and BAD } } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { - if (reg->is_Register()) { - masm->movptr(reg->as_Register(), Address(rsp, offset)); - } else if (reg->is_XMMRegister()) { - masm->movdqu(reg->as_XMMRegister(), Address(rsp, offset)); +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { + if (reg.type() == StorageType::INTEGER) { + masm->movptr(as_Register(reg), Address(rsp, offset)); + } else if (reg.type() == StorageType::VECTOR) { + masm->movdqu(as_XMMRegister(reg), Address(rsp, offset)); } else { // stack and BAD } } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { - Register tmp_reg = tmp->as_Register(); +static constexpr int RBP_BIAS = 16; // skip old rbp and return address + +static void move_reg64(MacroAssembler* masm, int out_stk_bias, + Register from_reg, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_reg); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(Address(rsp, to_reg.offset() + out_bias), from_reg); + break; + default: ShouldNotReachHere(); + } +} + +static void move_stack64(MacroAssembler* masm, Register tmp_reg, int out_stk_bias, + Address from_address, VMStorage to_reg) { + int out_bias = 0; + switch (to_reg.type()) { + case StorageType::INTEGER: + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_address); + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == XMM_MASK, "only moves to xmm registers supported"); + masm->movdqu(as_XMMRegister(to_reg), from_address); + break; + case StorageType::STACK: + out_bias = out_stk_bias; + case StorageType::FRAME_DATA: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(tmp_reg, from_address); + masm->movq(Address(rsp, to_reg.offset() + out_bias), tmp_reg); + break; + default: ShouldNotReachHere(); + } +} + +static void move_xmm(MacroAssembler* masm, int out_stk_bias, + XMMRegister from_reg, VMStorage to_reg) { + switch (to_reg.type()) { + case StorageType::INTEGER: // windows vargarg floats + assert(to_reg.segment_mask() == REG64_MASK, "only moves to 64-bit registers supported"); + masm->movq(as_Register(to_reg), from_reg); + break; + case StorageType::VECTOR: + assert(to_reg.segment_mask() == XMM_MASK, "only moves to xmm registers supported"); + masm->movdqu(as_XMMRegister(to_reg), from_reg); + break; + case StorageType::STACK: + assert(to_reg.stack_size() == 8, "only moves with 64-bit targets supported"); + masm->movq(Address(rsp, to_reg.offset() + out_stk_bias), from_reg); + break; + default: ShouldNotReachHere(); + } +} + +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { + Register tmp_reg = as_Register(tmp); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; - VMRegPair from_vmreg = move.from; - VMRegPair to_vmreg = move.to; - - masm->block_comment(err_msg("bt=%s", null_safe_string(type2name(arg_bt)))); - switch (arg_bt) { - case T_BOOLEAN: - case T_BYTE: - case T_SHORT: - case T_CHAR: - case T_INT: - masm->move32_64(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - break; + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; - case T_FLOAT: - if (to_vmreg.first()->is_Register()) { // Windows vararg call - masm->movq(to_vmreg.first()->as_Register(), from_vmreg.first()->as_XMMRegister()); - } else { - masm->float_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - } - break; + // replace any placeholders + if (from_reg.type() == StorageType::PLACEHOLDER) { + from_reg = locs.get(from_reg); + } + if (to_reg.type() == StorageType::PLACEHOLDER) { + to_reg = locs.get(to_reg); + } - case T_DOUBLE: - if (to_vmreg.first()->is_Register()) { // Windows vararg call - masm->movq(to_vmreg.first()->as_Register(), from_vmreg.first()->as_XMMRegister()); - } else { - masm->double_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); - } + switch (from_reg.type()) { + case StorageType::INTEGER: + assert(from_reg.segment_mask() == REG64_MASK, "only 64-bit register supported"); + move_reg64(masm, out_stk_bias, as_Register(from_reg), to_reg); break; - - case T_LONG: - masm->long_move(from_vmreg, to_vmreg, tmp_reg, in_stk_bias, out_stk_bias); + case StorageType::VECTOR: + assert(from_reg.segment_mask() == XMM_MASK, "only xmm register supported"); + move_xmm(masm, out_stk_bias, as_XMMRegister(from_reg), to_reg); break; - - default: - fatal("found in upcall args: %s", type2name(arg_bt)); + case StorageType::STACK: { + assert(from_reg.stack_size() == 8, "only stack_size 8 supported"); + Address from_addr(rbp, RBP_BIAS + from_reg.offset() + in_stk_bias); + move_stack64(masm, tmp_reg, out_stk_bias, from_addr, to_reg); + } break; + default: ShouldNotReachHere(); } } } diff --git a/src/hotspot/cpu/x86/register_x86.hpp b/src/hotspot/cpu/x86/register_x86.hpp index 83d12a809e0..e310646ba93 100644 --- a/src/hotspot/cpu/x86/register_x86.hpp +++ b/src/hotspot/cpu/x86/register_x86.hpp @@ -56,9 +56,9 @@ class Register { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } bool has_byte_register() const { return 0 <= raw_encoding() && raw_encoding() < number_of_byte_registers; } // derived registers, offsets, and addresses @@ -74,7 +74,7 @@ class Register { int operator==(const Register r) const { return _encoding == r._encoding; } int operator!=(const Register r) const { return _encoding != r._encoding; } - const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } + constexpr const RegisterImpl* operator->() const { return RegisterImpl::first() + _encoding; } }; extern Register::RegisterImpl all_RegisterImpls[Register::number_of_registers + 1] INTERNAL_VISIBILITY; @@ -202,9 +202,9 @@ class XMMRegister { public: // accessors - int raw_encoding() const { return this - first(); } - int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } - bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } + constexpr int raw_encoding() const { return this - first(); } + constexpr int encoding() const { assert(is_valid(), "invalid register"); return raw_encoding(); } + constexpr bool is_valid() const { return 0 <= raw_encoding() && raw_encoding() < number_of_registers; } // derived registers, offsets, and addresses inline XMMRegister successor() const; @@ -219,7 +219,7 @@ class XMMRegister { int operator==(const XMMRegister r) const { return _encoding == r._encoding; } int operator!=(const XMMRegister r) const { return _encoding != r._encoding; } - const XMMRegisterImpl* operator->() const { return XMMRegisterImpl::first() + _encoding; } + constexpr const XMMRegisterImpl* operator->() const { return XMMRegisterImpl::first() + _encoding; } // Actually available XMM registers for use, depending on actual CPU capabilities and flags. static int available_xmm_registers() { diff --git a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp index e37491edfe8..3e3214b51b1 100644 --- a/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp +++ b/src/hotspot/cpu/x86/upcallLinker_x86_64.cpp @@ -175,12 +175,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, const CallRegs call_regs = ForeignGlobals::parse_call_regs(jconv); CodeBuffer buffer("upcall_stub", /* code_size = */ 2048, /* locs_size = */ 1024); - Register shuffle_reg = rbx; + VMStorage shuffle_reg = as_VMStorage(rbx); JavaCallingConvention out_conv; NativeCallingConvention in_conv(call_regs._arg_regs); - ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg->as_VMReg()); - int stack_slots = SharedRuntime::out_preserve_stack_slots() + arg_shuffle.out_arg_stack_slots(); - int out_arg_area = align_up(stack_slots * VMRegImpl::stack_slot_size, StackAlignmentInBytes); + ArgumentShuffle arg_shuffle(in_sig_bt, total_in_args, out_sig_bt, total_out_args, &in_conv, &out_conv, shuffle_reg); + int preserved_bytes = SharedRuntime::out_preserve_stack_slots() * VMRegImpl::stack_slot_size; + int stack_bytes = preserved_bytes + arg_shuffle.out_arg_bytes(); + int out_arg_area = align_up(stack_bytes , StackAlignmentInBytes); #ifndef PRODUCT LogTarget(Trace, foreign, upcall) lt; @@ -208,10 +209,14 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, int frame_data_offset = reg_save_area_offset + reg_save_area_size; int frame_bottom_offset = frame_data_offset + sizeof(UpcallStub::FrameData); + StubLocations locs; int ret_buf_offset = -1; if (needs_return_buffer) { ret_buf_offset = frame_bottom_offset; frame_bottom_offset += ret_buf_size; + // use a free register for shuffling code to pick up return + // buffer address from + locs.set(StubLocations::RETURN_BUFFER, abi._scratch1); } int frame_size = frame_bottom_offset; @@ -273,9 +278,9 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, arg_spilller.generate_fill(_masm, arg_save_area_offset); if (needs_return_buffer) { assert(ret_buf_offset != -1, "no return buffer allocated"); - __ lea(abi._ret_buf_addr_reg, Address(rsp, ret_buf_offset)); + __ lea(as_Register(locs.get(StubLocations::RETURN_BUFFER)), Address(rsp, ret_buf_offset)); } - arg_shuffle.generate(_masm, shuffle_reg->as_VMReg(), abi._shadow_space_bytes, 0); + arg_shuffle.generate(_masm, shuffle_reg, abi._shadow_space_bytes, 0, locs); __ block_comment("} argument shuffle"); __ block_comment("{ receiver "); @@ -293,7 +298,7 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, if (!needs_return_buffer) { #ifdef ASSERT if (call_regs._ret_regs.length() == 1) { // 0 or 1 - VMReg j_expected_result_reg; + VMStorage j_expected_result_reg; switch (ret_type) { case T_BOOLEAN: case T_BYTE: @@ -301,19 +306,18 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, case T_CHAR: case T_INT: case T_LONG: - j_expected_result_reg = rax->as_VMReg(); + j_expected_result_reg = as_VMStorage(rax); break; case T_FLOAT: case T_DOUBLE: - j_expected_result_reg = xmm0->as_VMReg(); + j_expected_result_reg = as_VMStorage(xmm0); break; default: fatal("unexpected return type: %s", type2name(ret_type)); } // No need to move for now, since CallArranger can pick a return type // that goes in the same reg for both CCs. But, at least assert they are the same - assert(call_regs._ret_regs.at(0) == j_expected_result_reg, - "unexpected result register: %s != %s", call_regs._ret_regs.at(0)->name(), j_expected_result_reg->name()); + assert(call_regs._ret_regs.at(0) == j_expected_result_reg, "unexpected result register"); } #endif } else { @@ -321,12 +325,12 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, __ lea(rscratch1, Address(rsp, ret_buf_offset)); int offset = 0; for (int i = 0; i < call_regs._ret_regs.length(); i++) { - VMReg reg = call_regs._ret_regs.at(i); - if (reg->is_Register()) { - __ movptr(reg->as_Register(), Address(rscratch1, offset)); + VMStorage reg = call_regs._ret_regs.at(i); + if (reg.type() == StorageType::INTEGER) { + __ movptr(as_Register(reg), Address(rscratch1, offset)); offset += 8; - } else if (reg->is_XMMRegister()) { - __ movdqu(reg->as_XMMRegister(), Address(rscratch1, offset)); + } else if (reg.type() == StorageType::VECTOR) { + __ movdqu(as_XMMRegister(reg), Address(rscratch1, offset)); offset += 16; } else { ShouldNotReachHere(); @@ -389,9 +393,13 @@ address UpcallLinker::make_upcall_stub(jobject receiver, Method* entry, receiver, in_ByteSize(frame_data_offset)); - if (TraceOptimizedUpcallStubs) { - blob->print_on(tty); +#ifndef PRODUCT + if (lt.is_enabled()) { + ResourceMark rm; + LogStream ls(lt); + blob->print_on(&ls); } +#endif return blob->code_begin(); } diff --git a/src/hotspot/cpu/x86/vmstorage_x86.hpp b/src/hotspot/cpu/x86/vmstorage_x86.hpp new file mode 100644 index 00000000000..a6ad21b2179 --- /dev/null +++ b/src/hotspot/cpu/x86/vmstorage_x86.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022, 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 CPU_X86_VMSTORAGE_X86_INLINE_HPP +#define CPU_X86_VMSTORAGE_X86_INLINE_HPP + +#include + +#include "asm/register.hpp" +#include "code/vmreg.inline.hpp" + +// keep in sync with jdk/internal/foreign/abi/x64/X86_64Architecture +enum class StorageType : int8_t { + INTEGER = 0, + VECTOR = 1, + X87 = 2, + STACK = 3, + PLACEHOLDER = 4, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return type == StorageType::INTEGER || type == StorageType::VECTOR || type == StorageType::X87; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +constexpr uint16_t REG64_MASK = 0b0000000000001111; +constexpr uint16_t XMM_MASK = 0b0000000000000001; + +inline Register as_Register(VMStorage vms) { + assert(vms.type() == StorageType::INTEGER, "not the right type"); + return ::as_Register(vms.index()); +} + +inline XMMRegister as_XMMRegister(VMStorage vms) { + assert(vms.type() == StorageType::VECTOR, "not the right type"); + return ::as_XMMRegister(vms.index()); +} + +inline VMReg as_VMReg(VMStorage vms) { + switch (vms.type()) { + case StorageType::INTEGER: return as_Register(vms)->as_VMReg(); + case StorageType::VECTOR: return as_XMMRegister(vms)->as_VMReg(); + case StorageType::STACK: { + assert((vms.index() % VMRegImpl::stack_slot_size) == 0, "can not represent as VMReg"); + return VMRegImpl::stack2reg(vms.index() / VMRegImpl::stack_slot_size); + } + default: ShouldNotReachHere(); return VMRegImpl::Bad(); + } +} + +constexpr inline VMStorage as_VMStorage(Register reg) { + return VMStorage::reg_storage(StorageType::INTEGER, REG64_MASK, reg->encoding()); +} + +constexpr inline VMStorage as_VMStorage(XMMRegister reg) { + return VMStorage::reg_storage(StorageType::VECTOR, XMM_MASK, reg->encoding()); +} + +inline VMStorage as_VMStorage(VMReg reg) { + if (reg->is_Register()) { + return as_VMStorage(reg->as_Register()); + } else if (reg->is_XMMRegister()) { + return as_VMStorage(reg->as_XMMRegister()); + } else if (reg->is_stack()) { + return VMStorage::stack_storage(reg); + } else if (!reg->is_valid()) { + return VMStorage::invalid(); + } + + ShouldNotReachHere(); + return VMStorage::invalid(); +} + +#endif // CPU_X86_VMSTORAGE_X86_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/cpu/zero/downcallLinker_zero.cpp b/src/hotspot/cpu/zero/downcallLinker_zero.cpp index 3fc43c5031e..3f1241970f2 100644 --- a/src/hotspot/cpu/zero/downcallLinker_zero.cpp +++ b/src/hotspot/cpu/zero/downcallLinker_zero.cpp @@ -28,9 +28,10 @@ RuntimeStub* DowncallLinker::make_downcall_stub(BasicType* signature, int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer) { + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask) { Unimplemented(); return nullptr; } diff --git a/src/hotspot/cpu/zero/foreignGlobals_zero.cpp b/src/hotspot/cpu/zero/foreignGlobals_zero.cpp index 21f6e9fd464..7c35da7e3e0 100644 --- a/src/hotspot/cpu/zero/foreignGlobals_zero.cpp +++ b/src/hotspot/cpu/zero/foreignGlobals_zero.cpp @@ -33,24 +33,19 @@ const ABIDescriptor ForeignGlobals::parse_abi_descriptor(jobject jabi) { return {}; } -VMReg ForeignGlobals::vmstorage_to_vmreg(int type, int index) { - Unimplemented(); - return VMRegImpl::Bad(); -} - -int RegSpiller::pd_reg_size(VMReg reg) { +int RegSpiller::pd_reg_size(VMStorage reg) { Unimplemented(); return -1; } -void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMReg reg) { +void RegSpiller::pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg) { Unimplemented(); } -void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { +void ArgumentShuffle::pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { Unimplemented(); } diff --git a/src/hotspot/cpu/zero/vmstorage_zero.hpp b/src/hotspot/cpu/zero/vmstorage_zero.hpp new file mode 100644 index 00000000000..7536a6227e9 --- /dev/null +++ b/src/hotspot/cpu/zero/vmstorage_zero.hpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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 CPU_ZERO_VMSTORAGE_ZERO_INLINE_HPP +#define CPU_ZERO_VMSTORAGE_ZERO_INLINE_HPP + +#include + +#include "asm/register.hpp" + +enum class StorageType : int8_t { + STACK = 0, + PLACEHOLDER = 1, +// special locations used only by native code + FRAME_DATA = PLACEHOLDER + 1, + INVALID = -1 +}; + +// need to define this before constructing VMStorage (below) +constexpr inline bool VMStorage::is_reg(StorageType type) { + return false; +} +constexpr inline StorageType VMStorage::stack_type() { return StorageType::STACK; } +constexpr inline StorageType VMStorage::placeholder_type() { return StorageType::PLACEHOLDER; } +constexpr inline StorageType VMStorage::frame_data_type() { return StorageType::FRAME_DATA; } + +inline VMStorage as_VMStorage(VMReg reg) { + ShouldNotReachHere(); + return VMStorage::invalid(); +} + + +#endif // CPU_ZERO_VMSTORAGE_ZERO_INLINE_HPP \ No newline at end of file diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 0e523cac6e3..117e5be1c28 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -4131,17 +4131,17 @@ int jdk_internal_foreign_abi_ABIDescriptor::_outputStorage_offset; int jdk_internal_foreign_abi_ABIDescriptor::_volatileStorage_offset; int jdk_internal_foreign_abi_ABIDescriptor::_stackAlignment_offset; int jdk_internal_foreign_abi_ABIDescriptor::_shadowSpace_offset; -int jdk_internal_foreign_abi_ABIDescriptor::_targetAddrStorage_offset; -int jdk_internal_foreign_abi_ABIDescriptor::_retBufAddrStorage_offset; +int jdk_internal_foreign_abi_ABIDescriptor::_scratch1_offset; +int jdk_internal_foreign_abi_ABIDescriptor::_scratch2_offset; #define ABIDescriptor_FIELDS_DO(macro) \ - macro(_inputStorage_offset, k, "inputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_outputStorage_offset, k, "outputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_volatileStorage_offset, k, "volatileStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ - macro(_stackAlignment_offset, k, "stackAlignment", int_signature, false); \ - macro(_shadowSpace_offset, k, "shadowSpace", int_signature, false); \ - macro(_targetAddrStorage_offset, k, "targetAddrStorage", jdk_internal_foreign_abi_VMStorage_signature, false); \ - macro(_retBufAddrStorage_offset, k, "retBufAddrStorage", jdk_internal_foreign_abi_VMStorage_signature, false); + macro(_inputStorage_offset, k, "inputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_outputStorage_offset, k, "outputStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_volatileStorage_offset, k, "volatileStorage", jdk_internal_foreign_abi_VMStorage_array_array_signature, false); \ + macro(_stackAlignment_offset, k, "stackAlignment", int_signature, false); \ + macro(_shadowSpace_offset, k, "shadowSpace", int_signature, false); \ + macro(_scratch1_offset, k, "scratch1", jdk_internal_foreign_abi_VMStorage_signature, false); \ + macro(_scratch2_offset, k, "scratch2", jdk_internal_foreign_abi_VMStorage_signature, false); bool jdk_internal_foreign_abi_ABIDescriptor::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -4178,22 +4178,24 @@ jint jdk_internal_foreign_abi_ABIDescriptor::shadowSpace(oop entry) { return entry->int_field(_shadowSpace_offset); } -oop jdk_internal_foreign_abi_ABIDescriptor::targetAddrStorage(oop entry) { - return entry->obj_field(_targetAddrStorage_offset); +oop jdk_internal_foreign_abi_ABIDescriptor::scratch1(oop entry) { + return entry->obj_field(_scratch1_offset); } -oop jdk_internal_foreign_abi_ABIDescriptor::retBufAddrStorage(oop entry) { - return entry->obj_field(_retBufAddrStorage_offset); +oop jdk_internal_foreign_abi_ABIDescriptor::scratch2(oop entry) { + return entry->obj_field(_scratch2_offset); } int jdk_internal_foreign_abi_VMStorage::_type_offset; -int jdk_internal_foreign_abi_VMStorage::_index_offset; +int jdk_internal_foreign_abi_VMStorage::_indexOrOffset_offset; +int jdk_internal_foreign_abi_VMStorage::_segmentMaskOrSize_offset; int jdk_internal_foreign_abi_VMStorage::_debugName_offset; #define VMStorage_FIELDS_DO(macro) \ - macro(_type_offset, k, "type", int_signature, false); \ - macro(_index_offset, k, "index", int_signature, false); \ - macro(_debugName_offset, k, "debugName", string_signature, false); \ + macro(_type_offset, k, "type", byte_signature, false); \ + macro(_indexOrOffset_offset, k, "indexOrOffset", int_signature, false); \ + macro(_segmentMaskOrSize_offset, k, "segmentMaskOrSize", short_signature, false); \ + macro(_debugName_offset, k, "debugName", string_signature, false); \ bool jdk_internal_foreign_abi_VMStorage::is_instance(oop obj) { return obj != NULL && is_subclass(obj->klass()); @@ -4210,12 +4212,16 @@ void jdk_internal_foreign_abi_VMStorage::serialize_offsets(SerializeClosure* f) } #endif -jint jdk_internal_foreign_abi_VMStorage::type(oop entry) { - return entry->int_field(_type_offset); +jbyte jdk_internal_foreign_abi_VMStorage::type(oop entry) { + return entry->byte_field(_type_offset); } -jint jdk_internal_foreign_abi_VMStorage::index(oop entry) { - return entry->int_field(_index_offset); +jint jdk_internal_foreign_abi_VMStorage::index_or_offset(oop entry) { + return entry->int_field(_indexOrOffset_offset); +} + +jshort jdk_internal_foreign_abi_VMStorage::segment_mask_or_size(oop entry) { + return entry->short_field(_segmentMaskOrSize_offset); } oop jdk_internal_foreign_abi_VMStorage::debugName(oop entry) { diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 9c55961cb43..7d159dbcc63 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -1121,8 +1121,8 @@ class jdk_internal_foreign_abi_ABIDescriptor: AllStatic { static int _volatileStorage_offset; static int _stackAlignment_offset; static int _shadowSpace_offset; - static int _targetAddrStorage_offset; - static int _retBufAddrStorage_offset; + static int _scratch1_offset; + static int _scratch2_offset; static void compute_offsets(); @@ -1135,8 +1135,8 @@ class jdk_internal_foreign_abi_ABIDescriptor: AllStatic { static objArrayOop volatileStorage(oop entry); static jint stackAlignment(oop entry); static jint shadowSpace(oop entry); - static oop targetAddrStorage(oop entry); - static oop retBufAddrStorage(oop entry); + static oop scratch1(oop entry); + static oop scratch2(oop entry); // Testers static bool is_subclass(Klass* klass) { @@ -1151,7 +1151,8 @@ class jdk_internal_foreign_abi_VMStorage: AllStatic { private: static int _type_offset; - static int _index_offset; + static int _indexOrOffset_offset; + static int _segmentMaskOrSize_offset; static int _debugName_offset; static void compute_offsets(); @@ -1160,9 +1161,10 @@ class jdk_internal_foreign_abi_VMStorage: AllStatic { static void serialize_offsets(SerializeClosure* f) NOT_CDS_RETURN; // Accessors - static jint type(oop entry); - static jint index(oop entry); - static oop debugName(oop entry); + static jbyte type(oop entry); + static jint index_or_offset(oop entry); + static jshort segment_mask_or_size(oop entry); + static oop debugName(oop entry); // Testers static bool is_subclass(Klass* klass) { diff --git a/src/hotspot/share/code/codeBlob.cpp b/src/hotspot/share/code/codeBlob.cpp index a082dc962e3..c71a5dc3dee 100644 --- a/src/hotspot/share/code/codeBlob.cpp +++ b/src/hotspot/share/code/codeBlob.cpp @@ -792,6 +792,7 @@ void UpcallStub::verify() { void UpcallStub::print_on(outputStream* st) const { RuntimeBlob::print_on(st); print_value_on(st); + Disassembler::decode((RuntimeBlob*)this, st); } void UpcallStub::print_value_on(outputStream* st) const { diff --git a/src/hotspot/share/code/codeBlob.hpp b/src/hotspot/share/code/codeBlob.hpp index 6da296eb905..8e66deb914e 100644 --- a/src/hotspot/share/code/codeBlob.hpp +++ b/src/hotspot/share/code/codeBlob.hpp @@ -109,7 +109,7 @@ class CodeBlob { // that range. There is a similar range(s) on returns // which we don't detect. int _data_offset; // offset to where data region begins - int _frame_size; // size of stack frame + int _frame_size; // size of stack frame in words (NOT slots. On x64 these are 64bit words) bool _caller_must_gc_arguments; diff --git a/src/hotspot/share/prims/downcallLinker.cpp b/src/hotspot/share/prims/downcallLinker.cpp new file mode 100644 index 00000000000..ec20fd17d80 --- /dev/null +++ b/src/hotspot/share/prims/downcallLinker.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "downcallLinker.hpp" + +#include +#ifdef _WIN64 +#include +#include +#endif + +void DowncallLinker::capture_state(int32_t* value_ptr, int captured_state_mask) { + // keep in synch with jdk.internal.foreign.abi.PreservableValues + enum PreservableValues { + NONE = 0, + GET_LAST_ERROR = 1, + WSA_GET_LAST_ERROR = 1 << 1, + ERRNO = 1 << 2 + }; +#ifdef _WIN64 + if (captured_state_mask & GET_LAST_ERROR) { + *value_ptr = GetLastError(); + value_ptr++; + } + if (captured_state_mask & WSA_GET_LAST_ERROR) { + *value_ptr = WSAGetLastError(); + value_ptr++; + } +#endif + if (captured_state_mask & ERRNO) { + *value_ptr = errno; + } +} diff --git a/src/hotspot/share/prims/downcallLinker.hpp b/src/hotspot/share/prims/downcallLinker.hpp index 5f8fdf88ff8..86849c05158 100644 --- a/src/hotspot/share/prims/downcallLinker.hpp +++ b/src/hotspot/share/prims/downcallLinker.hpp @@ -34,9 +34,12 @@ class DowncallLinker: AllStatic { int num_args, BasicType ret_bt, const ABIDescriptor& abi, - const GrowableArray& input_registers, - const GrowableArray& output_registers, - bool needs_return_buffer); + const GrowableArray& input_registers, + const GrowableArray& output_registers, + bool needs_return_buffer, + int captured_state_mask); + + static void capture_state(int32_t* value_ptr, int captured_state_mask); }; #endif // SHARE_VM_PRIMS_DOWNCALLLINKER_HPP diff --git a/src/hotspot/share/prims/foreignGlobals.cpp b/src/hotspot/share/prims/foreignGlobals.cpp index 58f9d1305c3..2c8fdae969b 100644 --- a/src/hotspot/share/prims/foreignGlobals.cpp +++ b/src/hotspot/share/prims/foreignGlobals.cpp @@ -28,6 +28,39 @@ #include "prims/foreignGlobals.inline.hpp" #include "runtime/jniHandles.inline.hpp" +StubLocations::StubLocations() { + for (uint32_t i = 0; i < LOCATION_LIMIT; i++) { + _locs[i] = VMStorage::invalid(); + } +} + +void StubLocations::set(uint32_t loc, VMStorage storage) { + assert(loc < LOCATION_LIMIT, "oob"); + _locs[loc] = storage; +} + +void StubLocations::set_frame_data(uint32_t loc, int offset) { + set(loc, VMStorage(StorageType::FRAME_DATA, 8, offset)); +} + +VMStorage StubLocations::get(uint32_t loc) const { + assert(loc < LOCATION_LIMIT, "oob"); + VMStorage storage = _locs[loc]; + assert(storage.is_valid(), "not set"); + return storage; +} + +VMStorage StubLocations::get(VMStorage placeholder) const { + assert(placeholder.type() == StorageType::PLACEHOLDER, "must be"); + return get(placeholder.index()); +} + +int StubLocations::data_offset(uint32_t loc) const { + VMStorage storage = get(loc); + assert(storage.type() == StorageType::FRAME_DATA, "must be"); + return storage.offset(); +} + #define FOREIGN_ABI "jdk/internal/foreign/abi/" const CallRegs ForeignGlobals::parse_call_regs(jobject jconv) { @@ -49,13 +82,15 @@ const CallRegs ForeignGlobals::parse_call_regs(jobject jconv) { return result; } -VMReg ForeignGlobals::parse_vmstorage(oop storage) { - jint index = jdk_internal_foreign_abi_VMStorage::index(storage); - jint type = jdk_internal_foreign_abi_VMStorage::type(storage); - return vmstorage_to_vmreg(type, index); +VMStorage ForeignGlobals::parse_vmstorage(oop storage) { + jbyte type = jdk_internal_foreign_abi_VMStorage::type(storage); + jshort segment_mask_or_size = jdk_internal_foreign_abi_VMStorage::segment_mask_or_size(storage); + jint index_or_offset = jdk_internal_foreign_abi_VMStorage::index_or_offset(storage); + + return VMStorage(static_cast(type), segment_mask_or_size, index_or_offset); } -int RegSpiller::compute_spill_area(const GrowableArray& regs) { +int RegSpiller::compute_spill_area(const GrowableArray& regs) { int result_size = 0; for (int i = 0; i < regs.length(); i++) { result_size += pd_reg_size(regs.at(i)); @@ -67,7 +102,7 @@ void RegSpiller::generate(MacroAssembler* masm, int rsp_offset, bool spill) cons assert(rsp_offset != -1, "rsp_offset should be set"); int offset = rsp_offset; for (int i = 0; i < _regs.length(); i++) { - VMReg reg = _regs.at(i); + VMStorage reg = _regs.at(i); if (spill) { pd_store_reg(masm, offset, reg); } else { @@ -81,27 +116,23 @@ void ArgumentShuffle::print_on(outputStream* os) const { os->print_cr("Argument shuffle {"); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; - VMRegPair from_vmreg = move.from; - VMRegPair to_vmreg = move.to; - - os->print("Move a %s from (", null_safe_string(type2name(arg_bt))); - from_vmreg.first()->print_on(os); - os->print(","); - from_vmreg.second()->print_on(os); - os->print(") to ("); - to_vmreg.first()->print_on(os); - os->print(","); - to_vmreg.second()->print_on(os); - os->print_cr(")"); + BasicType arg_bt = move.bt; + VMStorage from_reg = move.from; + VMStorage to_reg = move.to; + + os->print("Move a %s from ", null_safe_string(type2name(arg_bt))); + from_reg.print_on(os); + os->print(" to "); + to_reg.print_on(os); + os->print_cr(""); } - os->print_cr("Stack argument slots: %d", _out_arg_stack_slots); + os->print_cr("Stack argument bytes: %d", _out_arg_bytes); os->print_cr("}"); } -int NativeCallingConvention::calling_convention(BasicType* sig_bt, VMRegPair* out_regs, int num_args) const { +int NativeCallingConvention::calling_convention(const BasicType* sig_bt, VMStorage* out_regs, int num_args) const { int src_pos = 0; - int stk_slots = 0; + uint32_t max_stack_offset = 0; for (int i = 0; i < num_args; i++) { switch (sig_bt[i]) { case T_BOOLEAN: @@ -110,53 +141,66 @@ int NativeCallingConvention::calling_convention(BasicType* sig_bt, VMRegPair* ou case T_SHORT: case T_INT: case T_FLOAT: { - assert(src_pos < _input_regs.length(), "oob"); - VMReg reg = _input_regs.at(src_pos++); - out_regs[i].set1(reg); - if (reg->is_stack()) - stk_slots += 2; + VMStorage reg = _input_regs.at(src_pos++); + out_regs[i] = reg; + if (reg.is_stack()) + max_stack_offset = MAX2(max_stack_offset, reg.offset() + reg.stack_size()); break; } case T_LONG: case T_DOUBLE: { assert((i + 1) < num_args && sig_bt[i + 1] == T_VOID, "expecting half"); - assert(src_pos < _input_regs.length(), "oob"); - VMReg reg = _input_regs.at(src_pos++); - out_regs[i].set2(reg); - if (reg->is_stack()) - stk_slots += 2; + VMStorage reg = _input_regs.at(src_pos++); + out_regs[i] = reg; + if (reg.is_stack()) + max_stack_offset = MAX2(max_stack_offset, reg.offset() + reg.stack_size()); break; } case T_VOID: // Halves of longs and doubles assert(i != 0 && (sig_bt[i - 1] == T_LONG || sig_bt[i - 1] == T_DOUBLE), "expecting half"); - out_regs[i].set_bad(); + out_regs[i] = VMStorage::invalid(); break; default: ShouldNotReachHere(); break; } } - return stk_slots; + return align_up(max_stack_offset, 8); +} + +int JavaCallingConvention::calling_convention(const BasicType* sig_bt, VMStorage* regs, int num_args) const { + VMRegPair* vm_regs = NEW_RESOURCE_ARRAY(VMRegPair, num_args); + int slots = SharedRuntime::java_calling_convention(sig_bt, vm_regs, num_args); + for (int i = 0; i < num_args; i++) { + VMRegPair pair = vm_regs[i]; + // note, we ignore second here. Signature should consist of register-size values. So there should be + // no need for multi-register pairs. + //assert(!pair.first()->is_valid() || pair.is_single_reg(), "must be: %s"); + regs[i] = as_VMStorage(pair.first()); + } + return slots << LogBytesPerInt; } class ComputeMoveOrder: public StackObj { class MoveOperation: public ResourceObj { friend class ComputeMoveOrder; private: - VMRegPair _src; - VMRegPair _dst; - bool _processed; - MoveOperation* _next; - MoveOperation* _prev; - BasicType _bt; - - static int get_id(VMRegPair r) { - return r.first()->value(); + VMStorage _src; + VMStorage _dst; + bool _processed; + MoveOperation* _next; + MoveOperation* _prev; + BasicType _bt; + + static int get_id(VMStorage r) { + assert((r.index_or_offset() & 0xFF000000) == 0, "index or offset too large"); + // assuming mask and size doesn't matter for now + return ((int) r.type()) | (r.index_or_offset() << 8); } public: - MoveOperation(VMRegPair src, VMRegPair dst, BasicType bt) - : _src(src), _dst(dst), _processed(false), _next(NULL), _prev(NULL), _bt(bt) {} + MoveOperation(VMStorage src, VMStorage dst, BasicType bt): + _src(src), _dst(dst), _processed(false), _next(NULL), _prev(NULL), _bt(bt) {} int src_id() const { return get_id(_src); } int dst_id() const { return get_id(_dst); } @@ -166,7 +210,7 @@ class ComputeMoveOrder: public StackObj { bool is_processed() const { return _processed; } // insert - void break_cycle(VMRegPair temp_register) { + void break_cycle(VMStorage temp_register) { // create a new store following the last store // to move from the temp_register to the original MoveOperation* new_store = new MoveOperation(temp_register, _dst, _bt); @@ -200,16 +244,17 @@ class ComputeMoveOrder: public StackObj { private: int _total_in_args; - const VMRegPair* _in_regs; + const VMStorage* _in_regs; int _total_out_args; - const VMRegPair* _out_regs; + const VMStorage* _out_regs; const BasicType* _in_sig_bt; - VMRegPair _tmp_vmreg; + VMStorage _tmp_vmreg; GrowableArray _edges; GrowableArray _moves; - ComputeMoveOrder(int total_in_args, const VMRegPair* in_regs, int total_out_args, VMRegPair* out_regs, - const BasicType* in_sig_bt, VMRegPair tmp_vmreg) : + public: + ComputeMoveOrder(int total_in_args, const VMStorage* in_regs, int total_out_args, VMStorage* out_regs, + const BasicType* in_sig_bt, VMStorage tmp_vmreg) : _total_in_args(total_in_args), _in_regs(in_regs), _total_out_args(total_out_args), @@ -232,16 +277,16 @@ class ComputeMoveOrder: public StackObj { for (int in_idx = _total_in_args - 1, out_idx = _total_out_args - 1; in_idx >= 0; in_idx--, out_idx--) { BasicType bt = _in_sig_bt[in_idx]; assert(bt != T_ARRAY, "array not expected"); - VMRegPair in_reg = _in_regs[in_idx]; - VMRegPair out_reg = _out_regs[out_idx]; + VMStorage in_reg = _in_regs[in_idx]; + VMStorage out_reg = _out_regs[out_idx]; - if (out_reg.first()->is_stack()) { + if (out_reg.is_stack()) { // Move operations where the dest is the stack can all be // scheduled first since they can't interfere with the other moves. // The input and output stack spaces are distinct from each other. Move move{bt, in_reg, out_reg}; _moves.push(move); - } else if (in_reg.first() == out_reg.first() + } else if (in_reg == out_reg || bt == T_VOID) { // 1. Can skip non-stack identity moves. // @@ -259,8 +304,9 @@ class ComputeMoveOrder: public StackObj { // Walk the edges breaking cycles between moves. The result list // can be walked in order to produce the proper set of loads - void compute_store_order(VMRegPair temp_register) { + void compute_store_order(VMStorage temp_register) { // Record which moves kill which values + // FIXME should be a map GrowableArray killer; // essentially a map of register id -> MoveOperation* for (int i = 0; i < _edges.length(); i++) { MoveOperation* s = _edges.at(i); @@ -304,9 +350,9 @@ class ComputeMoveOrder: public StackObj { } public: - static GrowableArray compute_move_order(int total_in_args, const VMRegPair* in_regs, - int total_out_args, VMRegPair* out_regs, - const BasicType* in_sig_bt, VMRegPair tmp_vmreg) { + static GrowableArray compute_move_order(int total_in_args, const VMStorage* in_regs, + int total_out_args, VMStorage* out_regs, + const BasicType* in_sig_bt, VMStorage tmp_vmreg) { ComputeMoveOrder cmo(total_in_args, in_regs, total_out_args, out_regs, in_sig_bt, tmp_vmreg); cmo.compute(); return cmo._moves; @@ -320,24 +366,15 @@ ArgumentShuffle::ArgumentShuffle( int num_out_args, const CallingConventionClosure* input_conv, const CallingConventionClosure* output_conv, - VMReg shuffle_temp) { + VMStorage shuffle_temp) { - VMRegPair* in_regs = NEW_RESOURCE_ARRAY(VMRegPair, num_in_args); + VMStorage* in_regs = NEW_RESOURCE_ARRAY(VMStorage, num_in_args); input_conv->calling_convention(in_sig_bt, in_regs, num_in_args); - VMRegPair* out_regs = NEW_RESOURCE_ARRAY(VMRegPair, num_out_args); - _out_arg_stack_slots = output_conv->calling_convention(out_sig_bt, out_regs, num_out_args); - - VMRegPair tmp_vmreg; - tmp_vmreg.set2(shuffle_temp); + VMStorage* out_regs = NEW_RESOURCE_ARRAY(VMStorage, num_out_args); + _out_arg_bytes = output_conv->calling_convention(out_sig_bt, out_regs, num_out_args); - // Compute a valid move order, using tmp_vmreg to break any cycles. - // Note that ComputeMoveOrder ignores the upper half of our VMRegPairs. - // We are not moving Java values here, only register-sized values, - // so we shouldn't have to worry about the upper half any ways. - // This should work fine on 32-bit as well, since we would only be - // moving 32-bit sized values (i.e. low-level MH shouldn't take any double/long). _moves = ComputeMoveOrder::compute_move_order(num_in_args, in_regs, num_out_args, out_regs, - in_sig_bt, tmp_vmreg); + in_sig_bt, shuffle_temp); } diff --git a/src/hotspot/share/prims/foreignGlobals.hpp b/src/hotspot/share/prims/foreignGlobals.hpp index ae876662e96..fee60f30643 100644 --- a/src/hotspot/share/prims/foreignGlobals.hpp +++ b/src/hotspot/share/prims/foreignGlobals.hpp @@ -26,60 +26,80 @@ #include "code/vmreg.hpp" #include "oops/oopsHierarchy.hpp" +#include "prims/vmstorage.hpp" #include "runtime/sharedRuntime.hpp" #include "utilities/growableArray.hpp" #include "utilities/macros.hpp" #include CPU_HEADER(foreignGlobals) +// needs to match StubLocations in Java code. +// placeholder locations to be filled in by +// the code gen code +class StubLocations { +public: + enum Location : uint32_t { + TARGET_ADDRESS, + RETURN_BUFFER, + CAPTURED_STATE_BUFFER, + LOCATION_LIMIT + }; +private: + VMStorage _locs[LOCATION_LIMIT]; +public: + StubLocations(); + + void set(uint32_t loc, VMStorage storage); + void set_frame_data(uint32_t loc, int offset); + VMStorage get(uint32_t loc) const; + VMStorage get(VMStorage placeholder) const; + int data_offset(uint32_t loc) const; +}; + class CallingConventionClosure { public: - virtual int calling_convention(BasicType* sig_bt, VMRegPair* regs, int num_args) const = 0; + virtual int calling_convention(const BasicType* sig_bt, VMStorage* regs, int num_args) const = 0; }; struct CallRegs { - GrowableArray _arg_regs; - GrowableArray _ret_regs; + GrowableArray _arg_regs; + GrowableArray _ret_regs; CallRegs(int num_args, int num_rets) : _arg_regs(num_args), _ret_regs(num_rets) {} }; + class ForeignGlobals { private: - template - static void parse_register_array(objArrayOop jarray, int type_index, GrowableArray& array, Func converter); + template + static void parse_register_array(objArrayOop jarray, StorageType type_index, GrowableArray& array, T (*converter)(int)); public: static const ABIDescriptor parse_abi_descriptor(jobject jabi); static const CallRegs parse_call_regs(jobject jconv); - static VMReg vmstorage_to_vmreg(int type, int index); - static VMReg parse_vmstorage(oop storage); + static VMStorage parse_vmstorage(oop storage); }; - - class JavaCallingConvention : public CallingConventionClosure { public: - int calling_convention(BasicType* sig_bt, VMRegPair* regs, int num_args) const override { - return SharedRuntime::java_calling_convention(sig_bt, regs, num_args); - } + int calling_convention(const BasicType* sig_bt, VMStorage* regs, int num_args) const override; }; class NativeCallingConvention : public CallingConventionClosure { - GrowableArray _input_regs; + GrowableArray _input_regs; public: - NativeCallingConvention(const GrowableArray& input_regs) + NativeCallingConvention(const GrowableArray& input_regs) : _input_regs(input_regs) {} - int calling_convention(BasicType* sig_bt, VMRegPair* out_regs, int num_args) const override; + int calling_convention(const BasicType* sig_bt, VMStorage* out_regs, int num_args) const override; }; class RegSpiller { - GrowableArray _regs; + GrowableArray _regs; int _spill_size_bytes; public: - RegSpiller(const GrowableArray& regs) : _regs(regs), _spill_size_bytes(compute_spill_area(regs)) { + RegSpiller(const GrowableArray& regs) : _regs(regs), _spill_size_bytes(compute_spill_area(regs)) { } int spill_size_bytes() const { return _spill_size_bytes; } @@ -87,39 +107,39 @@ class RegSpiller { void generate_fill(MacroAssembler* masm, int rsp_offset) const { return generate(masm, rsp_offset, false); } private: - static int compute_spill_area(const GrowableArray& regs); + static int compute_spill_area(const GrowableArray& regs); void generate(MacroAssembler* masm, int rsp_offset, bool is_spill) const; - static int pd_reg_size(VMReg reg); - static void pd_store_reg(MacroAssembler* masm, int offset, VMReg reg); - static void pd_load_reg(MacroAssembler* masm, int offset, VMReg reg); + static int pd_reg_size(VMStorage reg); + static void pd_store_reg(MacroAssembler* masm, int offset, VMStorage reg); + static void pd_load_reg(MacroAssembler* masm, int offset, VMStorage reg); }; struct Move { BasicType bt; - VMRegPair from; - VMRegPair to; + VMStorage from; + VMStorage to; }; class ArgumentShuffle { private: GrowableArray _moves; - int _out_arg_stack_slots; + int _out_arg_bytes; public: ArgumentShuffle( BasicType* in_sig_bt, int num_in_args, BasicType* out_sig_bt, int num_out_args, const CallingConventionClosure* input_conv, const CallingConventionClosure* output_conv, - VMReg shuffle_temp); + VMStorage shuffle_temp); - int out_arg_stack_slots() const { return _out_arg_stack_slots; } - void generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const { - pd_generate(masm, tmp, in_stk_bias, out_stk_bias); + int out_arg_bytes() const { return _out_arg_bytes; } + void generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const { + pd_generate(masm, tmp, in_stk_bias, out_stk_bias, locs); } void print_on(outputStream* os) const; private: - void pd_generate(MacroAssembler* masm, VMReg tmp, int in_stk_bias, int out_stk_bias) const; + void pd_generate(MacroAssembler* masm, VMStorage tmp, int in_stk_bias, int out_stk_bias, const StubLocations& locs) const; }; #endif // SHARE_PRIMS_FOREIGN_GLOBALS diff --git a/src/hotspot/share/prims/foreignGlobals.inline.hpp b/src/hotspot/share/prims/foreignGlobals.inline.hpp index cfd95c2a1e2..13053f0d1f8 100644 --- a/src/hotspot/share/prims/foreignGlobals.inline.hpp +++ b/src/hotspot/share/prims/foreignGlobals.inline.hpp @@ -31,13 +31,13 @@ #include "oops/objArrayOop.hpp" #include "oops/oopCast.inline.hpp" -template -void ForeignGlobals::parse_register_array(objArrayOop jarray, int type_index, GrowableArray& array, Func converter) { - objArrayOop subarray = oop_cast(jarray->obj_at(type_index)); +template +void ForeignGlobals::parse_register_array(objArrayOop jarray, StorageType type_index, GrowableArray& array, T (*converter)(int)) { + objArrayOop subarray = oop_cast(jarray->obj_at((int) type_index)); int subarray_length = subarray->length(); for (int i = 0; i < subarray_length; i++) { oop storage = subarray->obj_at(i); - jint index = jdk_internal_foreign_abi_VMStorage::index(storage); + jint index = jdk_internal_foreign_abi_VMStorage::index_or_offset(storage); array.push(converter(index)); } } diff --git a/src/hotspot/share/prims/nativeEntryPoint.cpp b/src/hotspot/share/prims/nativeEntryPoint.cpp index 75a9536526e..1a7ba6fe67b 100644 --- a/src/hotspot/share/prims/nativeEntryPoint.cpp +++ b/src/hotspot/share/prims/nativeEntryPoint.cpp @@ -36,7 +36,8 @@ #include "runtime/jniHandles.inline.hpp" JNI_ENTRY(jlong, NEP_makeDowncallStub(JNIEnv* env, jclass _unused, jobject method_type, jobject jabi, - jobjectArray arg_moves, jobjectArray ret_moves, jboolean needs_return_buffer)) + jobjectArray arg_moves, jobjectArray ret_moves, + jboolean needs_return_buffer, jint captured_state_mask)) ResourceMark rm; const ABIDescriptor abi = ForeignGlobals::parse_abi_descriptor(jabi); @@ -47,7 +48,7 @@ JNI_ENTRY(jlong, NEP_makeDowncallStub(JNIEnv* env, jclass _unused, jobject metho int pslots = java_lang_invoke_MethodType::ptype_slot_count(type); BasicType* basic_type = NEW_RESOURCE_ARRAY(BasicType, pslots); - GrowableArray input_regs(pcount); + GrowableArray input_regs(pcount); for (int i = 0, bt_idx = 0; i < pcount; i++) { oop type_oop = java_lang_invoke_MethodType::ptype(type, i); assert(java_lang_Class::is_primitive(type_oop), "Only primitives expected"); @@ -65,7 +66,7 @@ JNI_ENTRY(jlong, NEP_makeDowncallStub(JNIEnv* env, jclass _unused, jobject metho jint outs = ret_moves_oop->length(); - GrowableArray output_regs(outs); + GrowableArray output_regs(outs); oop type_oop = java_lang_invoke_MethodType::rtype(type); BasicType ret_bt = java_lang_Class::primitive_type(type_oop); for (int i = 0; i < outs; i++) { @@ -74,8 +75,9 @@ JNI_ENTRY(jlong, NEP_makeDowncallStub(JNIEnv* env, jclass _unused, jobject metho output_regs.push(ForeignGlobals::parse_vmstorage(ret_moves_oop->obj_at(i))); } - return (jlong) DowncallLinker::make_downcall_stub( - basic_type, pslots, ret_bt, abi, input_regs, output_regs, needs_return_buffer)->code_begin(); + return (jlong) DowncallLinker::make_downcall_stub(basic_type, pslots, ret_bt, abi, + input_regs, output_regs, + needs_return_buffer, captured_state_mask)->code_begin(); JNI_END JNI_ENTRY(jboolean, NEP_freeDowncallStub(JNIEnv* env, jclass _unused, jlong invoker)) @@ -95,7 +97,7 @@ JNI_END #define VM_STORAGE_ARR "[Ljdk/internal/foreign/abi/VMStorage;" static JNINativeMethod NEP_methods[] = { - {CC "makeDowncallStub", CC "(" METHOD_TYPE ABI_DESC VM_STORAGE_ARR VM_STORAGE_ARR "Z)J", FN_PTR(NEP_makeDowncallStub)}, + {CC "makeDowncallStub", CC "(" METHOD_TYPE ABI_DESC VM_STORAGE_ARR VM_STORAGE_ARR "ZI)J", FN_PTR(NEP_makeDowncallStub)}, {CC "freeDowncallStub0", CC "(J)Z", FN_PTR(NEP_freeDowncallStub)}, }; diff --git a/src/hotspot/share/prims/vmstorage.cpp b/src/hotspot/share/prims/vmstorage.cpp new file mode 100644 index 00000000000..bb62054f42e --- /dev/null +++ b/src/hotspot/share/prims/vmstorage.cpp @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "prims/vmstorage.hpp" + +void VMStorage::print_on(outputStream* os) const { + os->print("{type=%d, index=%d, %s=%d}", static_cast(_type), _index_or_offset, + is_stack() ? "size" : "segment_mask", _segment_mask_or_size); +} diff --git a/src/hotspot/share/prims/vmstorage.hpp b/src/hotspot/share/prims/vmstorage.hpp new file mode 100644 index 00000000000..a99f5d389af --- /dev/null +++ b/src/hotspot/share/prims/vmstorage.hpp @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2022, 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_PRIMS_VMSTORAGE_HPP +#define SHARE_PRIMS_VMSTORAGE_HPP + +#include + +#include "code/vmreg.hpp" +#include "utilities/debug.hpp" +#include "utilities/ostream.hpp" + +enum class StorageType : int8_t; // defined in arch specific headers + +class VMStorage { +public: + constexpr static StorageType INVALID_TYPE = static_cast(-1); +private: + StorageType _type; + // 1 byte of padding + uint16_t _segment_mask_or_size; + uint32_t _index_or_offset; // stack offset in bytes for stack storage + + friend bool operator==(const VMStorage& a, const VMStorage& b); + + constexpr inline static bool is_reg(StorageType type); + constexpr inline static StorageType stack_type(); + constexpr inline static StorageType placeholder_type(); + constexpr inline static StorageType frame_data_type(); +public: + constexpr VMStorage() : _type(INVALID_TYPE), _segment_mask_or_size(0), _index_or_offset(0) {}; + constexpr VMStorage(StorageType type, uint16_t segment_mask_or_size, uint32_t index_or_offset) + : _type(type), _segment_mask_or_size(segment_mask_or_size), _index_or_offset(index_or_offset) {}; + + constexpr static VMStorage reg_storage(StorageType type, uint16_t segment_mask, uint32_t index) { + assert(is_reg(type), "must be reg"); + return VMStorage(type, segment_mask, index); + } + + constexpr static VMStorage stack_storage(uint16_t size, uint32_t offset) { + return VMStorage(stack_type(), size, offset); + } + + static VMStorage stack_storage(VMReg reg) { + return stack_storage(BytesPerWord, checked_cast(reg->reg2stack() * VMRegImpl::stack_slot_size)); + } + + constexpr static VMStorage invalid() { + VMStorage result; + result._type = INVALID_TYPE; + return result; + } + + StorageType type() const { return _type; } + + // type specific accessors to make calling code more readable + uint16_t segment_mask() const { assert(is_reg(), "must be reg"); return _segment_mask_or_size; } + uint16_t stack_size() const { assert(is_stack() || is_frame_data(), "must be"); return _segment_mask_or_size; } + uint32_t index() const { assert(is_reg() || is_placeholder(), "must be"); return _index_or_offset; } + uint32_t offset() const { assert(is_stack() || is_frame_data(), "must be"); return _index_or_offset; } + uint32_t index_or_offset() const { assert(is_valid(), "must be valid"); return _index_or_offset; } + + bool is_valid() const { return _type != INVALID_TYPE; } + bool is_reg() const { return is_reg(_type); } + bool is_stack() const { return _type == stack_type(); } + bool is_placeholder() const { return _type == placeholder_type(); } + bool is_frame_data() const { return _type == frame_data_type(); } + + void print_on(outputStream* os) const; +}; + +inline bool operator==(const VMStorage& a, const VMStorage& b) { + return a._type == b._type + && a._index_or_offset == b._index_or_offset + && a._segment_mask_or_size == b._segment_mask_or_size; +} + +#include CPU_HEADER(vmstorage) + +#endif // SHARE_PRIMS_VMSTORAGE_HPP diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index c728915d34b..1e2b8753ed8 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1987,9 +1987,6 @@ const int ObjectAlignmentInBytes = 8; false AARCH64_ONLY(DEBUG_ONLY(||true)), \ "Mark all threads after a safepoint, and clear on a modify " \ "fence. Add cleanliness checks.") \ - \ - develop(bool, TraceOptimizedUpcallStubs, false, \ - "Trace optimized upcall stub generation") \ // end of RUNTIME_FLAGS diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index c8fa1b2320f..4789292de03 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -27,12 +27,17 @@ import jdk.internal.foreign.abi.AbstractLinker; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.CapturableState; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.javac.PreviewFeature; import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import java.lang.invoke.MethodHandle; +import java.util.Arrays; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; /** * A linker provides access to foreign functions from Java code, and access to Java code from foreign functions. @@ -282,7 +287,8 @@ default MethodHandle downcallHandle(MemorySegment symbol, FunctionDescriptor fun */ @PreviewFeature(feature=PreviewFeature.Feature.FOREIGN) sealed interface Option - permits LinkerOptions.FirstVariadicArg { + permits LinkerOptions.LinkerOptionImpl, + Option.CaptureCallState { /** * {@return a linker option used to denote the index of the first variadic argument layout in a @@ -292,5 +298,71 @@ sealed interface Option static Option firstVariadicArg(int index) { return new LinkerOptions.FirstVariadicArg(index); } + + /** + * {@return A linker option used to save portions of the execution state immediately after + * calling a foreign function associated with a downcall method handle, + * before it can be overwritten by the Java runtime, or read through conventional means} + *

    + * A downcall method handle linked with this option will feature an additional {@link MemorySegment} + * parameter directly following the target address parameter. This memory segment must be a + * native segment into which the captured state is written. + * + * @param capturedState the names of the values to save. + * @see CaptureCallState#supported() + */ + static CaptureCallState captureCallState(String... capturedState) { + Set set = Stream.of(capturedState) + .map(CapturableState::forName) + .collect(Collectors.toSet()); + return new LinkerOptions.CaptureCallStateImpl(set); + } + + /** + * A linker option for saving portions of the execution state immediately + * after calling a foreign function associated with a downcall method handle, + * before it can be overwritten by the runtime, or read through conventional means. + *

    + * Execution state is captured by a downcall method handle on invocation, by writing it + * to a native segment provided by the user to the downcall method handle. + *

    + * The native segment should have the layout {@linkplain CaptureCallState#layout associated} + * with the particular {@code CaptureCallState} instance used to link the downcall handle. + *

    + * Captured state can be retrieved from this native segment by constructing var handles + * from the {@linkplain #layout layout} associated with the {@code CaptureCallState} instance. + *

    + * The following example demonstrates the use of this linker option: + * {@snippet lang = "java": + * MemorySegment targetAddress = ... + * CaptureCallState ccs = Linker.Option.captureCallState("errno"); + * MethodHandle handle = Linker.nativeLinker().downcallHandle(targetAddress, FunctionDescriptor.ofVoid(), ccs); + * + * VarHandle errnoHandle = ccs.layout().varHandle(PathElement.groupElement("errno")); + * try (Arena arena = Arena.openConfined()) { + * MemorySegment capturedState = arena.allocate(ccs.layout()); + * handle.invoke(capturedState); + * int errno = errnoHandle.get(capturedState); + * // use errno + * } + * } + */ + sealed interface CaptureCallState extends Option + permits LinkerOptions.CaptureCallStateImpl { + /** + * {@return A struct layout that represents the layout of the native segment passed + * to a downcall handle linked with this {@code CapturedCallState} instance} + */ + StructLayout layout(); + + /** + * {@return the names of the state that can be capture by this implementation} + */ + static Set supported() { + return Arrays.stream(CapturableState.values()) + .map(CapturableState::stateName) + .collect(Collectors.toSet()); + } + } } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/ABIDescriptor.java b/src/java.base/share/classes/jdk/internal/foreign/abi/ABIDescriptor.java index 49b19bd0782..b25280edd28 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/ABIDescriptor.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/ABIDescriptor.java @@ -40,20 +40,29 @@ public class ABIDescriptor { final int stackAlignment; final int shadowSpace; + final VMStorage scratch1; + final VMStorage scratch2; + final VMStorage targetAddrStorage; final VMStorage retBufAddrStorage; + final VMStorage capturedStateStorage; public ABIDescriptor(Architecture arch, VMStorage[][] inputStorage, VMStorage[][] outputStorage, VMStorage[][] volatileStorage, int stackAlignment, int shadowSpace, - VMStorage targetAddrStorage, VMStorage retBufAddrStorage) { + VMStorage scratch1, VMStorage scratch2, + VMStorage targetAddrStorage, VMStorage retBufAddrStorage, + VMStorage capturedStateStorage) { this.arch = arch; this.inputStorage = inputStorage; this.outputStorage = outputStorage; this.volatileStorage = volatileStorage; this.stackAlignment = stackAlignment; this.shadowSpace = shadowSpace; + this.scratch1 = scratch1; + this.scratch2 = scratch2; this.targetAddrStorage = targetAddrStorage; this.retBufAddrStorage = retBufAddrStorage; + this.capturedStateStorage = capturedStateStorage; } public VMStorage targetAddrStorage() { @@ -63,4 +72,8 @@ public VMStorage targetAddrStorage() { public VMStorage retBufAddrStorage() { return retBufAddrStorage; } + + public VMStorage capturedStateStorage() { + return capturedStateStorage; + } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java index ef5ab91142d..862a1d47358 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/AbstractLinker.java @@ -53,7 +53,7 @@ public MethodHandle downcallHandle(FunctionDescriptor function, Option... option Objects.requireNonNull(function); Objects.requireNonNull(options); checkHasNaturalAlignment(function); - LinkerOptions optionSet = LinkerOptions.of(options); + LinkerOptions optionSet = LinkerOptions.forDowncall(function, options); return DOWNCALL_CACHE.get(new LinkRequest(function, optionSet), linkRequest -> { FunctionDescriptor fd = linkRequest.descriptor(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/Architecture.java index b37fc0a8067..c94c4485139 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/Architecture.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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,5 +27,4 @@ public interface Architecture { boolean isStackType(int cls); int typeSize(int cls); - int stackType(); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java index e77c1253cdb..458b174a4cb 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequence.java @@ -42,9 +42,12 @@ public class CallingSequence { private final List returnBindings; private final List> argumentBindings; + private final LinkerOptions linkerOptions; + public CallingSequence(boolean forUpcall, MethodType callerMethodType, MethodType calleeMethodType, FunctionDescriptor desc, boolean needsReturnBuffer, long returnBufferSize, long allocationSize, - List> argumentBindings, List returnBindings) { + List> argumentBindings, List returnBindings, + LinkerOptions linkerOptions) { this.forUpcall = forUpcall; this.callerMethodType = callerMethodType; this.calleeMethodType = calleeMethodType; @@ -54,6 +57,7 @@ public CallingSequence(boolean forUpcall, MethodType callerMethodType, MethodTyp this.allocationSize = allocationSize; this.returnBindings = returnBindings; this.argumentBindings = argumentBindings; + this.linkerOptions = linkerOptions; } /** @@ -181,6 +185,16 @@ public boolean hasReturnBindings() { return !returnBindings.isEmpty(); } + public int capturedStateMask() { + return linkerOptions.capturedCallState() + .mapToInt(CapturableState::mask) + .reduce(0, (a, b) -> a | b); + } + + public int numLeadingParams() { + return 2 + (linkerOptions.hasCapturedCallState() ? 1 : 0); // 2 for addr, allocator + } + public String asString() { StringBuilder sb = new StringBuilder(); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java index 665f0204fd3..c05e898eea9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CallingSequenceBuilder.java @@ -47,6 +47,7 @@ public class CallingSequenceBuilder { GetPropertyAction.privilegedGetProperty("java.lang.foreign.VERIFY_BINDINGS", "true")); private final ABIDescriptor abi; + private final LinkerOptions linkerOptions; private final boolean forUpcall; private final List> inputBindings = new ArrayList<>(); @@ -55,9 +56,10 @@ public class CallingSequenceBuilder { private MethodType mt = MethodType.methodType(void.class); private FunctionDescriptor desc = FunctionDescriptor.ofVoid(); - public CallingSequenceBuilder(ABIDescriptor abi, boolean forUpcall) { + public CallingSequenceBuilder(ABIDescriptor abi, boolean forUpcall, LinkerOptions linkerOptions) { this.abi = abi; this.forUpcall = forUpcall; + this.linkerOptions = linkerOptions; } public final CallingSequenceBuilder addArgumentBindings(Class carrier, MemoryLayout layout, @@ -95,6 +97,11 @@ public CallingSequence build() { MethodType callerMethodType; MethodType calleeMethodType; if (!forUpcall) { + if (linkerOptions.hasCapturedCallState()) { + addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of( + Binding.unboxAddress(), + Binding.vmStore(abi.capturedStateStorage(), long.class))); + } addArgumentBinding(0, MemorySegment.class, ValueLayout.ADDRESS, List.of( Binding.unboxAddress(), Binding.vmStore(abi.targetAddrStorage(), long.class))); @@ -117,7 +124,7 @@ public CallingSequence build() { calleeMethodType = mt; } return new CallingSequence(forUpcall, callerMethodType, calleeMethodType, desc, needsReturnBuffer, - returnBufferSize, allocationSize, inputBindings, outputBindings); + returnBufferSize, allocationSize, inputBindings, outputBindings, linkerOptions); } private MethodType computeCallerTypeForUpcall() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java b/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java new file mode 100644 index 00000000000..dc769550daf --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/CapturableState.java @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2022, 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. + */ +package jdk.internal.foreign.abi; + +import java.lang.foreign.ValueLayout; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import static java.lang.foreign.ValueLayout.JAVA_INT; + +public enum CapturableState { + GET_LAST_ERROR ("GetLastError", JAVA_INT, 1 << 0), + WSA_GET_LAST_ERROR("WSAGetLastError", JAVA_INT, 1 << 1), + ERRNO ("errno", JAVA_INT, 1 << 2); + + private final String stateName; + private final ValueLayout layout; + private final int mask; + + CapturableState(String stateName, ValueLayout layout, int mask) { + this.stateName = stateName; + this.layout = layout.withName(stateName); + this.mask = mask; + } + + public static CapturableState forName(String name) { + return Stream.of(values()) + .filter(stl -> stl.stateName().equals(name)) + .findAny() + .orElseThrow(() -> new IllegalArgumentException( + "Unknown name: " + name +", must be one of: " + + Stream.of(CapturableState.values()) + .map(CapturableState::stateName) + .collect(Collectors.joining(", ")))); + } + + public String stateName() { + return stateName; + } + + public ValueLayout layout() { + return layout; + } + + public int mask() { + return mask; + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java index 0275b20921d..59343475406 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/DowncallLinker.java @@ -85,7 +85,8 @@ public MethodHandle getBoundMethodHandle() { toStorageArray(argMoves), toStorageArray(retMoves), leafType, - callingSequence.needsReturnBuffer() + callingSequence.needsReturnBuffer(), + callingSequence.capturedStateMask() ); MethodHandle handle = JLIA.nativeMethodHandle(nep); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java index 9b0d08c1257..7e78f0d5002 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/LinkerOptions.java @@ -24,28 +24,36 @@ */ package jdk.internal.foreign.abi; +import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.Linker; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.StructLayout; +import java.util.Comparator; import java.util.HashMap; import java.util.Map; import java.util.Objects; +import java.util.Set; +import java.util.stream.Stream; public class LinkerOptions { - private static final LinkerOptions EMPTY = LinkerOptions.of(); - private final Map, Linker.Option> optionsMap; + private static final LinkerOptions EMPTY = new LinkerOptions(Map.of()); + private final Map, LinkerOptionImpl> optionsMap; - private LinkerOptions(Map, Linker.Option> optionsMap) { + private LinkerOptions(Map, LinkerOptionImpl> optionsMap) { this.optionsMap = optionsMap; } - public static LinkerOptions of(Linker.Option... options) { - Map, Linker.Option> optionMap = new HashMap<>(); + public static LinkerOptions forDowncall(FunctionDescriptor desc, Linker.Option... options) { + Map, LinkerOptionImpl> optionMap = new HashMap<>(); for (Linker.Option option : options) { if (optionMap.containsKey(option.getClass())) { throw new IllegalArgumentException("Duplicate option: " + option); } - optionMap.put(option.getClass(), option); + LinkerOptionImpl opImpl = (LinkerOptionImpl) option; + opImpl.validateForDowncall(desc); + optionMap.put(option.getClass(), opImpl); } return new LinkerOptions(optionMap); @@ -64,6 +72,15 @@ public boolean isVarargsIndex(int argIndex) { return fva != null && argIndex >= fva.index(); } + public boolean hasCapturedCallState() { + return getOption(CaptureCallStateImpl.class) != null; + } + + public Stream capturedCallState() { + CaptureCallStateImpl stl = getOption(CaptureCallStateImpl.class); + return stl == null ? Stream.empty() : stl.saved().stream(); + } + @Override public boolean equals(Object o) { if (this == o) return true; @@ -76,5 +93,39 @@ public int hashCode() { return Objects.hash(optionsMap); } - public record FirstVariadicArg(int index) implements Linker.Option { } + public sealed interface LinkerOptionImpl extends Linker.Option + permits FirstVariadicArg, + CaptureCallStateImpl { + default void validateForDowncall(FunctionDescriptor descriptor) { + throw new IllegalArgumentException("Not supported for downcall: " + this); + } + } + + public record FirstVariadicArg(int index) implements LinkerOptionImpl { + @Override + public void validateForDowncall(FunctionDescriptor descriptor) { + if (index < 0 || index > descriptor.argumentLayouts().size()) { + throw new IllegalArgumentException("Index '" + index + "' not in bounds for descriptor: " + descriptor); + } + } + } + + public record CaptureCallStateImpl(Set saved) implements LinkerOptionImpl, Linker.Option.CaptureCallState { + + @Override + public void validateForDowncall(FunctionDescriptor descriptor) { + // done during construction + } + + @Override + public StructLayout layout() { + return MemoryLayout.structLayout( + saved.stream() + .sorted(Comparator.comparingInt(CapturableState::ordinal)) + .map(CapturableState::layout) + .toArray(MemoryLayout[]::new) + ); + } + } + } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/NativeEntryPoint.java b/src/java.base/share/classes/jdk/internal/foreign/abi/NativeEntryPoint.java index aad5091c6ee..9426c404c9f 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/NativeEntryPoint.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/NativeEntryPoint.java @@ -47,7 +47,7 @@ public class NativeEntryPoint { private static final SoftReferenceCache NEP_CACHE = new SoftReferenceCache<>(); private record CacheKey(MethodType methodType, ABIDescriptor abi, List argMoves, List retMoves, - boolean needsReturnBuffer) {} + boolean needsReturnBuffer, int capturedStateMask) {} private NativeEntryPoint(MethodType methodType, long downcallStubAddress) { this.methodType = methodType; @@ -56,26 +56,38 @@ private NativeEntryPoint(MethodType methodType, long downcallStubAddress) { public static NativeEntryPoint make(ABIDescriptor abi, VMStorage[] argMoves, VMStorage[] returnMoves, - MethodType methodType, boolean needsReturnBuffer) { + MethodType methodType, + boolean needsReturnBuffer, + int capturedStateMask) { if (returnMoves.length > 1 != needsReturnBuffer) { - throw new IllegalArgumentException("Multiple register return, but needsReturnBuffer was false"); + throw new AssertionError("Multiple register return, but needsReturnBuffer was false"); } + checkType(methodType, needsReturnBuffer, capturedStateMask); - assert (methodType.parameterType(0) == long.class) : "Address expected"; - assert (!needsReturnBuffer || methodType.parameterType(1) == long.class) : "return buffer address expected"; - - CacheKey key = new CacheKey(methodType, abi, Arrays.asList(argMoves), Arrays.asList(returnMoves), needsReturnBuffer); + CacheKey key = new CacheKey(methodType, abi, Arrays.asList(argMoves), Arrays.asList(returnMoves), needsReturnBuffer, capturedStateMask); return NEP_CACHE.get(key, k -> { - long downcallStub = makeDowncallStub(methodType, abi, argMoves, returnMoves, needsReturnBuffer); + long downcallStub = makeDowncallStub(methodType, abi, argMoves, returnMoves, needsReturnBuffer, capturedStateMask); NativeEntryPoint nep = new NativeEntryPoint(methodType, downcallStub); CLEANER.register(nep, () -> freeDowncallStub(downcallStub)); return nep; }); } + private static void checkType(MethodType methodType, boolean needsReturnBuffer, int savedValueMask) { + if (methodType.parameterType(0) != long.class) { + throw new AssertionError("Address expected as first param: " + methodType); + } + int checkIdx = 1; + if ((needsReturnBuffer && methodType.parameterType(checkIdx++) != long.class) + || (savedValueMask != 0 && methodType.parameterType(checkIdx) != long.class)) { + throw new AssertionError("return buffer and/or preserved value address expected: " + methodType); + } + } + private static native long makeDowncallStub(MethodType methodType, ABIDescriptor abi, VMStorage[] encArgMoves, VMStorage[] encRetMoves, - boolean needsReturnBuffer); + boolean needsReturnBuffer, + int capturedStateMask); private static native boolean freeDowncallStub0(long downcallStub); private static void freeDowncallStub(long downcallStub) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index 991b44067f2..5ca0a6d7ca8 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -108,17 +108,18 @@ public static long alignUp(long addr, long alignment) { * @param cDesc the function descriptor of the native function (with actual return layout) * @return the adapted handle */ - public static MethodHandle adaptDowncallForIMR(MethodHandle handle, FunctionDescriptor cDesc) { + public static MethodHandle adaptDowncallForIMR(MethodHandle handle, FunctionDescriptor cDesc, CallingSequence sequence) { if (handle.type().returnType() != void.class) throw new IllegalArgumentException("return expected to be void for in memory returns: " + handle.type()); - if (handle.type().parameterType(2) != MemorySegment.class) + int imrAddrIdx = sequence.numLeadingParams(); + if (handle.type().parameterType(imrAddrIdx) != MemorySegment.class) throw new IllegalArgumentException("MemorySegment expected as third param: " + handle.type()); if (cDesc.returnLayout().isEmpty()) throw new IllegalArgumentException("Return layout needed: " + cDesc); MethodHandle ret = identity(MemorySegment.class); // (MemorySegment) MemorySegment handle = collectArguments(ret, 1, handle); // (MemorySegment, MemorySegment, SegmentAllocator, MemorySegment, ...) MemorySegment - handle = mergeArguments(handle, 0, 3); // (MemorySegment, MemorySegment, SegmentAllocator, ...) MemorySegment + handle = mergeArguments(handle, 0, 1 + imrAddrIdx); // (MemorySegment, MemorySegment, SegmentAllocator, ...) MemorySegment handle = collectArguments(handle, 0, insertArguments(MH_ALLOC_BUFFER, 1, cDesc.returnLayout().get())); // (SegmentAllocator, MemorySegment, SegmentAllocator, ...) MemorySegment handle = mergeArguments(handle, 0, 2); // (SegmentAllocator, MemorySegment, ...) MemorySegment handle = swapArguments(handle, 0, 1); // (MemorySegment, SegmentAllocator, ...) MemorySegment diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/StubLocations.java b/src/java.base/share/classes/jdk/internal/foreign/abi/StubLocations.java new file mode 100644 index 00000000000..e3a45250658 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/StubLocations.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022, 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. + */ +package jdk.internal.foreign.abi; + +// must keep in sync with StubLocations in VM code +public enum StubLocations { + TARGET_ADDRESS, + RETURN_BUFFER, + CAPTURED_STATE_BUFFER; + + public VMStorage storage(byte type) { + return new VMStorage(type, (short) 8, ordinal()); + } +} diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/VMStorage.java b/src/java.base/share/classes/jdk/internal/foreign/abi/VMStorage.java index fe5ed1afa78..1237650e026 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/VMStorage.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/VMStorage.java @@ -24,52 +24,23 @@ */ package jdk.internal.foreign.abi; -import java.util.Objects; - -public class VMStorage { - private final int type; - private final int index; - - private final String debugName; - - public VMStorage(int type, int index, String debugName) { - this.type = type; - this.index = index; - this.debugName = debugName; - } - - public int type() { - return type; - } - - public int index() { - return index; - } - - public String name() { - return debugName; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - VMStorage vmStorage = (VMStorage) o; - return type == vmStorage.type && - index == vmStorage.index; - } +/** + * + * @param type the type of storage. e.g. stack, or which register type (GP, FP, vector) + * @param segmentMaskOrSize the (on stack) size in bytes when type = stack, a register mask otherwise, + * the register mask indicates which segments of a register are used. + * @param indexOrOffset the index is either a register number within a type, or + * a stack offset in bytes if type = stack. + * (a particular platform might add a bias to this in generate code) + * @param debugName the debug name + */ +public record VMStorage(byte type, + short segmentMaskOrSize, + int indexOrOffset, + String debugName) { - @Override - public int hashCode() { - return Objects.hash(type, index); + public VMStorage(byte type, short segmentMaskOrSize, int indexOrOffset) { + this(type, segmentMaskOrSize, indexOrOffset, "Stack@" + indexOrOffset); } - @Override - public String toString() { - return "VMStorage{" + - "type=" + type + - ", index=" + index + - ", debugName='" + debugName + '\'' + - '}'; - } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/AArch64Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/AArch64Architecture.java index 94067a02ad6..35ff00055d9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/AArch64Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/AArch64Architecture.java @@ -27,118 +27,118 @@ import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Architecture; +import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; public class AArch64Architecture implements Architecture { public static final Architecture INSTANCE = new AArch64Architecture(); + private static final short REG64_MASK = 0b0000_0000_0000_0001; + private static final short V128_MASK = 0b0000_0000_0000_0001; + private static final int INTEGER_REG_SIZE = 8; private static final int VECTOR_REG_SIZE = 16; - private static final int STACK_SLOT_SIZE = 8; @Override public boolean isStackType(int cls) { - return cls == StorageClasses.STACK; + return cls == StorageType.STACK; } @Override public int typeSize(int cls) { switch (cls) { - case StorageClasses.INTEGER: return INTEGER_REG_SIZE; - case StorageClasses.VECTOR: return VECTOR_REG_SIZE; - case StorageClasses.STACK: return STACK_SLOT_SIZE; + case StorageType.INTEGER: return INTEGER_REG_SIZE; + case StorageType.VECTOR: return VECTOR_REG_SIZE; + // STACK is deliberately omitted } throw new IllegalArgumentException("Invalid Storage Class: " + cls); } - @Override - public int stackType() { - return StorageClasses.STACK; + public interface StorageType { + byte INTEGER = 0; + byte VECTOR = 1; + byte STACK = 2; + byte PLACEHOLDER = 3; } - public interface StorageClasses { - int INTEGER = 0; - int VECTOR = 1; - int STACK = 3; + public static class Regs { // break circular dependency + public static final VMStorage r0 = integerRegister(0); + public static final VMStorage r1 = integerRegister(1); + public static final VMStorage r2 = integerRegister(2); + public static final VMStorage r3 = integerRegister(3); + public static final VMStorage r4 = integerRegister(4); + public static final VMStorage r5 = integerRegister(5); + public static final VMStorage r6 = integerRegister(6); + public static final VMStorage r7 = integerRegister(7); + public static final VMStorage r8 = integerRegister(8); + public static final VMStorage r9 = integerRegister(9); + public static final VMStorage r10 = integerRegister(10); + public static final VMStorage r11 = integerRegister(11); + public static final VMStorage r12 = integerRegister(12); + public static final VMStorage r13 = integerRegister(13); + public static final VMStorage r14 = integerRegister(14); + public static final VMStorage r15 = integerRegister(15); + public static final VMStorage r16 = integerRegister(16); + public static final VMStorage r17 = integerRegister(17); + public static final VMStorage r18 = integerRegister(18); + public static final VMStorage r19 = integerRegister(19); + public static final VMStorage r20 = integerRegister(20); + public static final VMStorage r21 = integerRegister(21); + public static final VMStorage r22 = integerRegister(22); + public static final VMStorage r23 = integerRegister(23); + public static final VMStorage r24 = integerRegister(24); + public static final VMStorage r25 = integerRegister(25); + public static final VMStorage r26 = integerRegister(26); + public static final VMStorage r27 = integerRegister(27); + public static final VMStorage r28 = integerRegister(28); + public static final VMStorage r29 = integerRegister(29); + public static final VMStorage r30 = integerRegister(30); + public static final VMStorage r31 = integerRegister(31); + public static final VMStorage v0 = vectorRegister(0); + public static final VMStorage v1 = vectorRegister(1); + public static final VMStorage v2 = vectorRegister(2); + public static final VMStorage v3 = vectorRegister(3); + public static final VMStorage v4 = vectorRegister(4); + public static final VMStorage v5 = vectorRegister(5); + public static final VMStorage v6 = vectorRegister(6); + public static final VMStorage v7 = vectorRegister(7); + public static final VMStorage v8 = vectorRegister(8); + public static final VMStorage v9 = vectorRegister(9); + public static final VMStorage v10 = vectorRegister(10); + public static final VMStorage v11 = vectorRegister(11); + public static final VMStorage v12 = vectorRegister(12); + public static final VMStorage v13 = vectorRegister(13); + public static final VMStorage v14 = vectorRegister(14); + public static final VMStorage v15 = vectorRegister(15); + public static final VMStorage v16 = vectorRegister(16); + public static final VMStorage v17 = vectorRegister(17); + public static final VMStorage v18 = vectorRegister(18); + public static final VMStorage v19 = vectorRegister(19); + public static final VMStorage v20 = vectorRegister(20); + public static final VMStorage v21 = vectorRegister(21); + public static final VMStorage v22 = vectorRegister(22); + public static final VMStorage v23 = vectorRegister(23); + public static final VMStorage v24 = vectorRegister(24); + public static final VMStorage v25 = vectorRegister(25); + public static final VMStorage v26 = vectorRegister(26); + public static final VMStorage v27 = vectorRegister(27); + public static final VMStorage v28 = vectorRegister(28); + public static final VMStorage v29 = vectorRegister(29); + public static final VMStorage v30 = vectorRegister(30); + public static final VMStorage v31 = vectorRegister(31); } - public static final VMStorage r0 = integerRegister(0); - public static final VMStorage r1 = integerRegister(1); - public static final VMStorage r2 = integerRegister(2); - public static final VMStorage r3 = integerRegister(3); - public static final VMStorage r4 = integerRegister(4); - public static final VMStorage r5 = integerRegister(5); - public static final VMStorage r6 = integerRegister(6); - public static final VMStorage r7 = integerRegister(7); - public static final VMStorage r8 = integerRegister(8); - public static final VMStorage r9 = integerRegister(9); - public static final VMStorage r10 = integerRegister(10); - public static final VMStorage r11 = integerRegister(11); - public static final VMStorage r12 = integerRegister(12); - public static final VMStorage r13 = integerRegister(13); - public static final VMStorage r14 = integerRegister(14); - public static final VMStorage r15 = integerRegister(15); - public static final VMStorage r16 = integerRegister(16); - public static final VMStorage r17 = integerRegister(17); - public static final VMStorage r18 = integerRegister(18); - public static final VMStorage r19 = integerRegister(19); - public static final VMStorage r20 = integerRegister(20); - public static final VMStorage r21 = integerRegister(21); - public static final VMStorage r22 = integerRegister(22); - public static final VMStorage r23 = integerRegister(23); - public static final VMStorage r24 = integerRegister(24); - public static final VMStorage r25 = integerRegister(25); - public static final VMStorage r26 = integerRegister(26); - public static final VMStorage r27 = integerRegister(27); - public static final VMStorage r28 = integerRegister(28); - public static final VMStorage r29 = integerRegister(29); - public static final VMStorage r30 = integerRegister(30); - public static final VMStorage r31 = integerRegister(31); - - public static final VMStorage v0 = vectorRegister(0); - public static final VMStorage v1 = vectorRegister(1); - public static final VMStorage v2 = vectorRegister(2); - public static final VMStorage v3 = vectorRegister(3); - public static final VMStorage v4 = vectorRegister(4); - public static final VMStorage v5 = vectorRegister(5); - public static final VMStorage v6 = vectorRegister(6); - public static final VMStorage v7 = vectorRegister(7); - public static final VMStorage v8 = vectorRegister(8); - public static final VMStorage v9 = vectorRegister(9); - public static final VMStorage v10 = vectorRegister(10); - public static final VMStorage v11 = vectorRegister(11); - public static final VMStorage v12 = vectorRegister(12); - public static final VMStorage v13 = vectorRegister(13); - public static final VMStorage v14 = vectorRegister(14); - public static final VMStorage v15 = vectorRegister(15); - public static final VMStorage v16 = vectorRegister(16); - public static final VMStorage v17 = vectorRegister(17); - public static final VMStorage v18 = vectorRegister(18); - public static final VMStorage v19 = vectorRegister(19); - public static final VMStorage v20 = vectorRegister(20); - public static final VMStorage v21 = vectorRegister(21); - public static final VMStorage v22 = vectorRegister(22); - public static final VMStorage v23 = vectorRegister(23); - public static final VMStorage v24 = vectorRegister(24); - public static final VMStorage v25 = vectorRegister(25); - public static final VMStorage v26 = vectorRegister(26); - public static final VMStorage v27 = vectorRegister(27); - public static final VMStorage v28 = vectorRegister(28); - public static final VMStorage v29 = vectorRegister(29); - public static final VMStorage v30 = vectorRegister(30); - public static final VMStorage v31 = vectorRegister(31); - private static VMStorage integerRegister(int index) { - return new VMStorage(StorageClasses.INTEGER, index, "r" + index); + return new VMStorage(StorageType.INTEGER, REG64_MASK, index, "r" + index); } private static VMStorage vectorRegister(int index) { - return new VMStorage(StorageClasses.VECTOR, index, "v" + index); + return new VMStorage(StorageType.VECTOR, V128_MASK, index, "v" + index); } - public static VMStorage stackStorage(int index) { - return new VMStorage(StorageClasses.STACK, index, "Stack@" + index); + public static VMStorage stackStorage(short size, int byteOffset) { + return new VMStorage(StorageType.STACK, size, byteOffset); } public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, @@ -149,7 +149,7 @@ public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, VMStorage[] volatileVectorRegs, int stackAlignment, int shadowSpace, - VMStorage targetAddrStorage, VMStorage retBufAddrStorage) { + VMStorage scratch1, VMStorage scratch2) { return new ABIDescriptor( INSTANCE, new VMStorage[][] { @@ -166,7 +166,10 @@ public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, }, stackAlignment, shadowSpace, - targetAddrStorage, retBufAddrStorage); + scratch1, scratch2, + StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER), + StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER), + StubLocations.CAPTURED_STATE_BUFFER.storage(StorageType.PLACEHOLDER)); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java index c0353581d33..afc292fdd28 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/CallArranger.java @@ -1,6 +1,6 @@ /* * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2019, 2021, Arm Limited. All rights reserved. + * Copyright (c) 2019, 2022, Arm 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 @@ -50,6 +50,7 @@ import static jdk.internal.foreign.PlatformLayouts.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; +import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; /** * For the AArch64 C ABI specifically, this class uses CallingSequenceBuilder @@ -84,12 +85,11 @@ public abstract class CallArranger { new VMStorage[] { r0, r1 }, new VMStorage[] { v0, v1, v2, v3 }, new VMStorage[] { r9, r10, r11, r12, r13, r14, r15 }, - new VMStorage[] { v16, v17, v18, v19, v20, v21, v22, v23, v25, + new VMStorage[] { v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31 }, 16, // Stack is always 16 byte aligned on AArch64 0, // No shadow space - r9, // target addr reg - r10 // return buffer addr reg + r9, r10 // scratch 1 & 2 ); public record Bindings(CallingSequence callingSequence, @@ -119,7 +119,7 @@ public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean for } public Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { - CallingSequenceBuilder csb = new CallingSequenceBuilder(C, forUpcall); + CallingSequenceBuilder csb = new CallingSequenceBuilder(C, forUpcall, options); BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false); @@ -152,7 +152,7 @@ public MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc, Lin MethodHandle handle = new DowncallLinker(C, bindings.callingSequence).getBoundMethodHandle(); if (bindings.isInMemoryReturn) { - handle = SharedUtils.adaptDowncallForIMR(handle, cDesc); + handle = SharedUtils.adaptDowncallForIMR(handle, cDesc, bindings.callingSequence); } return handle; @@ -186,32 +186,28 @@ public StorageCalculator(boolean forArguments) { this.forArguments = forArguments; } + void alignStack(long alignment) { + stackOffset = Utils.alignUp(stackOffset, alignment); + } + VMStorage stackAlloc(long size, long alignment) { assert forArguments : "no stack returns"; - // Implementation limit: each arg must take up at least an 8 byte stack slot (on the Java side) - // There is currently no way to address stack offsets that are not multiples of 8 bytes - // The VM can only address multiple-of-4-bytes offsets, which is also not good enough for some ABIs - // see JDK-8283462 and related issues - long stackSlotAlignment = Math.max(alignment, STACK_SLOT_SIZE); - long alignedStackOffset = Utils.alignUp(stackOffset, stackSlotAlignment); - // macos-aarch64 ABI potentially requires addressing stack offsets that are not multiples of 8 bytes - // Reject such call types here, to prevent undefined behavior down the line - // Reject if the above stack-slot-aligned offset does not match the offset the ABI really wants - // Except for variadic arguments, which _are_ passed at 8-byte-aligned offsets - if (requiresSubSlotStackPacking() && alignedStackOffset != Utils.alignUp(stackOffset, alignment) - && !forVarArgs) // varargs are given a pass on all aarch64 ABIs - throw new UnsupportedOperationException("Call type not supported on this platform"); - - stackOffset = alignedStackOffset; + long alignedStackOffset = Utils.alignUp(stackOffset, alignment); + + short encodedSize = (short) size; + assert (encodedSize & 0xFFFF) == size; VMStorage storage = - stackStorage((int)(stackOffset / STACK_SLOT_SIZE)); - stackOffset += size; + AArch64Architecture.stackStorage(encodedSize, (int)alignedStackOffset); + stackOffset = alignedStackOffset + size; return storage; } VMStorage stackAlloc(MemoryLayout layout) { - return stackAlloc(layout.byteSize(), layout.byteAlignment()); + long stackSlotAlignment = requiresSubSlotStackPacking() && !forVarArgs + ? layout.byteAlignment() + : Math.max(layout.byteAlignment(), STACK_SLOT_SIZE); + return stackAlloc(layout.byteSize(), stackSlotAlignment); } VMStorage[] regAlloc(int type, int count) { @@ -244,11 +240,31 @@ VMStorage nextStorage(int type, MemoryLayout layout) { return storage[0]; } + VMStorage[] nextStorageForHFA(GroupLayout group) { + final int nFields = group.memberLayouts().size(); + VMStorage[] regs = regAlloc(StorageType.VECTOR, nFields); + if (regs == null && requiresSubSlotStackPacking() && !forVarArgs) { + // For the ABI variants that pack arguments spilled to the + // stack, HFA arguments are spilled as if their individual + // fields had been allocated separately rather than as if the + // struct had been spilled as a whole. + + VMStorage[] slots = new VMStorage[nFields]; + for (int i = 0; i < nFields; i++) { + slots[i] = stackAlloc(group.memberLayouts().get(i)); + } + + return slots; + } else { + return regs; + } + } + void adjustForVarArgs() { // This system passes all variadic parameters on the stack. Ensure // no further arguments are allocated to registers. - nRegs[StorageClasses.INTEGER] = MAX_REGISTER_ARGUMENTS; - nRegs[StorageClasses.VECTOR] = MAX_REGISTER_ARGUMENTS; + nRegs[StorageType.INTEGER] = MAX_REGISTER_ARGUMENTS; + nRegs[StorageType.VECTOR] = MAX_REGISTER_ARGUMENTS; forVarArgs = true; } } @@ -279,6 +295,12 @@ protected void spillStructUnbox(Binding.Builder bindings, MemoryLayout layout) { .vmStore(storage, type); offset += STACK_SLOT_SIZE; } + + if (requiresSubSlotStackPacking()) { + // Pad to the next stack slot boundary instead of packing + // additional arguments into the unused space. + storageCalculator.alignStack(STACK_SLOT_SIZE); + } } protected void spillStructBox(Binding.Builder bindings, MemoryLayout layout) { @@ -298,6 +320,12 @@ protected void spillStructBox(Binding.Builder bindings, MemoryLayout layout) { .bufferStore(offset, type); offset += STACK_SLOT_SIZE; } + + if (requiresSubSlotStackPacking()) { + // Pad to the next stack slot boundary instead of packing + // additional arguments into the unused space. + storageCalculator.alignStack(STACK_SLOT_SIZE); + } } abstract List getBindings(Class carrier, MemoryLayout layout); @@ -326,14 +354,14 @@ List getBindings(Class carrier, MemoryLayout layout) { case STRUCT_REGISTER: { assert carrier == MemorySegment.class; VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.INTEGER, layout); + StorageType.INTEGER, layout); if (regs != null) { int regIndex = 0; long offset = 0; while (offset < layout.byteSize()) { final long copy = Math.min(layout.byteSize() - offset, 8); VMStorage storage = regs[regIndex++]; - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(copy, useFloat); if (offset + copy < layout.byteSize()) { bindings.dup(); @@ -352,21 +380,20 @@ List getBindings(Class carrier, MemoryLayout layout) { bindings.copy(layout) .unboxAddress(); VMStorage storage = storageCalculator.nextStorage( - StorageClasses.INTEGER, AArch64.C_POINTER); + StorageType.INTEGER, AArch64.C_POINTER); bindings.vmStore(storage, long.class); break; } case STRUCT_HFA: { assert carrier == MemorySegment.class; GroupLayout group = (GroupLayout)layout; - VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.VECTOR, group.memberLayouts().size()); + VMStorage[] regs = storageCalculator.nextStorageForHFA(group); if (regs != null) { long offset = 0; for (int i = 0; i < group.memberLayouts().size(); i++) { VMStorage storage = regs[i]; final long size = group.memberLayouts().get(i).byteSize(); - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(size, useFloat); if (i + 1 < group.memberLayouts().size()) { bindings.dup(); @@ -383,19 +410,19 @@ List getBindings(Class carrier, MemoryLayout layout) { case POINTER: { bindings.unboxAddress(); VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageType.INTEGER, layout); bindings.vmStore(storage, long.class); break; } case INTEGER: { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageType.INTEGER, layout); bindings.vmStore(storage, carrier); break; } case FLOAT: { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + storageCalculator.nextStorage(StorageType.VECTOR, layout); bindings.vmStore(storage, carrier); break; } @@ -428,7 +455,7 @@ List getBindings(Class carrier, MemoryLayout layout) { assert carrier == MemorySegment.class; bindings.allocate(layout); VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.INTEGER, layout); + StorageType.INTEGER, layout); if (regs != null) { int regIndex = 0; long offset = 0; @@ -436,7 +463,7 @@ List getBindings(Class carrier, MemoryLayout layout) { final long copy = Math.min(layout.byteSize() - offset, 8); VMStorage storage = regs[regIndex++]; bindings.dup(); - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(copy, useFloat); bindings.vmLoad(storage, type) .bufferStore(offset, type); @@ -449,7 +476,7 @@ List getBindings(Class carrier, MemoryLayout layout) { case STRUCT_REFERENCE -> { assert carrier == MemorySegment.class; VMStorage storage = storageCalculator.nextStorage( - StorageClasses.INTEGER, AArch64.C_POINTER); + StorageType.INTEGER, AArch64.C_POINTER); bindings.vmLoad(storage, long.class) .boxAddress(layout); } @@ -457,14 +484,13 @@ List getBindings(Class carrier, MemoryLayout layout) { assert carrier == MemorySegment.class; bindings.allocate(layout); GroupLayout group = (GroupLayout) layout; - VMStorage[] regs = storageCalculator.regAlloc( - StorageClasses.VECTOR, group.memberLayouts().size()); + VMStorage[] regs = storageCalculator.nextStorageForHFA(group); if (regs != null) { long offset = 0; for (int i = 0; i < group.memberLayouts().size(); i++) { VMStorage storage = regs[i]; final long size = group.memberLayouts().get(i).byteSize(); - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(size, useFloat); bindings.dup() .vmLoad(storage, type) @@ -477,18 +503,18 @@ List getBindings(Class carrier, MemoryLayout layout) { } case POINTER -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageType.INTEGER, layout); bindings.vmLoad(storage, long.class) .boxAddressRaw(Utils.pointeeSize(layout)); } case INTEGER -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.INTEGER, layout); + storageCalculator.nextStorage(StorageType.INTEGER, layout); bindings.vmLoad(storage, carrier); } case FLOAT -> { VMStorage storage = - storageCalculator.nextStorage(StorageClasses.VECTOR, layout); + storageCalculator.nextStorage(StorageType.VECTOR, layout); bindings.vmLoad(storage, carrier); } default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/X86_64Architecture.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/X86_64Architecture.java index c5bd9814977..a0a14790527 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/X86_64Architecture.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/X86_64Architecture.java @@ -26,116 +26,126 @@ import jdk.internal.foreign.abi.ABIDescriptor; import jdk.internal.foreign.abi.Architecture; +import jdk.internal.foreign.abi.StubLocations; import jdk.internal.foreign.abi.VMStorage; import java.util.stream.IntStream; public class X86_64Architecture implements Architecture { public static final Architecture INSTANCE = new X86_64Architecture(); + + private static final short REG8_H_MASK = 0b0000_0000_0000_0010; + private static final short REG8_L_MASK = 0b0000_0000_0000_0001; + private static final short REG16_MASK = 0b0000_0000_0000_0011; + private static final short REG32_MASK = 0b0000_0000_0000_0111; + private static final short REG64_MASK = 0b0000_0000_0000_1111; + private static final short XMM_MASK = 0b0000_0000_0000_0001; + private static final short YMM_MASK = 0b0000_0000_0000_0011; + private static final short ZMM_MASK = 0b0000_0000_0000_0111; + private static final short STP_MASK = 0b0000_0000_0000_0001; + private static final int INTEGER_REG_SIZE = 8; // bytes private static final int VECTOR_REG_SIZE = 16; // size of XMM register private static final int X87_REG_SIZE = 16; - private static final int STACK_SLOT_SIZE = 8; @Override public boolean isStackType(int cls) { - return cls == StorageClasses.STACK; + return cls == StorageType.STACK; } @Override public int typeSize(int cls) { switch (cls) { - case StorageClasses.INTEGER: return INTEGER_REG_SIZE; - case StorageClasses.VECTOR: return VECTOR_REG_SIZE; - case StorageClasses.X87: return X87_REG_SIZE; - case StorageClasses.STACK: return STACK_SLOT_SIZE; + case StorageType.INTEGER: return INTEGER_REG_SIZE; + case StorageType.VECTOR: return VECTOR_REG_SIZE; + case StorageType.X87: return X87_REG_SIZE; + // STACK is deliberately omitted } throw new IllegalArgumentException("Invalid Storage Class: " +cls); } - @Override - public int stackType() { - return StorageClasses.STACK; + // must keep in sync with StorageType in VM code + public interface StorageType { + byte INTEGER = 0; + byte VECTOR = 1; + byte X87 = 2; + byte STACK = 3; + byte PLACEHOLDER = 4; } - public interface StorageClasses { - int INTEGER = 0; - int VECTOR = 1; - int X87 = 2; - int STACK = 3; + public static class Regs { // break circular dependency + public static final VMStorage rax = integerRegister(0, "rax"); + public static final VMStorage rcx = integerRegister(1, "rcx"); + public static final VMStorage rdx = integerRegister(2, "rdx"); + public static final VMStorage rbx = integerRegister(3, "rbx"); + public static final VMStorage rsp = integerRegister(4, "rsp"); + public static final VMStorage rbp = integerRegister(5, "rbp"); + public static final VMStorage rsi = integerRegister(6, "rsi"); + public static final VMStorage rdi = integerRegister(7, "rdi"); + public static final VMStorage r8 = integerRegister(8, "r8"); + public static final VMStorage r9 = integerRegister(9, "r9"); + public static final VMStorage r10 = integerRegister(10, "r10"); + public static final VMStorage r11 = integerRegister(11, "r11"); + public static final VMStorage r12 = integerRegister(12, "r12"); + public static final VMStorage r13 = integerRegister(13, "r13"); + public static final VMStorage r14 = integerRegister(14, "r14"); + public static final VMStorage r15 = integerRegister(15, "r15"); + + public static final VMStorage xmm0 = vectorRegister(0, "xmm0"); + public static final VMStorage xmm1 = vectorRegister(1, "xmm1"); + public static final VMStorage xmm2 = vectorRegister(2, "xmm2"); + public static final VMStorage xmm3 = vectorRegister(3, "xmm3"); + public static final VMStorage xmm4 = vectorRegister(4, "xmm4"); + public static final VMStorage xmm5 = vectorRegister(5, "xmm5"); + public static final VMStorage xmm6 = vectorRegister(6, "xmm6"); + public static final VMStorage xmm7 = vectorRegister(7, "xmm7"); + public static final VMStorage xmm8 = vectorRegister(8, "xmm8"); + public static final VMStorage xmm9 = vectorRegister(9, "xmm9"); + public static final VMStorage xmm10 = vectorRegister(10, "xmm10"); + public static final VMStorage xmm11 = vectorRegister(11, "xmm11"); + public static final VMStorage xmm12 = vectorRegister(12, "xmm12"); + public static final VMStorage xmm13 = vectorRegister(13, "xmm13"); + public static final VMStorage xmm14 = vectorRegister(14, "xmm14"); + public static final VMStorage xmm15 = vectorRegister(15, "xmm15"); + public static final VMStorage xmm16 = vectorRegister(16, "xmm16"); + public static final VMStorage xmm17 = vectorRegister(17, "xmm17"); + public static final VMStorage xmm18 = vectorRegister(18, "xmm18"); + public static final VMStorage xmm19 = vectorRegister(19, "xmm19"); + public static final VMStorage xmm20 = vectorRegister(20, "xmm20"); + public static final VMStorage xmm21 = vectorRegister(21, "xmm21"); + public static final VMStorage xmm22 = vectorRegister(22, "xmm22"); + public static final VMStorage xmm23 = vectorRegister(23, "xmm23"); + public static final VMStorage xmm24 = vectorRegister(24, "xmm24"); + public static final VMStorage xmm25 = vectorRegister(25, "xmm25"); + public static final VMStorage xmm26 = vectorRegister(26, "xmm26"); + public static final VMStorage xmm27 = vectorRegister(27, "xmm27"); + public static final VMStorage xmm28 = vectorRegister(28, "xmm28"); + public static final VMStorage xmm29 = vectorRegister(29, "xmm29"); + public static final VMStorage xmm30 = vectorRegister(30, "xmm30"); + public static final VMStorage xmm31 = vectorRegister(31, "xmm31"); } - public static final VMStorage rax = integerRegister(0, "rax"); - public static final VMStorage rcx = integerRegister(1, "rcx"); - public static final VMStorage rdx = integerRegister(2, "rdx"); - public static final VMStorage rbx = integerRegister(3, "rbx"); - public static final VMStorage rsp = integerRegister(4, "rsp"); - public static final VMStorage rbp = integerRegister(5, "rbp"); - public static final VMStorage rsi = integerRegister(6, "rsi"); - public static final VMStorage rdi = integerRegister(7, "rdi"); - public static final VMStorage r8 = integerRegister(8, "r8"); - public static final VMStorage r9 = integerRegister(9, "r9"); - public static final VMStorage r10 = integerRegister(10, "r10"); - public static final VMStorage r11 = integerRegister(11, "r11"); - public static final VMStorage r12 = integerRegister(12, "r12"); - public static final VMStorage r13 = integerRegister(13, "r13"); - public static final VMStorage r14 = integerRegister(14, "r14"); - public static final VMStorage r15 = integerRegister(15, "r15"); - - public static final VMStorage xmm0 = vectorRegister(0, "xmm0"); - public static final VMStorage xmm1 = vectorRegister(1, "xmm1"); - public static final VMStorage xmm2 = vectorRegister(2, "xmm2"); - public static final VMStorage xmm3 = vectorRegister(3, "xmm3"); - public static final VMStorage xmm4 = vectorRegister(4, "xmm4"); - public static final VMStorage xmm5 = vectorRegister(5, "xmm5"); - public static final VMStorage xmm6 = vectorRegister(6, "xmm6"); - public static final VMStorage xmm7 = vectorRegister(7, "xmm7"); - public static final VMStorage xmm8 = vectorRegister(8, "xmm8"); - public static final VMStorage xmm9 = vectorRegister(9, "xmm9"); - public static final VMStorage xmm10 = vectorRegister(10, "xmm10"); - public static final VMStorage xmm11 = vectorRegister(11, "xmm11"); - public static final VMStorage xmm12 = vectorRegister(12, "xmm12"); - public static final VMStorage xmm13 = vectorRegister(13, "xmm13"); - public static final VMStorage xmm14 = vectorRegister(14, "xmm14"); - public static final VMStorage xmm15 = vectorRegister(15, "xmm15"); - public static final VMStorage xmm16 = vectorRegister(16, "xmm16"); - public static final VMStorage xmm17 = vectorRegister(17, "xmm17"); - public static final VMStorage xmm18 = vectorRegister(18, "xmm18"); - public static final VMStorage xmm19 = vectorRegister(19, "xmm19"); - public static final VMStorage xmm20 = vectorRegister(20, "xmm20"); - public static final VMStorage xmm21 = vectorRegister(21, "xmm21"); - public static final VMStorage xmm22 = vectorRegister(22, "xmm22"); - public static final VMStorage xmm23 = vectorRegister(23, "xmm23"); - public static final VMStorage xmm24 = vectorRegister(24, "xmm24"); - public static final VMStorage xmm25 = vectorRegister(25, "xmm25"); - public static final VMStorage xmm26 = vectorRegister(26, "xmm26"); - public static final VMStorage xmm27 = vectorRegister(27, "xmm27"); - public static final VMStorage xmm28 = vectorRegister(28, "xmm28"); - public static final VMStorage xmm29 = vectorRegister(29, "xmm29"); - public static final VMStorage xmm30 = vectorRegister(30, "xmm30"); - public static final VMStorage xmm31 = vectorRegister(31, "xmm31"); - private static VMStorage integerRegister(int index, String debugName) { - return new VMStorage(StorageClasses.INTEGER, index, debugName); + return new VMStorage(StorageType.INTEGER, REG64_MASK, index, debugName); } private static VMStorage vectorRegister(int index, String debugName) { - return new VMStorage(StorageClasses.VECTOR, index, debugName); + return new VMStorage(StorageType.VECTOR, XMM_MASK, index, debugName); } - public static VMStorage stackStorage(int index) { - return new VMStorage(StorageClasses.STACK, index, "Stack@" + index); + public static VMStorage stackStorage(short size, int byteOffset) { + return new VMStorage(StorageType.STACK, size, byteOffset); } public static VMStorage x87Storage(int index) { - return new VMStorage(StorageClasses.X87, index, "X87(" + index + ")"); + return new VMStorage(StorageType.X87, STP_MASK, index, "X87(" + index + ")"); } public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, VMStorage[] inputVectorRegs, VMStorage[] outputIntRegs, VMStorage[] outputVectorRegs, int numX87Outputs, VMStorage[] volatileIntRegs, VMStorage[] volatileVectorRegs, int stackAlignment, int shadowSpace, - VMStorage targetAddrStorage, VMStorage retBufAddrStorage) { + VMStorage scratch1, VMStorage scratch2) { return new ABIDescriptor( INSTANCE, new VMStorage[][] { @@ -153,7 +163,10 @@ public static ABIDescriptor abiFor(VMStorage[] inputIntRegs, VMStorage[] inputVe }, stackAlignment, shadowSpace, - targetAddrStorage, retBufAddrStorage); + scratch1, scratch2, + StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER), + StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER), + StubLocations.CAPTURED_STATE_BUFFER.storage(StorageType.PLACEHOLDER)); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index 441529c2765..735aabcd149 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -31,9 +31,11 @@ import jdk.internal.foreign.abi.CallingSequence; import jdk.internal.foreign.abi.CallingSequenceBuilder; import jdk.internal.foreign.abi.DowncallLinker; +import jdk.internal.foreign.abi.LinkerOptions; import jdk.internal.foreign.abi.SharedUtils; import jdk.internal.foreign.abi.UpcallLinker; import jdk.internal.foreign.abi.VMStorage; +import jdk.internal.foreign.abi.x64.X86_64Architecture; import java.lang.foreign.SegmentScope; import java.lang.foreign.FunctionDescriptor; @@ -49,6 +51,7 @@ import static jdk.internal.foreign.PlatformLayouts.SysV; import static jdk.internal.foreign.abi.Binding.vmStore; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; /** * For the SysV x64 C ABI specifically, this class uses namely CallingSequenceBuilder @@ -57,9 +60,11 @@ * This includes taking care of synthetic arguments like pointers to return buffers for 'in-memory' returns. */ public class CallArranger { - public static final int MAX_INTEGER_ARGUMENT_REGISTERS = 6; - public static final int MAX_VECTOR_ARGUMENT_REGISTERS = 8; - private static final ABIDescriptor CSysV = abiFor( + private static final int STACK_SLOT_SIZE = 8; + private static final int MAX_INTEGER_ARGUMENT_REGISTERS = 6; + private static final int MAX_VECTOR_ARGUMENT_REGISTERS = 8; + + private static final ABIDescriptor CSysV = X86_64Architecture.abiFor( new VMStorage[] { rdi, rsi, rdx, rcx, r8, r9, rax }, new VMStorage[] { xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7 }, new VMStorage[] { rax, rdx }, @@ -69,8 +74,7 @@ public class CallArranger { new VMStorage[] { xmm8, xmm9, xmm10, xmm11, xmm12, xmm13, xmm14, xmm15 }, 16, 0, //no shadow space - r10, // target addr reg - r11 // ret buf addr reg + r10, r11 // scratch 1 & 2 ); public record Bindings( @@ -80,7 +84,11 @@ public record Bindings( } public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall) { - CallingSequenceBuilder csb = new CallingSequenceBuilder(CSysV, forUpcall); + return getBindings(mt, cDesc, forUpcall, LinkerOptions.empty()); + } + + public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { + CallingSequenceBuilder csb = new CallingSequenceBuilder(CSysV, forUpcall, options); BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); BindingCalculator retCalc = forUpcall ? new UnboxBindingCalculator(false) : new BoxBindingCalculator(false); @@ -111,14 +119,14 @@ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, bool return new Bindings(csb.build(), returnInMemory, argCalc.storageCalculator.nVectorReg); } - public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc) { - Bindings bindings = getBindings(mt, cDesc, false); + public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDesc, LinkerOptions options) { + Bindings bindings = getBindings(mt, cDesc, false, options); MethodHandle handle = new DowncallLinker(CSysV, bindings.callingSequence).getBoundMethodHandle(); handle = MethodHandles.insertArguments(handle, handle.type().parameterCount() - 1, bindings.nVectorArgs); if (bindings.isInMemoryReturn) { - handle = SharedUtils.adaptDowncallForIMR(handle, cDesc); + handle = SharedUtils.adaptDowncallForIMR(handle, cDesc, bindings.callingSequence); } return handle; @@ -153,15 +161,15 @@ public StorageCalculator(boolean forArguments) { } private int maxRegisterArguments(int type) { - return type == StorageClasses.INTEGER ? + return type == StorageType.INTEGER ? MAX_INTEGER_ARGUMENT_REGISTERS : MAX_VECTOR_ARGUMENT_REGISTERS; } VMStorage stackAlloc() { assert forArguments : "no stack returns"; - VMStorage storage = stackStorage((int)stackOffset); - stackOffset++; + VMStorage storage = X86_64Architecture.stackStorage((short) STACK_SLOT_SIZE, (int)stackOffset); + stackOffset += STACK_SLOT_SIZE; return storage; } @@ -199,23 +207,23 @@ VMStorage[] structStorages(TypeClass typeClass) { VMStorage[] storage = new VMStorage[(int)(nIntegerReg + nVectorReg)]; for (int i = 0 ; i < typeClass.classes.size() ; i++) { boolean sse = typeClass.classes.get(i) == ArgumentClassImpl.SSE; - storage[i] = nextStorage(sse ? StorageClasses.VECTOR : StorageClasses.INTEGER); + storage[i] = nextStorage(sse ? StorageType.VECTOR : StorageType.INTEGER); } return storage; } int registerCount(int type) { return switch (type) { - case StorageClasses.INTEGER -> nIntegerReg; - case StorageClasses.VECTOR -> nVectorReg; + case StorageType.INTEGER -> nIntegerReg; + case StorageType.VECTOR -> nVectorReg; default -> throw new IllegalStateException(); }; } void incrementRegisterCount(int type) { switch (type) { - case StorageClasses.INTEGER -> nIntegerReg++; - case StorageClasses.VECTOR -> nVectorReg++; + case StorageType.INTEGER -> nIntegerReg++; + case StorageType.VECTOR -> nVectorReg++; default -> throw new IllegalStateException(); } } @@ -253,7 +261,7 @@ List getBindings(Class carrier, MemoryLayout layout) { if (offset + copy < layout.byteSize()) { bindings.dup(); } - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(copy, useFloat); bindings.bufferLoad(offset, type) .vmStore(storage, type); @@ -262,15 +270,15 @@ List getBindings(Class carrier, MemoryLayout layout) { } case POINTER -> { bindings.unboxAddress(); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmStore(storage, long.class); } case INTEGER -> { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmStore(storage, carrier); } case FLOAT -> { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); + VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR); bindings.vmStore(storage, carrier); } default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); @@ -300,7 +308,7 @@ List getBindings(Class carrier, MemoryLayout layout) { final long copy = Math.min(layout.byteSize() - offset, 8); VMStorage storage = regs[regIndex++]; bindings.dup(); - boolean useFloat = storage.type() == StorageClasses.VECTOR; + boolean useFloat = storage.type() == StorageType.VECTOR; Class type = SharedUtils.primitiveCarrierForSize(copy, useFloat); bindings.vmLoad(storage, type) .bufferStore(offset, type); @@ -308,16 +316,16 @@ List getBindings(Class carrier, MemoryLayout layout) { } } case POINTER -> { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmLoad(storage, long.class) .boxAddressRaw(Utils.pointeeSize(layout)); } case INTEGER -> { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmLoad(storage, carrier); } case FLOAT -> { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); + VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR); bindings.vmLoad(storage, carrier); } default -> throw new UnsupportedOperationException("Unhandled class " + argumentClass); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index 80896bdb9fc..e181e9182f9 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -54,7 +54,7 @@ private SysVx64Linker() { } @Override protected MethodHandle arrangeDowncall(MethodType inferredMethodType, FunctionDescriptor function, LinkerOptions options) { - return CallArranger.arrangeDowncall(inferredMethodType, function); + return CallArranger.arrangeDowncall(inferredMethodType, function, options); } @Override diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index ff68ea08ea8..61a68c4bfc5 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -48,6 +48,7 @@ import static jdk.internal.foreign.PlatformLayouts.Win64; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; /** * For the Windowx x64 C ABI specifically, this class uses CallingSequenceBuilder @@ -69,8 +70,7 @@ public class CallArranger { new VMStorage[] { xmm4, xmm5 }, 16, 32, - r10, // target addr reg - r11 // ret buf addr reg + r10, r11 // scratch 1 & 2 ); public record Bindings( @@ -84,7 +84,7 @@ public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, bool public static Bindings getBindings(MethodType mt, FunctionDescriptor cDesc, boolean forUpcall, LinkerOptions options) { class CallingSequenceBuilderHelper { - final CallingSequenceBuilder csb = new CallingSequenceBuilder(CWindows, forUpcall); + final CallingSequenceBuilder csb = new CallingSequenceBuilder(CWindows, forUpcall, options); final BindingCalculator argCalc = forUpcall ? new BoxBindingCalculator(true) : new UnboxBindingCalculator(true); final BindingCalculator retCalc = @@ -125,7 +125,7 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe MethodHandle handle = new DowncallLinker(CWindows, bindings.callingSequence).getBoundMethodHandle(); if (bindings.isInMemoryReturn) { - handle = SharedUtils.adaptDowncallForIMR(handle, cDesc); + handle = SharedUtils.adaptDowncallForIMR(handle, cDesc, bindings.callingSequence); } return handle; @@ -164,7 +164,7 @@ VMStorage nextStorage(int type) { // stack assert stackOffset == Utils.alignUp(stackOffset, STACK_SLOT_SIZE); // should always be aligned - VMStorage storage = X86_64Architecture.stackStorage((int) (stackOffset / STACK_SLOT_SIZE)); + VMStorage storage = X86_64Architecture.stackStorage((short) STACK_SLOT_SIZE, (int) stackOffset); stackOffset += STACK_SLOT_SIZE; return storage; } @@ -176,7 +176,7 @@ VMStorage nextStorage(int type) { public VMStorage extraVarargsStorage() { assert forArguments; - return CWindows.inputStorage[StorageClasses.INTEGER][nRegs - 1]; + return CWindows.inputStorage[StorageType.INTEGER][nRegs - 1]; } } @@ -198,7 +198,7 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean switch (argumentClass) { case STRUCT_REGISTER: { assert carrier == MemorySegment.class; - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); Class type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false); bindings.bufferLoad(0, type) .vmStore(storage, type); @@ -208,28 +208,28 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean assert carrier == MemorySegment.class; bindings.copy(layout) .unboxAddress(); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmStore(storage, long.class); break; } case POINTER: { bindings.unboxAddress(); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmStore(storage, long.class); break; } case INTEGER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmStore(storage, carrier); break; } case FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); + VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR); bindings.vmStore(storage, carrier); break; } case VARARG_FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); + VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR); if (!INSTANCE.isStackType(storage.type())) { // need extra for register arg VMStorage extraStorage = storageCalculator.extraVarargsStorage(); bindings.dup() @@ -262,7 +262,7 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean assert carrier == MemorySegment.class; bindings.allocate(layout) .dup(); - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); Class type = SharedUtils.primitiveCarrierForSize(layout.byteSize(), false); bindings.vmLoad(storage, type) .bufferStore(0, type); @@ -270,24 +270,24 @@ public List getBindings(Class carrier, MemoryLayout layout, boolean } case STRUCT_REFERENCE: { assert carrier == MemorySegment.class; - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmLoad(storage, long.class) .boxAddress(layout); break; } case POINTER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmLoad(storage, long.class) .boxAddressRaw(Utils.pointeeSize(layout)); break; } case INTEGER: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.INTEGER); + VMStorage storage = storageCalculator.nextStorage(StorageType.INTEGER); bindings.vmLoad(storage, carrier); break; } case FLOAT: { - VMStorage storage = storageCalculator.nextStorage(StorageClasses.VECTOR); + VMStorage storage = storageCalculator.nextStorage(StorageType.VECTOR); bindings.vmLoad(storage, carrier); break; } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 666704047c7..4fa18293238 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -474,8 +474,8 @@ java/beans/XMLEncoder/Test6570354.java 8015593 macosx-all # jdk_foreign -java/foreign/TestUpcallStack.java 8275584 macosx-aarch64 -java/foreign/TestDowncallStack.java 8275584 macosx-aarch64 +java/foreign/callarranger/TestAarch64CallArranger.java generic-x86 +java/foreign/TestLargeSegmentCopy.java generic-x86 ############################################################################ diff --git a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java index 49d4f7d4f69..205ce9c7083 100644 --- a/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java +++ b/test/jdk/java/foreign/MemoryLayoutPrincipalTotalityTest.java @@ -34,7 +34,7 @@ import static java.lang.foreign.ValueLayout.*; import static org.testng.Assert.*; -public class MemoryLayoutPrincipalTotalityTest extends NativeTestHelper { +public class MemoryLayoutPrincipalTotalityTest { // The tests in this class is mostly there to ensure compile-time pattern matching totality. diff --git a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java index 9abccdaf9f8..31a38813330 100644 --- a/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java +++ b/test/jdk/java/foreign/MemoryLayoutTypeRetentionTest.java @@ -35,7 +35,7 @@ import static java.lang.foreign.ValueLayout.*; import static org.testng.Assert.*; -public class MemoryLayoutTypeRetentionTest extends NativeTestHelper { +public class MemoryLayoutTypeRetentionTest { // These tests check both compile-time and runtime properties. // withName() et al. should return the same type as the original object. diff --git a/test/jdk/java/foreign/TestLargeSegmentCopy.java b/test/jdk/java/foreign/TestLargeSegmentCopy.java index 0ed9b3971af..f75c2e75ca9 100644 --- a/test/jdk/java/foreign/TestLargeSegmentCopy.java +++ b/test/jdk/java/foreign/TestLargeSegmentCopy.java @@ -25,6 +25,7 @@ /* * @test * @enablePreview + * @requires sun.arch.data.model == "64" * @bug 8292851 * @run testng/othervm -Xmx4G TestLargeSegmentCopy */ diff --git a/test/jdk/java/foreign/TestLinker.java b/test/jdk/java/foreign/TestLinker.java index 8077e3ef841..121e986adb7 100644 --- a/test/jdk/java/foreign/TestLinker.java +++ b/test/jdk/java/foreign/TestLinker.java @@ -24,9 +24,11 @@ /* * @test * @enablePreview + * @requires os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" * @run testng TestLinker */ +import org.testng.annotations.DataProvider; import org.testng.annotations.Test; import java.lang.foreign.FunctionDescriptor; @@ -47,4 +49,27 @@ public void testLinkerOptionsCache() { assertNotSame(mh1, mh2); } + @DataProvider + public static Object[][] invalidIndexCases() { + return new Object[][]{ + { -1, }, + { 42, }, + }; + } + + @Test(dataProvider = "invalidIndexCases", + expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*not in bounds for descriptor.*") + public void testInvalidOption(int invalidIndex) { + Linker.Option option = Linker.Option.firstVariadicArg(invalidIndex); + FunctionDescriptor desc = FunctionDescriptor.ofVoid(); + Linker.nativeLinker().downcallHandle(desc, option); // throws + } + + @Test(expectedExceptions = IllegalArgumentException.class, + expectedExceptionsMessageRegExp = ".*Unknown name.*") + public void testInvalidPreservedValueName() { + Linker.Option.captureCallState("foo"); // throws + } + } diff --git a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java index 190df4e96a5..037db225c65 100644 --- a/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java +++ b/test/jdk/java/foreign/callarranger/CallArrangerTestBase.java @@ -32,16 +32,17 @@ public class CallArrangerTestBase { public static void checkArgumentBindings(CallingSequence callingSequence, Binding[][] argumentBindings) { - assertEquals(callingSequence.argumentBindingsCount(), argumentBindings.length); + assertEquals(callingSequence.argumentBindingsCount(), argumentBindings.length, + callingSequence.asString() + " != " + Arrays.deepToString(argumentBindings)); for (int i = 0; i < callingSequence.argumentBindingsCount(); i++) { List actual = callingSequence.argumentBindings(i); Binding[] expected = argumentBindings[i]; - assertEquals(actual, Arrays.asList(expected)); + assertEquals(actual, Arrays.asList(expected), "bindings at: " + i + ": " + actual + " != " + Arrays.toString(expected)); } } public static void checkReturnBindings(CallingSequence callingSequence, Binding[] returnBindings) { - assertEquals(callingSequence.returnBindings(), Arrays.asList(returnBindings)); + assertEquals(callingSequence.returnBindings(), Arrays.asList(returnBindings), callingSequence.returnBindings() + " != " + Arrays.toString(returnBindings)); } } diff --git a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java index c4c8670e8bd..6b33f237b60 100644 --- a/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestAarch64CallArranger.java @@ -25,6 +25,7 @@ /* * @test * @enablePreview + * @requires sun.arch.data.model == "64" * @modules java.base/jdk.internal.foreign * java.base/jdk.internal.foreign.abi * java.base/jdk.internal.foreign.abi.aarch64 @@ -34,10 +35,13 @@ import java.lang.foreign.FunctionDescriptor; import java.lang.foreign.MemoryLayout; +import java.lang.foreign.StructLayout; import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.StubLocations; +import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.aarch64.CallArranger; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -49,6 +53,7 @@ import static jdk.internal.foreign.PlatformLayouts.AArch64.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.*; +import static jdk.internal.foreign.abi.aarch64.AArch64Architecture.Regs.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -56,6 +61,9 @@ public class TestAarch64CallArranger extends CallArrangerTestBase { + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + private static final VMStorage RETURN_BUFFER_STORAGE = StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); @@ -68,7 +76,7 @@ public void testEmpty() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) } + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -92,7 +100,7 @@ public void testInteger() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(r2, int.class) }, @@ -101,8 +109,8 @@ public void testInteger() { { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), int.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 8), int.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -122,7 +130,7 @@ public void testTwoIntTwoFloat() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -144,7 +152,7 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, expectedBindings }); @@ -204,7 +212,7 @@ public void testMultipleStructs() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct1), unboxAddress(), @@ -235,7 +243,7 @@ public void testReturnStruct1() { assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(r8, long.class) @@ -259,8 +267,8 @@ public void testReturnStruct2() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, - { unboxAddress(), vmStore(r9, long.class) } + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{ @@ -288,8 +296,8 @@ public void testStructHFA1() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(v0, float.class) }, { vmStore(r0, int.class) }, { @@ -326,7 +334,7 @@ public void testStructHFA3() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, float.class), @@ -350,9 +358,9 @@ public void testStructHFA3() { { dup(), bufferLoad(0, long.class), - vmStore(stackStorage(0), long.class), + vmStore(stackStorage((short) 8, 0), long.class), bufferLoad(8, int.class), - vmStore(stackStorage(1), int.class), + vmStore(stackStorage((short) 4, 8), int.class), } }); @@ -380,7 +388,7 @@ public void testStructStackSpill() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct), unboxAddress(), vmStore(r0, long.class) }, { copy(struct), unboxAddress(), vmStore(r1, long.class) }, { vmStore(r2, int.class) }, @@ -389,8 +397,8 @@ public void testStructStackSpill() { { vmStore(r5, int.class) }, { vmStore(r6, int.class) }, { vmStore(r7, int.class) }, - { copy(struct), unboxAddress(), vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), int.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage((short) 8, 0), long.class) }, + { vmStore(stackStorage((short) 4, 8), int.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -401,7 +409,7 @@ public void testVarArgsInRegs() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(1))); + CallArranger.Bindings bindings = CallArranger.LINUX.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(1))); assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); @@ -410,7 +418,7 @@ public void testVarArgsInRegs() { // This is identical to the non-variadic calling sequence checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, { vmStore(r1, int.class) }, { vmStore(v0, float.class) }, @@ -424,7 +432,7 @@ public void testVarArgsOnStack() { MethodType mt = MethodType.methodType(void.class, int.class, int.class, float.class); FunctionDescriptor fd = FunctionDescriptor.ofVoid(C_INT, C_INT, C_FLOAT); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid(ADDRESS, C_INT, C_INT, C_FLOAT); - CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(1))); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(1))); assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); @@ -433,10 +441,207 @@ public void testVarArgsOnStack() { // The two variadic arguments should be allocated on the stack checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r9, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, int.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 8), float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack() { + MethodType mt = MethodType.methodType(void.class, + int.class, int.class, int.class, int.class, + int.class, int.class, int.class, int.class, + int.class, int.class, short.class, byte.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_INT, C_INT, C_INT, C_INT, + C_INT, C_INT, C_INT, C_INT, + C_INT, C_INT, C_SHORT, C_CHAR); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(r0, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), float.class) }, + { vmStore(r1, int.class) }, + { vmStore(r2, int.class) }, + { vmStore(r3, int.class) }, + { vmStore(r4, int.class) }, + { vmStore(r5, int.class) }, + { vmStore(r6, int.class) }, + { vmStore(r7, int.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { vmStore(stackStorage((short) 4, 4), int.class) }, + { cast(short.class, int.class), vmStore(stackStorage((short) 2, 8), int.class) }, + { cast(byte.class, int.class), vmStore(stackStorage((short) 1, 10), int.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack2() { + StructLayout struct = MemoryLayout.structLayout( + C_FLOAT, + C_FLOAT + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + int.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_INT, struct); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { vmStore(stackStorage((short) 4, 0), int.class) }, + { + dup(), + bufferLoad(0, int.class), + vmStore(stackStorage((short) 4, 4), int.class), + bufferLoad(4, int.class), + vmStore(stackStorage((short) 4, 8), int.class), + } + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack3() { + StructLayout struct = MemoryLayout.structLayout( + C_POINTER, + C_POINTER + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + MemorySegment.class, float.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + struct, C_FLOAT); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { dup(), + bufferLoad(0, long.class), vmStore(stackStorage((short) 8, 0), long.class), + bufferLoad(8, long.class), vmStore(stackStorage((short) 8, 8), long.class) }, + { vmStore(stackStorage((short) 4, 16), float.class) }, + }); + + checkReturnBindings(callingSequence, new Binding[]{}); + } + + @Test + public void testMacArgsOnStack4() { + StructLayout struct = MemoryLayout.structLayout( + C_INT, + C_INT, + C_POINTER + ); + MethodType mt = MethodType.methodType(void.class, + long.class, long.class, long.class, long.class, + long.class, long.class, long.class, long.class, + double.class, double.class, double.class, double.class, + double.class, double.class, double.class, double.class, + float.class, MemorySegment.class); + FunctionDescriptor fd = FunctionDescriptor.ofVoid( + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, C_LONG_LONG, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_DOUBLE, C_DOUBLE, C_DOUBLE, C_DOUBLE, + C_FLOAT, struct); + CallArranger.Bindings bindings = CallArranger.MACOS.getBindings(mt, fd, false); + + assertFalse(bindings.isInMemoryReturn()); + CallingSequence callingSequence = bindings.callingSequence(); + assertEquals(callingSequence.callerMethodType(), mt.insertParameterTypes(0, MemorySegment.class)); + assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); + + checkArgumentBindings(callingSequence, new Binding[][]{ + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { vmStore(r0, long.class) }, + { vmStore(r1, long.class) }, + { vmStore(r2, long.class) }, + { vmStore(r3, long.class) }, + { vmStore(r4, long.class) }, + { vmStore(r5, long.class) }, + { vmStore(r6, long.class) }, + { vmStore(r7, long.class) }, + { vmStore(v0, double.class) }, + { vmStore(v1, double.class) }, + { vmStore(v2, double.class) }, + { vmStore(v3, double.class) }, + { vmStore(v4, double.class) }, + { vmStore(v5, double.class) }, + { vmStore(v6, double.class) }, + { vmStore(v7, double.class) }, + { vmStore(stackStorage((short) 4, 0), float.class) }, + { dup(), + bufferLoad(0, long.class), vmStore(stackStorage((short) 8, 8), long.class), + bufferLoad(8, long.class), vmStore(stackStorage((short) 8, 16), long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); diff --git a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java index 01066b550ae..a17d3b79af7 100644 --- a/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestSysVCallArranger.java @@ -38,6 +38,8 @@ import java.lang.foreign.MemorySegment; import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; +import jdk.internal.foreign.abi.StubLocations; +import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.x64.sysv.CallArranger; import org.testng.annotations.DataProvider; import org.testng.annotations.Test; @@ -48,6 +50,7 @@ import static jdk.internal.foreign.PlatformLayouts.SysV.*; import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; @@ -55,6 +58,10 @@ public class TestSysVCallArranger extends CallArrangerTestBase { + private static final short STACK_SLOT_SIZE = 8; + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + private static final VMStorage RETURN_BUFFER_STORAGE = StubLocations.RETURN_BUFFER.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); @@ -67,7 +74,7 @@ public void testEmpty() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rax, long.class) } }); @@ -95,7 +102,7 @@ public void testNestedStructs() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, int.class), vmStore(rsi, int.class)}, { vmStore(rax, long.class) }, @@ -126,7 +133,7 @@ public void testNestedUnion() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { dup(), bufferLoad(0, long.class), vmStore(rdi, long.class), bufferLoad(8, long.class), vmStore(rsi, long.class)}, { vmStore(rax, long.class) }, @@ -156,9 +163,9 @@ public void testNestedStructsUnaligned() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, - { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class)}, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { dup(), bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class)}, { vmStore(rax, long.class) }, }); @@ -186,9 +193,9 @@ public void testNestedUnionUnaligned() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, - { dup(), bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), - bufferLoad(8, int.class), vmStore(stackStorage(1), int.class)}, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, + { dup(), bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), + bufferLoad(8, int.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class)}, { vmStore(rax, long.class) }, }); @@ -211,7 +218,7 @@ public void testIntegerRegs() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { vmStore(rdx, int.class) }, @@ -242,7 +249,7 @@ public void testDoubleRegs() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -277,15 +284,15 @@ public void testMixed() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, long.class) }, { vmStore(rsi, long.class) }, { vmStore(rdx, long.class) }, { vmStore(rcx, long.class) }, { vmStore(r8, long.class) }, { vmStore(r9, long.class) }, - { vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class) }, { vmStore(xmm0, float.class) }, { vmStore(xmm1, float.class) }, { vmStore(xmm2, float.class) }, @@ -294,8 +301,8 @@ public void testMixed() { { vmStore(xmm5, float.class) }, { vmStore(xmm6, float.class) }, { vmStore(xmm7, float.class) }, - { vmStore(stackStorage(2), float.class) }, - { vmStore(stackStorage(3), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), float.class) }, { vmStore(rax, long.class) }, }); @@ -334,7 +341,7 @@ public void testAbiExample() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rdi, int.class) }, { vmStore(rsi, int.class) }, { @@ -347,8 +354,8 @@ public void testAbiExample() { { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, { vmStore(r9, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class) }, { vmStore(rax, long.class) }, }); @@ -377,7 +384,7 @@ public void testMemoryAddress() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) }, }); @@ -399,7 +406,7 @@ public void testStruct(MemoryLayout struct, Binding[] expectedBindings) { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, expectedBindings, { vmStore(rax, long.class) }, }); @@ -425,20 +432,20 @@ public static Object[][] structs() { }, { MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG), new Binding[]{ dup(), - bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), + bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), dup(), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class), - bufferLoad(16, long.class), vmStore(stackStorage(2), long.class) + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class), + bufferLoad(16, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 16), long.class) } }, { MemoryLayout.structLayout(C_LONG, C_LONG, C_LONG, C_LONG), new Binding[]{ dup(), - bufferLoad(0, long.class), vmStore(stackStorage(0), long.class), + bufferLoad(0, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class), dup(), - bufferLoad(8, long.class), vmStore(stackStorage(1), long.class), + bufferLoad(8, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class), dup(), - bufferLoad(16, long.class), vmStore(stackStorage(2), long.class), - bufferLoad(24, long.class), vmStore(stackStorage(3), long.class) + bufferLoad(16, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 16), long.class), + bufferLoad(24, long.class), vmStore(stackStorage(STACK_SLOT_SIZE, 24), long.class) } }, }; @@ -458,8 +465,8 @@ public void testReturnRegisterStruct() { assertEquals(callingSequence.functionDesc(), fd.appendArgumentLayouts(C_LONG).insertArgumentLayouts(0, ADDRESS, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r11, long.class) }, - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(RETURN_BUFFER_STORAGE, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rax, long.class) } }); @@ -490,7 +497,7 @@ public void testIMR() { assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER, C_LONG)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rdi, long.class) }, { vmStore(rax, long.class) } }); diff --git a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java index 2deedfa10e6..968f3e8db29 100644 --- a/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java +++ b/test/jdk/java/foreign/callarranger/TestWindowsCallArranger.java @@ -39,6 +39,8 @@ import jdk.internal.foreign.abi.Binding; import jdk.internal.foreign.abi.CallingSequence; import jdk.internal.foreign.abi.LinkerOptions; +import jdk.internal.foreign.abi.StubLocations; +import jdk.internal.foreign.abi.VMStorage; import jdk.internal.foreign.abi.x64.windows.CallArranger; import org.testng.annotations.Test; @@ -50,11 +52,15 @@ import static jdk.internal.foreign.abi.Binding.*; import static jdk.internal.foreign.abi.Binding.copy; import static jdk.internal.foreign.abi.x64.X86_64Architecture.*; +import static jdk.internal.foreign.abi.x64.X86_64Architecture.Regs.*; import static org.testng.Assert.*; public class TestWindowsCallArranger extends CallArrangerTestBase { + private static final short STACK_SLOT_SIZE = 8; + private static final VMStorage TARGET_ADDRESS_STORAGE = StubLocations.TARGET_ADDRESS.storage(StorageType.PLACEHOLDER); + @Test public void testEmpty() { MethodType mt = MethodType.methodType(void.class); @@ -67,7 +73,7 @@ public void testEmpty() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) } + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); } @@ -84,7 +90,7 @@ public void testIntegerRegs() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { vmStore(r8, int.class) }, @@ -106,7 +112,7 @@ public void testDoubleRegs() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(xmm0, double.class) }, { vmStore(xmm1, double.class) }, { vmStore(xmm2, double.class) }, @@ -130,15 +136,15 @@ public void testMixed() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, long.class) }, { vmStore(rdx, long.class) }, { vmStore(xmm2, float.class) }, { vmStore(xmm3, float.class) }, - { vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), long.class) }, - { vmStore(stackStorage(2), float.class) }, - { vmStore(stackStorage(3), float.class) } + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), float.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), float.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -161,7 +167,7 @@ public void testAbiExample() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(rdx, int.class) }, { @@ -170,13 +176,13 @@ public void testAbiExample() { vmStore(r8, long.class) }, { vmStore(r9, int.class) }, - { vmStore(stackStorage(0), int.class) }, - { vmStore(stackStorage(1), double.class) }, - { vmStore(stackStorage(2), double.class) }, - { vmStore(stackStorage(3), double.class) }, - { vmStore(stackStorage(4), int.class) }, - { vmStore(stackStorage(5), int.class) }, - { vmStore(stackStorage(6), int.class) } + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 24), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 32), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 40), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 48), int.class) } }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -190,7 +196,7 @@ public void testAbiExampleVarargs() { C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); FunctionDescriptor fdExpected = FunctionDescriptor.ofVoid( ADDRESS, C_INT, C_DOUBLE, C_INT, C_DOUBLE, C_DOUBLE); - CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false, LinkerOptions.of(firstVariadicArg(2))); + CallArranger.Bindings bindings = CallArranger.getBindings(mt, fd, false, LinkerOptions.forDowncall(fd, firstVariadicArg(2))); assertFalse(bindings.isInMemoryReturn()); CallingSequence callingSequence = bindings.callingSequence(); @@ -198,12 +204,12 @@ public void testAbiExampleVarargs() { assertEquals(callingSequence.functionDesc(), fdExpected); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { vmStore(rcx, int.class) }, { vmStore(xmm1, double.class) }, { vmStore(r8, int.class) }, { dup(), vmStore(r9, double.class), vmStore(xmm3, double.class) }, - { vmStore(stackStorage(0), double.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 0), double.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); @@ -232,7 +238,7 @@ public void testStructRegister() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { bufferLoad(0, long.class), vmStore(rcx, long.class) } }); @@ -262,7 +268,7 @@ public void testStructReference() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct), unboxAddress(), @@ -293,7 +299,7 @@ public void testMemoryAddress() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -314,7 +320,7 @@ public void testReturnRegisterStruct() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, }); checkReturnBindings(callingSequence, @@ -338,7 +344,7 @@ public void testIMR() { assertEquals(callingSequence.functionDesc(), FunctionDescriptor.ofVoid(ADDRESS, C_POINTER)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { unboxAddress(), vmStore(rcx, long.class) } }); @@ -367,23 +373,23 @@ public void testStackStruct() { assertEquals(callingSequence.functionDesc(), fd.insertArgumentLayouts(0, ADDRESS)); checkArgumentBindings(callingSequence, new Binding[][]{ - { unboxAddress(), vmStore(r10, long.class) }, + { unboxAddress(), vmStore(TARGET_ADDRESS_STORAGE, long.class) }, { copy(struct), unboxAddress(), vmStore(rcx, long.class) }, { vmStore(rdx, int.class) }, { vmStore(xmm2, double.class) }, { unboxAddress(), vmStore(r9, long.class) }, - { copy(struct), unboxAddress(), vmStore(stackStorage(0), long.class) }, - { vmStore(stackStorage(1), int.class) }, - { vmStore(stackStorage(2), double.class) }, - { unboxAddress(), vmStore(stackStorage(3), long.class) }, - { copy(struct), unboxAddress(), vmStore(stackStorage(4), long.class) }, - { vmStore(stackStorage(5), int.class) }, - { vmStore(stackStorage(6), double.class) }, - { unboxAddress(), vmStore(stackStorage(7), long.class) }, - { copy(struct), unboxAddress(), vmStore(stackStorage(8), long.class) }, - { vmStore(stackStorage(9), int.class) }, - { vmStore(stackStorage(10), double.class) }, - { unboxAddress(), vmStore(stackStorage(11), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 0), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 8), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 16), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 24), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 32), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 40), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 48), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 56), long.class) }, + { copy(struct), unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 64), long.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 72), int.class) }, + { vmStore(stackStorage(STACK_SLOT_SIZE, 80), double.class) }, + { unboxAddress(), vmStore(stackStorage(STACK_SLOT_SIZE, 88), long.class) }, }); checkReturnBindings(callingSequence, new Binding[]{}); diff --git a/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java new file mode 100644 index 00000000000..deba982a7cb --- /dev/null +++ b/test/jdk/java/foreign/capturecallstate/TestCaptureCallState.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022, 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 + * @enablePreview + * @library ../ /test/lib + * @requires ((os.arch == "amd64" | os.arch == "x86_64") & sun.arch.data.model == "64") | os.arch == "aarch64" + * @run testng/othervm --enable-native-access=ALL-UNNAMED TestCaptureCallState + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import java.lang.foreign.Arena; +import java.lang.foreign.FunctionDescriptor; +import java.lang.foreign.Linker; +import java.lang.foreign.MemoryLayout; +import java.lang.foreign.MemorySegment; +import java.lang.foreign.StructLayout; +import java.lang.invoke.MethodHandle; +import java.lang.invoke.VarHandle; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; + +import static java.lang.foreign.MemoryLayout.PathElement.groupElement; +import static java.lang.foreign.ValueLayout.JAVA_DOUBLE; +import static java.lang.foreign.ValueLayout.JAVA_INT; +import static java.lang.foreign.ValueLayout.JAVA_LONG; +import static org.testng.Assert.assertEquals; + +public class TestCaptureCallState extends NativeTestHelper { + + static { + System.loadLibrary("CaptureCallState"); + if (IS_WINDOWS) { + String system32 = System.getenv("SystemRoot") + "\\system32"; + System.load(system32 + "\\Kernel32.dll"); + System.load(system32 + "\\Ws2_32.dll"); + } + } + + private record SaveValuesCase(String nativeTarget, FunctionDescriptor nativeDesc, String threadLocalName, Consumer resultCheck) {} + + @Test(dataProvider = "cases") + public void testSavedThreadLocal(SaveValuesCase testCase) throws Throwable { + Linker.Option.CaptureCallState stl = Linker.Option.captureCallState(testCase.threadLocalName()); + MethodHandle handle = downcallHandle(testCase.nativeTarget(), testCase.nativeDesc(), stl); + + VarHandle errnoHandle = stl.layout().varHandle(groupElement(testCase.threadLocalName())); + + try (Arena arena = Arena.openConfined()) { + MemorySegment saveSeg = arena.allocate(stl.layout()); + int testValue = 42; + boolean needsAllocator = testCase.nativeDesc().returnLayout().map(StructLayout.class::isInstance).orElse(false); + Object result = needsAllocator + ? handle.invoke(arena, saveSeg, testValue) + : handle.invoke(saveSeg, testValue); + testCase.resultCheck().accept(result); + int savedErrno = (int) errnoHandle.get(saveSeg); + assertEquals(savedErrno, testValue); + } + } + + @DataProvider + public static Object[][] cases() { + List cases = new ArrayList<>(); + + cases.add(new SaveValuesCase("set_errno_V", FunctionDescriptor.ofVoid(JAVA_INT), "errno", o -> {})); + cases.add(new SaveValuesCase("set_errno_I", FunctionDescriptor.of(JAVA_INT, JAVA_INT), "errno", o -> assertEquals((int) o, 42))); + cases.add(new SaveValuesCase("set_errno_D", FunctionDescriptor.of(JAVA_DOUBLE, JAVA_INT), "errno", o -> assertEquals((double) o, 42.0))); + + cases.add(structCase("SL", Map.of(JAVA_LONG.withName("x"), 42L))); + cases.add(structCase("SLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L))); + cases.add(structCase("SLLL", Map.of(JAVA_LONG.withName("x"), 42L, + JAVA_LONG.withName("y"), 42L, + JAVA_LONG.withName("z"), 42L))); + cases.add(structCase("SD", Map.of(JAVA_DOUBLE.withName("x"), 42D))); + cases.add(structCase("SDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D))); + cases.add(structCase("SDDD", Map.of(JAVA_DOUBLE.withName("x"), 42D, + JAVA_DOUBLE.withName("y"), 42D, + JAVA_DOUBLE.withName("z"), 42D))); + + if (IS_WINDOWS) { + cases.add(new SaveValuesCase("SetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "GetLastError", o -> {})); + cases.add(new SaveValuesCase("WSASetLastError", FunctionDescriptor.ofVoid(JAVA_INT), "WSAGetLastError", o -> {})); + } + + return cases.stream().map(tc -> new Object[] {tc}).toArray(Object[][]::new); + } + + static SaveValuesCase structCase(String name, Map fields) { + StructLayout layout = MemoryLayout.structLayout(fields.keySet().toArray(MemoryLayout[]::new)); + + Consumer check = o -> {}; + for (var field : fields.entrySet()) { + MemoryLayout fieldLayout = field.getKey(); + VarHandle fieldHandle = layout.varHandle(MemoryLayout.PathElement.groupElement(fieldLayout.name().get())); + Object value = field.getValue(); + check = check.andThen(o -> assertEquals(fieldHandle.get(o), value)); + } + + return new SaveValuesCase("set_errno_" + name, FunctionDescriptor.of(layout, JAVA_INT), "errno", check); + } + +} + diff --git a/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c new file mode 100644 index 00000000000..9a8925474a2 --- /dev/null +++ b/test/jdk/java/foreign/capturecallstate/libCaptureCallState.c @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2022, 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 + +#ifdef _WIN64 +#define EXPORT __declspec(dllexport) +#else +#define EXPORT +#endif + +EXPORT void set_errno_V(int value) { + errno = value; +} + +EXPORT int set_errno_I(int value) { + errno = value; + return 42; +} + +EXPORT double set_errno_D(int value) { + errno = value; + return 42.0; +} + +struct SL { + long long x; +}; + +EXPORT struct SL set_errno_SL(int value) { + errno = value; + struct SL s; + s.x = 42; + return s; +} + +struct SLL { + long long x; + long long y; +}; + +EXPORT struct SLL set_errno_SLL(int value) { + errno = value; + struct SLL s; + s.x = 42; + s.y = 42; + return s; +} + +struct SLLL { + long long x; + long long y; + long long z; +}; + +EXPORT struct SLLL set_errno_SLLL(int value) { + errno = value; + struct SLLL s; + s.x = 42; + s.y = 42; + s.z = 42; + return s; +} + +struct SD { + double x; +}; + +EXPORT struct SD set_errno_SD(int value) { + errno = value; + struct SD s; + s.x = 42.0; + return s; +} + +struct SDD { + double x; + double y; +}; + +EXPORT struct SDD set_errno_SDD(int value) { + errno = value; + struct SDD s; + s.x = 42.0; + s.y = 42.0; + return s; +} + +struct SDDD { + double x; + double y; + double z; +}; + +EXPORT struct SDDD set_errno_SDDD(int value) { + errno = value; + struct SDDD s; + s.x = 42.0; + s.y = 42.0; + s.z = 42.0; + return s; +} From 328845926d3c1984f65450bfe01ebbc2c0315a69 Mon Sep 17 00:00:00 2001 From: Tyler Steele Date: Mon, 5 Dec 2022 14:53:52 +0000 Subject: [PATCH 047/494] 8297606: [AIX] Broken build after JDK-8295475 Reviewed-by: mdoerr, stuefe --- make/autoconf/flags-cflags.m4 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/autoconf/flags-cflags.m4 b/make/autoconf/flags-cflags.m4 index ebae9e8f00f..1fdd0143adf 100644 --- a/make/autoconf/flags-cflags.m4 +++ b/make/autoconf/flags-cflags.m4 @@ -532,7 +532,7 @@ AC_DEFUN([FLAGS_SETUP_CFLAGS_HELPER], # Suggested additions: -qsrcmsg to get improved error reporting # set -qtbtable=full for a better traceback table/better stacks in hs_err when xlc16 is used TOOLCHAIN_CFLAGS_JDK="-qtbtable=full -qchars=signed -qfullpath -qsaveopt -qstackprotect" # add on both CFLAGS - TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced \ + TOOLCHAIN_CFLAGS_JVM="-qtbtable=full -qtune=balanced -fno-exceptions \ -qalias=noansi -qstrict -qtls=default -qnortti -qnoeh -qignerrno -qstackprotect" elif test "x$TOOLCHAIN_TYPE" = xmicrosoft; then TOOLCHAIN_CFLAGS_JVM="-nologo -MD -Zc:preprocessor -Zc:strictStrings -MP" From 19d849884bd7a9718a5050b9709657f231a1ddbc Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Mon, 5 Dec 2022 15:20:16 +0000 Subject: [PATCH 048/494] 8297495: j.u.concurrent updates for JDK 20 Reviewed-by: jpai --- .../java/util/concurrent/ForkJoinPool.java | 33 +++ .../util/concurrent/ForkJoinWorkerThread.java | 11 + .../concurrent/tck/ForkJoinPool20Test.java | 219 ++++++++++++++++++ .../util/concurrent/tck/JSR166TestCase.java | 17 +- 4 files changed, 276 insertions(+), 4 deletions(-) create mode 100644 test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java index 64d63da9233..dd4950269e6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinPool.java @@ -2852,6 +2852,10 @@ public void execute(Runnable task) { /** * Submits a ForkJoinTask for execution. * + * @implSpec + * This method is equivalent to {@link #externalSubmit(ForkJoinTask)} + * when called from a thread that is not in this pool. + * * @param task the task to submit * @param the type of the task's result * @return the task @@ -2898,6 +2902,31 @@ public ForkJoinTask submit(Runnable task) { // Added mainly for possible use in Loom + /** + * Submits the given task as if submitted from a non-{@code ForkJoinTask} + * client. The task is added to a scheduling queue for submissions to the + * pool even when called from a thread in the pool. + * + * @implSpec + * This method is equivalent to {@link #submit(ForkJoinTask)} when called + * from a thread that is not in this pool. + * + * @return the task + * @param task the task to submit + * @param the type of the task's result + * @throws NullPointerException if the task is null + * @throws RejectedExecutionException if the task cannot be + * scheduled for execution + * @since 20 + */ + public ForkJoinTask externalSubmit(ForkJoinTask task) { + U.storeStoreFence(); // ensure safely publishable + task.markPoolSubmission(); + WorkQueue q = submissionQueue(true); + q.push(task, this, true); + return task; + } + /** * Submits the given task without guaranteeing that it will * eventually execute in the absence of available active threads. @@ -2909,6 +2938,9 @@ public ForkJoinTask submit(Runnable task) { * @param task the task * @param the type of the task's result * @return the task + * @throws NullPointerException if the task is null + * @throws RejectedExecutionException if the task cannot be + * scheduled for execution * @since 19 */ public ForkJoinTask lazySubmit(ForkJoinTask task) { @@ -3267,6 +3299,7 @@ public long getStealCount() { * granularities. * * @return the number of queued tasks + * @see ForkJoinWorkerThread#getQueuedTaskCount() */ public long getQueuedTaskCount() { WorkQueue[] qs; WorkQueue q; diff --git a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java index 13fc7a86040..f7281998251 100644 --- a/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java +++ b/src/java.base/share/classes/java/util/concurrent/ForkJoinWorkerThread.java @@ -138,6 +138,17 @@ public int getPoolIndex() { return workQueue.getPoolIndex(); } + /** + * {@return a (non-negative) estimate of the number of tasks in the + * thread's queue} + * + * @since 20 + * @see ForkJoinPool#getQueuedTaskCount() + */ + public int getQueuedTaskCount() { + return workQueue.queueSize(); + } + /** * Initializes internal state after construction but before * processing any tasks. If you override this method, you must diff --git a/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java new file mode 100644 index 00000000000..b35ab064d53 --- /dev/null +++ b/test/jdk/java/util/concurrent/tck/ForkJoinPool20Test.java @@ -0,0 +1,219 @@ +/* + * 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. + */ + +/* + * This file is available under and governed by the GNU General Public + * License version 2 only, as published by the Free Software Foundation. + * However, the following notice accompanied the original version of this + * file: + * + * Written by Doug Lea with assistance from members of JCP JSR-166 + * Expert Group and released to the public domain, as explained at + * http://creativecommons.org/publicdomain/zero/1.0/ + */ + +import java.util.concurrent.ForkJoinPool; +import java.util.concurrent.ForkJoinTask; +import java.util.concurrent.ForkJoinWorkerThread; +import java.util.concurrent.Future; +import java.util.concurrent.RejectedExecutionException; +import java.util.concurrent.atomic.AtomicReference; +import java.util.concurrent.locks.LockSupport; + +import junit.framework.Test; +import junit.framework.TestSuite; + +/** + * Tests for ForkJoinPool and ForkJoinWorkerThread additions in JDK 20. + */ +public class ForkJoinPool20Test extends JSR166TestCase { + public static void main(String[] args) { + main(suite(), args); + } + + public static Test suite() { + return new TestSuite(ForkJoinPool20Test.class); + } + + /** + * Test that tasks submitted with externalSubmit execute. + */ + public void testExternalSubmit1() throws Exception { + try (var pool = new ForkJoinPool()) { + // submit from external client + var task1 = ForkJoinTask.adapt(() -> "foo"); + pool.externalSubmit(task1); + assertEquals(task1.get(), "foo"); + + // submit from worker thread + Future> task2 = pool.submit(() -> { + return pool.externalSubmit(ForkJoinTask.adapt(() -> "foo")); + }); + assertEquals(task2.get().get(), "foo"); + } + } + + /** + * Test that tasks submitted with externalSubmit are pushed to a submission queue. + */ + public void testExternalSubmit2() throws Exception { + try (var pool = new ForkJoinPool(1)) { + pool.submit(() -> { + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == 0); + + for (int count = 1; count <= 3; count++) { + var task = ForkJoinTask.adapt(() -> { }); + pool.externalSubmit(task); + + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == count); + } + }).get(); + } + } + + /** + * Test externalSubmit return value. + */ + public void testExternalSubmitReturnsTask() { + try (var pool = new ForkJoinPool()) { + var task = ForkJoinTask.adapt(() -> "foo"); + assertTrue(pool.externalSubmit(task) == task); + } + } + + /** + * Test externalSubmit(null) throws NullPointerException. + */ + public void testExternalSubmitWithNull() { + try (var pool = new ForkJoinPool()) { + assertThrows(NullPointerException.class, () -> pool.externalSubmit(null)); + } + } + + /** + * Test externalSubmit throws RejectedExecutionException when pool is shutdown. + */ + public void testExternalSubmitWhenShutdown() { + try (var pool = new ForkJoinPool()) { + pool.shutdown(); + var task = ForkJoinTask.adapt(() -> { }); + assertThrows(RejectedExecutionException.class, () -> pool.externalSubmit(task)); + } + } + + /** + * Test that tasks submitted with submit(ForkJoinTask) are pushed to a + * submission queue. + */ + public void testSubmit() throws Exception { + try (var pool = new ForkJoinPool(1)) { + ForkJoinWorkerThread worker = submitBusyTask(pool); + try { + assertTrue(worker.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == 0); + + for (int count = 1; count <= 3; count++) { + var task = ForkJoinTask.adapt(() -> { }); + pool.submit(task); + + // task should be in submission queue + assertTrue(worker.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedTaskCount() == 0); + assertTrue(pool.getQueuedSubmissionCount() == count); + } + } finally { + LockSupport.unpark(worker); + } + } + } + + /** + * Test ForkJoinWorkerThread::getQueuedTaskCount returns the number of tasks in the + * current thread's queue. This test runs with parallelism of 1 to ensure that tasks + * aren't stolen. + */ + public void testGetQueuedTaskCount1() throws Exception { + try (var pool = new ForkJoinPool(1)) { + pool.submit(() -> { + var worker = (ForkJoinWorkerThread) Thread.currentThread(); + assertTrue(worker.getQueuedTaskCount() == 0); + + for (int count = 1; count <= 3; count++) { + pool.submit(() -> { }); + + // task should be in this thread's task queue + assertTrue(worker.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedSubmissionCount() == 0); + } + }).get(); + } + } + + /** + * Test ForkJoinWorkerThread::getQueuedTaskCount returns the number of tasks in the + * thread's queue. This test runs with parallelism of 2 and one worker active running + * a task. This gives the test two task queues to sample. + */ + public void testGetQueuedTaskCount2() throws Exception { + try (var pool = new ForkJoinPool(2)) { + // keep one worker thread active + ForkJoinWorkerThread worker1 = submitBusyTask(pool); + try { + pool.submit(() -> { + var worker2 = (ForkJoinWorkerThread) Thread.currentThread(); + for (int count = 1; count <= 3; count++) { + pool.submit(() -> { }); + + // task should be in this thread's task queue + assertTrue(worker1.getQueuedTaskCount() == 0); + assertTrue(worker2.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedTaskCount() == count); + assertTrue(pool.getQueuedSubmissionCount() == 0); + } + }).get(); + } finally { + LockSupport.unpark(worker1); // release worker1 + } + } + } + + /** + * Submits a task to the pool, returning the worker thread that runs the + * task. The task runs until the thread is unparked. + */ + static ForkJoinWorkerThread submitBusyTask(ForkJoinPool pool) throws Exception { + var ref = new AtomicReference(); + pool.submit(() -> { + ref.set((ForkJoinWorkerThread) Thread.currentThread()); + LockSupport.park(); + }); + ForkJoinWorkerThread worker; + while ((worker = ref.get()) == null) { + Thread.sleep(20); + } + return worker; + } +} diff --git a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java index 427ec44cf5f..a5d491f6ce0 100644 --- a/test/jdk/java/util/concurrent/tck/JSR166TestCase.java +++ b/test/jdk/java/util/concurrent/tck/JSR166TestCase.java @@ -513,7 +513,8 @@ public String run() { public static boolean atLeastJava14() { return JAVA_CLASS_VERSION >= 58.0; } public static boolean atLeastJava15() { return JAVA_CLASS_VERSION >= 59.0; } public static boolean atLeastJava16() { return JAVA_CLASS_VERSION >= 60.0; } - public static boolean atLeastJava17() { return JAVA_CLASS_VERSION >= 61.0; } + public static boolean atLeastJava19() { return JAVA_CLASS_VERSION >= 63.0; } + public static boolean atLeastJava20() { return JAVA_CLASS_VERSION >= 64.0; } /** * Collects all JSR166 unit tests as one suite. @@ -633,12 +634,20 @@ public static Test suite() { addNamedTestClasses(suite, java9TestClassNames); } - if (atLeastJava17()) { - String[] java17TestClassNames = { + if (atLeastJava19()) { + String[] java19TestClassNames = { "ForkJoinPool19Test", }; - addNamedTestClasses(suite, java17TestClassNames); + addNamedTestClasses(suite, java19TestClassNames); } + + if (atLeastJava20()) { + String[] java20TestClassNames = { + "ForkJoinPool20Test", + }; + addNamedTestClasses(suite, java20TestClassNames); + } + return suite; } From a38c63da5632fe727838ff1ed88d9601bf954801 Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Mon, 5 Dec 2022 15:28:51 +0000 Subject: [PATCH 049/494] 8297733: Refactor Cast binding to enum Reviewed-by: mcimadamore --- .../jdk/internal/foreign/abi/Binding.java | 59 ++++++++++++++++++- .../foreign/abi/BindingSpecializer.java | 35 ++++------- 2 files changed, 68 insertions(+), 26 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java index 39c1116a2ca..1949c660832 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java @@ -25,6 +25,7 @@ package jdk.internal.foreign.abi; import jdk.internal.foreign.NativeMemorySegmentImpl; +import jdk.internal.foreign.Utils; import java.lang.foreign.Arena; import java.lang.foreign.MemoryLayout; @@ -367,7 +368,28 @@ static Dup dup() { } static Binding cast(Class fromType, Class toType) { - return new Cast(fromType, toType); + if (fromType == int.class) { + if (toType == boolean.class) { + return Cast.INT_TO_BOOLEAN; + } else if (toType == byte.class) { + return Cast.INT_TO_BYTE; + } else if (toType == short.class) { + return Cast.INT_TO_SHORT; + } else if (toType == char.class) { + return Cast.INT_TO_CHAR; + } + } else if (toType == int.class) { + if (fromType == boolean.class) { + return Cast.BOOLEAN_TO_INT; + } else if (fromType == byte.class) { + return Cast.BYTE_TO_INT; + } else if (fromType == short.class) { + return Cast.SHORT_TO_INT; + } else if (fromType == char.class) { + return Cast.CHAR_TO_INT; + } + } + throw new IllegalArgumentException("Unknown conversion: " + fromType + " -> " + toType); } @@ -713,7 +735,40 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun * value onto the stack. * */ - record Cast(Class fromType, Class toType) implements Binding { + enum Cast implements Binding { + INT_TO_BOOLEAN(int.class, boolean.class) { + @Override + public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, + BindingInterpreter.LoadFunc loadFunc, Context context) { + // implement least significant byte non-zero test + int arg = (int) stack.pop(); + boolean result = Utils.byteToBoolean((byte) arg); + stack.push(result); + } + }, + INT_TO_BYTE(int.class, byte.class), + INT_TO_CHAR(int.class, char.class), + INT_TO_SHORT(int.class, short.class), + BOOLEAN_TO_INT(boolean.class, int.class), + BYTE_TO_INT(byte.class, int.class), + CHAR_TO_INT(char.class, int.class), + SHORT_TO_INT(short.class, int.class); + + private final Class fromType; + private final Class toType; + + Cast(Class fromType, Class toType) { + this.fromType = fromType; + this.toType = toType; + } + + public Class fromType() { + return fromType; + } + + public Class toType() { + return toType; + } @Override public Tag tag() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 13bfb7054d6..3c5edba2443 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -676,10 +676,9 @@ private void emitCast(Binding.Cast cast) { Class fromType = cast.fromType(); Class toType = cast.toType(); - if (fromType == int.class) { - popType(int.class); - - if (toType == boolean.class) { + popType(fromType); + switch (cast) { + case INT_TO_BOOLEAN -> { // implement least significant byte non-zero test // select first byte @@ -688,28 +687,16 @@ private void emitCast(Binding.Cast cast) { // convert to boolean emitInvokeStatic(Utils.class, "byteToBoolean", "(B)Z"); - } else if (toType == byte.class) { - mv.visitInsn(I2B); - } else if (toType == short.class) { - mv.visitInsn(I2S); - } else { - assert toType == char.class; - mv.visitInsn(I2C); } - - pushType(toType); - } else { - popType(fromType); - - assert fromType == boolean.class - || fromType == byte.class - || fromType == short.class - || fromType == char.class; - // no-op in bytecode - - assert toType == int.class; - pushType(int.class); + case INT_TO_BYTE -> mv.visitInsn(I2B); + case INT_TO_CHAR -> mv.visitInsn(I2C); + case INT_TO_SHORT -> mv.visitInsn(I2S); + case BOOLEAN_TO_INT, BYTE_TO_INT, CHAR_TO_INT, SHORT_TO_INT -> { + // no-op in bytecode + } + default -> throw new IllegalStateException("Unknown cast: " + cast); } + pushType(toType); } private void emitUnboxAddress() { From 6a7a0db587446160e77c9ac225669e5a0c9bc638 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Hannes=20Walln=C3=B6fer?= Date: Mon, 5 Dec 2022 16:23:01 +0000 Subject: [PATCH 050/494] 8296619: Upgrade jQuery to 3.6.1 Reviewed-by: jjg --- .../resources/script-dir/jquery-3.6.0.min.js | 2 - .../{jquery-3.6.0.js => jquery-3.6.1.js} | 214 ++++++++++-------- .../resources/script-dir/jquery-3.6.1.min.js | 2 + .../doclets/toolkit/util/DocPaths.java | 2 +- src/jdk.javadoc/share/legal/jquery.md | 6 +- .../javadoc/doclet/testSearch/TestSearch.java | 4 +- .../jdk/javadoc/tool/api/basic/APITest.java | 2 +- 7 files changed, 130 insertions(+), 102 deletions(-) delete mode 100644 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js rename src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/{jquery-3.6.0.js => jquery-3.6.1.js} (98%) create mode 100644 src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.1.min.js diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js deleted file mode 100644 index c4c6022f298..00000000000 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.0.min.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! jQuery v3.6.0 | (c) OpenJS Foundation and other contributors | jquery.org/license */ -!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.0",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var _t,zt=[],Ut=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=zt.pop()||S.expando+"_"+wt.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Ut.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Ut.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Ut,"$1"+r):!1!==e.jsonp&&(e.url+=(Tt.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,zt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((_t=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===_t.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=Fe(y.pixelPosition,function(e,t){if(t)return t=We(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 to avoid XSS via location.hash (#9521) - // Strict HTML recognition (#11290: must start with <) + // Prioritize #id over to avoid XSS via location.hash (trac-9521) + // Strict HTML recognition (trac-11290: must start with <) // Shortcut simple #id case for speed rquickExpr = /^(?:\s*(<[\w\W]+>)[^>]*|#([\w-]+))$/, @@ -4087,7 +4087,7 @@ jQuery.extend( { isReady: false, // A counter to track how many items to wait for before - // the ready event fires. See #6781 + // the ready event fires. See trac-6781 readyWait: 1, // Handle when the DOM is ready @@ -4215,7 +4215,7 @@ function fcamelCase( _all, letter ) { // Convert dashed to camelCase; used by the css and data modules // Support: IE <=9 - 11, Edge 12 - 15 -// Microsoft forgot to hump their vendor prefix (#9572) +// Microsoft forgot to hump their vendor prefix (trac-9572) function camelCase( string ) { return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); } @@ -4251,7 +4251,7 @@ Data.prototype = { value = {}; // We can accept data for non-element nodes in modern browsers, - // but we should not, see #8335. + // but we should not, see trac-8335. // Always return an empty object. if ( acceptData( owner ) ) { @@ -4490,7 +4490,7 @@ jQuery.fn.extend( { while ( i-- ) { // Support: IE 11 only - // The attrs elements can be null (#14894) + // The attrs elements can be null (trac-14894) if ( attrs[ i ] ) { name = attrs[ i ].name; if ( name.indexOf( "data-" ) === 0 ) { @@ -4913,9 +4913,9 @@ var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); input = document.createElement( "input" ); // Support: Android 4.0 - 4.3 only - // Check state lost if the name is set (#11217) + // Check state lost if the name is set (trac-11217) // Support: Windows Web Apps (WWA) - // `name` and `type` must use .setAttribute for WWA (#14901) + // `name` and `type` must use .setAttribute for WWA (trac-14901) input.setAttribute( "type", "radio" ); input.setAttribute( "checked", "checked" ); input.setAttribute( "name", "t" ); @@ -4939,7 +4939,7 @@ var rscriptType = ( /^$|^module$|\/(?:java|ecma)script/i ); } )(); -// We have to close these tags to support XHTML (#13200) +// We have to close these tags to support XHTML (trac-13200) var wrapMap = { // XHTML parsers do not magically insert elements in the @@ -4965,7 +4965,7 @@ if ( !support.option ) { function getAll( context, tag ) { // Support: IE <=9 - 11 only - // Use typeof to avoid zero-argument method invocation on host objects (#15151) + // Use typeof to avoid zero-argument method invocation on host objects (trac-15151) var ret; if ( typeof context.getElementsByTagName !== "undefined" ) { @@ -5048,7 +5048,7 @@ function buildFragment( elems, context, scripts, selection, ignored ) { // Remember the top-level container tmp = fragment.firstChild; - // Ensure the created nodes are orphaned (#12392) + // Ensure the created nodes are orphaned (trac-12392) tmp.textContent = ""; } } @@ -5469,15 +5469,15 @@ jQuery.event = { for ( ; cur !== this; cur = cur.parentNode || this ) { - // Don't check non-elements (#13208) - // Don't process clicks on disabled elements (#6911, #8165, #11382, #11764) + // Don't check non-elements (trac-13208) + // Don't process clicks on disabled elements (trac-6911, trac-8165, trac-11382, trac-11764) if ( cur.nodeType === 1 && !( event.type === "click" && cur.disabled === true ) ) { matchedHandlers = []; matchedSelectors = {}; for ( i = 0; i < delegateCount; i++ ) { handleObj = handlers[ i ]; - // Don't conflict with Object.prototype properties (#13203) + // Don't conflict with Object.prototype properties (trac-13203) sel = handleObj.selector + " "; if ( matchedSelectors[ sel ] === undefined ) { @@ -5731,7 +5731,7 @@ jQuery.Event = function( src, props ) { // Create target properties // Support: Safari <=6 - 7 only - // Target should not be a text node (#504, #13143) + // Target should not be a text node (trac-504, trac-13143) this.target = ( src.target && src.target.nodeType === 3 ) ? src.target.parentNode : src.target; @@ -5854,10 +5854,10 @@ jQuery.each( { focus: "focusin", blur: "focusout" }, function( type, delegateTyp return true; }, - // Suppress native focus or blur as it's already being fired - // in leverageNative. - _default: function() { - return true; + // Suppress native focus or blur if we're currently inside + // a leveraged native-event stack + _default: function( event ) { + return dataPriv.get( event.target, type ); }, delegateType: delegateType @@ -5956,7 +5956,8 @@ var // checked="checked" or checked rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rcleanScript = /^\s*\s*$/g; + + rcleanScript = /^\s*\s*$/g; // Prefer a tbody over its parent table for containing new rows function manipulationTarget( elem, content ) { @@ -6070,7 +6071,7 @@ function domManip( collection, args, callback, ignored ) { // Use the original fragment for the last item // instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). + // being emptied incorrectly in certain situations (trac-8070). for ( ; i < l; i++ ) { node = fragment; @@ -6111,6 +6112,12 @@ function domManip( collection, args, callback, ignored ) { }, doc ); } } else { + + // Unwrap a CDATA section containing script contents. This shouldn't be + // needed as in XML documents they're already not visible when + // inspecting element contents and in HTML documents they have no + // meaning but we're preserving that logic for backwards compatibility. + // This will be removed completely in 4.0. See gh-4904. DOMEval( node.textContent.replace( rcleanScript, "" ), node, doc ); } } @@ -6393,9 +6400,12 @@ jQuery.each( { } ); var rnumnonpx = new RegExp( "^(" + pnum + ")(?!px)[a-z%]+$", "i" ); +var rcustomProp = /^--/; + + var getStyles = function( elem ) { - // Support: IE <=11 only, Firefox <=30 (#15098, #14150) + // Support: IE <=11 only, Firefox <=30 (trac-15098, trac-14150) // IE throws on elements created in popups // FF meanwhile throws on frame elements through "defaultView.getComputedStyle" var view = elem.ownerDocument.defaultView; @@ -6430,6 +6440,15 @@ var swap = function( elem, options, callback ) { var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); +var whitespace = "[\\x20\\t\\r\\n\\f]"; + + +var rtrimCSS = new RegExp( + "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", + "g" +); + + ( function() { @@ -6495,7 +6514,7 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); } // Support: IE <=9 - 11 only - // Style of cloned element affects source element cloned (#8908) + // Style of cloned element affects source element cloned (trac-8908) div.style.backgroundClip = "content-box"; div.cloneNode( true ).style.backgroundClip = ""; support.clearCloneStyle = div.style.backgroundClip === "content-box"; @@ -6575,6 +6594,7 @@ var rboxStyle = new RegExp( cssExpand.join( "|" ), "i" ); function curCSS( elem, name, computed ) { var width, minWidth, maxWidth, ret, + isCustomProp = rcustomProp.test( name ), // Support: Firefox 51+ // Retrieving style before computed somehow @@ -6585,11 +6605,22 @@ function curCSS( elem, name, computed ) { computed = computed || getStyles( elem ); // getPropertyValue is needed for: - // .css('filter') (IE 9 only, #12537) - // .css('--customProperty) (#3144) + // .css('filter') (IE 9 only, trac-12537) + // .css('--customProperty) (gh-3144) if ( computed ) { ret = computed.getPropertyValue( name ) || computed[ name ]; + // trim whitespace for custom property (issue gh-4926) + if ( isCustomProp ) { + + // rtrim treats U+000D CARRIAGE RETURN and U+000C FORM FEED + // as whitespace while CSS does not, but this is not a problem + // because CSS preprocessing replaces them with U+000A LINE FEED + // (which *is* CSS whitespace) + // https://www.w3.org/TR/css-syntax-3/#input-preprocessing + ret = ret.replace( rtrimCSS, "$1" ); + } + if ( ret === "" && !isAttached( elem ) ) { ret = jQuery.style( elem, name ); } @@ -6685,7 +6716,6 @@ var // except "table", "table-cell", or "table-caption" // See here for display values: https://developer.mozilla.org/en-US/docs/CSS/display rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rcustomProp = /^--/, cssShow = { position: "absolute", visibility: "hidden", display: "block" }, cssNormalTransform = { letterSpacing: "0", @@ -6921,15 +6951,15 @@ jQuery.extend( { if ( value !== undefined ) { type = typeof value; - // Convert "+=" or "-=" to relative numbers (#7345) + // Convert "+=" or "-=" to relative numbers (trac-7345) if ( type === "string" && ( ret = rcssNum.exec( value ) ) && ret[ 1 ] ) { value = adjustCSS( elem, name, ret ); - // Fixes bug #9237 + // Fixes bug trac-9237 type = "number"; } - // Make sure that null and NaN values aren't set (#7116) + // Make sure that null and NaN values aren't set (trac-7116) if ( value == null || value !== value ) { return; } @@ -7553,7 +7583,7 @@ function Animation( elem, properties, options ) { remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), // Support: Android 2.3 only - // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (#12497) + // Archaic crash bug won't allow us to use `1 - ( 0.5 || 0 )` (trac-12497) temp = remaining / animation.duration || 0, percent = 1 - temp, index = 0, @@ -7943,7 +7973,6 @@ jQuery.fx.speeds = { // Based off of the plugin by Clint Helfers, with permission. -// https://web.archive.org/web/20100324014747/http://blindsignals.com/index.php/2009/07/jquery-delay/ jQuery.fn.delay = function( time, type ) { time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; type = type || "fx"; @@ -8168,8 +8197,7 @@ jQuery.extend( { // Support: IE <=9 - 11 only // elem.tabIndex doesn't always return the // correct value when it hasn't been explicitly set - // https://web.archive.org/web/20141116233347/http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - // Use proper attribute retrieval(#12072) + // Use proper attribute retrieval (trac-12072) var tabindex = jQuery.find.attr( elem, "tabindex" ); if ( tabindex ) { @@ -8273,8 +8301,7 @@ function classesToArray( value ) { jQuery.fn.extend( { addClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; + var classNames, cur, curValue, className, i, finalValue; if ( isFunction( value ) ) { return this.each( function( j ) { @@ -8282,36 +8309,35 @@ jQuery.fn.extend( { } ); } - classes = classesToArray( value ); + classNames = classesToArray( value ); - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + if ( classNames.length ) { + return this.each( function() { + curValue = getClass( this ); + cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { - if ( cur.indexOf( " " + clazz + " " ) < 0 ) { - cur += clazz + " "; + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; + if ( cur.indexOf( " " + className + " " ) < 0 ) { + cur += className + " "; } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); + this.setAttribute( "class", finalValue ); } } - } + } ); } return this; }, removeClass: function( value ) { - var classes, elem, cur, curValue, clazz, j, finalValue, - i = 0; + var classNames, cur, curValue, className, i, finalValue; if ( isFunction( value ) ) { return this.each( function( j ) { @@ -8323,45 +8349,42 @@ jQuery.fn.extend( { return this.attr( "class", "" ); } - classes = classesToArray( value ); + classNames = classesToArray( value ); - if ( classes.length ) { - while ( ( elem = this[ i++ ] ) ) { - curValue = getClass( elem ); + if ( classNames.length ) { + return this.each( function() { + curValue = getClass( this ); // This expression is here for better compressibility (see addClass) - cur = elem.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); + cur = this.nodeType === 1 && ( " " + stripAndCollapse( curValue ) + " " ); if ( cur ) { - j = 0; - while ( ( clazz = classes[ j++ ] ) ) { + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; // Remove *all* instances - while ( cur.indexOf( " " + clazz + " " ) > -1 ) { - cur = cur.replace( " " + clazz + " ", " " ); + while ( cur.indexOf( " " + className + " " ) > -1 ) { + cur = cur.replace( " " + className + " ", " " ); } } // Only assign if different to avoid unneeded rendering. finalValue = stripAndCollapse( cur ); if ( curValue !== finalValue ) { - elem.setAttribute( "class", finalValue ); + this.setAttribute( "class", finalValue ); } } - } + } ); } return this; }, toggleClass: function( value, stateVal ) { - var type = typeof value, + var classNames, className, i, self, + type = typeof value, isValidValue = type === "string" || Array.isArray( value ); - if ( typeof stateVal === "boolean" && isValidValue ) { - return stateVal ? this.addClass( value ) : this.removeClass( value ); - } - if ( isFunction( value ) ) { return this.each( function( i ) { jQuery( this ).toggleClass( @@ -8371,17 +8394,20 @@ jQuery.fn.extend( { } ); } - return this.each( function() { - var className, i, self, classNames; + if ( typeof stateVal === "boolean" && isValidValue ) { + return stateVal ? this.addClass( value ) : this.removeClass( value ); + } + + classNames = classesToArray( value ); + return this.each( function() { if ( isValidValue ) { // Toggle individual class names - i = 0; self = jQuery( this ); - classNames = classesToArray( value ); - while ( ( className = classNames[ i++ ] ) ) { + for ( i = 0; i < classNames.length; i++ ) { + className = classNames[ i ]; // Check each className given, space separated list if ( self.hasClass( className ) ) { @@ -8515,7 +8541,7 @@ jQuery.extend( { val : // Support: IE <=10 - 11 only - // option.text throws exceptions (#14686, #14858) + // option.text throws exceptions (trac-14686, trac-14858) // Strip and collapse whitespace // https://html.spec.whatwg.org/#strip-and-collapse-whitespace stripAndCollapse( jQuery.text( elem ) ); @@ -8542,7 +8568,7 @@ jQuery.extend( { option = options[ i ]; // Support: IE <=9 only - // IE8-9 doesn't update selected after form reset (#2551) + // IE8-9 doesn't update selected after form reset (trac-2551) if ( ( option.selected || i === index ) && // Don't return options that are disabled or in a disabled optgroup @@ -8685,8 +8711,8 @@ jQuery.extend( jQuery.event, { return; } - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) + // Determine event propagation path in advance, per W3C events spec (trac-9951) + // Bubble up to document, then to window; watch for a global ownerDocument var (trac-9724) if ( !onlyHandlers && !special.noBubble && !isWindow( elem ) ) { bubbleType = special.delegateType || type; @@ -8738,7 +8764,7 @@ jQuery.extend( jQuery.event, { acceptData( elem ) ) { // Call a native DOM method on the target with the same name as the event. - // Don't do default actions on window, that's where global variables be (#6170) + // Don't do default actions on window, that's where global variables be (trac-6170) if ( ontype && isFunction( elem[ type ] ) && !isWindow( elem ) ) { // Don't re-trigger an onFOO event when we call its FOO() method @@ -9012,7 +9038,7 @@ var rantiCache = /([?&])_=[^&]*/, rheaders = /^(.*?):[ \t]*([^\r\n]*)$/mg, - // #7653, #8125, #8152: local protocol detection + // trac-7653, trac-8125, trac-8152: local protocol detection rlocalProtocol = /^(?:about|app|app-storage|.+-extension|file|res|widget):$/, rnoContent = /^(?:GET|HEAD)$/, rprotocol = /^\/\//, @@ -9035,7 +9061,7 @@ var */ transports = {}, - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression + // Avoid comment-prolog char sequence (trac-10098); must appease lint and evade compression allTypes = "*/".concat( "*" ), // Anchor tag for parsing the document origin @@ -9106,7 +9132,7 @@ function inspectPrefiltersOrTransports( structure, options, originalOptions, jqX // A special extend for ajax options // that takes "flat" options (not to be deep extended) -// Fixes #9887 +// Fixes trac-9887 function ajaxExtend( target, src ) { var key, deep, flatOptions = jQuery.ajaxSettings.flatOptions || {}; @@ -9517,12 +9543,12 @@ jQuery.extend( { deferred.promise( jqXHR ); // Add protocol if not provided (prefilters might expect it) - // Handle falsy url in the settings object (#10093: consistency with old signature) + // Handle falsy url in the settings object (trac-10093: consistency with old signature) // We also use the url parameter if available s.url = ( ( url || s.url || location.href ) + "" ) .replace( rprotocol, location.protocol + "//" ); - // Alias method option to type as per ticket #12004 + // Alias method option to type as per ticket trac-12004 s.type = options.method || options.type || s.method || s.type; // Extract dataTypes list @@ -9565,7 +9591,7 @@ jQuery.extend( { } // We can fire global events as of now if asked to - // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (#15118) + // Don't fire events if jQuery.event is undefined in an AMD-usage scenario (trac-15118) fireGlobals = jQuery.event && s.global; // Watch for a new set of requests @@ -9594,7 +9620,7 @@ jQuery.extend( { if ( s.data && ( s.processData || typeof s.data === "string" ) ) { cacheURL += ( rquery.test( cacheURL ) ? "&" : "?" ) + s.data; - // #9682: remove data so that it's not used in an eventual retry + // trac-9682: remove data so that it's not used in an eventual retry delete s.data; } @@ -9867,7 +9893,7 @@ jQuery._evalUrl = function( url, options, doc ) { return jQuery.ajax( { url: url, - // Make this explicit, since user can override this through ajaxSetup (#11264) + // Make this explicit, since user can override this through ajaxSetup (trac-11264) type: "GET", dataType: "script", cache: true, @@ -9976,7 +10002,7 @@ var xhrSuccessStatus = { 0: 200, // Support: IE <=9 only - // #1450: sometimes IE returns 1223 when it should be 204 + // trac-1450: sometimes IE returns 1223 when it should be 204 1223: 204 }, xhrSupported = jQuery.ajaxSettings.xhr(); @@ -10048,7 +10074,7 @@ jQuery.ajaxTransport( function( options ) { } else { complete( - // File: protocol always yields status 0; see #8605, #14207 + // File: protocol always yields status 0; see trac-8605, trac-14207 xhr.status, xhr.statusText ); @@ -10109,7 +10135,7 @@ jQuery.ajaxTransport( function( options ) { xhr.send( options.hasContent && options.data || null ); } catch ( e ) { - // #14683: Only rethrow if this hasn't been notified as an error yet + // trac-14683: Only rethrow if this hasn't been notified as an error yet if ( callback ) { throw e; } @@ -10753,7 +10779,9 @@ jQuery.each( // Support: Android <=4.0 only // Make sure we trim BOM and NBSP -var rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; +// Require that the "whitespace run" starts from a non-whitespace +// to avoid O(N^2) behavior when the engine would try matching "\s+$" at each space position. +var rtrim = /^[\s\uFEFF\xA0]+|([^\s\uFEFF\xA0])[\s\uFEFF\xA0]+$/g; // Bind a function to a context, optionally partially applying any // arguments. @@ -10820,7 +10848,7 @@ jQuery.isNumeric = function( obj ) { jQuery.trim = function( text ) { return text == null ? "" : - ( text + "" ).replace( rtrim, "" ); + ( text + "" ).replace( rtrim, "$1" ); }; @@ -10868,8 +10896,8 @@ jQuery.noConflict = function( deep ) { }; // Expose jQuery and $ identifiers, even in AMD -// (#7102#comment:10, https://github.com/jquery/jquery/pull/557) -// and CommonJS for browser emulators (#13566) +// (trac-7102#comment:10, https://github.com/jquery/jquery/pull/557) +// and CommonJS for browser emulators (trac-13566) if ( typeof noGlobal === "undefined" ) { window.jQuery = window.$ = jQuery; } diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.1.min.js b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.1.min.js new file mode 100644 index 00000000000..2c69bc908b1 --- /dev/null +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/formats/html/resources/script-dir/jquery-3.6.1.min.js @@ -0,0 +1,2 @@ +/*! jQuery v3.6.1 | (c) OpenJS Foundation and other contributors | jquery.org/license */ +!function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,y=n.hasOwnProperty,a=y.toString,l=a.call(Object),v={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType&&"function"!=typeof e.item},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.6.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&v(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!y||!y.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ve(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace(B,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ye(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ve(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e&&e.namespaceURI,n=e&&(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],y=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&y.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||y.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||y.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||y.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||y.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||y.push(".#.+[+~]"),e.querySelectorAll("\\\f"),y.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&y.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&y.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&y.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),y.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),y=y.length&&new RegExp(y.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),v=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},j=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&v(p,e)?-1:t==C||t.ownerDocument==p&&v(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!y||!y.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function j(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||D,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,D=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),v.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",v.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",v.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ye(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ve(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function je(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function De(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function qe(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Le(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),v.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(v.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):c.css(f)}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return B(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=_e(v.pixelPosition,function(e,t){if(t)return t=Be(e,n),Pe.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return B(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0 """, """ - + """, """ """, @@ -695,7 +695,7 @@ void checkInvalidUsageIndexTag() { void checkJqueryAndImageFiles(boolean expectedOutput) { checkFiles(expectedOutput, "search.js", - "script-dir/jquery-3.6.0.min.js", + "script-dir/jquery-3.6.1.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", "resources/x.png", diff --git a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java index 75c9ce61db9..787f8a93d8c 100644 --- a/test/langtools/jdk/javadoc/tool/api/basic/APITest.java +++ b/test/langtools/jdk/javadoc/tool/api/basic/APITest.java @@ -201,7 +201,7 @@ protected void error(String msg) { "help-doc.html", "index-all.html", "index.html", - "script-dir/jquery-3.6.0.min.js", + "script-dir/jquery-3.6.1.min.js", "script-dir/jquery-ui.min.js", "script-dir/jquery-ui.min.css", "search.html", From 601264d97d5cb1a8feb4aebadcb58bf2364916b4 Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 5 Dec 2022 17:54:15 +0000 Subject: [PATCH 051/494] 8273357: SecurityManager deprecation warning from java/awt/regtesthelpers/Util.java Reviewed-by: kizune, aivanov --- test/jdk/java/awt/regtesthelpers/Util.java | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/java/awt/regtesthelpers/Util.java b/test/jdk/java/awt/regtesthelpers/Util.java index d0ec8bcc5c9..8ea239b2036 100644 --- a/test/jdk/java/awt/regtesthelpers/Util.java +++ b/test/jdk/java/awt/regtesthelpers/Util.java @@ -450,6 +450,7 @@ public static int getWMID() { Method m_addExports = Class.forName("java.awt.Helper").getDeclaredMethod("addExports", String.class, java.lang.Module.class); // We may be called from non-X11 system, and this permission cannot be delegated to a test. m_addExports.invoke(null, "sun.awt.X11", Util.class.getModule()); + @SuppressWarnings("removal") Method m_getWMID = (Method)AccessController.doPrivileged(new PrivilegedAction() { public Object run() { try { From 7d20a60a983e459ea1c4e843fbde70fb796c6249 Mon Sep 17 00:00:00 2001 From: "ravi.ra.gupta" Date: Mon, 5 Dec 2022 18:41:42 +0000 Subject: [PATCH 052/494] 8297489: Modify TextAreaTextEventTest.java as to verify the content change of TextComponent sends TextEvent Reviewed-by: honkar, aivanov --- .../ComponentEvent/TextAreaTextEventTest.java | 141 --------------- .../TextComponentTextEventTest.java | 161 ++++++++++++++++++ 2 files changed, 161 insertions(+), 141 deletions(-) delete mode 100644 test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java create mode 100644 test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java diff --git a/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java b/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java deleted file mode 100644 index 1825244d0b0..00000000000 --- a/test/jdk/java/awt/event/ComponentEvent/TextAreaTextEventTest.java +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2007, 2022, 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. - */ - -import java.awt.Dimension; -import java.awt.EventQueue; -import java.awt.FlowLayout; -import java.awt.Frame; -import java.awt.Point; -import java.awt.Robot; -import java.awt.TextArea; -import java.awt.event.InputEvent; -import java.awt.event.KeyEvent; - -/* - * @test - * @key headful - * @bug 8296632 - * @summary Verify the content changes of a TextArea via TextListener. - * @run main TextAreaTextEventTest - */ -public class TextAreaTextEventTest { - - private static Frame frame; - private volatile static TextArea textArea; - private volatile static boolean textChanged = false; - private volatile static Point textAreaAt; - private volatile static Dimension textAreaSize; - private static Robot robot = null; - - public static void main(String[] args) throws Exception { - try { - EventQueue.invokeAndWait(TextAreaTextEventTest::initializeGUI); - - robot = new Robot(); - robot.setAutoDelay(100); - - robot.waitForIdle(); - EventQueue.invokeAndWait(() -> { - textAreaAt = textArea.getLocationOnScreen(); - textAreaSize = textArea.getSize(); - }); - robot.mouseMove(textAreaAt.x + textAreaSize.width / 2, - textAreaAt.y + textAreaSize.height / 2); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - typeKey(KeyEvent.VK_T); - - robot.waitForIdle(); - if (!textChanged) { - throw new RuntimeException( - "FAIL: TextEvent not triggered when key 'T' typed on TextArea"); - } - - typeKey(KeyEvent.VK_E); - typeKey(KeyEvent.VK_S); - typeKey(KeyEvent.VK_T); - - textChanged = false; - typeKey(KeyEvent.VK_ENTER); - - robot.waitForIdle(); - if (!textChanged) { - throw new RuntimeException( - "FAIL: TextEvent not triggered when Enter pressed on TextArea"); - } - - textChanged = false; - robot.mouseMove(textAreaAt.x + 4, textAreaAt.y + 10); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); - for (int i = 0; i < textAreaSize.width / 2; i++) { - robot.mouseMove(textAreaAt.x + 4 + i, textAreaAt.y + 10); - } - robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); - - robot.waitForIdle(); - if (textChanged) { - throw new RuntimeException( - "FAIL: TextEvent triggered when text is selected on TextArea!"); - } - - textChanged = false; - typeKey(KeyEvent.VK_F3); - - robot.waitForIdle(); - if (textChanged) { - throw new RuntimeException( - "FAIL: TextEvent triggered when special key F3 is pressed on TextArea!"); - } - System.out.println("Test passed!"); - } finally { - EventQueue.invokeAndWait(TextAreaTextEventTest::disposeFrame); - } - } - - private static void initializeGUI() { - frame = new Frame("Test Frame"); - frame.setLayout(new FlowLayout()); - textArea = new TextArea(5, 15); - textArea.addTextListener((event) -> { - System.out.println("Got a text event: " + event); - textChanged = true; - }); - frame.add(textArea); - frame.pack(); - frame.setLocationRelativeTo(null); - frame.setVisible(true); - } - - public static void disposeFrame() { - if (frame != null) { - frame.dispose(); - } - } - - private static void typeKey(int key) throws Exception { - robot.keyPress(key); - robot.keyRelease(key); - } -} diff --git a/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java b/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java new file mode 100644 index 00000000000..8ffd151fde2 --- /dev/null +++ b/test/jdk/java/awt/event/ComponentEvent/TextComponentTextEventTest.java @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2007, 2022, 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. + */ + +import java.awt.Dimension; +import java.awt.EventQueue; +import java.awt.FlowLayout; +import java.awt.Frame; +import java.awt.Point; +import java.awt.Robot; +import java.awt.TextArea; +import java.awt.TextComponent; +import java.awt.TextField; +import java.awt.event.InputEvent; +import java.awt.event.KeyEvent; + +/* + * @test + * @key headful + * @bug 8297489 8296632 + * @summary Verify the content changes of a TextComponent via TextListener. + * @run main TextComponentTextEventTest + */ +public class TextComponentTextEventTest { + + private static Frame frame; + private static Robot robot = null; + private volatile static TextComponent[] components; + private volatile static boolean textChanged = false; + private volatile static Point textCompAt; + private volatile static Dimension textCompSize; + + private static void initializeGUI() { + TextField textField = new TextField(20); + textField.addTextListener((event) -> { + textChanged = true; + System.out.println("TextField got a text event: " + event); + }); + + TextArea textArea = new TextArea(5, 15); + textArea.addTextListener((event) -> { + System.out.println("TextArea got a text event: " + event); + textChanged = true; + }); + + components = new TextComponent[] { textField, textArea }; + + frame = new Frame("Test Frame"); + frame.setLayout(new FlowLayout()); + for (TextComponent textComp : components) { + frame.add(textComp); + } + frame.pack(); + frame.setLocationRelativeTo(null); + frame.setVisible(true); + } + + public static void main(String[] args) throws Exception { + try { + EventQueue.invokeAndWait(TextComponentTextEventTest::initializeGUI); + robot = new Robot(); + robot.setAutoDelay(100); + robot.setAutoWaitForIdle(true); + + for (TextComponent textComp : components) { + robot.waitForIdle(); + EventQueue.invokeAndWait(() -> { + textCompAt = textComp.getLocationOnScreen(); + textCompSize = textComp.getSize(); + }); + + robot.mouseMove(textCompAt.x + textCompSize.width / 2, + textCompAt.y + textCompSize.height / 2); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + typeKey(KeyEvent.VK_T); + + robot.waitForIdle(); + if (!textChanged) { + throw new RuntimeException( + "FAIL: TextEvent not triggered when text entered in " + textComp); + } + + typeKey(KeyEvent.VK_E); + typeKey(KeyEvent.VK_S); + typeKey(KeyEvent.VK_T); + + textChanged = false; + typeKey(KeyEvent.VK_ENTER); + + robot.waitForIdle(); + if (textComp instanceof TextField && textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when Enter pressed on " + textComp); + } else if (textComp instanceof TextArea && !textChanged) { + throw new RuntimeException( + "FAIL: TextEvent not triggered when Enter pressed on " + textComp); + } + + textChanged = false; + robot.mouseMove(textCompAt.x + 4, textCompAt.y + 10); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + robot.mousePress(InputEvent.BUTTON1_DOWN_MASK); + for (int i = 0; i < textCompSize.width / 2; i++) { + robot.mouseMove(textCompAt.x + 4 + i, textCompAt.y + 10); + } + robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK); + + robot.waitForIdle(); + if (textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when selection made in " + textComp); + } + + textChanged = false; + typeKey(KeyEvent.VK_F3); + + robot.waitForIdle(); + if (textChanged) { + throw new RuntimeException( + "FAIL: TextEvent triggered when F3 pressed on " + textComp); + } + } + System.out.println("Test passed!"); + } finally { + EventQueue.invokeAndWait(TextComponentTextEventTest::disposeFrame); + } + } + + public static void disposeFrame() { + if (frame != null) { + frame.dispose(); + } + } + + private static void typeKey(int key) { + robot.keyPress(key); + robot.keyRelease(key); + } +} From 9827b75c451100d2d5f3e068a8758468fd9189e0 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Mon, 5 Dec 2022 20:40:35 +0000 Subject: [PATCH 053/494] 8298043: jdk/jfr/api/consumer/recordingstream/TestStop.java failed with "Expected outer stream to have 3 events" Reviewed-by: mgronlun --- .../internal/consumer/EventDirectoryStream.java | 15 +++++++++------ .../jfr/internal/management/StreamBarrier.java | 4 ++++ test/jdk/ProblemList.txt | 1 - .../api/consumer/recordingstream/TestStop.java | 2 +- test/jdk/jdk/jfr/jmx/streaming/TestStop.java | 2 +- 5 files changed, 15 insertions(+), 9 deletions(-) diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java index bc0d31191af..f0ed752cefd 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/EventDirectoryStream.java @@ -166,18 +166,21 @@ protected void processRecursionSafe() throws IOException { processUnordered(disp); } currentParser.resetCache(); - barrier.check(); // block if recording is being stopped long endNanos = currentParser.getStartNanos() + currentParser.getChunkDuration(); // same conversion as in RecordingInfo - long endMillis = Instant.ofEpochSecond(0, endNanos).toEpochMilli(); - if (barrier.getStreamEnd() <= endMillis) { - return; - } if (endNanos > filterEnd) { return; } } - if (isLastChunk()) { + long endNanos = currentParser.getStartNanos() + currentParser.getChunkDuration(); + long endMillis = Instant.ofEpochSecond(0, endNanos).toEpochMilli(); + + barrier.check(); // block if recording is being stopped + if (barrier.getStreamEnd() <= endMillis) { + return; + } + + if (!barrier.hasStreamEnd() && isLastChunk()) { // Recording was stopped/closed externally, and no more data to process. return; } diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamBarrier.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamBarrier.java index 97715923018..ed94a908d47 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamBarrier.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/management/StreamBarrier.java @@ -62,6 +62,10 @@ public synchronized long getStreamEnd() { return end; } + public synchronized boolean hasStreamEnd() { + return end != Long.MAX_VALUE; + } + public synchronized void activate() { activated = true; } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 4fa18293238..f61e2d5d516 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -749,7 +749,6 @@ jdk/jfr/startupargs/TestStartDuration.java 8214685 windows- jdk/jfr/jvm/TestWaste.java 8282427 generic-all jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 jdk/jfr/api/consumer/TestRecordingFileWrite.java 8287699 generic-all -jdk/jfr/api/consumer/recordingstream/TestStop.java 8298043 generic-all ############################################################################ diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java index 44e2b59680a..5cabd9e6884 100644 --- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestStop.java @@ -149,7 +149,7 @@ private static void testNestedStop() throws Exception { if (dumpOuter.size() != 3) { throw new AssertionError("Expected outer dump to have 3 events"); } - if (outerCount.get() == 3) { + if (outerCount.get() != 3) { throw new AssertionError("Expected outer stream to have 3 events"); } if (dumpInner.size() != 1) { diff --git a/test/jdk/jdk/jfr/jmx/streaming/TestStop.java b/test/jdk/jdk/jfr/jmx/streaming/TestStop.java index b6825ec1626..83656cba8a7 100644 --- a/test/jdk/jdk/jfr/jmx/streaming/TestStop.java +++ b/test/jdk/jdk/jfr/jmx/streaming/TestStop.java @@ -158,7 +158,7 @@ private static void testNestedStop() throws Exception { if (dumpOuter.size() != 3) { throw new AssertionError("Expected outer dump to have 3 events"); } - if (outerCount.get() == 3) { + if (outerCount.get() != 3) { throw new AssertionError("Expected outer stream to have 3 events"); } if (dumpInner.size() != 1) { From da0917a2ae148ccb415accffbe1117a3dc5fdf2d Mon Sep 17 00:00:00 2001 From: Jorn Vernee Date: Mon, 5 Dec 2022 20:47:06 +0000 Subject: [PATCH 054/494] 8297729: Replace GrowableArray in ComputeMoveOrder with hash table Reviewed-by: coleenp, jsjolen --- src/hotspot/share/prims/foreignGlobals.cpp | 94 +++++++++++++--------- src/hotspot/share/prims/foreignGlobals.hpp | 1 - 2 files changed, 54 insertions(+), 41 deletions(-) diff --git a/src/hotspot/share/prims/foreignGlobals.cpp b/src/hotspot/share/prims/foreignGlobals.cpp index 2c8fdae969b..266d3b9e017 100644 --- a/src/hotspot/share/prims/foreignGlobals.cpp +++ b/src/hotspot/share/prims/foreignGlobals.cpp @@ -27,6 +27,7 @@ #include "memory/resourceArea.hpp" #include "prims/foreignGlobals.inline.hpp" #include "runtime/jniHandles.inline.hpp" +#include "utilities/resourceHash.hpp" StubLocations::StubLocations() { for (uint32_t i = 0; i < LOCATION_LIMIT; i++) { @@ -116,11 +117,10 @@ void ArgumentShuffle::print_on(outputStream* os) const { os->print_cr("Argument shuffle {"); for (int i = 0; i < _moves.length(); i++) { Move move = _moves.at(i); - BasicType arg_bt = move.bt; VMStorage from_reg = move.from; VMStorage to_reg = move.to; - os->print("Move a %s from ", null_safe_string(type2name(arg_bt))); + os->print("Move from "); from_reg.print_on(os); os->print(" to "); to_reg.print_on(os); @@ -182,44 +182,58 @@ int JavaCallingConvention::calling_convention(const BasicType* sig_bt, VMStorage } class ComputeMoveOrder: public StackObj { + class MoveOperation; + + // segment_mask_or_size is not taken into account since + // VMStorages that differ only in mask or size can still + // conflict + static inline unsigned hash(const VMStorage& vms) { + return static_cast(vms.type()) ^ vms.index_or_offset(); + } + static inline bool equals(const VMStorage& a, const VMStorage& b) { + return a.type() == b.type() && a.index_or_offset() == b.index_or_offset(); + } + + using KillerTable = ResourceHashtable< + VMStorage, MoveOperation*, + 32, // doesn't need to be big. don't have that many argument registers (in known ABIs) + AnyObj::RESOURCE_AREA, + mtInternal, + ComputeMoveOrder::hash, + ComputeMoveOrder::equals + >; + class MoveOperation: public ResourceObj { friend class ComputeMoveOrder; private: - VMStorage _src; - VMStorage _dst; - bool _processed; + VMStorage _src; + VMStorage _dst; + bool _processed; MoveOperation* _next; MoveOperation* _prev; - BasicType _bt; - - static int get_id(VMStorage r) { - assert((r.index_or_offset() & 0xFF000000) == 0, "index or offset too large"); - // assuming mask and size doesn't matter for now - return ((int) r.type()) | (r.index_or_offset() << 8); - } public: - MoveOperation(VMStorage src, VMStorage dst, BasicType bt): - _src(src), _dst(dst), _processed(false), _next(NULL), _prev(NULL), _bt(bt) {} + MoveOperation(VMStorage src, VMStorage dst): + _src(src), _dst(dst), _processed(false), _next(nullptr), _prev(nullptr) {} - int src_id() const { return get_id(_src); } - int dst_id() const { return get_id(_dst); } - MoveOperation* next() const { return _next; } - MoveOperation* prev() const { return _prev; } - void set_processed() { _processed = true; } - bool is_processed() const { return _processed; } + const VMStorage& src() const { return _src; } + const VMStorage& dst() const { return _dst; } + MoveOperation* next() const { return _next; } + MoveOperation* prev() const { return _prev; } + void set_processed() { _processed = true; } + bool is_processed() const { return _processed; } // insert void break_cycle(VMStorage temp_register) { // create a new store following the last store // to move from the temp_register to the original - MoveOperation* new_store = new MoveOperation(temp_register, _dst, _bt); + MoveOperation* new_store = new MoveOperation(temp_register, _dst); // break the cycle of links and insert new_store at the end // break the reverse link. MoveOperation* p = prev(); assert(p->next() == this, "must be"); - _prev = NULL; + _prev = nullptr; p->_next = new_store; new_store->_prev = p; @@ -227,18 +241,19 @@ class ComputeMoveOrder: public StackObj { _dst = temp_register; } - void link(GrowableArray& killer) { + void link(KillerTable& killer) { // link this store in front the store that it depends on - MoveOperation* n = killer.at_grow(src_id(), NULL); - if (n != NULL) { - assert(_next == NULL && n->_prev == NULL, "shouldn't have been set yet"); - _next = n; - n->_prev = this; + MoveOperation** n = killer.get(_src); + if (n != nullptr) { + MoveOperation* src_killer = *n; + assert(_next == nullptr && src_killer->_prev == nullptr, "shouldn't have been set yet"); + _next = src_killer; + src_killer->_prev = this; } } Move as_move() { - return {_bt, _src, _dst}; + return {_src, _dst}; } }; @@ -280,11 +295,11 @@ class ComputeMoveOrder: public StackObj { VMStorage in_reg = _in_regs[in_idx]; VMStorage out_reg = _out_regs[out_idx]; - if (out_reg.is_stack()) { + if (out_reg.is_stack() || out_reg.is_frame_data()) { // Move operations where the dest is the stack can all be // scheduled first since they can't interfere with the other moves. // The input and output stack spaces are distinct from each other. - Move move{bt, in_reg, out_reg}; + Move move{in_reg, out_reg}; _moves.push(move); } else if (in_reg == out_reg || bt == T_VOID) { @@ -294,7 +309,7 @@ class ComputeMoveOrder: public StackObj { // Don't need to do anything. continue; } else { - _edges.append(new MoveOperation(in_reg, out_reg, bt)); + _edges.append(new MoveOperation(in_reg, out_reg)); } } // Break any cycles in the register moves and emit the in the @@ -305,16 +320,15 @@ class ComputeMoveOrder: public StackObj { // Walk the edges breaking cycles between moves. The result list // can be walked in order to produce the proper set of loads void compute_store_order(VMStorage temp_register) { - // Record which moves kill which values - // FIXME should be a map - GrowableArray killer; // essentially a map of register id -> MoveOperation* + // Record which moves kill which registers + KillerTable killer; // a map of VMStorage -> MoveOperation* for (int i = 0; i < _edges.length(); i++) { MoveOperation* s = _edges.at(i); - assert(killer.at_grow(s->dst_id(), NULL) == NULL, + assert(!killer.contains(s->dst()), "multiple moves with the same register as destination"); - killer.at_put_grow(s->dst_id(), s, NULL); + killer.put(s->dst(), s); } - assert(killer.at_grow(MoveOperation::get_id(temp_register), NULL) == NULL, + assert(!killer.contains(temp_register), "make sure temp isn't in the registers that are killed"); // create links between loads and stores @@ -332,14 +346,14 @@ class ComputeMoveOrder: public StackObj { if (!s->is_processed()) { MoveOperation* start = s; // search for the beginning of the chain or cycle - while (start->prev() != NULL && start->prev() != s) { + while (start->prev() != nullptr && start->prev() != s) { start = start->prev(); } if (start->prev() == s) { start->break_cycle(temp_register); } // walk the chain forward inserting to store list - while (start != NULL) { + while (start != nullptr) { _moves.push(start->as_move()); start->set_processed(); diff --git a/src/hotspot/share/prims/foreignGlobals.hpp b/src/hotspot/share/prims/foreignGlobals.hpp index fee60f30643..d0160f23226 100644 --- a/src/hotspot/share/prims/foreignGlobals.hpp +++ b/src/hotspot/share/prims/foreignGlobals.hpp @@ -116,7 +116,6 @@ class RegSpiller { }; struct Move { - BasicType bt; VMStorage from; VMStorage to; }; From 8af6e8a67fc0355f11c270c3ea794366741856fa Mon Sep 17 00:00:00 2001 From: Phil Race Date: Mon, 5 Dec 2022 21:26:44 +0000 Subject: [PATCH 055/494] 8298123: Problem List MaximizedToIconified.java on macOS Reviewed-by: dcubed --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index f61e2d5d516..7532f3550d7 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -119,6 +119,7 @@ java/awt/Focus/FocusOwnerFrameOnClick/FocusOwnerFrameOnClick.java 8081489 generi java/awt/Focus/IconifiedFrameFocusChangeTest/IconifiedFrameFocusChangeTest.java 6849364 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusToFrontTest.java 6848406 generic-all java/awt/Focus/AutoRequestFocusTest/AutoRequestFocusSetVisibleTest.java 6848407 generic-all +java/awt/Frame/MaximizedToIconified/MaximizedToIconified.java 8296972 macosx-all java/awt/Frame/MaximizedUndecorated/MaximizedUndecorated.java 8022302 generic-all java/awt/Frame/RestoreToOppositeScreen/RestoreToOppositeScreen.java 8286840 linux-all java/awt/FileDialog/FileDialogIconTest/FileDialogIconTest.java 8160558 windows-all From 884b9ade41c9803076f55f44cd5efd3530e92ab2 Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 6 Dec 2022 00:13:22 +0000 Subject: [PATCH 056/494] 8293453: tools/jpackage/share/AddLShortcutTest.java "Failed: Check the number of mismatched pixels [1024] of [1024] is < [0.100000] threshold" Reviewed-by: almatvee --- .../internal/ExecutableRebrander.java | 24 +++++++++++++---- .../resources/WinResources.properties | 1 + .../resources/WinResources_de.properties | 1 + .../resources/WinResources_ja.properties | 1 + .../resources/WinResources_zh_CN.properties | 1 + .../jpackage/test/LauncherIconVerifier.java | 26 ++++++++++++++----- 6 files changed, 43 insertions(+), 11 deletions(-) diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java index 2a2bf2d86b9..cc7d7b019f5 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/ExecutableRebrander.java @@ -98,7 +98,7 @@ private void rebrandExecutable(Map params, Path icon, createSubstituteData( params), target); if (icon != null) { - iconSwap(resourceLock, icon.toString()); + iconSwapWrapper(resourceLock, icon.toString()); } }); } @@ -208,10 +208,8 @@ private void rebrandProperties(long resourceLock, OverridableResource properties }); } - if (versionSwap(resourceLock, propList.toArray(String[]::new)) != 0) { - throw new RuntimeException(MessageFormat.format( - I18N.getString("error.version-swap"), target)); - } + versionSwapWrapper(resourceLock, propList.toArray(String[]::new), + target.toString()); } private static void validateValueAndPut( @@ -228,6 +226,22 @@ private static void validateValueAndPut( data.put(key, value); } + private static void iconSwapWrapper(long resourceLock, + String iconTarget) { + if (iconSwap(resourceLock, iconTarget) != 0) { + throw new RuntimeException(MessageFormat.format(I18N.getString( + "error.icon-swap"), iconTarget)); + } + } + + private static void versionSwapWrapper(long resourceLock, + String[] executableProperties, String target) { + if (versionSwap(resourceLock, executableProperties) != 0) { + throw new RuntimeException(MessageFormat.format(I18N.getString( + "error.version-swap"), target)); + } + } + private List extraActions; static { diff --git a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties index ab507ec4262..5d2a6d97541 100644 --- a/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties +++ b/src/jdk.jpackage/windows/classes/jdk/jpackage/internal/resources/WinResources.properties @@ -50,6 +50,7 @@ error.msi-product-version-major-out-of-range=Major version must be in the range error.msi-product-version-build-out-of-range=Build part of version must be in the range [0, 65535] error.msi-product-version-minor-out-of-range=Minor version must be in the range [0, 255] error.version-swap=Failed to update version information for {0} +error.icon-swap=Failed to update icon for {0} error.invalid-envvar=Invalid value of {0} environment variable error.lock-resource=Failed to lock: {0} error.read-wix-l10n-file=Failed to parse {0} file 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 92458db1506..acce36d1024 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 @@ -48,6 +48,7 @@ error.msi-product-version-major-out-of-range=Hauptversion muss im Bereich [0, 25 error.msi-product-version-build-out-of-range=Build-Teil der Version muss im Bereich [0, 65535] liegen error.msi-product-version-minor-out-of-range=Nebenversion muss im Bereich [0, 255] liegen error.version-swap=Versionsinformationen f\u00FCr {0} konnten nicht aktualisiert werden +error.icon-swap=Failed to update icon for {0} error.invalid-envvar=Ung\u00FCltiger Wert der {0}-Umgebungsvariable error.lock-resource=Sperren nicht erfolgreich: {0} error.read-wix-l10n-file=Datei {0} konnte nicht geparst werden 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 a9a31140537..6f6de6a987d 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 @@ -49,6 +49,7 @@ error.msi-product-version-major-out-of-range=\u30E1\u30B8\u30E3\u30FC\u30FB\u30D error.msi-product-version-build-out-of-range=\u30D0\u30FC\u30B8\u30E7\u30F3\u306E\u30D3\u30EB\u30C9\u90E8\u5206\u306F\u7BC4\u56F2[0, 65535]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 error.msi-product-version-minor-out-of-range=\u30DE\u30A4\u30CA\u30FC\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u306F\u7BC4\u56F2[0, 255]\u5185\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 error.version-swap={0}\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u306E\u66F4\u65B0\u306B\u5931\u6557\u3057\u307E\u3057\u305F +error.icon-swap=Failed to update icon for {0} error.invalid-envvar={0}\u74B0\u5883\u5909\u6570\u306E\u5024\u304C\u7121\u52B9\u3067\u3059 error.lock-resource=\u30ED\u30C3\u30AF\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {0} error.read-wix-l10n-file={0}\u30D5\u30A1\u30A4\u30EB\u306E\u89E3\u6790\u306B\u5931\u6557\u3057\u307E\u3057\u305F 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 45d75524041..04005a39167 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 @@ -49,6 +49,7 @@ error.msi-product-version-major-out-of-range=\u4E3B\u7248\u672C\u5FC5\u987B\u4F4 error.msi-product-version-build-out-of-range=\u7248\u672C\u7684\u5DE5\u4F5C\u7248\u672C\u90E8\u5206\u5FC5\u987B\u4F4D\u4E8E [0, 65535] \u8303\u56F4\u4E2D error.msi-product-version-minor-out-of-range=\u6B21\u7248\u672C\u5FC5\u987B\u4F4D\u4E8E [0, 255] \u8303\u56F4\u4E2D error.version-swap=\u65E0\u6CD5\u66F4\u65B0 {0} \u7684\u7248\u672C\u4FE1\u606F +error.icon-swap=Failed to update icon for {0} error.invalid-envvar={0} \u73AF\u5883\u53D8\u91CF\u7684\u503C\u65E0\u6548 error.lock-resource=\u65E0\u6CD5\u9501\u5B9A\uFF1A{0} error.read-wix-l10n-file=\u65E0\u6CD5\u89E3\u6790 {0} \u6587\u4EF6 diff --git a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java index c5bf16d1291..5ae7fc2a21a 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/LauncherIconVerifier.java @@ -169,9 +169,9 @@ private WinIconVerifier() { "unlockResource", long.class); unlockResource.setAccessible(true); - iconSwap = executableRebranderClass.getDeclaredMethod("iconSwap", - long.class, String.class); - iconSwap.setAccessible(true); + iconSwapWrapper = executableRebranderClass.getDeclaredMethod( + "iconSwapWrapper", long.class, String.class); + iconSwapWrapper.setAccessible(true); } catch (ClassNotFoundException | NoSuchMethodException | SecurityException ex) { throw Functional.rethrowUnchecked(ex); @@ -180,8 +180,22 @@ private WinIconVerifier() { private Path extractIconFromExecutable(Path outputDir, Path executable, String label) { + // Run .NET code to extract icon from the given executable. + // ExtractAssociatedIcon() will succeed even if the target file + // is locked (by an antivirus). It will output a default icon + // in case of error. To prevent this "fail safe" behavior we try + // lock the target file with Open() call. If the attempt + // fails ExtractAssociatedIcon() is not called and the script exits + // with the exit code that will be trapped + // inside of Executor.executeAndRepeatUntilExitCode() method that + // will keep running the script until it succeeds or the number of + // allowed attempts is exceeded. + Path extractedIcon = outputDir.resolve(label + ".bmp"); String script = String.join(";", + String.format( + "try { [System.io.File]::Open('%s', 'Open', 'Read', 'None') } catch { exit 100 }", + executable.toAbsolutePath().normalize()), "[System.Reflection.Assembly]::LoadWithPartialName('System.Drawing')", String.format( "[System.Drawing.Icon]::ExtractAssociatedIcon('%s').ToBitmap().Save('%s', [System.Drawing.Imaging.ImageFormat]::Bmp)", @@ -189,7 +203,7 @@ private Path extractIconFromExecutable(Path outputDir, Path executable, extractedIcon.toAbsolutePath().normalize())); Executor.of("powershell", "-NoLogo", "-NoProfile", "-Command", - script).execute(); + script).executeAndRepeatUntilExitCode(0, 5, 10); return extractedIcon; } @@ -230,7 +244,7 @@ private void setIcon(Path iconPath, Path launcherPath) { "Failed to lock [%s] executable", launcherPath)); } - iconSwap.invoke(null, new Object[]{lock, + iconSwapWrapper.invoke(null, new Object[]{lock, iconPath.toAbsolutePath().normalize().toString()}); } finally { if (lock != 0) { @@ -250,7 +264,7 @@ private void setIcon(Path iconPath, Path launcherPath) { private final Class executableRebranderClass; private final Method lockResource; private final Method unlockResource; - private final Method iconSwap; + private final Method iconSwapWrapper; } private String launcherName; From 8d8a28ffcbd974bb1a5389839a7e3046a232f85d Mon Sep 17 00:00:00 2001 From: Alexey Semenyuk Date: Tue, 6 Dec 2022 00:14:31 +0000 Subject: [PATCH 057/494] 8296489: tools/jpackage/windows/WinL10nTest.java fails with timeout Reviewed-by: almatvee --- test/jdk/tools/jpackage/windows/WinL10nTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/tools/jpackage/windows/WinL10nTest.java b/test/jdk/tools/jpackage/windows/WinL10nTest.java index d5e84d6f867..deb6b1a8705 100644 --- a/test/jdk/tools/jpackage/windows/WinL10nTest.java +++ b/test/jdk/tools/jpackage/windows/WinL10nTest.java @@ -48,7 +48,7 @@ * @requires (os.family == "windows") * @modules jdk.jpackage/jdk.jpackage.internal * @compile WinL10nTest.java - * @run main/othervm/timeout=360 -Xmx512m jdk.jpackage.test.Main + * @run main/othervm/timeout=1440 -Xmx512m jdk.jpackage.test.Main * --jpt-run=WinL10nTest */ From ba2d28e911f4f523334f98fd0186680acafb6f0a Mon Sep 17 00:00:00 2001 From: Jayathirth D V Date: Tue, 6 Dec 2022 03:43:28 +0000 Subject: [PATCH 058/494] 8298027: Remove SCCS id's from awt jtreg tests Reviewed-by: aivanov --- test/jdk/java/awt/font/TextLayout/TestOldHangul.java | 3 +-- test/jdk/java/awt/font/TextLayout/TestTibetan.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/test/jdk/java/awt/font/TextLayout/TestOldHangul.java b/test/jdk/java/awt/font/TextLayout/TestOldHangul.java index b52ba38557d..5327c20dba3 100644 --- a/test/jdk/java/awt/font/TextLayout/TestOldHangul.java +++ b/test/jdk/java/awt/font/TextLayout/TestOldHangul.java @@ -21,7 +21,7 @@ * */ -/* @test @(#)TestOldHangul.java +/* @test * @summary Verify Old Hangul display * @bug 6886358 * @ignore Requires a special font installed. @@ -80,4 +80,3 @@ public void actionPerformed(ActionEvent actionEvent) { frame.setVisible(true); } } - diff --git a/test/jdk/java/awt/font/TextLayout/TestTibetan.java b/test/jdk/java/awt/font/TextLayout/TestTibetan.java index bc55472a3cd..86594ddf4c1 100644 --- a/test/jdk/java/awt/font/TextLayout/TestTibetan.java +++ b/test/jdk/java/awt/font/TextLayout/TestTibetan.java @@ -21,7 +21,7 @@ * */ -/* @test @(#)TestTibetan.java +/* @test * @summary verify tibetan output * @bug 6886358 * @ignore Requires a special font installed @@ -84,4 +84,3 @@ public void actionPerformed(ActionEvent actionEvent) { frame.setVisible(true); } } - From ee9ba7456403c59a6e14d22cf9c2f53eef97ea57 Mon Sep 17 00:00:00 2001 From: Srikanth Adayapalam Date: Tue, 6 Dec 2022 04:23:40 +0000 Subject: [PATCH 059/494] 8295184: Printing messages with a RecordComponentElement does not include position Reviewed-by: vromero --- .../com/sun/tools/javac/code/Symbol.java | 26 +++--- .../com/sun/tools/javac/comp/Check.java | 10 +++ .../com/sun/tools/javac/comp/TypeEnter.java | 6 +- .../com/sun/tools/javac/tree/TreeInfo.java | 8 ++ .../RecordComponentSourcePositionTest.java | 90 +++++++++++++++++++ .../8295184/ReproducingAP.java | 63 +++++++++++++ .../recordComponent/8295184/TestWarning.java | 36 ++++++++ 7 files changed, 223 insertions(+), 16 deletions(-) create mode 100644 test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java create mode 100644 test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java create mode 100644 test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java index 4f3276b156a..3ead7b1d1db 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Symbol.java @@ -1519,14 +1519,14 @@ public RecordComponent findRecordComponentToRemove(JCVariableDecl var) { /* creates a record component if non is related to the given variable and recreates a brand new one * in other case */ - public RecordComponent createRecordComponent(RecordComponent existing, JCVariableDecl var, List annotations) { + public RecordComponent createRecordComponent(RecordComponent existing, JCVariableDecl rcDecl, VarSymbol varSym) { RecordComponent rc = null; if (existing != null) { recordComponents = List.filter(recordComponents, existing); - recordComponents = recordComponents.append(rc = new RecordComponent(var.sym, existing.originalAnnos, existing.isVarargs)); + recordComponents = recordComponents.append(rc = new RecordComponent(varSym, existing.ast, existing.isVarargs)); } else { // Didn't find the record component: create one. - recordComponents = recordComponents.append(rc = new RecordComponent(var.sym, annotations)); + recordComponents = recordComponents.append(rc = new RecordComponent(varSym, rcDecl)); } return rc; } @@ -1786,9 +1786,7 @@ public R accept(Symbol.Visitor v, P p) { public static class RecordComponent extends VarSymbol implements RecordComponentElement { public MethodSymbol accessor; public JCTree.JCMethodDecl accessorMeth; - /* the original annotations applied to the record component - */ - private final List originalAnnos; + /* if the user happens to erroneously declare two components with the same name, we need a way to differentiate * them, the code will fail anyway but we need to keep the information for better error recovery */ @@ -1796,23 +1794,25 @@ public static class RecordComponent extends VarSymbol implements RecordComponent private final boolean isVarargs; + private JCVariableDecl ast; + /** * Construct a record component, given its flags, name, type and owner. */ public RecordComponent(Name name, Type type, Symbol owner) { super(PUBLIC, name, type, owner); pos = -1; - originalAnnos = List.nil(); + ast = null; isVarargs = false; } - public RecordComponent(VarSymbol field, List annotations) { - this(field, annotations, field.type.hasTag(TypeTag.ARRAY) && ((ArrayType)field.type).isVarargs()); + public RecordComponent(VarSymbol field, JCVariableDecl ast) { + this(field, ast, field.type.hasTag(TypeTag.ARRAY) && ((ArrayType)field.type).isVarargs()); } - public RecordComponent(VarSymbol field, List annotations, boolean isVarargs) { + public RecordComponent(VarSymbol field, JCVariableDecl ast, boolean isVarargs) { super(PUBLIC, field.name, field.type, field.owner); - this.originalAnnos = annotations; + this.ast = ast; this.pos = field.pos; /* it is better to store the original information for this one, instead of relying * on the info in the type of the symbol. This is because on the presence of APs @@ -1822,7 +1822,9 @@ public RecordComponent(VarSymbol field, List annotations, boolean this.isVarargs = isVarargs; } - public List getOriginalAnnos() { return originalAnnos; } + public List getOriginalAnnos() { return this.ast == null ? List.nil() : this.ast.mods.annotations; } + + public JCVariableDecl declarationFor() { return this.ast; } public boolean isVarargs() { return isVarargs; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java index cd7827411e4..e1dbbabb8f7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Check.java @@ -3006,6 +3006,16 @@ private void validateAnnotation(JCAnnotation a, JCTree declarationTree, Symbol s Arrays.stream(getTargetNames(anno.type.tsym)).anyMatch(name -> name == names.RECORD_COMPONENT) ).collect(List.collector())); + JCVariableDecl fieldAST = (JCVariableDecl) declarationTree; + for (JCAnnotation fieldAnnot : fieldAST.mods.annotations) { + for (JCAnnotation rcAnnot : rc.declarationFor().mods.annotations) { + if (rcAnnot.pos == fieldAnnot.pos) { + rcAnnot.setType(fieldAnnot.type); + break; + } + } + } + /* At this point, we used to carry over any type annotations from the VARDEF to the record component, but * that is problematic, since we get here only when *some* annotation is applied to the SE5 (declaration) * annotation location, inadvertently failing to carry over the type annotations when the VarDef has no diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java index 27f06398064..cd767f7db3b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/TypeEnter.java @@ -996,10 +996,8 @@ protected void runPhase(Env env) { memberEnter.memberEnter(field, env); - sym.createRecordComponent(rc, field, - field.mods.annotations.isEmpty() ? - List.nil() : - new TreeCopier(make.at(field.pos)).copy(field.mods.annotations)); + JCVariableDecl rcDecl = new TreeCopier(make.at(field.pos)).copy(field); + sym.createRecordComponent(rc, rcDecl, field.sym); } enterThisAndSuper(sym, env); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java index 901724ddcab..a9d406c9584 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/tree/TreeInfo.java @@ -30,6 +30,7 @@ import com.sun.source.tree.Tree; import com.sun.source.util.TreePath; import com.sun.tools.javac.code.*; +import com.sun.tools.javac.code.Symbol.RecordComponent; import com.sun.tools.javac.comp.AttrContext; import com.sun.tools.javac.comp.Env; import com.sun.tools.javac.tree.JCTree.*; @@ -46,6 +47,7 @@ import static com.sun.tools.javac.tree.JCTree.Tag.BLOCK; import static com.sun.tools.javac.tree.JCTree.Tag.SYNCHRONIZED; +import javax.lang.model.element.ElementKind; import javax.tools.JavaFileObject; import java.util.function.Predicate; @@ -792,6 +794,12 @@ protected boolean checkMatch(JCTree that, Symbol thatSym) { result = that; return true; } + if (this.sym.getKind() == ElementKind.RECORD_COMPONENT) { + if (thatSym != null && thatSym.getKind() == ElementKind.FIELD && (thatSym.flags_field & RECORD) != 0) { + RecordComponent rc = thatSym.enclClass().getRecordComponent((VarSymbol)thatSym); + return checkMatch(rc.declarationFor(), rc); + } + } return false; } } diff --git a/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java b/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java new file mode 100644 index 00000000000..ae611e3d511 --- /dev/null +++ b/test/langtools/tools/javac/records/recordComponent/8295184/RecordComponentSourcePositionTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2022, 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 8295184 + * @summary Printing messages with a RecordComponentElement does not include position + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @compile TestWarning.java + * @compile ReproducingAP.java + * @run main RecordComponentSourcePositionTest + */ + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.List; + +import toolbox.JavacTask; +import toolbox.TestRunner; +import toolbox.ToolBox; +import toolbox.Task; + +public class RecordComponentSourcePositionTest extends TestRunner { + + ToolBox tb; + + public RecordComponentSourcePositionTest() { + super(System.err); + tb = new ToolBox(); + } + + public static void main(String[] args) throws Exception { + RecordComponentSourcePositionTest t = new RecordComponentSourcePositionTest(); + t.runTests(); + } + + @Test + public void testRecordComponentPositionInDiagnostics() throws Exception { + String code = """ + @TestWarning(includeAnnotation = true) + public record Test( + @TestWarning(includeAnnotation = true) int first, + @TestWarning int second) { + } + + @TestWarning + record Test2() {} + """; + + Path curPath = Path.of("."); + + List output = new JavacTask(tb) + .sources(code) + .outdir(curPath) + .options("-XDrawDiagnostics", "-processor", "ReproducingAP") + .run() + .writeAll() + .getOutputLines(Task.OutputKind.DIRECT); + + List expected = Arrays.asList( + "Test.java:1:1: compiler.warn.proc.messager: Reporting Test with an annotation", + "Test.java:3:9: compiler.warn.proc.messager: Reporting first with an annotation", + "Test.java:4:26: compiler.warn.proc.messager: Reporting second", + "Test.java:8:1: compiler.warn.proc.messager: Reporting Test2", + "4 warnings"); + tb.checkEqual(expected, output); + } +} diff --git a/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java b/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java new file mode 100644 index 00000000000..c9de1fdafd3 --- /dev/null +++ b/test/langtools/tools/javac/records/recordComponent/8295184/ReproducingAP.java @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.util.Set; + +import javax.annotation.processing.AbstractProcessor; +import javax.annotation.processing.RoundEnvironment; +import javax.annotation.processing.SupportedSourceVersion; +import javax.lang.model.SourceVersion; +import javax.lang.model.element.TypeElement; + +public class ReproducingAP extends AbstractProcessor { + + @Override + public Set getSupportedAnnotationTypes() { + return Set.of(TestWarning.class.getName()); + } + + @Override + public SourceVersion getSupportedSourceVersion() { + return SourceVersion.latest(); + } + + @Override + public boolean process(Set annotations, RoundEnvironment roundEnv) { + roundEnv.getElementsAnnotatedWith(TestWarning.class).forEach(e -> { + var annotation = e.getAnnotation(TestWarning.class); + if (annotation.includeAnnotation()) { + processingEnv.getMessager().printMessage( + javax.tools.Diagnostic.Kind.WARNING, + "Reporting " + e.getSimpleName() + " with an annotation", + e, + e.getAnnotationMirrors().get(0)); + } else { + processingEnv.getMessager().printMessage( + javax.tools.Diagnostic.Kind.WARNING, + "Reporting " + e.getSimpleName(), + e); + } + }); + return false; + } +} diff --git a/test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java b/test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java new file mode 100644 index 00000000000..942e6c1ad10 --- /dev/null +++ b/test/langtools/tools/javac/records/recordComponent/8295184/TestWarning.java @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +/** + * Direct {@link ReproducingAP} to emit a warning. + */ +@Target({ElementType.TYPE, ElementType.RECORD_COMPONENT}) +public @interface TestWarning { + /** + * {@return {@code true} to include the relevant mirror in the warning message} + */ + boolean includeAnnotation() default false; +} From 04012c4310806bb638737b577351851242950298 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Tue, 6 Dec 2022 06:30:59 +0000 Subject: [PATCH 060/494] 8298111: Cleanups after UseMallocOnly removal Reviewed-by: coleenp --- src/hotspot/share/memory/arena.hpp | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/hotspot/share/memory/arena.hpp b/src/hotspot/share/memory/arena.hpp index 35a47f953ac..b7e80baa948 100644 --- a/src/hotspot/share/memory/arena.hpp +++ b/src/hotspot/share/memory/arena.hpp @@ -101,8 +101,6 @@ class Arena : public CHeapObjBase { void* grow(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM); size_t _size_in_bytes; // Size of arena (used for native memory tracking) - debug_only(void* malloc(size_t size);) - void* internal_amalloc(size_t x, AllocFailType alloc_failmode = AllocFailStrategy::EXIT_OOM) { assert(is_aligned(x, BytesPerWord), "misaligned size"); if (pointer_delta(_max, _hwm, 1) >= x) { @@ -173,9 +171,6 @@ class Arena : public CHeapObjBase { size_t size_in_bytes() const { return _size_in_bytes; }; void set_size_in_bytes(size_t size); - static void free_malloced_objects(Chunk* chunk, char* hwm, char* max, char* hwm2) PRODUCT_RETURN; - static void free_all(char** start, char** end) PRODUCT_RETURN; - private: // Reset this Arena to empty, access will trigger grow if necessary void reset(void) { From e9754181af17f77e066eaabba5aacf6b404dabaa Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 6 Dec 2022 06:48:21 +0000 Subject: [PATCH 061/494] 8298102: Remove DirtyCardToOopClosure::_last_explicit_min_done Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/space.hpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index adeb539a073..17be87aa6ac 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -258,7 +258,6 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { // alternatively, the lowest address that // shouldn't be done again. NULL means infinity.) NOT_PRODUCT(HeapWord* _last_bottom;) - NOT_PRODUCT(HeapWord* _last_explicit_min_done;) // Get the actual top of the area on which the closure will // operate, given where the top is assumed to be (the end of the @@ -283,14 +282,12 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { _cl(cl), _sp(sp), _precision(precision), _boundary(boundary), _min_done(NULL) { NOT_PRODUCT(_last_bottom = NULL); - NOT_PRODUCT(_last_explicit_min_done = NULL); } void do_MemRegion(MemRegion mr) override; void set_min_done(HeapWord* min_done) { _min_done = min_done; - NOT_PRODUCT(_last_explicit_min_done = _min_done); } #ifndef PRODUCT void set_last_bottom(HeapWord* last_bottom) { From f5ad515db0b8f5545137c47200e81d78f89aa09c Mon Sep 17 00:00:00 2001 From: Yude Lin Date: Tue, 6 Dec 2022 07:16:27 +0000 Subject: [PATCH 062/494] 8297247: Add GarbageCollectorMXBean for Remark and Cleanup pause time in G1 Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1FullGCScope.cpp | 2 +- src/hotspot/share/gc/g1/g1FullGCScope.hpp | 2 +- .../share/gc/g1/g1MonitoringSupport.cpp | 35 ++++++++- .../share/gc/g1/g1MonitoringSupport.hpp | 30 ++++++-- src/hotspot/share/gc/g1/g1VMOperations.cpp | 2 +- src/hotspot/share/gc/g1/g1YoungCollector.cpp | 5 +- .../gc/TestMemoryMXBeansAndPoolsPresence.java | 3 +- .../jtreg/gc/g1/TestRemarkCleanupMXBean.java | 74 +++++++++++++++++++ .../TestStringDeduplicationTools.java | 4 + .../gc/testlibrary/g1/MixedGCProvoker.java | 13 +++- ...bageCollectionNotificationContentTest.java | 12 ++- .../GarbageCollectionNotificationTest.java | 12 ++- .../management/MemoryMXBean/MemoryTest.java | 14 +++- test/lib/jdk/test/lib/jfr/GCHelper.java | 1 + 14 files changed, 185 insertions(+), 24 deletions(-) create mode 100644 test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.cpp b/src/hotspot/share/gc/g1/g1FullGCScope.cpp index 70621ac3449..a453aebc2fa 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.cpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.cpp @@ -50,7 +50,7 @@ G1FullGCScope::G1FullGCScope(G1MonitoringSupport* monitoring_support, _active(), _tracer_mark(&_timer, _tracer), _soft_refs(clear_soft, _g1h->soft_ref_policy()), - _monitoring_scope(monitoring_support, true /* full_gc */, true /* all_memory_pools_affected */), + _monitoring_scope(monitoring_support), _heap_printer(_g1h), _region_compaction_threshold(do_maximal_compaction ? HeapRegion::GrainWords : diff --git a/src/hotspot/share/gc/g1/g1FullGCScope.hpp b/src/hotspot/share/gc/g1/g1FullGCScope.hpp index 80dce2535dd..3863be8358b 100644 --- a/src/hotspot/share/gc/g1/g1FullGCScope.hpp +++ b/src/hotspot/share/gc/g1/g1FullGCScope.hpp @@ -55,7 +55,7 @@ class G1FullGCScope : public StackObj { IsGCActiveMark _active; G1FullGCJFRTracerMark _tracer_mark; ClearedAllSoftRefs _soft_refs; - G1MonitoringScope _monitoring_scope; + G1FullGCMonitoringScope _monitoring_scope; G1HeapPrinterMark _heap_printer; size_t _region_compaction_threshold; diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index e8bbb062dd4..beef2738ac9 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -90,6 +90,7 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : _g1h(g1h), _incremental_memory_manager("G1 Young Generation", "end of minor GC"), _full_gc_memory_manager("G1 Old Generation", "end of major GC"), + _conc_gc_memory_manager("G1 Concurrent GC", "end of concurrent GC pause"), _eden_space_pool(NULL), _survivor_space_pool(NULL), _old_gen_pool(NULL), @@ -199,6 +200,8 @@ void G1MonitoringSupport::initialize_serviceability() { _full_gc_memory_manager.add_pool(_survivor_space_pool); _full_gc_memory_manager.add_pool(_old_gen_pool); + _conc_gc_memory_manager.add_pool(_old_gen_pool); + _incremental_memory_manager.add_pool(_eden_space_pool); _incremental_memory_manager.add_pool(_survivor_space_pool); _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); @@ -210,9 +213,10 @@ MemoryUsage G1MonitoringSupport::memory_usage() { } GrowableArray G1MonitoringSupport::memory_managers() { - GrowableArray memory_managers(2); + GrowableArray memory_managers(3); memory_managers.append(&_incremental_memory_manager); memory_managers.append(&_full_gc_memory_manager); + memory_managers.append(&_conc_gc_memory_manager); return memory_managers; } @@ -344,10 +348,13 @@ MemoryUsage G1MonitoringSupport::old_gen_memory_usage(size_t initial_size, size_ max_size); } -G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* monitoring_support, bool full_gc, bool all_memory_pools_affected) : +G1MonitoringScope::G1MonitoringScope(G1MonitoringSupport* monitoring_support, + CollectorCounters* collection_counters, + GCMemoryManager* gc_memory_manager, + bool all_memory_pools_affected) : _monitoring_support(monitoring_support), - _tcs(full_gc ? monitoring_support->_full_collection_counters : monitoring_support->_incremental_collection_counters), - _tms(full_gc ? &monitoring_support->_full_gc_memory_manager : &monitoring_support->_incremental_memory_manager, + _tcs(collection_counters), + _tms(gc_memory_manager, G1CollectedHeap::heap()->gc_cause(), all_memory_pools_affected) { } @@ -356,3 +363,23 @@ G1MonitoringScope::~G1MonitoringScope() { // Needs to be called after updating pool sizes. MemoryService::track_memory_usage(); } + +G1YoungGCMonitoringScope::G1YoungGCMonitoringScope(G1MonitoringSupport* monitoring_support, + bool all_memory_pools_affected) : + G1MonitoringScope(monitoring_support, + monitoring_support->_incremental_collection_counters, + &monitoring_support->_incremental_memory_manager, + all_memory_pools_affected) { +} + +G1FullGCMonitoringScope::G1FullGCMonitoringScope(G1MonitoringSupport* monitoring_support) : + G1MonitoringScope(monitoring_support, + monitoring_support->_full_collection_counters, + &monitoring_support->_full_gc_memory_manager) { +} + +G1ConcGCMonitoringScope::G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support) : + G1MonitoringScope(monitoring_support, + monitoring_support->_conc_collection_counters, + &monitoring_support->_conc_gc_memory_manager) { +} diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp index 0e35b54d676..024e6583144 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp @@ -121,13 +121,16 @@ class MemoryPool; class G1MonitoringSupport : public CHeapObj { friend class VMStructs; - friend class G1MonitoringScope; + friend class G1YoungGCMonitoringScope; + friend class G1FullGCMonitoringScope; + friend class G1ConcGCMonitoringScope; G1CollectedHeap* _g1h; // java.lang.management MemoryManager and MemoryPool support GCMemoryManager _incremental_memory_manager; GCMemoryManager _full_gc_memory_manager; + GCMemoryManager _conc_gc_memory_manager; MemoryPool* _eden_space_pool; MemoryPool* _survivor_space_pool; @@ -210,10 +213,6 @@ class G1MonitoringSupport : public CHeapObj { void update_eden_size(); - CollectorCounters* conc_collection_counters() { - return _conc_collection_counters; - } - // Monitoring support used by // MemoryService // jstat counters @@ -241,9 +240,26 @@ class G1MonitoringScope : public StackObj { G1MonitoringSupport* _monitoring_support; TraceCollectorStats _tcs; TraceMemoryManagerStats _tms; -public: - G1MonitoringScope(G1MonitoringSupport* monitoring_support, bool full_gc, bool all_memory_pools_affected); +protected: + G1MonitoringScope(G1MonitoringSupport* monitoring_support, + CollectorCounters* collection_counters, + GCMemoryManager* gc_memory_manager, + bool all_memory_pools_affected = true); ~G1MonitoringScope(); }; +class G1YoungGCMonitoringScope : public G1MonitoringScope { +public: + G1YoungGCMonitoringScope(G1MonitoringSupport* monitoring_support, bool all_memory_pools_affected); +}; + +class G1FullGCMonitoringScope : public G1MonitoringScope { +public: + G1FullGCMonitoringScope(G1MonitoringSupport* monitoring_support); +}; + +class G1ConcGCMonitoringScope : public G1MonitoringScope { +public: + G1ConcGCMonitoringScope(G1MonitoringSupport* monitoring_support); +}; #endif // SHARE_GC_G1_G1MONITORINGSUPPORT_HPP diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index e0e3d7e25ba..4d3d81424d7 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -172,7 +172,7 @@ void VM_G1PauseConcurrent::doit() { GCTraceTimePauseTimer timer(_message, g1h->concurrent_mark()->gc_timer_cm()); GCTraceTimeDriver t(&logger, &timer); - TraceCollectorStats tcs(g1h->monitoring_support()->conc_collection_counters()); + G1ConcGCMonitoringScope monitoring_scope(g1h->monitoring_support()); SvcGCMarker sgcm(SvcGCMarker::CONCURRENT); IsGCActiveMark x; diff --git a/src/hotspot/share/gc/g1/g1YoungCollector.cpp b/src/hotspot/share/gc/g1/g1YoungCollector.cpp index a9999b80236..88bf355dfce 100644 --- a/src/hotspot/share/gc/g1/g1YoungCollector.cpp +++ b/src/hotspot/share/gc/g1/g1YoungCollector.cpp @@ -1056,9 +1056,8 @@ void G1YoungCollector::collect() { // JFR G1YoungGCJFRTracerMark jtm(gc_timer_stw(), gc_tracer_stw(), _gc_cause); // JStat/MXBeans - G1MonitoringScope ms(monitoring_support(), - false /* full_gc */, - collector_state()->in_mixed_phase() /* all_memory_pools_affected */); + G1YoungGCMonitoringScope ms(monitoring_support(), + collector_state()->in_mixed_phase() /* all_memory_pools_affected */); // Create the heap printer before internal pause timing to have // heap information printed as last part of detailed GC log. G1HeapPrinterMark hpm(_g1h); diff --git a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java index 3fdf50be317..57704252b2f 100644 --- a/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java +++ b/test/hotspot/jtreg/gc/TestMemoryMXBeansAndPoolsPresence.java @@ -96,7 +96,8 @@ public static void main(String[] args) { switch (args[0]) { case "G1": test(new GCBeanDescription("G1 Young Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}), - new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"})); + new GCBeanDescription("G1 Old Generation", new String[] {"G1 Eden Space", "G1 Survivor Space", "G1 Old Gen"}), + new GCBeanDescription("G1 Concurrent GC", new String[] {"G1 Old Gen"})); break; case "Parallel": test(new GCBeanDescription("PS Scavenge", new String[] {"PS Eden Space", "PS Survivor Space"}), diff --git a/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java b/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java new file mode 100644 index 00000000000..9b8e3843b99 --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestRemarkCleanupMXBean.java @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2022, 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 gc.g1; + +/* + * @test TestRemarkCleanupMXBean + * @bug 8297247 + * @summary Test that Remark and Cleanup are correctly reported by + * a GarbageCollectorMXBean + * @requires vm.gc.G1 + * @library /test/lib / + * @build jdk.test.whitebox.WhiteBox + * @modules java.base/jdk.internal.misc + * java.management + * @run driver jdk.test.lib.helpers.ClassFileInstaller jdk.test.whitebox.WhiteBox + * @run main/othervm -XX:+UseG1GC -Xlog:gc + * -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI + * gc.g1.TestRemarkCleanupMXBean + */ + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.ManagementFactory; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.gc.GC; +import gc.testlibrary.g1.MixedGCProvoker; + +public class TestRemarkCleanupMXBean { + public static void main(String[] args) throws Exception { + GarbageCollectorMXBean g1ConcGCBean = null; + String expectedName = "G1 Concurrent GC"; + for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) { + if (expectedName.equals(bean.getName())) { + g1ConcGCBean = bean; + break; + } + } + if (g1ConcGCBean == null) { + throw new RuntimeException("Unable to find GC bean: " + expectedName); + } + + long before = g1ConcGCBean.getCollectionCount(); + MixedGCProvoker.provokeConcMarkCycle(); + long after = g1ConcGCBean.getCollectionCount(); + + if (after >= before + 2) { // Must report a Remark and a Cleanup + System.out.println(g1ConcGCBean.getName() + " reports a difference " + + after + " - " + before + " = " + (after - before)); + } else { + throw new RuntimeException("Remark or Cleanup not reported by " + + g1ConcGCBean.getName()); + } + } +} diff --git a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java index 728155a23c0..f0f93676251 100644 --- a/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java +++ b/test/hotspot/jtreg/gc/stringdedup/TestStringDeduplicationTools.java @@ -104,6 +104,10 @@ public void handleNotification(Notification n, Object o) { if ("end of GC cycle".equals(info.getGcAction())) { gcCount++; } + } else if (info.getGcName().startsWith("G1")) { + if ("end of minor GC".equals(info.getGcAction())) { + gcCount++; + } } else { gcCount++; } diff --git a/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java b/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java index 664ff403d97..f35deefd67b 100644 --- a/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java +++ b/test/hotspot/jtreg/gc/testlibrary/g1/MixedGCProvoker.java @@ -73,13 +73,20 @@ public static void allocateOldObjects( } /** - * Provoke at least one mixed gc by starting a marking cycle, waiting for its end and triggering two GCs. - * @param liveOldObjects The objects supposed to survive this marking cycle. + * Provoke a concurrent mark cycle, and wait for it to end. */ - public static void provokeMixedGC(List liveOldObjects) { + public static void provokeConcMarkCycle() { Helpers.waitTillCMCFinished(getWhiteBox(), 10); getWhiteBox().g1StartConcMarkCycle(); Helpers.waitTillCMCFinished(getWhiteBox(), 10); + } + + /** + * Provoke at least one mixed gc by starting a marking cycle, waiting for its end and triggering two GCs. + * @param liveOldObjects The objects supposed to survive this marking cycle. + */ + public static void provokeMixedGC(List liveOldObjects) { + provokeConcMarkCycle(); getWhiteBox().youngGC(); // the "Prepare Mixed" gc getWhiteBox().youngGC(); // the "Mixed" gc diff --git a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java index ec05aa9ed15..be8329ac48f 100644 --- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java +++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java @@ -29,7 +29,11 @@ * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false * @modules java.management/sun.management * jdk.management - * @run main/othervm -Xms64m -Xmx64m GarbageCollectionNotificationContentTest + * @library /test/lib /test/hotspot/jtreg + * @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 + * -Xms64m -Xmx64m GarbageCollectionNotificationContentTest */ import java.util.*; @@ -42,6 +46,8 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.reflect.Field; +import jdk.test.whitebox.gc.GC; +import gc.testlibrary.g1.MixedGCProvoker; public class GarbageCollectionNotificationContentTest { private static HashMap listenerInvoked @@ -100,6 +106,10 @@ public static void main(String[] args) throws Exception { for(int i = 0; i<10000000; i++) { data[i%32] = new int[8]; } + // Trigger G1's concurrent mark + if (GC.G1.isSelected()) { + MixedGCProvoker.provokeConcMarkCycle(); + } int wakeup = 0; synchronized(synchronizer) { while(count != number) { diff --git a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java index 5c42827eb4d..a9f98c56448 100644 --- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java +++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationTest.java @@ -29,7 +29,11 @@ * @requires vm.opt.ExplicitGCInvokesConcurrent == null | vm.opt.ExplicitGCInvokesConcurrent == false * @modules java.management/sun.management * jdk.management - * @run main/othervm GarbageCollectionNotificationTest + * @library /test/lib /test/hotspot/jtreg + * @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 + * GarbageCollectionNotificationTest */ import java.util.*; @@ -42,6 +46,8 @@ import java.security.AccessController; import java.security.PrivilegedAction; import java.lang.reflect.Field; +import jdk.test.whitebox.gc.GC; +import gc.testlibrary.g1.MixedGCProvoker; public class GarbageCollectionNotificationTest { private static HashMap listenerInvoked = new HashMap(); @@ -99,6 +105,10 @@ public static void main(String[] args) throws Exception { for(int i = 0; i<100000000; i++) { data[i%32] = new int[8]; } + // Trigger G1's concurrent mark + if (GC.G1.isSelected()) { + MixedGCProvoker.provokeConcMarkCycle(); + } int wakeup = 0; synchronized(synchronizer) { while(count != number) { diff --git a/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java b/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java index d07f2f93fa0..510f65d5da3 100644 --- a/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java +++ b/test/jdk/java/lang/management/MemoryMXBean/MemoryTest.java @@ -26,7 +26,7 @@ * @bug 4530538 * @summary Basic unit test of MemoryMXBean.getMemoryPools() and * MemoryMXBean.getMemoryManager(). - * @requires vm.gc != "Z" & vm.gc != "Shenandoah" + * @requires vm.gc != "Z" & vm.gc != "Shenandoah" & !vm.gc.G1 * @author Mandy Chung * * @modules jdk.management @@ -45,6 +45,18 @@ * @run main MemoryTest 2 1 */ +/* + * @test + * @bug 4530538 + * @summary Basic unit test of MemoryMXBean.getMemoryPools() and + * MemoryMXBean.getMemoryManager(). + * @requires vm.gc.G1 + * @author Mandy Chung + * + * @modules jdk.management + * @run main MemoryTest 3 3 + */ + /* * NOTE: This expected result is hardcoded in this test and this test * will be affected if the heap memory layout is changed in diff --git a/test/lib/jdk/test/lib/jfr/GCHelper.java b/test/lib/jdk/test/lib/jfr/GCHelper.java index 699c272905e..316a4767e25 100644 --- a/test/lib/jdk/test/lib/jfr/GCHelper.java +++ b/test/lib/jdk/test/lib/jfr/GCHelper.java @@ -175,6 +175,7 @@ public static List removeFirstAndLastGC(List event // old GarbageCollectionMXBeans. beanCollectorTypes.put("G1 Old Generation", false); + beanCollectorTypes.put("G1 Concurrent GC", false); beanCollectorTypes.put("PS MarkSweep", false); beanCollectorTypes.put("MarkSweepCompact", false); From 0bd04a658963c1126faa776cb8a96c23beb5e3e6 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Tue, 6 Dec 2022 07:18:44 +0000 Subject: [PATCH 063/494] 8297951: C2: Create skeleton predicates for all If nodes in loop predication Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/loopPredicate.cpp | 12 ++- ...TestMissingSkeletonPredicateForIfNode.java | 78 +++++++++++++++++++ 2 files changed, 83 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestMissingSkeletonPredicateForIfNode.java diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 98093deb903..07300c81c0c 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1337,13 +1337,11 @@ bool PhaseIdealLoop::loop_predication_impl_helper(IdealLoopTree *loop, ProjNode* upper_bound_iff->set_req(1, upper_bound_bol); if (TraceLoopPredicate) tty->print_cr("upper bound check if: %s %d ", negate ? " negated" : "", lower_bound_iff->_idx); - // Fall through into rest of the clean up code which will move - // any dependent nodes onto the upper bound test. - new_predicate_proj = upper_bound_proj; - - if (iff->is_RangeCheck()) { - new_predicate_proj = insert_initial_skeleton_predicate(iff, loop, proj, predicate_proj, upper_bound_proj, scale, offset, init, limit, stride, rng, overflow, reason); - } + // Fall through into rest of the cleanup code which will move any dependent nodes to the skeleton predicates of the + // upper bound test. We always need to create skeleton predicates in order to properly remove dead loops when later + // splitting the predicated loop into (unreachable) sub-loops (i.e. done by unrolling, peeling, pre/main/post etc.). + new_predicate_proj = insert_initial_skeleton_predicate(iff, loop, proj, predicate_proj, upper_bound_proj, scale, + offset, init, limit, stride, rng, overflow, reason); #ifndef PRODUCT if (TraceLoopOpts && !TraceLoopPredicate) { diff --git a/test/hotspot/jtreg/compiler/loopopts/TestMissingSkeletonPredicateForIfNode.java b/test/hotspot/jtreg/compiler/loopopts/TestMissingSkeletonPredicateForIfNode.java new file mode 100644 index 00000000000..debc4a3890b --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestMissingSkeletonPredicateForIfNode.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 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 8297951 + * @summary Test that crashes because we do not emit skeleton predicates for normal If nodes for which a range check + * predicate is created in loop predication. + * @requires vm.debug == true & vm.compiler2.enabled + * @run main/othervm -XX:-TieredCompilation -Xbatch -XX:-RangeCheckElimination -XX:+BailoutToInterpreterForThrows + compiler.loopopts.TestMissingSkeletonPredicateForIfNode + */ +package compiler.loopopts; + +public class TestMissingSkeletonPredicateForIfNode { + static int iFld = 2, x; + static short limit = 10; + + public static void main(String[] args) throws Exception { + for (int i = 0; i < 5000; i++) { + try { + test(i % 2 == 0, i % 3); + } catch (Exception e) { + // Expected + } + } + } + + public static void test(boolean flag, int arg) throws Exception { + int sum = 1; + int[] iArr2 = new int[4]; + RuntimeException r = new RuntimeException(); + + for (int i = 0; i < limit; i+=2) { // Pre/main/post + Unrolled once. This results in the following type for the iv phi i: [2..SHORT_MAX] + x = 5 / sum; + if (Integer.compareUnsigned(i, iArr2.length) < 0) { // (**) Loop predication creates a RC predicate for this check + // After unrolling, we have: + // + // iArr2[i] + // iArr2[i+2] + // + // The type of iArr2[i+2] is [4..SHORT_MAX+2] (we need limit to be short such that we do not have an integer overflow + // which would set the type to int). However, the type of the CastII node for the index i+2 is [0..3] because its size + // is only 4. Since the type of i+2 is outside the range of the CastII node, the CastII node is replaced by top and + // some of the data nodes and memory nodes die. We are left with a broken graph and later assert because of that. + iFld += iArr2[i]; // RangeCheck node is removed because it shares the same bool as the If (**). + sum += iFld; + } else { + // Emits an UCT with -XX:+BailoutToInterpreterForThrows and therefore the If (**) satisfies the condition of being a + // range check if with one of its blocks being an UCT. + throw r; + } + if (i > 50) { + break; + } + } + } +} From 923c746650204e36053251c19cf91b7e41e938b0 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Tue, 6 Dec 2022 07:30:52 +0000 Subject: [PATCH 064/494] 8298057: (fs) Remove PollingWatchService.POLLING_INIT_DELAY Reviewed-by: bpb, jpai --- .../share/classes/sun/nio/fs/PollingWatchService.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java index 72166700e7c..582462c36c1 100644 --- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java +++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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,9 +61,7 @@ class PollingWatchService extends AbstractWatchService { - // Wait between polling thread creation and first poll (seconds) - private static final int POLLING_INIT_DELAY = 1; - // Default time between polls (seconds) + // default polling interval in seconds private static final int DEFAULT_POLLING_INTERVAL = 2; // map of registrations @@ -252,7 +250,6 @@ void update(long lastModified, int tickCount) { * directory and queue keys when entries are added, modified, or deleted. */ private class PollingWatchKey extends AbstractWatchKey { - private final Object fileKey; // current event set @@ -311,10 +308,10 @@ void enable(Set> events, long period) { // update the events this.events = events; - // create the periodic task with initialDelay set to the specified constant + // create the periodic task to poll directories Runnable thunk = new Runnable() { public void run() { poll(); }}; this.poller = scheduledExecutor - .scheduleAtFixedRate(thunk, POLLING_INIT_DELAY, period, TimeUnit.SECONDS); + .scheduleAtFixedRate(thunk, period, period, TimeUnit.SECONDS); } } From 2a243a33cc09f4674b232d89f36fb731055009d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Tue, 6 Dec 2022 08:24:17 +0000 Subject: [PATCH 065/494] 8267617: Certificate's IP x509 NameConstraints raises ArrayIndexOutOfBoundsException Reviewed-by: mullan --- .../sun/security/x509/IPAddressName.java | 13 ++-- .../x509/IPAddressName/ConstrainsTest.java | 78 +++++++++++++++++++ 2 files changed, 86 insertions(+), 5 deletions(-) create mode 100644 test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java diff --git a/src/java.base/share/classes/sun/security/x509/IPAddressName.java b/src/java.base/share/classes/sun/security/x509/IPAddressName.java index eb08cbbb95a..0e3be16a2b3 100644 --- a/src/java.base/share/classes/sun/security/x509/IPAddressName.java +++ b/src/java.base/share/classes/sun/security/x509/IPAddressName.java @@ -401,11 +401,12 @@ else if (inputName.equals(this)) else { IPAddressName otherName = (IPAddressName)inputName; byte[] otherAddress = otherName.address; - if (otherAddress.length == 4 && address.length == 4) + if ((otherAddress.length == 4 && address.length == 4) || + (otherAddress.length == 16 && address.length == 16)) { // Two host addresses constraintType = NAME_SAME_TYPE; - else if ((otherAddress.length == 8 && address.length == 8) || - (otherAddress.length == 32 && address.length == 32)) { + } else if ((otherAddress.length == 8 && address.length == 8) || + (otherAddress.length == 32 && address.length == 32)) { // Two subnet addresses // See if one address fully encloses the other address boolean otherSubsetOfThis = true; @@ -440,7 +441,8 @@ else if (thisSubsetOfOther) constraintType = NAME_WIDENS; else constraintType = NAME_SAME_TYPE; - } else if (otherAddress.length == 8 || otherAddress.length == 32) { + } else if ((otherAddress.length == 8 && address.length == 4) || + (otherAddress.length == 32 && address.length == 16)) { //Other is a subnet, this is a host address int i = 0; int maskOffset = otherAddress.length/2; @@ -454,7 +456,8 @@ else if (thisSubsetOfOther) constraintType = NAME_WIDENS; else constraintType = NAME_SAME_TYPE; - } else if (address.length == 8 || address.length == 32) { + } else if ((otherAddress.length == 4 && address.length == 8) || + (otherAddress.length == 16 && address.length == 32)) { //This is a subnet, other is a host address int i = 0; int maskOffset = address.length/2; diff --git a/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java b/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java new file mode 100644 index 00000000000..63772eef335 --- /dev/null +++ b/test/jdk/sun/security/x509/IPAddressName/ConstrainsTest.java @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2022, 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. + */ + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import sun.security.x509.GeneralNameInterface; +import sun.security.x509.IPAddressName; + +import java.io.IOException; + +import static org.testng.Assert.assertEquals; + +/* + * @test + * @summary Verify IPAddressName.constrains + * @bug 8267617 + * @modules java.base/sun.security.x509 + * @run testng ConstrainsTest + */ +public class ConstrainsTest { + + IPAddressName ipv4Addr = new IPAddressName("127.0.0.1"); + IPAddressName ipv4Mask = new IPAddressName("127.0.0.0/255.0.0.0"); + IPAddressName ipv6Addr = new IPAddressName("::1"); + IPAddressName ipv6Mask = new IPAddressName("::/0"); + + public ConstrainsTest() throws IOException { + } + + @DataProvider(name = "names") + public Object[][] names() { + Object[][] data = { + {ipv4Addr, ipv4Addr, GeneralNameInterface.NAME_MATCH}, + {ipv4Addr, ipv4Mask, GeneralNameInterface.NAME_WIDENS}, + {ipv4Addr, ipv6Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Addr, ipv6Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Mask, ipv4Addr, GeneralNameInterface.NAME_NARROWS}, + {ipv4Mask, ipv4Mask, GeneralNameInterface.NAME_MATCH}, + {ipv4Mask, ipv6Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv4Mask, ipv6Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv4Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv4Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Addr, ipv6Addr, GeneralNameInterface.NAME_MATCH}, + {ipv6Addr, ipv6Mask, GeneralNameInterface.NAME_WIDENS}, + {ipv6Mask, ipv4Addr, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Mask, ipv4Mask, GeneralNameInterface.NAME_SAME_TYPE}, + {ipv6Mask, ipv6Addr, GeneralNameInterface.NAME_NARROWS}, + {ipv6Mask, ipv6Mask, GeneralNameInterface.NAME_MATCH}, + }; + return data; + } + + @Test(dataProvider = "names") + public void testNameContains(IPAddressName addr1, IPAddressName addr2, int result) throws IOException { + assertEquals(addr1.constrains(addr2), result); + } + +} From f8f46305ef0d1c12154075c7a7d4dc75f91529b5 Mon Sep 17 00:00:00 2001 From: Julian Waters Date: Tue, 6 Dec 2022 08:42:36 +0000 Subject: [PATCH 066/494] 8297963: Partially fix string expansion issues in UTIL_DEFUN_NAMED and related macros Reviewed-by: ihse --- make/autoconf/flags.m4 | 8 ++++---- make/autoconf/util.m4 | 45 +++++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 24 deletions(-) diff --git a/make/autoconf/flags.m4 b/make/autoconf/flags.m4 index 9b5cb4b3751..ddb2b4c8e0a 100644 --- a/make/autoconf/flags.m4 +++ b/make/autoconf/flags.m4 @@ -503,14 +503,14 @@ UTIL_DEFUN_NAMED([FLAGS_CXX_COMPILER_CHECK_ARGUMENTS], UTIL_DEFUN_NAMED([FLAGS_COMPILER_CHECK_ARGUMENTS], [*ARGUMENT IF_TRUE IF_FALSE PREFIX], [$@], [ - FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARG_ARGUMENT], + FLAGS_C_COMPILER_CHECK_ARGUMENTS(ARGUMENT: ARG_ARGUMENT, IF_TRUE: [C_COMP_SUPPORTS="yes"], IF_FALSE: [C_COMP_SUPPORTS="no"], - PREFIX: [ARG_PREFIX]) - FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: [ARG_ARGUMENT], + PREFIX: ARG_PREFIX) + FLAGS_CXX_COMPILER_CHECK_ARGUMENTS(ARGUMENT: ARG_ARGUMENT, IF_TRUE: [CXX_COMP_SUPPORTS="yes"], IF_FALSE: [CXX_COMP_SUPPORTS="no"], - PREFIX: [ARG_PREFIX]) + PREFIX: ARG_PREFIX) AC_MSG_CHECKING([if both ARG_PREFIX[CC] and ARG_PREFIX[CXX] support "ARG_ARGUMENT"]) supports=no diff --git a/make/autoconf/util.m4 b/make/autoconf/util.m4 index d2171338d00..30abe298e4b 100644 --- a/make/autoconf/util.m4 +++ b/make/autoconf/util.m4 @@ -52,7 +52,7 @@ m4_include([util_paths.m4]) AC_DEFUN([UTIL_DEFUN_NAMED], [ AC_DEFUN($1, [ - m4_foreach(arg, m4_split(m4_normalize($2)), [ + m4_foreach([arg], m4_split(m4_normalize($2)), [ m4_if(m4_bregexp(arg, [^\*]), -1, [ m4_set_add(legal_named_args, arg) @@ -64,13 +64,18 @@ AC_DEFUN([UTIL_DEFUN_NAMED], ) ]) - m4_foreach([arg], [$3], [ - m4_if(m4_bregexp(arg, [: ]), -1, m4_define([arg], m4_bpatsubst(arg, [:], [: ]))) - m4_define(arg_name, m4_substr(arg, 0, m4_bregexp(arg, [: ]))) + # Delicate quoting and unquoting sequence to ensure the actual value is passed along unchanged + # For details on how this works, see https://git.openjdk.org/jdk/pull/11458#discussion_r1038173051 + # WARNING: Proceed at the risk of your own sanity, getting this to work has made me completely + # incapable of feeling love or any other positive emotion + # ~Julian + m4_foreach([arg], m4_dquote(m4_dquote_elt($3)), [ + m4_if(m4_index(arg, [: ]), -1, [m4_define([arg], m4_dquote(m4_bpatsubst(m4_dquote(arg), [:], [: ])))]) + m4_define(arg_name, m4_substr(arg, 0, m4_index(arg, [: ]))) m4_set_contains(legal_named_args, arg_name, [],[AC_MSG_ERROR([Internal error: m4_if(arg_name, , arg, arg_name) is not a valid named argument to [$1]. Valid arguments are 'm4_set_contents(defined_args, [ ]) m4_set_contents(legal_named_args, [ ])'.])]) m4_set_remove(required_named_args, arg_name) m4_set_remove(legal_named_args, arg_name) - m4_pushdef([ARG_][]arg_name, m4_bpatsubst(m4_substr(arg, m4_incr(m4_incr(m4_bregexp(arg, [: ])))), [^\s*], [])) + m4_pushdef([ARG_][]arg_name, m4_bpatsubst(m4_bpatsubst(m4_dquote(m4_dquote(arg)), arg_name[: ]), [^\s*])) m4_set_add(defined_args, arg_name) m4_undefine([arg_name]) ]) @@ -376,18 +381,18 @@ UTIL_DEFUN_NAMED([UTIL_ARG_ENABLE], m4_define(ARG_GIVEN, m4_translit(ARG_NAME, [a-z-], [A-Z_])[_GIVEN]) # If DESC is not specified, set it to a generic description. - m4_define([ARG_DESC], m4_if(ARG_DESC, , [Enable the ARG_NAME feature], m4_normalize(ARG_DESC))) + m4_define([ARG_DESC], m4_if(m4_quote(ARG_DESC), , [[Enable the ARG_NAME feature]], [m4_normalize(ARG_DESC)])) # If CHECKING_MSG is not specified, set it to a generic description. - m4_define([ARG_CHECKING_MSG], m4_if(ARG_CHECKING_MSG, , [for --enable-ARG_NAME], m4_normalize(ARG_CHECKING_MSG))) + m4_define([ARG_CHECKING_MSG], m4_if(m4_quote(ARG_CHECKING_MSG), , [[for --enable-ARG_NAME]], [m4_normalize(ARG_CHECKING_MSG)])) # If the code blocks are not given, set them to the empty statements to avoid # tripping up bash. - m4_define([ARG_CHECK_AVAILABLE], m4_if(ARG_CHECK_AVAILABLE, , :, ARG_CHECK_AVAILABLE)) - m4_define([ARG_IF_GIVEN], m4_if(ARG_IF_GIVEN, , :, ARG_IF_GIVEN)) - m4_define([ARG_IF_NOT_GIVEN], m4_if(ARG_IF_NOT_GIVEN, , :, ARG_IF_NOT_GIVEN)) - m4_define([ARG_IF_ENABLED], m4_if(ARG_IF_ENABLED, , :, ARG_IF_ENABLED)) - m4_define([ARG_IF_DISABLED], m4_if(ARG_IF_DISABLED, , :, ARG_IF_DISABLED)) + m4_if(ARG_CHECK_AVAILABLE, , [m4_define([ARG_CHECK_AVAILABLE], [:])]) + m4_if(ARG_IF_GIVEN, , [m4_define([ARG_IF_GIVEN], [:])]) + m4_if(ARG_IF_NOT_GIVEN, , [m4_define([ARG_IF_NOT_GIVEN], [:])]) + m4_if(ARG_IF_ENABLED, , [m4_define([ARG_IF_ENABLED], [:])]) + m4_if(ARG_IF_DISABLED, , [m4_define([ARG_IF_DISABLED], [:])]) ########################## # Part 2: Set up autoconf shell code @@ -650,21 +655,21 @@ UTIL_DEFUN_NAMED([UTIL_ARG_WITH], m4_define(ARG_GIVEN, m4_translit(ARG_NAME, [a-z-], [A-Z_])[_GIVEN]) # If DESC is not specified, set it to a generic description. - m4_define([ARG_DESC], m4_if(ARG_DESC, , [Give a value for the ARG_NAME feature], m4_normalize(ARG_DESC))) + m4_define([ARG_DESC], m4_if(m4_quote(ARG_DESC), , [[Give a value for the ARG_NAME feature]], [m4_normalize(ARG_DESC)])) # If CHECKING_MSG is not specified, set it to a generic description. - m4_define([ARG_CHECKING_MSG], m4_if(ARG_CHECKING_MSG, , [for --with-ARG_NAME], m4_normalize(ARG_CHECKING_MSG))) + m4_define([ARG_CHECKING_MSG], m4_if(m4_quote(ARG_CHECKING_MSG), , [[for --with-ARG_NAME]], [m4_normalize(ARG_CHECKING_MSG)])) m4_define([ARG_HAS_AUTO_BLOCK], m4_if(ARG_IF_AUTO, , false, true)) # If the code blocks are not given, set them to the empty statements to avoid # tripping up bash. - m4_define([ARG_CHECK_AVAILABLE], m4_if(ARG_CHECK_AVAILABLE, , :, ARG_CHECK_AVAILABLE)) - m4_define([ARG_CHECK_VALUE], m4_if(ARG_CHECK_VALUE, , :, ARG_CHECK_VALUE)) - m4_define([ARG_CHECK_FOR_FILES], m4_if(ARG_CHECK_FOR_FILES, , :, ARG_CHECK_FOR_FILES)) - m4_define([ARG_IF_AUTO], m4_if(ARG_IF_AUTO, , :, ARG_IF_AUTO)) - m4_define([ARG_IF_GIVEN], m4_if(ARG_IF_GIVEN, , :, ARG_IF_GIVEN)) - m4_define([ARG_IF_NOT_GIVEN], m4_if(ARG_IF_NOT_GIVEN, , :, ARG_IF_NOT_GIVEN)) + m4_if(ARG_CHECK_AVAILABLE, , [m4_define([ARG_CHECK_AVAILABLE], [:])]) + m4_if(ARG_CHECK_VALUE, , [m4_define([ARG_CHECK_VALUE], [:])]) + m4_if(ARG_CHECK_FOR_FILES, , [m4_define([ARG_CHECK_FOR_FILES], [:])]) + m4_if(ARG_IF_AUTO, , [m4_define([ARG_IF_AUTO], [:])]) + m4_if(ARG_IF_GIVEN, , [m4_define([ARG_IF_GIVEN], [:])]) + m4_if(ARG_IF_NOT_GIVEN, , [m4_define([ARG_IF_NOT_GIVEN], [:])]) ########################## # Part 2: Set up autoconf shell code From a61399854a9db8e3c0cb3f391fa557cb37e02571 Mon Sep 17 00:00:00 2001 From: Pengfei Li Date: Tue, 6 Dec 2022 09:16:47 +0000 Subject: [PATCH 067/494] 8297689: Fix incorrect result of Short.reverseBytes() call in loops Reviewed-by: thartmann, jbhateja --- src/hotspot/share/opto/vectornode.cpp | 12 ++- src/hotspot/share/prims/vectorSupport.cpp | 9 +- .../vectorization/TestReverseBytes.java | 3 +- .../TestSubwordReverseBytes.java | 102 ++++++++++++++++++ .../vectorization/runner/BasicCharOpTest.java | 22 ++++ .../runner/BasicShortOpTest.java | 22 ++++ 6 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 5ee9b816246..85dbf9e42cf 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -169,10 +169,18 @@ int VectorNode::opcode(int sopc, BasicType bt) { case Op_ReverseL: return (is_integral_type(bt) ? Op_ReverseV : 0); case Op_ReverseBytesS: + case Op_ReverseBytesUS: + // Subword operations in superword usually don't have precise info + // about signedness. But the behavior of reverseBytes for short and + // char are exactly the same. + return ((bt == T_SHORT || bt == T_CHAR) ? Op_ReverseBytesV : 0); case Op_ReverseBytesI: + // There is no reverseBytes() in Byte class but T_BYTE may appear + // in VectorAPI calls. We still use ReverseBytesI for T_BYTE to + // ensure vector intrinsification succeeds. + return ((bt == T_INT || bt == T_BYTE) ? Op_ReverseBytesV : 0); case Op_ReverseBytesL: - case Op_ReverseBytesUS: - return (is_integral_type(bt) ? Op_ReverseBytesV : 0); + return (bt == T_LONG ? Op_ReverseBytesV : 0); case Op_CompressBits: // Not implemented. Returning 0 temporarily return 0; diff --git a/src/hotspot/share/prims/vectorSupport.cpp b/src/hotspot/share/prims/vectorSupport.cpp index 6ba1d6a282f..92d0371806c 100644 --- a/src/hotspot/share/prims/vectorSupport.cpp +++ b/src/hotspot/share/prims/vectorSupport.cpp @@ -520,8 +520,13 @@ int VectorSupport::vop2ideal(jint id, BasicType bt) { } case VECTOR_OP_REVERSE_BYTES: { switch (bt) { - case T_BYTE: - case T_SHORT: + case T_SHORT: return Op_ReverseBytesS; + // Superword requires type consistency between the ReverseBytes* + // node and the data. But there's no ReverseBytesB node because + // no reverseBytes() method in Java Byte class. T_BYTE can only + // appear in VectorAPI calls. We reuse Op_ReverseBytesI for this + // to ensure vector intrinsification succeeds. + case T_BYTE: // Intentionally fall-through case T_INT: return Op_ReverseBytesI; case T_LONG: return Op_ReverseBytesL; default: fatal("REVERSE_BYTES: %s", type2name(bt)); diff --git a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java index fec99f9e749..2d399fbd274 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestReverseBytes.java @@ -25,8 +25,7 @@ * @bug 8288112 * @summary Auto-vectorization of ReverseBytes operations. * @requires vm.compiler2.enabled - * @requires vm.cpu.features ~= ".*avx2.*" - * @requires os.simpleArch == "x64" + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | os.simpleArch == "AArch64" * @library /test/lib / * @run driver compiler.vectorization.TestReverseBytes */ diff --git a/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java b/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java new file mode 100644 index 00000000000..69e97e5c0ef --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestSubwordReverseBytes.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2022, Arm 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.vectorization; + +import compiler.lib.ir_framework.*; + +/* + * @test + * @bug 8297689 + * @summary Test miscompilation of reverseBytes call from subword types + * @library /test/lib / + * @requires vm.compiler2.enabled + * @run driver compiler.vectorization.TestSubwordReverseBytes + */ + +public class TestSubwordReverseBytes { + private static final int SIZE = 32000; + + private static int[] idx = new int[SIZE]; + private static short[] rbs = new short[SIZE]; + private static char[] rbc = new char[SIZE]; + + static { + for (int i = 0; i < SIZE; i++) { + idx[i] = i; + } + for (short s = 0; s < SIZE; s++) { + rbs[s] = Short.reverseBytes(s); + } + for (char c = 0; c < SIZE; c++) { + rbc[c] = Character.reverseBytes(c); + } + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_V}) + public static int[] testShortReverseBytes() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes((short) idx[i]); + } + return res; + } + + @Run(test = "testShortReverseBytes") + public static void testShort() { + int[] res = testShortReverseBytes(); + for (int i = 0; i < SIZE; i++) { + if (res[i] != rbs[i]) { + throw new RuntimeException("Wrong result: expected = " + + (int) rbs[i] + ", actual = " + res[i]); + } + } + } + + @Test + @IR(failOn = {IRNode.REVERSE_BYTES_V}) + public static int[] testCharacterReverseBytes() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes((char) idx[i]); + } + return res; + } + + @Run(test = "testCharacterReverseBytes") + public static void testChar() { + int[] res = testCharacterReverseBytes(); + for (int i = 0; i < SIZE; i++) { + if (res[i] != rbc[i]) { + throw new RuntimeException("Wrong result: expected = " + + (int) rbc[i] + ", actual = " + res[i]); + } + } + } + + public static void main(String[] args) { + TestFramework.run(); + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java index a894f7a93cb..ec2119eec21 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicCharOpTest.java @@ -47,15 +47,18 @@ public class BasicCharOpTest extends VectorizationTestRunner { private char[] a; private char[] b; private char[] c; + private int[] idx; public BasicCharOpTest() { a = new char[SIZE]; b = new char[SIZE]; c = new char[SIZE]; + idx = new int[SIZE]; for (int i = 0; i < SIZE; i++) { a[i] = (char) (20 * i); b[i] = (char) (i + 44444); c[i] = (char) 10000; + idx[i] = i; } } @@ -189,5 +192,24 @@ public char[] vectorUnsignedShiftRight() { } return res; } + + // ------------- ReverseBytes ------------- + @Test + public char[] reverseBytesWithChar() { + char[] res = new char[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes(a[i]); + } + return res; + } + + @Test + public int[] reverseBytesWithInt() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Character.reverseBytes((char) idx[i]); + } + return res; + } } diff --git a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java index 19011325c2e..1dd424499c1 100644 --- a/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java +++ b/test/hotspot/jtreg/compiler/vectorization/runner/BasicShortOpTest.java @@ -47,15 +47,18 @@ public class BasicShortOpTest extends VectorizationTestRunner { private short[] a; private short[] b; private short[] c; + private int[] idx; public BasicShortOpTest() { a = new short[SIZE]; b = new short[SIZE]; c = new short[SIZE]; + idx = new int[SIZE]; for (int i = 0; i < SIZE; i++) { a[i] = (short) (-12 * i); b[i] = (short) (9 * i + 8888); c[i] = (short) -32323; + idx[i] = i; } } @@ -187,5 +190,24 @@ public short[] vectorUnsignedShiftRight() { } return res; } + + // ------------- ReverseBytes ------------- + @Test + public short[] reverseBytesWithShort() { + short[] res = new short[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes(a[i]); + } + return res; + } + + @Test + public int[] reverseBytesWithInt() { + int[] res = new int[SIZE]; + for (int i = 0; i < SIZE; i++) { + res[i] = Short.reverseBytes((short) idx[i]); + } + return res; + } } From 4458de95f845c036c1c8e28df7043e989beaee98 Mon Sep 17 00:00:00 2001 From: Fei Gao Date: Tue, 6 Dec 2022 09:35:27 +0000 Subject: [PATCH 068/494] 8297172: Fix some issues of auto-vectorization of `Long.bitCount/numberOfTrailingZeros/numberOfLeadingZeros()` Reviewed-by: kvn, thartmann --- src/hotspot/cpu/aarch64/aarch64_vector.ad | 31 +------ src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 | 31 +------ src/hotspot/cpu/x86/x86.ad | 48 ---------- src/hotspot/share/opto/superword.cpp | 59 ++++++++----- src/hotspot/share/opto/superword.hpp | 1 + src/hotspot/share/opto/vectornode.cpp | 11 --- src/hotspot/share/opto/vectornode.hpp | 15 +++- .../irTests/TestDisableAutoVectOpcodes.java | 16 ++++ .../compiler/lib/ir_framework/IRNode.java | 10 +++ .../TestNumberOfContinuousZeros.java | 88 +++++++++++++++++++ .../vectorization/TestPopCountVectorLong.java | 4 +- 11 files changed, 172 insertions(+), 142 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 7868d7cf46b..0a64d35dd47 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -132,6 +132,8 @@ source %{ // Vector API intrinsics. if ((opcode == Op_VectorCastD2X && bt == T_INT) || (opcode == Op_VectorCastL2X && bt == T_FLOAT) || + (opcode == Op_CountLeadingZerosV && bt == T_LONG) || + (opcode == Op_CountTrailingZerosV && bt == T_LONG) || opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -5672,7 +5674,6 @@ instruct vpopcountI(vReg dst, vReg src) %{ // vector popcount - LONG instruct vpopcountL(vReg dst, vReg src) %{ - predicate(Matcher::vector_element_basic_type(n) == T_LONG); match(Set dst (PopCountVL src)); format %{ "vpopcountL $dst, $src" %} ins_encode %{ @@ -5688,32 +5689,6 @@ instruct vpopcountL(vReg dst, vReg src) %{ ins_pipe(pipe_slow); %} -// If the PopCountVL is generated by auto-vectorization, the dst basic -// type is T_INT. And once we have unified the type definition for -// Vector API and auto-vectorization, this rule can be merged with -// "vpopcountL" rule. - -instruct vpopcountL_I(vReg dst, vReg src, vReg tmp) %{ - predicate(Matcher::vector_element_basic_type(n) == T_INT); - match(Set dst (PopCountVL src)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "vpopcountL_I $dst, $src\t# KILL $tmp" %} - ins_encode %{ - if (UseSVE == 0) { - __ cnt($dst$$FloatRegister, __ T16B, $src$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T16B, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T8H, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T4S, $dst$$FloatRegister); - __ xtn($dst$$FloatRegister, __ T2S, $dst$$FloatRegister, __ T2D); - } else { - __ sve_cnt($dst$$FloatRegister, __ D, ptrue, $src$$FloatRegister); - __ sve_vector_narrow($dst$$FloatRegister, __ S, - $dst$$FloatRegister, __ D, $tmp$$FloatRegister); - } - %} - ins_pipe(pipe_slow); -%} - // vector popcount - predicated instruct vpopcountI_masked(vReg dst_src, pRegGov pg) %{ @@ -5729,7 +5704,7 @@ instruct vpopcountI_masked(vReg dst_src, pRegGov pg) %{ %} instruct vpopcountL_masked(vReg dst_src, pRegGov pg) %{ - predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); + predicate(UseSVE > 0); match(Set dst_src (PopCountVL dst_src pg)); format %{ "vpopcountL_masked $dst_src, $pg, $dst_src" %} ins_encode %{ diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index 118611b1675..65adf7d6ee0 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -122,6 +122,8 @@ source %{ // Vector API intrinsics. if ((opcode == Op_VectorCastD2X && bt == T_INT) || (opcode == Op_VectorCastL2X && bt == T_FLOAT) || + (opcode == Op_CountLeadingZerosV && bt == T_LONG) || + (opcode == Op_CountTrailingZerosV && bt == T_LONG) || opcode == Op_AddReductionVD || opcode == Op_AddReductionVF || opcode == Op_MulReductionVD || opcode == Op_MulReductionVF || opcode == Op_MulVL) { @@ -4055,7 +4057,6 @@ instruct vpopcountI(vReg dst, vReg src) %{ // vector popcount - LONG instruct vpopcountL(vReg dst, vReg src) %{ - predicate(Matcher::vector_element_basic_type(n) == T_LONG); match(Set dst (PopCountVL src)); format %{ "vpopcountL $dst, $src" %} ins_encode %{ @@ -4071,37 +4072,11 @@ instruct vpopcountL(vReg dst, vReg src) %{ ins_pipe(pipe_slow); %} -// If the PopCountVL is generated by auto-vectorization, the dst basic -// type is T_INT. And once we have unified the type definition for -// Vector API and auto-vectorization, this rule can be merged with -// "vpopcountL" rule. - -instruct vpopcountL_I(vReg dst, vReg src, vReg tmp) %{ - predicate(Matcher::vector_element_basic_type(n) == T_INT); - match(Set dst (PopCountVL src)); - effect(TEMP_DEF dst, TEMP tmp); - format %{ "vpopcountL_I $dst, $src\t# KILL $tmp" %} - ins_encode %{ - if (UseSVE == 0) { - __ cnt($dst$$FloatRegister, __ T16B, $src$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T16B, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T8H, $dst$$FloatRegister); - __ uaddlp($dst$$FloatRegister, __ T4S, $dst$$FloatRegister); - __ xtn($dst$$FloatRegister, __ T2S, $dst$$FloatRegister, __ T2D); - } else { - __ sve_cnt($dst$$FloatRegister, __ D, ptrue, $src$$FloatRegister); - __ sve_vector_narrow($dst$$FloatRegister, __ S, - $dst$$FloatRegister, __ D, $tmp$$FloatRegister); - } - %} - ins_pipe(pipe_slow); -%} - // vector popcount - predicated UNARY_OP_PREDICATE(vpopcountI, PopCountVI, sve_cnt) instruct vpopcountL_masked(vReg dst_src, pRegGov pg) %{ - predicate(UseSVE > 0 && Matcher::vector_element_basic_type(n) == T_LONG); + predicate(UseSVE > 0); match(Set dst_src (PopCountVL dst_src pg)); format %{ "vpopcountL_masked $dst_src, $pg, $dst_src" %} ins_encode %{ diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index a6f2adabb28..629ae77567d 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -8875,12 +8875,6 @@ instruct vpopcount_integral_reg_evex(vec dst, vec src) %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); __ vector_popcount_integral_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, k0, true, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (opcode == Op_PopCountVL && Matcher::vector_element_basic_type(this) == T_INT) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -8911,18 +8905,6 @@ instruct vpopcount_avx_reg(vec dst, vec src, vec xtmp1, vec xtmp2, rRegP rtmp) % BasicType bt = Matcher::vector_element_basic_type(this, $src); __ vector_popcount_integral(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (opcode == Op_PopCountVL && Matcher::vector_element_basic_type(this) == T_INT) { - if (VM_Version::supports_avx512vl()) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } else { - assert(VM_Version::supports_avx2(), ""); - __ vpshufd($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - } - } %} ins_pipe( pipe_slow ); %} @@ -8939,15 +8921,8 @@ instruct vcount_trailing_zeros_reg_evex(vec dst, vec src, vec xtmp, rRegP rtmp) ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_trailing_zeros_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, $xtmp$$XMMRegister, k0, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountTrailingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (bt == T_LONG && rbt == T_INT) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -8993,17 +8968,8 @@ instruct vcount_trailing_zeros_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, v ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_trailing_zeros_avx(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, PopCountVL - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (bt == T_LONG && rbt == T_INT) { - assert(VM_Version::supports_avx2(), ""); - __ vpshufd($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - __ vpermq($dst$$XMMRegister, $dst$$XMMRegister, 8, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -9408,15 +9374,8 @@ instruct vcount_leading_zeros_IL_reg_evex(vec dst, vec src) %{ ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_leading_zeros_evex(bt, $dst$$XMMRegister, $src$$XMMRegister, xnoreg, xnoreg, xnoreg, k0, noreg, true, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountLeadingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (rbt == T_INT && bt == T_LONG) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} @@ -9491,15 +9450,8 @@ instruct vcount_leading_zeros_reg_avx(vec dst, vec src, vec xtmp1, vec xtmp2, ve ins_encode %{ int vlen_enc = vector_length_encoding(this, $src); BasicType bt = Matcher::vector_element_basic_type(this, $src); - BasicType rbt = Matcher::vector_element_basic_type(this); __ vector_count_leading_zeros_avx(bt, $dst$$XMMRegister, $src$$XMMRegister, $xtmp1$$XMMRegister, $xtmp2$$XMMRegister, $xtmp3$$XMMRegister, $rtmp$$Register, vlen_enc); - // TODO: Once auto-vectorizer supports ConvL2I operation, CountLeadingZerosV - // should be succeeded by its corresponding vector IR and following - // special handling should be removed. - if (rbt == T_INT && bt == T_LONG) { - __ evpmovqd($dst$$XMMRegister, $dst$$XMMRegister, vlen_enc); - } %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index fc4051aaeaf..35dce686ec5 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2079,6 +2079,14 @@ bool SuperWord::implemented(Node_List* p) { } else if (is_cmove_fp_opcode(opc)) { retValue = is_cmov_pack(p) && VectorNode::implemented(opc, size, velt_basic_type(p0)); NOT_PRODUCT(if(retValue && is_trace_cmov()) {tty->print_cr("SWPointer::implemented: found cmove pack"); print_pack(p);}) + } else if (requires_long_to_int_conversion(opc)) { + // Java API for Long.bitCount/numberOfLeadingZeros/numberOfTrailingZeros + // returns int type, but Vector API for them returns long type. To unify + // the implementation in backend, superword splits the vector implementation + // for Java API into an execution node with long type plus another node + // converting long to int. + retValue = VectorNode::implemented(opc, size, T_LONG) && + VectorCastNode::implemented(Op_ConvL2I, size, T_LONG, T_INT); } else { // Vector unsigned right shift for signed subword types behaves differently // from Java Spec. But when the shift amount is a constant not greater than @@ -2096,6 +2104,18 @@ bool SuperWord::implemented(Node_List* p) { bool SuperWord::is_cmov_pack(Node_List* p) { return _cmovev_kit.pack(p->at(0)) != NULL; } + +bool SuperWord::requires_long_to_int_conversion(int opc) { + switch(opc) { + case Op_PopCountL: + case Op_CountLeadingZerosL: + case Op_CountTrailingZerosL: + return true; + default: + return false; + } +} + //------------------------------same_inputs-------------------------- // For pack p, are all idx operands the same? bool SuperWord::same_inputs(Node_List* p, int idx) { @@ -2666,16 +2686,28 @@ bool SuperWord::output() { opc == Op_AbsI || opc == Op_AbsL || opc == Op_NegF || opc == Op_NegD || opc == Op_RoundF || opc == Op_RoundD || - opc == Op_PopCountI || opc == Op_PopCountL || opc == Op_ReverseBytesI || opc == Op_ReverseBytesL || opc == Op_ReverseBytesUS || opc == Op_ReverseBytesS || opc == Op_ReverseI || opc == Op_ReverseL || - opc == Op_CountLeadingZerosI || opc == Op_CountLeadingZerosL || - opc == Op_CountTrailingZerosI || opc == Op_CountTrailingZerosL) { + opc == Op_PopCountI || opc == Op_CountLeadingZerosI || + opc == Op_CountTrailingZerosI) { assert(n->req() == 2, "only one input expected"); Node* in = vector_opd(p, 1); vn = VectorNode::make(opc, in, NULL, vlen, velt_basic_type(n)); vlen_in_bytes = vn->as_Vector()->length_in_bytes(); + } else if (requires_long_to_int_conversion(opc)) { + // Java API for Long.bitCount/numberOfLeadingZeros/numberOfTrailingZeros + // returns int type, but Vector API for them returns long type. To unify + // the implementation in backend, superword splits the vector implementation + // for Java API into an execution node with long type plus another node + // converting long to int. + assert(n->req() == 2, "only one input expected"); + Node* in = vector_opd(p, 1); + Node* longval = VectorNode::make(opc, in, NULL, vlen, T_LONG); + _igvn.register_new_node_with_optimizer(longval); + _phase->set_ctrl(longval, _phase->get_ctrl(p->at(0))); + vn = VectorCastNode::make(Op_VectorCastL2X, longval, T_INT, vlen); + vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else if (VectorNode::is_convert_opcode(opc)) { assert(n->req() == 2, "only one input expected"); BasicType bt = velt_basic_type(n); @@ -3198,27 +3230,11 @@ bool SuperWord::is_vector_use(Node* use, int u_idx) { return true; } - if (VectorNode::is_type_transition_long_to_int(use)) { - // PopCountL/CountLeadingZerosL/CountTrailingZerosL takes long and produces - // int - hence the special checks on alignment and size. - if (u_pk->size() != d_pk->size()) { - return false; - } - for (uint i = 0; i < MIN2(d_pk->size(), u_pk->size()); i++) { - Node* ui = u_pk->at(i); - Node* di = d_pk->at(i); - if (alignment(ui) * 2 != alignment(di)) { - return false; - } - } - return true; - } - if (u_pk->size() != d_pk->size()) return false; if (longer_type_for_conversion(use) != T_ILLEGAL) { - // type conversion takes a type of a kind of size and produces a type of + // These opcodes take a type of a kind of size and produce a type of // another size - hence the special checks on alignment and size. for (uint i = 0; i < u_pk->size(); i++) { Node* ui = u_pk->at(i); @@ -3467,7 +3483,8 @@ void SuperWord::compute_max_depth() { } BasicType SuperWord::longer_type_for_conversion(Node* n) { - if (!VectorNode::is_convert_opcode(n->Opcode()) || + if (!(VectorNode::is_convert_opcode(n->Opcode()) || + requires_long_to_int_conversion(n->Opcode())) || !in_bb(n->in(1))) { return T_ILLEGAL; } diff --git a/src/hotspot/share/opto/superword.hpp b/src/hotspot/share/opto/superword.hpp index 3fac2871e76..5da1d7b21c2 100644 --- a/src/hotspot/share/opto/superword.hpp +++ b/src/hotspot/share/opto/superword.hpp @@ -457,6 +457,7 @@ class SuperWord : public ResourceObj { bool is_cmov_pack(Node_List* p); bool is_cmov_pack_internal_node(Node_List* p, Node* nd) { return is_cmov_pack(p) && !nd->is_CMove(); } static bool is_cmove_fp_opcode(int opc) { return (opc == Op_CMoveF || opc == Op_CMoveD); } + static bool requires_long_to_int_conversion(int opc); // For pack p, are all idx operands the same? bool same_inputs(Node_List* p, int idx); // CloneMap utilities diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 85dbf9e42cf..92ec6d80cfe 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -343,17 +343,6 @@ bool VectorNode::is_muladds2i(Node* n) { return false; } -bool VectorNode::is_type_transition_long_to_int(Node* n) { - switch(n->Opcode()) { - case Op_PopCountL: - case Op_CountLeadingZerosL: - case Op_CountTrailingZerosL: - return true; - default: - return false; - } -} - bool VectorNode::is_roundopD(Node* n) { if (n->Opcode() == Op_RoundDoubleMode) { return true; diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 590fe106616..aa672ca983e 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -99,7 +99,6 @@ class VectorNode : public TypeNode { static bool is_type_transition_short_to_int(Node* n); static bool is_type_transition_to_int(Node* n); static bool is_muladds2i(Node* n); - static bool is_type_transition_long_to_int(Node* n); static bool is_roundopD(Node* n); static bool is_scalar_rotate(Node* n); static bool is_vector_rotate_supported(int opc, uint vlen, BasicType bt); @@ -551,7 +550,9 @@ class PopCountVINode : public VectorNode { // Vector popcount long bits class PopCountVLNode : public VectorNode { public: - PopCountVLNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) {} + PopCountVLNode(Node* in, const TypeVect* vt) : VectorNode(in,vt) { + assert(vt->element_basic_type() == T_LONG, "must be long"); + } virtual int Opcode() const; }; @@ -1732,7 +1733,10 @@ class RotateLeftVNode : public VectorNode { class CountLeadingZerosVNode : public VectorNode { public: CountLeadingZerosVNode(Node* in, const TypeVect* vt) - : VectorNode(in, vt) {} + : VectorNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == vt->element_basic_type(), + "must be the same"); + } virtual int Opcode() const; }; @@ -1740,7 +1744,10 @@ class CountLeadingZerosVNode : public VectorNode { class CountTrailingZerosVNode : public VectorNode { public: CountTrailingZerosVNode(Node* in, const TypeVect* vt) - : VectorNode(in, vt) {} + : VectorNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == vt->element_basic_type(), + "must be the same"); + } virtual int Opcode() const; }; diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java b/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java index d60625d722e..f493b3fc307 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestDisableAutoVectOpcodes.java @@ -116,4 +116,20 @@ private static void testMulReductionVD() { dresult += result; } + @Test + @IR(failOn = {IRNode.COUNTTRAILINGZEROS_VL}) + public void testNumberOfTrailingZeros() { + for (int i = 0; i < SIZE; ++i) { + inta[i] = Long.numberOfTrailingZeros(longa[i]); + } + } + + @Test + @IR(failOn = {IRNode.COUNTLEADINGZEROS_VL}) + public void testNumberOfLeadingZeros() { + for (int i = 0; i < SIZE; ++i) { + inta[i] = Long.numberOfLeadingZeros(longa[i]); + } + } + } diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 5997435a748..6f30d9f83be 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -714,6 +714,16 @@ public class IRNode { superWordNodes(POPCOUNT_VL, "PopCountVL"); } + public static final String COUNTTRAILINGZEROS_VL = PREFIX + "COUNTTRAILINGZEROS_VL" + POSTFIX; + static { + superWordNodes(COUNTTRAILINGZEROS_VL, "CountTrailingZerosV"); + } + + public static final String COUNTLEADINGZEROS_VL = PREFIX + "COUNTLEADINGZEROS_VL" + POSTFIX; + static { + superWordNodes(COUNTLEADINGZEROS_VL, "CountLeadingZerosV"); + } + public static final String POPULATE_INDEX = PREFIX + "POPULATE_INDEX" + POSTFIX; static { String regex = START + "PopulateIndex" + MID + END; diff --git a/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java new file mode 100644 index 00000000000..c64b851096d --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestNumberOfContinuousZeros.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, Arm 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. + */ + +/** +* @test +* @key randomness +* @summary Test vectorization of numberOfTrailingZeros/numberOfLeadingZeros for Long +* @requires vm.compiler2.enabled +* @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*avx2.*") | +* (os.simpleArch == "aarch64" & vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) +* @library /test/lib / +* @run driver compiler.vectorization.TestNumberOfContinuousZeros +*/ + +package compiler.vectorization; + +import compiler.lib.ir_framework.*; +import java.util.Random; +import jdk.test.lib.Asserts; + +public class TestNumberOfContinuousZeros { + private long[] input; + private int[] output; + private static final int LEN = 1024; + private Random rng; + + public static void main(String args[]) { + TestFramework.run(); + } + + public TestNumberOfContinuousZeros() { + input = new long[LEN]; + output = new int[LEN]; + rng = new Random(42); + for (int i = 0; i < LEN; ++i) { + input[i] = rng.nextLong(); + } + } + + @Test + @IR(counts = {IRNode.COUNTTRAILINGZEROS_VL, "> 0"}) + public void vectorizeNumberOfTrailingZeros() { + for (int i = 0; i < LEN; ++i) { + output[i] = Long.numberOfTrailingZeros(input[i]); + } + } + + @Test + @IR(counts = {IRNode.COUNTLEADINGZEROS_VL, "> 0"}) + public void vectorizeNumberOfLeadingZeros() { + for (int i = 0; i < LEN; ++i) { + output[i] = Long.numberOfLeadingZeros(input[i]); + } + } + + @Run(test = {"vectorizeNumberOfTrailingZeros", "vectorizeNumberOfLeadingZeros"}) + public void checkResult() { + vectorizeNumberOfTrailingZeros(); + for (int i = 0; i < LEN; ++i) { + Asserts.assertEquals(output[i], Long.numberOfTrailingZeros(input[i])); + } + vectorizeNumberOfLeadingZeros(); + for (int i = 0; i < LEN; ++i) { + Asserts.assertEquals(output[i], Long.numberOfLeadingZeros(input[i])); + } + } +} + diff --git a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java index b6b2e42ce9b..20912582b7f 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestPopCountVectorLong.java @@ -25,8 +25,8 @@ * @test * @summary Test vectorization of popcount for Long * @requires vm.compiler2.enabled -* @requires vm.cpu.features ~= ".*avx512bw.*" | (vm.cpu.features ~= ".*sve.*" & (vm.opt.UseSVE == "null" | vm.opt.UseSVE > 0)) -* @requires os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64" | os.arch=="aarch64" +* @requires ((os.arch=="x86" | os.arch=="i386" | os.arch=="amd64" | os.arch=="x86_64") & vm.cpu.features ~= ".*avx512bw.*") | +* os.simpleArch == "aarch64" * @library /test/lib / * @run driver compiler.vectorization.TestPopCountVectorLong */ From a9e6c62ba7df8d28cef9579c57a0386736bd9dbf Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Tue, 6 Dec 2022 10:09:59 +0000 Subject: [PATCH 069/494] 8297186: G1 triggers unnecessary full GCs when heap utilization is low Reviewed-by: kbarrett, sjohanss --- src/hotspot/share/gc/g1/g1Policy.cpp | 73 ++++++++++------ src/hotspot/share/gc/g1/g1Policy.hpp | 7 +- .../jtreg/gc/g1/TestOneEdenRegionAfterGC.java | 85 +++++++++++++++++++ .../runtime/cds/appcds/LotsOfClasses.java | 1 + 4 files changed, 135 insertions(+), 31 deletions(-) create mode 100644 test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index 78ab9b5af94..dbf7519a6c3 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -188,15 +188,19 @@ uint G1Policy::calculate_desired_eden_length_by_mmu() const { } void G1Policy::update_young_length_bounds() { + assert(!Universe::is_fully_initialized() || SafepointSynchronize::is_at_safepoint(), "must be"); bool for_young_only_phase = collector_state()->in_young_only_phase(); + // Request at least one eden region to ensure progress. + bool after_gc = true; update_young_length_bounds(_analytics->predict_pending_cards(for_young_only_phase), - _analytics->predict_rs_length(for_young_only_phase)); + _analytics->predict_rs_length(for_young_only_phase), + after_gc); } -void G1Policy::update_young_length_bounds(size_t pending_cards, size_t rs_length) { +void G1Policy::update_young_length_bounds(size_t pending_cards, size_t rs_length, bool after_gc) { uint old_young_list_target_length = young_list_target_length(); - uint new_young_list_desired_length = calculate_young_desired_length(pending_cards, rs_length); + uint new_young_list_desired_length = calculate_young_desired_length(pending_cards, rs_length, after_gc); uint new_young_list_target_length = calculate_young_target_length(new_young_list_desired_length); uint new_young_list_max_length = calculate_young_max_length(new_young_list_target_length); @@ -224,28 +228,24 @@ void G1Policy::update_young_length_bounds(size_t pending_cards, size_t rs_length // // - sizer min/max bounds on young gen // - pause time goal for whole young gen evacuation -// - MMU goal influencing eden to make GCs spaced apart. -// - a minimum one eden region length. +// - MMU goal influencing eden to make GCs spaced apart +// - if after a GC, request at least one eden region to avoid immediate full gcs // -// We may enter with already allocated eden and survivor regions, that may be -// higher than the maximum, or the above goals may result in a desired value -// smaller than are already allocated. -// The main reason is revising young length, with or without the GCLocker being -// active. +// We may enter with already allocated eden and survivor regions because there +// are survivor regions (after gc). Young gen revising can call this method at any +// time too. // -uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_length) const { +// For this method it does not matter if the above goals may result in a desired +// value smaller than what is already allocated or what can actually be allocated. +// This return value is only an expectation. +// +uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_length, bool after_gc) const { uint min_young_length_by_sizer = _young_gen_sizer.min_desired_young_length(); uint max_young_length_by_sizer = _young_gen_sizer.max_desired_young_length(); assert(min_young_length_by_sizer >= 1, "invariant"); assert(max_young_length_by_sizer >= min_young_length_by_sizer, "invariant"); - // Absolute minimum eden length. - // Enforcing a minimum eden length helps at startup when the predictors are not - // yet trained on the application to avoid unnecessary (but very short) full gcs - // on very small (initial) heaps. - uint const MinDesiredEdenLength = 1; - // Calculate the absolute and desired min bounds first. // This is how many survivor regions we already have. @@ -261,6 +261,10 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le // so adjust the result accordingly. uint absolute_max_young_length = MAX2(max_young_length_by_sizer, absolute_min_young_length); + // The absolute minimum young gen length (as provided by the young gen sizer) ensures + // that we desire at least one young gen region. + assert(absolute_min_young_length > 0, "must be"); + uint desired_eden_length_by_mmu = 0; uint desired_eden_length_by_pause = 0; @@ -277,10 +281,8 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le // Incorporate MMU concerns; assume that it overrides the pause time // goal, as the default value has been chosen to effectively disable it. - // Also request at least one eden region, see above for reasons. - uint desired_eden_length = MAX3(desired_eden_length_by_pause, - desired_eden_length_by_mmu, - MinDesiredEdenLength); + uint desired_eden_length = MAX2(desired_eden_length_by_pause, + desired_eden_length_by_mmu); desired_young_length = desired_eden_length + survivor_length; } else { @@ -291,19 +293,31 @@ uint G1Policy::calculate_young_desired_length(size_t pending_cards, size_t rs_le // Clamp to absolute min/max after we determined desired lengths. desired_young_length = clamp(desired_young_length, absolute_min_young_length, absolute_max_young_length); - log_trace(gc, ergo, heap)("Young desired length %u " + // After a garbage collection, make room for at least one eden region (i.e. in addition to + // already allocated survivor regions). + // This may make desired regions go over absolute maximum length by the heap sizer, however + // the immediate full gcs after that young gc (particularly on small heaps) are worse. + if (after_gc && (allocated_young_length >= desired_young_length)) { + log_trace(gc, ergo, heap)("Young desired length: Desired young region length less than already " + "allocated region length, but requesting one eden region minimum. " + "Expanding desired young length from %u to %u.", + desired_young_length, + allocated_young_length + 1); + desired_young_length = allocated_young_length + 1; + } + + log_trace(gc, ergo, heap)("Young desired length %u (after gc: %s) " "survivor length %u " "allocated young length %u " "absolute min young length %u " "absolute max young length %u " "desired eden length by mmu %u " - "desired eden length by pause %u " - "desired eden length by default %u", - desired_young_length, survivor_length, + "desired eden length by pause %u ", + desired_young_length, BOOL_TO_STR(after_gc), + survivor_length, allocated_young_length, absolute_min_young_length, absolute_max_young_length, desired_eden_length_by_mmu, - desired_eden_length_by_pause, - MinDesiredEdenLength); + desired_eden_length_by_pause); assert(desired_young_length >= allocated_young_length, "must be"); return desired_young_length; @@ -534,7 +548,10 @@ void G1Policy::revise_young_list_target_length(size_t rs_length) { size_t thread_buffer_cards = _analytics->predict_dirtied_cards_in_thread_buffers(); G1DirtyCardQueueSet& dcqs = G1BarrierSet::dirty_card_queue_set(); size_t pending_cards = dcqs.num_cards() + thread_buffer_cards; - update_young_length_bounds(pending_cards, rs_length); + // We are only revising young gen length to meet pause time goal, so do not request + // at least one eden region for progress. At this point we actually want to run into + // a GC soon if young gen is already (too) large. + update_young_length_bounds(pending_cards, rs_length, false /* need_one_eden_region */); } void G1Policy::record_full_collection_start() { diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index c7b04bce49f..efd91c3df9b 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -210,9 +210,10 @@ class G1Policy: public CHeapObj { // Updates the internal young gen maximum and target and desired lengths. // If no parameters are passed, predict pending cards and the RS length using - // the prediction model. + // the prediction model. If after_gc is set, make sure that there is one eden region + // available (if there is enough space) to guarantee some progress. void update_young_length_bounds(); - void update_young_length_bounds(size_t pending_cards, size_t rs_length); + void update_young_length_bounds(size_t pending_cards, size_t rs_length, bool after_gc); // Calculate and return the minimum desired eden length based on the MMU target. uint calculate_desired_eden_length_by_mmu() const; @@ -240,7 +241,7 @@ class G1Policy: public CHeapObj { // Calculate desired young length based on current situation without taking actually // available free regions into account. - uint calculate_young_desired_length(size_t pending_cards, size_t rs_length) const; + uint calculate_young_desired_length(size_t pending_cards, size_t rs_length, bool after_gc) const; // Limit the given desired young length to available free regions. uint calculate_young_target_length(uint desired_young_length) const; // The GCLocker might cause us to need more regions than the target. Calculate diff --git a/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java new file mode 100644 index 00000000000..688d85d4ffb --- /dev/null +++ b/test/hotspot/jtreg/gc/g1/TestOneEdenRegionAfterGC.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, 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 gc.g1; + +/* + * @test + * @bug 8297186 + * @requires vm.gc.G1 + * @library /test/lib + * @run driver gc.g1.TestOneEdenRegionAfterGC + * @summary Test that on a very small heap g1 with very little data (smaller than region size) + * will use at least one eden region after gc to avoid full gcs. + */ + +import jdk.test.lib.process.OutputAnalyzer; +import jdk.test.lib.process.ProcessTools; + +public class TestOneEdenRegionAfterGC { + private static long YoungGenSize = 32 * 1024 * 1024; + + private static OutputAnalyzer run() throws Exception { + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder( + "-Xbootclasspath/a:.", + "-Xmn" + YoungGenSize, + "-Xmx512M", + "-Xms512M", + "-XX:G1HeapRegionSize=32M", + "-XX:+UseG1GC", + "-Xlog:gc,gc+ergo*=trace", + TestOneEdenRegionAfterGC.Allocate.class.getName(), + "" + YoungGenSize); + return new OutputAnalyzer(pb.start()); + } + + public static void main(String args[]) throws Exception { + OutputAnalyzer out = run(); + + out.shouldMatch(".*Pause Young \\(Normal\\).*"); + out.shouldNotMatch(".*Pause Full.*"); + } + + public static class Allocate { + public static Object dummy; + + public static void main(String [] args) throws Exception { + if (args.length != 1) { + throw new IllegalArgumentException("Usage: "); + } + + long youngGenSize = Long.parseLong(args[0]); + triggerYoungGCs(youngGenSize); + } + + public static void triggerYoungGCs(long youngGenSize) { + long approxAllocSize = 32 * 1024; + long numAllocations = 2 * youngGenSize / approxAllocSize; + + for (long i = 0; i < numAllocations; i++) { + dummy = new byte[(int)approxAllocSize]; + } + } + } +} + diff --git a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java index 0f71c1ba389..1c2431d7c81 100644 --- a/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java +++ b/test/hotspot/jtreg/runtime/cds/appcds/LotsOfClasses.java @@ -48,6 +48,7 @@ public static void main(String[] args) throws Exception { opts.addSuffix("ALL-SYSTEM"); opts.addSuffix("-Xlog:hashtables"); opts.addSuffix("-Xmx500m"); + opts.addSuffix("-XX:MetaspaceSize=500M"); // avoid heap fragmentation by avoiding metaspace-limit induced GCs opts.addSuffix("-Xlog:gc+region+cds"); opts.addSuffix("-Xlog:cds=debug"); // test detailed metadata info printing From 84b927a05bcb7bf32a12829070ffd3a5670066d2 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Tue, 6 Dec 2022 10:42:59 +0000 Subject: [PATCH 070/494] 8296024: Usage of DirectBuffer::address should be guarded Reviewed-by: mcimadamore, alanb, psandoz, bpb --- .../crypto/provider/GaloisCounterMode.java | 16 +- .../share/classes/java/nio/Buffer.java | 36 +- .../share/classes/java/util/zip/Adler32.java | 9 +- .../share/classes/java/util/zip/CRC32.java | 6 +- .../share/classes/java/util/zip/CRC32C.java | 8 +- .../share/classes/java/util/zip/Deflater.java | 31 +- .../share/classes/java/util/zip/Inflater.java | 31 +- .../share/classes/java/util/zip/ZipUtils.java | 4 + .../jdk/internal/access/JavaNioAccess.java | 26 +- src/java.base/share/classes/module-info.java | 4 +- .../sun/nio/ch/DatagramChannelImpl.java | 26 +- .../classes/sun/nio/ch/DirectBuffer.java | 7 + .../share/classes/sun/nio/ch/IOUtil.java | 74 ++-- .../share/lib/security/default.policy | 1 + .../fs/UnixUserDefinedFileAttributeView.java | 16 +- .../sun/security/pkcs11/P11AEADCipher.java | 156 ++++---- .../sun/security/pkcs11/P11Cipher.java | 353 +++++++++--------- .../sun/security/pkcs11/P11Digest.java | 15 +- .../sun/security/pkcs11/P11KeyWrapCipher.java | 145 +++---- .../classes/sun/security/pkcs11/P11Mac.java | 14 +- .../sun/security/pkcs11/P11PSSSignature.java | 15 +- .../sun/security/pkcs11/P11Signature.java | 13 +- .../sun/nio/ch/sctp/SctpChannelImpl.java | 33 +- .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 32 +- 24 files changed, 638 insertions(+), 433 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index e639a016ff1..d55aff35499 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -25,6 +25,8 @@ package com.sun.crypto.provider; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; @@ -92,6 +94,8 @@ abstract class GaloisCounterMode extends CipherSpi { static final byte[] EMPTY_BUF = new byte[0]; + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private boolean initialized = false; SymmetricCipher blockCipher; @@ -909,6 +913,8 @@ int doLastBlock(GCMOperation op, ByteBuffer buffer, ByteBuffer src, */ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { if (src.isDirect() && dst.isDirect()) { + // The use of DirectBuffer::address below need not be guarded as + // no access is made to actual memory. DirectBuffer dsrc = (DirectBuffer) src; DirectBuffer ddst = (DirectBuffer) dst; @@ -946,7 +952,6 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { ((DirectBuffer) dst).address() - dstaddr + dst.position()) { return dst; } - } else if (!src.isDirect() && !dst.isDirect()) { // if src is read only, then we need a copy if (!src.isReadOnly()) { @@ -1585,8 +1590,13 @@ public int doFinal(ByteBuffer src, ByteBuffer dst) int ofs = dst.arrayOffset() + dst.position(); Arrays.fill(dst.array(), ofs , ofs + len, (byte)0); } else { - Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(), - len + dst.position(), (byte)0); + NIO_ACCESS.acquireSession(dst); + try { + Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(), + len + dst.position(), (byte) 0); + } finally { + NIO_ACCESS.releaseSession(dst); + } } throw new AEADBadTagException("Tag mismatch"); } diff --git a/src/java.base/share/classes/java/nio/Buffer.java b/src/java.base/share/classes/java/nio/Buffer.java index 229a4fb4f23..06d28a066bf 100644 --- a/src/java.base/share/classes/java/nio/Buffer.java +++ b/src/java.base/share/classes/java/nio/Buffer.java @@ -37,6 +37,7 @@ import java.io.FileDescriptor; import java.lang.foreign.MemorySegment; +import java.lang.ref.Reference; import java.util.Objects; import java.util.Spliterator; @@ -779,6 +780,7 @@ final void checkSession() { // setup access to this package in SharedSecrets SharedSecrets.setJavaNioAccess( new JavaNioAccess() { + @Override public BufferPool getDirectBufferPool() { return Bits.BUFFER_POOL; @@ -824,16 +826,34 @@ public MemorySegment bufferSegment(Buffer buffer) { } @Override - public Runnable acquireSession(Buffer buffer, boolean async) { - var session = buffer.session(); - if (session == null) { - return null; + public void acquireSession(Buffer buffer) { + var scope = buffer.session(); + if (scope != null) { + scope.acquire0(); } - if (async && session.ownerThread() != null) { - throw new IllegalStateException("Confined session not supported"); + } + + @Override + public void releaseSession(Buffer buffer) { + try { + var scope = buffer.session(); + if (scope != null) { + scope.release0(); + } + } finally { + Reference.reachabilityFence(buffer); } - session.acquire0(); - return session::release0; + } + + @Override + public boolean isThreadConfined(Buffer buffer) { + var scope = buffer.session(); + return scope != null && scope.ownerThread() != null; + } + + @Override + public boolean hasSession(Buffer buffer) { + return buffer.session() != null; } @Override diff --git a/src/java.base/share/classes/java/util/zip/Adler32.java b/src/java.base/share/classes/java/util/zip/Adler32.java index 3c3adec344d..b8e0bc190c1 100644 --- a/src/java.base/share/classes/java/util/zip/Adler32.java +++ b/src/java.base/share/classes/java/util/zip/Adler32.java @@ -25,11 +25,13 @@ package java.util.zip; -import java.lang.ref.Reference; import java.nio.ByteBuffer; -import sun.nio.ch.DirectBuffer; + import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; +import sun.nio.ch.DirectBuffer; + +import static java.util.zip.ZipUtils.NIO_ACCESS; /** * A class that can be used to compute the Adler-32 checksum of a data @@ -96,10 +98,11 @@ public void update(ByteBuffer buffer) { if (rem <= 0) return; if (buffer.isDirect()) { + NIO_ACCESS.acquireSession(buffer); try { adler = updateByteBuffer(adler, ((DirectBuffer)buffer).address(), pos, rem); } finally { - Reference.reachabilityFence(buffer); + NIO_ACCESS.releaseSession(buffer); } } else if (buffer.hasArray()) { adler = updateBytes(adler, buffer.array(), pos + buffer.arrayOffset(), rem); diff --git a/src/java.base/share/classes/java/util/zip/CRC32.java b/src/java.base/share/classes/java/util/zip/CRC32.java index 9d41392d172..84e6f26e45e 100644 --- a/src/java.base/share/classes/java/util/zip/CRC32.java +++ b/src/java.base/share/classes/java/util/zip/CRC32.java @@ -25,7 +25,6 @@ package java.util.zip; -import java.lang.ref.Reference; import java.nio.ByteBuffer; import java.util.Objects; @@ -33,6 +32,8 @@ import jdk.internal.util.Preconditions; import jdk.internal.vm.annotation.IntrinsicCandidate; +import static java.util.zip.ZipUtils.NIO_ACCESS; + /** * A class that can be used to compute the CRC-32 of a data stream. * @@ -96,10 +97,11 @@ public void update(ByteBuffer buffer) { if (rem <= 0) return; if (buffer.isDirect()) { + NIO_ACCESS.acquireSession(buffer); try { crc = updateByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, rem); } finally { - Reference.reachabilityFence(buffer); + NIO_ACCESS.releaseSession(buffer); } } else if (buffer.hasArray()) { crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), rem); diff --git a/src/java.base/share/classes/java/util/zip/CRC32C.java b/src/java.base/share/classes/java/util/zip/CRC32C.java index a8b4d1b7565..a813e910009 100644 --- a/src/java.base/share/classes/java/util/zip/CRC32C.java +++ b/src/java.base/share/classes/java/util/zip/CRC32C.java @@ -24,7 +24,6 @@ */ package java.util.zip; -import java.lang.ref.Reference; import java.nio.ByteBuffer; import java.nio.ByteOrder; @@ -33,6 +32,8 @@ import jdk.internal.vm.annotation.IntrinsicCandidate; import sun.nio.ch.DirectBuffer; +import static java.util.zip.ZipUtils.NIO_ACCESS; + /** * A class that can be used to compute the CRC-32C of a data stream. * @@ -171,11 +172,12 @@ public void update(ByteBuffer buffer) { } if (buffer.isDirect()) { + NIO_ACCESS.acquireSession(buffer); try { - crc = updateDirectByteBuffer(crc, ((DirectBuffer) buffer).address(), + crc = updateDirectByteBuffer(crc, ((DirectBuffer)buffer).address(), pos, limit); } finally { - Reference.reachabilityFence(buffer); + NIO_ACCESS.releaseSession(buffer); } } else if (buffer.hasArray()) { crc = updateBytes(crc, buffer.array(), pos + buffer.arrayOffset(), diff --git a/src/java.base/share/classes/java/util/zip/Deflater.java b/src/java.base/share/classes/java/util/zip/Deflater.java index 155264e4afe..3e550d14178 100644 --- a/src/java.base/share/classes/java/util/zip/Deflater.java +++ b/src/java.base/share/classes/java/util/zip/Deflater.java @@ -26,7 +26,6 @@ package java.util.zip; import java.lang.ref.Cleaner.Cleanable; -import java.lang.ref.Reference; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import java.util.Objects; @@ -35,6 +34,8 @@ import jdk.internal.util.Preconditions; import sun.nio.ch.DirectBuffer; +import static java.util.zip.ZipUtils.NIO_ACCESS; + /** * This class provides support for general purpose compression using the * popular ZLIB compression library. The ZLIB compression library was @@ -337,11 +338,12 @@ public void setDictionary(ByteBuffer dictionary) { int remaining = Math.max(dictionary.limit() - position, 0); ensureOpen(); if (dictionary.isDirect()) { - long address = ((DirectBuffer) dictionary).address(); + NIO_ACCESS.acquireSession(dictionary); try { + long address = ((DirectBuffer) dictionary).address(); setDictionaryBuffer(zsRef.address(), address + position, remaining); } finally { - Reference.reachabilityFence(dictionary); + NIO_ACCESS.releaseSession(dictionary); } } else { byte[] array = ZipUtils.getBufferArray(dictionary); @@ -587,6 +589,7 @@ public int deflate(byte[] output, int off, int len, int flush) { inputPos = input.position(); int inputRem = Math.max(input.limit() - inputPos, 0); if (input.isDirect()) { + NIO_ACCESS.acquireSession(input); try { long inputAddress = ((DirectBuffer) input).address(); result = deflateBufferBytes(zsRef.address(), @@ -594,7 +597,7 @@ public int deflate(byte[] output, int off, int len, int flush) { output, off, len, flush, params); } finally { - Reference.reachabilityFence(input); + NIO_ACCESS.releaseSession(input); } } else { byte[] inputArray = ZipUtils.getBufferArray(input); @@ -709,14 +712,15 @@ public int deflate(ByteBuffer output, int flush) { if (input == null) { inputPos = this.inputPos; if (output.isDirect()) { - long outputAddress = ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = ((DirectBuffer) output).address(); result = deflateBytesBuffer(zsRef.address(), inputArray, inputPos, inputLim - inputPos, outputAddress + outputPos, outputRem, flush, params); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); @@ -730,17 +734,19 @@ public int deflate(ByteBuffer output, int flush) { inputPos = input.position(); int inputRem = Math.max(input.limit() - inputPos, 0); if (input.isDirect()) { - long inputAddress = ((DirectBuffer) input).address(); + NIO_ACCESS.acquireSession(input); try { + long inputAddress = ((DirectBuffer) input).address(); if (output.isDirect()) { - long outputAddress = outputPos + ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = outputPos + ((DirectBuffer) output).address(); result = deflateBufferBuffer(zsRef.address(), inputAddress + inputPos, inputRem, outputAddress, outputRem, flush, params); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); @@ -751,20 +757,21 @@ public int deflate(ByteBuffer output, int flush) { flush, params); } } finally { - Reference.reachabilityFence(input); + NIO_ACCESS.releaseSession(input); } } else { byte[] inputArray = ZipUtils.getBufferArray(input); int inputOffset = ZipUtils.getBufferOffset(input); if (output.isDirect()) { - long outputAddress = ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = ((DirectBuffer) output).address(); result = deflateBytesBuffer(zsRef.address(), inputArray, inputOffset + inputPos, inputRem, outputAddress + outputPos, outputRem, flush, params); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); diff --git a/src/java.base/share/classes/java/util/zip/Inflater.java b/src/java.base/share/classes/java/util/zip/Inflater.java index 8a7f742f41f..a3cbdd1d1bf 100644 --- a/src/java.base/share/classes/java/util/zip/Inflater.java +++ b/src/java.base/share/classes/java/util/zip/Inflater.java @@ -26,7 +26,6 @@ package java.util.zip; import java.lang.ref.Cleaner.Cleanable; -import java.lang.ref.Reference; import java.nio.ByteBuffer; import java.nio.ReadOnlyBufferException; import java.util.Objects; @@ -35,6 +34,8 @@ import jdk.internal.util.Preconditions; import sun.nio.ch.DirectBuffer; +import static java.util.zip.ZipUtils.NIO_ACCESS; + /** * This class provides support for general purpose decompression using the * popular ZLIB compression library. The ZLIB compression library was @@ -259,11 +260,12 @@ public void setDictionary(ByteBuffer dictionary) { int remaining = Math.max(dictionary.limit() - position, 0); ensureOpen(); if (dictionary.isDirect()) { - long address = ((DirectBuffer) dictionary).address(); + NIO_ACCESS.acquireSession(dictionary); try { + long address = ((DirectBuffer) dictionary).address(); setDictionaryBuffer(zsRef.address(), address + position, remaining); } finally { - Reference.reachabilityFence(dictionary); + NIO_ACCESS.releaseSession(dictionary); } } else { byte[] array = ZipUtils.getBufferArray(dictionary); @@ -383,13 +385,14 @@ public int inflate(byte[] output, int off, int len) try { int inputRem = Math.max(input.limit() - inputPos, 0); if (input.isDirect()) { + NIO_ACCESS.acquireSession(input); try { long inputAddress = ((DirectBuffer) input).address(); result = inflateBufferBytes(zsRef.address(), inputAddress + inputPos, inputRem, output, off, len); } finally { - Reference.reachabilityFence(input); + NIO_ACCESS.releaseSession(input); } } else { byte[] inputArray = ZipUtils.getBufferArray(input); @@ -517,13 +520,14 @@ public int inflate(ByteBuffer output) throws DataFormatException { inputPos = this.inputPos; try { if (output.isDirect()) { - long outputAddress = ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = ((DirectBuffer) output).address(); result = inflateBytesBuffer(zsRef.address(), inputArray, inputPos, inputLim - inputPos, outputAddress + outputPos, outputRem); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); @@ -541,16 +545,18 @@ public int inflate(ByteBuffer output) throws DataFormatException { int inputRem = Math.max(input.limit() - inputPos, 0); try { if (input.isDirect()) { - long inputAddress = ((DirectBuffer) input).address(); + NIO_ACCESS.acquireSession(input); try { + long inputAddress = ((DirectBuffer) input).address(); if (output.isDirect()) { - long outputAddress = ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = ((DirectBuffer) output).address(); result = inflateBufferBuffer(zsRef.address(), inputAddress + inputPos, inputRem, outputAddress + outputPos, outputRem); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); @@ -560,19 +566,20 @@ public int inflate(ByteBuffer output) throws DataFormatException { outputArray, outputOffset + outputPos, outputRem); } } finally { - Reference.reachabilityFence(input); + NIO_ACCESS.releaseSession(input); } } else { byte[] inputArray = ZipUtils.getBufferArray(input); int inputOffset = ZipUtils.getBufferOffset(input); if (output.isDirect()) { - long outputAddress = ((DirectBuffer) output).address(); + NIO_ACCESS.acquireSession(output); try { + long outputAddress = ((DirectBuffer) output).address(); result = inflateBytesBuffer(zsRef.address(), inputArray, inputOffset + inputPos, inputRem, outputAddress + outputPos, outputRem); } finally { - Reference.reachabilityFence(output); + NIO_ACCESS.releaseSession(output); } } else { byte[] outputArray = ZipUtils.getBufferArray(output); diff --git a/src/java.base/share/classes/java/util/zip/ZipUtils.java b/src/java.base/share/classes/java/util/zip/ZipUtils.java index cca1454f5be..0cbc2e28795 100644 --- a/src/java.base/share/classes/java/util/zip/ZipUtils.java +++ b/src/java.base/share/classes/java/util/zip/ZipUtils.java @@ -36,10 +36,14 @@ import static java.util.zip.ZipConstants.ENDHDR; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; class ZipUtils { + static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // used to adjust values between Windows and java epoch private static final long WINDOWS_EPOCH_IN_MICROSECONDS = -11644473600000000L; diff --git a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java index 9e54ef59884..b34a0d42085 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaNioAccess.java @@ -86,12 +86,26 @@ public interface JavaNioAccess { MemorySegment bufferSegment(Buffer buffer); /** - * Used by I/O operations to make a buffer's session non-closeable - * (for the duration of the I/O operation) by acquiring the session. - * Null is returned if the buffer has no scope, or acquiring is not - * required to guarantee safety. - */ - Runnable acquireSession(Buffer buffer, boolean async); + * Used by operations to make a buffer's session non-closeable + * (for the duration of the operation) by acquiring the session. + * {@snippet lang = java: + * acquireSession(buffer); + * try { + * performOperation(buffer); + * } finally { + * releaseSession(buffer); + * } + *} + * + * @see #releaseSession(Buffer) + */ + void acquireSession(Buffer buffer); + + void releaseSession(Buffer buffer); + + boolean isThreadConfined(Buffer buffer); + + boolean hasSession(Buffer buffer); /** * Used by {@code jdk.internal.foreign.MappedMemorySegmentImpl} and byte buffer var handle views. diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index d75b1d9a1ff..86d8866049c 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -166,7 +166,9 @@ jdk.jartool, jdk.jlink, jdk.jfr, - jdk.net; + jdk.net, + jdk.sctp, + jdk.crypto.cryptoki; exports jdk.internal.foreign to jdk.incubator.vector; exports jdk.internal.event to diff --git a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java index e1651e31014..d8f7cd0cb72 100644 --- a/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java +++ b/src/java.base/share/classes/sun/nio/ch/DatagramChannelImpl.java @@ -71,6 +71,8 @@ import java.util.concurrent.locks.ReentrantLock; import java.util.function.Consumer; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.ref.CleanerFactory; import sun.net.ResourceManager; import sun.net.ext.ExtendedSocketOptions; @@ -87,6 +89,8 @@ class DatagramChannelImpl // Used to make native read and write calls private static final NativeDispatcher nd = new DatagramDispatcher(); + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // true if interruptible (can be false to emulate legacy DatagramSocket) private final boolean interruptible; @@ -780,13 +784,18 @@ private int receiveIntoNativeBuffer(ByteBuffer bb, int rem, int pos, boolean connected) throws IOException { - int n = receive0(fd, - ((DirectBuffer)bb).address() + pos, rem, - sourceSockAddr.address(), - connected); - if (n > 0) - bb.position(pos + n); - return n; + NIO_ACCESS.acquireSession(bb); + try { + int n = receive0(fd, + ((DirectBuffer)bb).address() + pos, rem, + sourceSockAddr.address(), + connected); + if (n > 0) + bb.position(pos + n); + return n; + } finally { + NIO_ACCESS.releaseSession(bb); + } } /** @@ -930,6 +939,7 @@ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, int rem = (pos <= lim ? lim - pos : 0); int written; + NIO_ACCESS.acquireSession(bb); try { int addressLen = targetSocketAddress(target); written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, @@ -938,6 +948,8 @@ private int sendFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, if (isConnected()) throw pue; written = rem; + } finally { + NIO_ACCESS.releaseSession(bb); } if (written > 0) bb.position(pos + written); diff --git a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java index cba31015f0c..8fcea1eb57d 100644 --- a/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java +++ b/src/java.base/share/classes/sun/nio/ch/DirectBuffer.java @@ -30,6 +30,13 @@ public interface DirectBuffer { + // Use of the returned address must be guarded if this DirectBuffer + // is backed by a memory session that is explicitly closeable. + // + // Failure to do this means the outcome is undefined including + // silent unrelated memory mutation and JVM crashes. + // + // See JavaNioAccess for methods to safely acquire/release resources. public long address(); public Object attachment(); diff --git a/src/java.base/share/classes/sun/nio/ch/IOUtil.java b/src/java.base/share/classes/sun/nio/ch/IOUtil.java index 6ed206e9a23..55522fd717d 100644 --- a/src/java.base/share/classes/sun/nio/ch/IOUtil.java +++ b/src/java.base/share/classes/sun/nio/ch/IOUtil.java @@ -31,12 +31,13 @@ import java.util.Objects; import jdk.internal.access.JavaNioAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.foreign.MemorySessionImpl; /** * File-descriptor based I/O utilities that are shared by NIO classes. */ -public class IOUtil { +public final class IOUtil { /** * Max number of iovec structures that readv/writev supports @@ -128,7 +129,7 @@ private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, int written = 0; if (rem == 0) return 0; - var handle = acquireScope(bb, async); + acquireScope(bb, async); try { if (position != -1) { written = nd.pwrite(fd, bufferAddress(bb) + pos, rem, position); @@ -136,7 +137,7 @@ private static int writeFromNativeBuffer(FileDescriptor fd, ByteBuffer bb, written = nd.write(fd, bufferAddress(bb) + pos, rem); } } finally { - releaseScope(handle); + releaseScope(bb); } if (written > 0) bb.position(pos + written); @@ -181,9 +182,9 @@ static long write(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, int i = offset; while (i < count && iov_len < IOV_MAX && writevLen < WRITEV_MAX) { ByteBuffer buf = bufs[i]; - var h = acquireScope(buf, async); - if (h != null) { - handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers); + acquireScope(buf, async); + if (NIO_ACCESS.hasSession(buf)) { + handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers); } int pos = buf.position(); int lim = buf.limit(); @@ -331,7 +332,7 @@ private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, if (rem == 0) return 0; int n = 0; - var handle = acquireScope(bb, async); + acquireScope(bb, async); try { if (position != -1) { n = nd.pread(fd, bufferAddress(bb) + pos, rem, position); @@ -339,7 +340,7 @@ private static int readIntoNativeBuffer(FileDescriptor fd, ByteBuffer bb, n = nd.read(fd, bufferAddress(bb) + pos, rem); } } finally { - releaseScope(handle); + releaseScope(bb); } if (n > 0) bb.position(pos + n); @@ -393,9 +394,9 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, ByteBuffer buf = bufs[i]; if (buf.isReadOnly()) throw new IllegalArgumentException("Read-only buffer"); - var h = acquireScope(buf, async); - if (h != null) { - handleReleasers = LinkedRunnable.of(Releaser.of(h), handleReleasers); + acquireScope(buf, async); + if (NIO_ACCESS.hasSession(buf)) { + handleReleasers = LinkedRunnable.of(Releaser.of(buf), handleReleasers); } int pos = buf.position(); int lim = buf.limit(); @@ -474,15 +475,16 @@ static long read(FileDescriptor fd, ByteBuffer[] bufs, int offset, int length, private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); - static Runnable acquireScope(ByteBuffer bb, boolean async) { - return NIO_ACCESS.acquireSession(bb, async); + static void acquireScope(ByteBuffer bb, boolean async) { + if (async && NIO_ACCESS.isThreadConfined(bb)) { + throw new IllegalStateException("Confined session not supported"); + } + NIO_ACCESS.acquireSession(bb); } - private static void releaseScope(Runnable handle) { - if (handle == null) - return; + private static void releaseScope(ByteBuffer bb) { try { - handle.run(); + NIO_ACCESS.releaseSession(bb); } catch (Exception e) { throw new IllegalStateException(e); } @@ -495,15 +497,14 @@ static Runnable acquireScopes(ByteBuffer[] buffers) { static Runnable acquireScopes(ByteBuffer buf, ByteBuffer[] buffers) { if (buffers == null) { assert buf != null; - return IOUtil.Releaser.ofNullable(IOUtil.acquireScope(buf, true)); + IOUtil.acquireScope(buf, true); + return IOUtil.Releaser.of(buf); } else { assert buf == null; Runnable handleReleasers = null; for (var b : buffers) { - var h = IOUtil.acquireScope(b, true); - if (h != null) { - handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(h), handleReleasers); - } + IOUtil.acquireScope(b, true); + handleReleasers = IOUtil.LinkedRunnable.of(IOUtil.Releaser.of(b), handleReleasers); } return handleReleasers; } @@ -514,12 +515,11 @@ static void releaseScopes(Runnable releasers) { releasers.run(); } - static record LinkedRunnable(Runnable node, Runnable next) - implements Runnable - { + record LinkedRunnable(Runnable node, Runnable next) implements Runnable { LinkedRunnable { Objects.requireNonNull(node); } + @Override public void run() { try { @@ -529,20 +529,28 @@ public void run() { next.run(); } } + static LinkedRunnable of(Runnable first, Runnable second) { return new LinkedRunnable(first, second); } } - static record Releaser(Runnable handle) implements Runnable { - Releaser { Objects.requireNonNull(handle) ; } - @Override public void run() { releaseScope(handle); } - static Runnable of(Runnable handle) { return new Releaser(handle); } - static Runnable ofNullable(Runnable handle) { - if (handle == null) - return () -> { }; - return new Releaser(handle); + record Releaser(ByteBuffer bb) implements Runnable { + Releaser { + Objects.requireNonNull(bb); + } + + @Override + public void run() { + releaseScope(bb); + } + + static Runnable of(ByteBuffer bb) { + return NIO_ACCESS.hasSession(bb) + ? new Releaser(bb) + : () -> {}; } + } static long bufferAddress(ByteBuffer buf) { diff --git a/src/java.base/share/lib/security/default.policy b/src/java.base/share/lib/security/default.policy index 39a57aa9372..2a01c06250a 100644 --- a/src/java.base/share/lib/security/default.policy +++ b/src/java.base/share/lib/security/default.policy @@ -134,6 +134,7 @@ grant codeBase "jrt:/jdk.crypto.cryptoki" { permission java.lang.RuntimePermission "accessClassInPackage.com.sun.crypto.provider"; permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.misc"; + permission java.lang.RuntimePermission "accessClassInPackage.jdk.internal.access"; permission java.lang.RuntimePermission "accessClassInPackage.sun.security.*"; permission java.lang.RuntimePermission "accessClassInPackage.sun.nio.ch"; diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java index fe28dd6ce26..41528a55e37 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java +++ b/src/java.base/unix/classes/sun/nio/fs/UnixUserDefinedFileAttributeView.java @@ -25,11 +25,13 @@ package sun.nio.fs; -import java.lang.ref.Reference; import java.nio.file.*; import java.nio.ByteBuffer; import java.io.IOException; import java.util.*; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import jdk.internal.misc.Unsafe; import static sun.nio.fs.UnixConstants.*; @@ -43,6 +45,8 @@ abstract class UnixUserDefinedFileAttributeView { private static final Unsafe unsafe = Unsafe.getUnsafe(); + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // namespace for extended user attributes private static final String USER_NAMESPACE = "user."; @@ -174,14 +178,15 @@ public int read(String name, ByteBuffer dst) throws IOException { assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - if (dst instanceof sun.nio.ch.DirectBuffer buf) { + if (dst instanceof sun.nio.ch.DirectBuffer ddst) { + NIO_ACCESS.acquireSession(dst); try { - long address = buf.address() + pos; + long address = ddst.address() + pos; int n = read(name, address, rem); dst.position(pos + n); return n; } finally { - Reference.reachabilityFence(buf); + NIO_ACCESS.releaseSession(dst); } } else { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { @@ -237,13 +242,14 @@ public int write(String name, ByteBuffer src) throws IOException { int rem = (pos <= lim ? lim - pos : 0); if (src instanceof sun.nio.ch.DirectBuffer buf) { + NIO_ACCESS.acquireSession(src); try { long address = buf.address() + pos; write(name, address, rem); src.position(pos + rem); return rem; } finally { - Reference.reachabilityFence(buf); + NIO_ACCESS.releaseSession(src); } } else { try (NativeBuffer nb = NativeBuffers.getNativeBuffer(rem)) { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 2a833dbd77a..7a91d17e74c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -35,6 +35,8 @@ import javax.crypto.*; import javax.crypto.spec.*; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; @@ -55,6 +57,8 @@ */ final class P11AEADCipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // supported AEAD algorithms/transformations private enum Transformation { AES_GCM("AES", "GCM", "NOPADDING", 16, 16), @@ -705,84 +709,94 @@ private int implDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) } boolean doCancel = true; + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - byte[] in = null; - int inOfs = 0; - if (dataBuffer.size() > 0) { - if (inLen > 0) { - byte[] temp = new byte[inLen]; - inBuffer.get(temp); - dataBuffer.write(temp, 0, temp.length); - } - in = dataBuffer.toByteArray(); - inOfs = 0; - inLen = in.length; - } else { - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = inBuffer.position(); - } else { - if (inBuffer.hasArray()) { - in = inBuffer.array(); - inOfs = inBuffer.position() + inBuffer.arrayOffset(); + NIO_ACCESS.acquireSession(outBuffer); + try { + try { + ensureInitialized(); + + long inAddr = 0; + byte[] in = null; + int inOfs = 0; + if (dataBuffer.size() > 0) { + if (inLen > 0) { + byte[] temp = new byte[inLen]; + inBuffer.get(temp); + dataBuffer.write(temp, 0, temp.length); + } + in = dataBuffer.toByteArray(); + inOfs = 0; + inLen = in.length; } else { - in = new byte[inLen]; - inBuffer.get(in); + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = inBuffer.position(); + } else { + if (inBuffer.hasArray()) { + in = inBuffer.array(); + inOfs = inBuffer.position() + inBuffer.arrayOffset(); + } else { + in = new byte[inLen]; + inBuffer.get(in); + } + } + } + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); + } else { + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - } - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); - } else { - outArray = new byte[outLen]; - } - } - int k = 0; - if (encrypt) { - k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; - } else { - // Special handling to match SunJCE provider behavior - if (inLen == 0) { - return 0; + int k = 0; + if (encrypt) { + k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } else { + // Special handling to match SunJCE provider behavior + if (inLen == 0) { + return 0; + } + k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } + inBuffer.position(inBuffer.limit()); + outBuffer.position(outBuffer.position() + k); + return k; + } catch (PKCS11Exception e) { + // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only + // keep the operation active on CKR_BUFFER_TOO_SMALL errors or + // successful calls to determine the output length. However, + // these cases are not expected here because the output length + // is checked in the OpenJDK side before making the PKCS#11 call. + // Thus, doCancel can safely be 'false'. + doCancel = false; + handleException(e); + throw new ProviderException("doFinal() failed", e); + } finally { + if (encrypt) { + lastEncKey = this.p11Key; + lastEncIv = this.iv; + requireReinit = true; + } + reset(doCancel); } - k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - inBuffer.position(inBuffer.limit()); - outBuffer.position(outBuffer.position() + k); - return k; - } catch (PKCS11Exception e) { - // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only - // keep the operation active on CKR_BUFFER_TOO_SMALL errors or - // successful calls to determine the output length. However, - // these cases are not expected here because the output length - // is checked in the OpenJDK side before making the PKCS#11 call. - // Thus, doCancel can safely be 'false'. - doCancel = false; - handleException(e); - throw new ProviderException("doFinal() failed", e); } finally { - if (encrypt) { - lastEncKey = this.p11Key; - lastEncIv = this.iv; - requireReinit = true; - } - reset(doCancel); + NIO_ACCESS.releaseSession(inBuffer); } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java index 2574ae685ac..873c69d5b00 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Cipher.java @@ -34,6 +34,8 @@ import javax.crypto.*; import javax.crypto.spec.*; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; @@ -56,6 +58,8 @@ */ final class P11Cipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // mode constant for ECB mode private static final int MODE_ECB = 3; // mode constant for CBC mode @@ -678,115 +682,123 @@ private int implUpdate(ByteBuffer inBuffer, ByteBuffer outBuffer) throw new ShortBufferException(); } int origPos = inBuffer.position(); + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - int inOfs = 0; - byte[] inArray = null; - - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = origPos; - } else if (inBuffer.hasArray()) { - inArray = inBuffer.array(); - inOfs = (origPos + inBuffer.arrayOffset()); - } + NIO_ACCESS.acquireSession(outBuffer); + try { + ensureInitialized(); + + long inAddr = 0; + int inOfs = 0; + byte[] inArray = null; + + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = origPos; + } else if (inBuffer.hasArray()) { + inArray = inBuffer.array(); + inOfs = (origPos + inBuffer.arrayOffset()); + } - long outAddr = 0; - int outOfs = 0; - byte[] outArray = null; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = (outBuffer.position() + outBuffer.arrayOffset()); + long outAddr = 0; + int outOfs = 0; + byte[] outArray = null; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); } else { - outArray = new byte[outLen]; + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = (outBuffer.position() + outBuffer.arrayOffset()); + } else { + outArray = new byte[outLen]; + } } - } - int k = 0; - int newPadBufferLen = 0; - if (paddingObj != null && (!encrypt || reqBlockUpdates)) { - if (padBufferLen != 0) { - if (padBufferLen != padBuffer.length) { - int bufCapacity = padBuffer.length - padBufferLen; - if (inLen > bufCapacity) { - bufferInputBytes(inBuffer, bufCapacity); - inOfs += bufCapacity; - inLen -= bufCapacity; + int k = 0; + int newPadBufferLen = 0; + if (paddingObj != null && (!encrypt || reqBlockUpdates)) { + if (padBufferLen != 0) { + if (padBufferLen != padBuffer.length) { + int bufCapacity = padBuffer.length - padBufferLen; + if (inLen > bufCapacity) { + bufferInputBytes(inBuffer, bufCapacity); + inOfs += bufCapacity; + inLen -= bufCapacity; + } else { + bufferInputBytes(inBuffer, inLen); + return 0; + } + } + if (encrypt) { + k = token.p11.C_EncryptUpdate(session.id(), 0, + padBuffer, 0, padBufferLen, outAddr, outArray, + outOfs, outLen); } else { - bufferInputBytes(inBuffer, inLen); - return 0; + k = token.p11.C_DecryptUpdate(session.id(), 0, + padBuffer, 0, padBufferLen, outAddr, outArray, + outOfs, outLen); } + padBufferLen = 0; + } + newPadBufferLen = inLen & (blockSize - 1); + if (!encrypt && newPadBufferLen == 0) { + // While decrypting with implUpdate, the last encrypted block + // is always held in a buffer. If it's the final one (unknown + // at this point), it may contain padding bytes and need further + // processing. In implDoFinal (where we know it's the final one) + // the buffer is decrypted, unpadded and returned. + newPadBufferLen = padBuffer.length; + } + inLen -= newPadBufferLen; + } + if (inLen > 0) { + if (inAddr == 0 && inArray == null) { + inArray = new byte[inLen]; + inBuffer.get(inArray); + } else { + inBuffer.position(inBuffer.position() + inLen); } if (encrypt) { - k = token.p11.C_EncryptUpdate(session.id(), 0, - padBuffer, 0, padBufferLen, outAddr, outArray, - outOfs, outLen); + k += token.p11.C_EncryptUpdate(session.id(), inAddr, + inArray, inOfs, inLen, outAddr, outArray, + (outOfs + k), (outLen - k)); } else { - k = token.p11.C_DecryptUpdate(session.id(), 0, - padBuffer, 0, padBufferLen, outAddr, outArray, - outOfs, outLen); + k += token.p11.C_DecryptUpdate(session.id(), inAddr, + inArray, inOfs, inLen, outAddr, outArray, + (outOfs + k), (outLen - k)); } - padBufferLen = 0; } - newPadBufferLen = inLen & (blockSize - 1); - if (!encrypt && newPadBufferLen == 0) { - // While decrypting with implUpdate, the last encrypted block - // is always held in a buffer. If it's the final one (unknown - // at this point), it may contain padding bytes and need further - // processing. In implDoFinal (where we know it's the final one) - // the buffer is decrypted, unpadded and returned. - newPadBufferLen = padBuffer.length; + // update 'padBuffer' if using our own padding impl. + if (paddingObj != null && newPadBufferLen > 0) { + bufferInputBytes(inBuffer, newPadBufferLen); } - inLen -= newPadBufferLen; - } - if (inLen > 0) { - if (inAddr == 0 && inArray == null) { - inArray = new byte[inLen]; - inBuffer.get(inArray); + bytesBuffered += (inLen - k); + if (!(outBuffer instanceof DirectBuffer) && + !outBuffer.hasArray()) { + outBuffer.put(outArray, outOfs, k); } else { - inBuffer.position(inBuffer.position() + inLen); + outBuffer.position(outBuffer.position() + k); } - if (encrypt) { - k += token.p11.C_EncryptUpdate(session.id(), inAddr, - inArray, inOfs, inLen, outAddr, outArray, - (outOfs + k), (outLen - k)); - } else { - k += token.p11.C_DecryptUpdate(session.id(), inAddr, - inArray, inOfs, inLen, outAddr, outArray, - (outOfs + k), (outLen - k)); + return k; + } catch (PKCS11Exception e) { + // Reset input buffer to its original position for + inBuffer.position(origPos); + if (e.match(CKR_BUFFER_TOO_SMALL)) { + throw (ShortBufferException) + (new ShortBufferException().initCause(e)); } + // Some implementations such as the NSS Software Token do not + // cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate + // failure (as required by the PKCS#11 standard). See JDK-8258833 + // for further information. + reset(true); + throw new ProviderException("update() failed", e); + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - // update 'padBuffer' if using our own padding impl. - if (paddingObj != null && newPadBufferLen > 0) { - bufferInputBytes(inBuffer, newPadBufferLen); - } - bytesBuffered += (inLen - k); - if (!(outBuffer instanceof DirectBuffer) && - !outBuffer.hasArray()) { - outBuffer.put(outArray, outOfs, k); - } else { - outBuffer.position(outBuffer.position() + k); - } - return k; - } catch (PKCS11Exception e) { - // Reset input buffer to its original position for - inBuffer.position(origPos); - if (e.match(CKR_BUFFER_TOO_SMALL)) { - throw (ShortBufferException) - (new ShortBufferException().initCause(e)); - } - // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_EncryptUpdate/C_DecryptUpdate - // failure (as required by the PKCS#11 standard). See JDK-8258833 - // for further information. - reset(true); - throw new ProviderException("update() failed", e); + } finally { + NIO_ACCESS.releaseSession(inBuffer); } } @@ -877,99 +889,104 @@ private int implDoFinal(ByteBuffer outBuffer) } boolean doCancel = true; + NIO_ACCESS.acquireSession(outBuffer); try { - ensureInitialized(); - - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); + try { + ensureInitialized(); + + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); } else { - outArray = new byte[outLen]; + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - int k = 0; + int k = 0; - if (encrypt) { - if (paddingObj != null) { - int startOff = 0; - if (reqBlockUpdates) { - // call C_EncryptUpdate first if the padBuffer is full - // to make room for padding bytes - if (padBufferLen == padBuffer.length) { - k = token.p11.C_EncryptUpdate(session.id(), - 0, padBuffer, 0, padBufferLen, - outAddr, outArray, outOfs, outLen); - } else { - startOff = padBufferLen; + if (encrypt) { + if (paddingObj != null) { + int startOff = 0; + if (reqBlockUpdates) { + // call C_EncryptUpdate first if the padBuffer is full + // to make room for padding bytes + if (padBufferLen == padBuffer.length) { + k = token.p11.C_EncryptUpdate(session.id(), + 0, padBuffer, 0, padBufferLen, + outAddr, outArray, outOfs, outLen); + } else { + startOff = padBufferLen; + } } - } - int actualPadLen = paddingObj.setPaddingBytes(padBuffer, - startOff, requiredOutLen - bytesBuffered); - k += token.p11.C_EncryptUpdate(session.id(), - 0, padBuffer, 0, startOff + actualPadLen, - outAddr, outArray, outOfs + k, outLen - k); - } - // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_EncryptUpdate failure (as - // required by the PKCS#11 standard). Cancel is not needed - // only after this point. See JDK-8258833 for further - // information. - doCancel = false; - k += token.p11.C_EncryptFinal(session.id(), - outAddr, outArray, (outOfs + k), (outLen - k)); - } else { - // Special handling to match SunJCE provider behavior - if (bytesBuffered == 0 && padBufferLen == 0) { - return 0; - } - - if (paddingObj != null) { - if (padBufferLen != 0) { - k = token.p11.C_DecryptUpdate(session.id(), - 0, padBuffer, 0, padBufferLen, - 0, padBuffer, 0, padBuffer.length); - padBufferLen = 0; + int actualPadLen = paddingObj.setPaddingBytes(padBuffer, + startOff, requiredOutLen - bytesBuffered); + k += token.p11.C_EncryptUpdate(session.id(), + 0, padBuffer, 0, startOff + actualPadLen, + outAddr, outArray, outOfs + k, outLen - k); } // Some implementations such as the NSS Software Token do not - // cancel the operation upon a C_DecryptUpdate failure (as + // cancel the operation upon a C_EncryptUpdate failure (as // required by the PKCS#11 standard). Cancel is not needed // only after this point. See JDK-8258833 for further // information. doCancel = false; - k += token.p11.C_DecryptFinal(session.id(), - 0, padBuffer, k, padBuffer.length - k); + k += token.p11.C_EncryptFinal(session.id(), + outAddr, outArray, (outOfs + k), (outLen - k)); + } else { + // Special handling to match SunJCE provider behavior + if (bytesBuffered == 0 && padBufferLen == 0) { + return 0; + } - int actualPadLen = paddingObj.unpad(padBuffer, k); - k -= actualPadLen; - outArray = padBuffer; - outOfs = 0; + if (paddingObj != null) { + if (padBufferLen != 0) { + k = token.p11.C_DecryptUpdate(session.id(), + 0, padBuffer, 0, padBufferLen, + 0, padBuffer, 0, padBuffer.length); + padBufferLen = 0; + } + // Some implementations such as the NSS Software Token do not + // cancel the operation upon a C_DecryptUpdate failure (as + // required by the PKCS#11 standard). Cancel is not needed + // only after this point. See JDK-8258833 for further + // information. + doCancel = false; + k += token.p11.C_DecryptFinal(session.id(), + 0, padBuffer, k, padBuffer.length - k); + + int actualPadLen = paddingObj.unpad(padBuffer, k); + k -= actualPadLen; + outArray = padBuffer; + outOfs = 0; + } else { + doCancel = false; + k = token.p11.C_DecryptFinal(session.id(), + outAddr, outArray, outOfs, outLen); + } + } + if ((!encrypt && paddingObj != null) || + (!(outBuffer instanceof DirectBuffer) && + !outBuffer.hasArray())) { + outBuffer.put(outArray, outOfs, k); } else { - doCancel = false; - k = token.p11.C_DecryptFinal(session.id(), - outAddr, outArray, outOfs, outLen); + outBuffer.position(outBuffer.position() + k); } + return k; + } catch (PKCS11Exception e) { + handleException(e); + throw new ProviderException("doFinal() failed", e); + } finally { + reset(doCancel); } - if ((!encrypt && paddingObj != null) || - (!(outBuffer instanceof DirectBuffer) && - !outBuffer.hasArray())) { - outBuffer.put(outArray, outOfs, k); - } else { - outBuffer.position(outBuffer.position() + k); - } - return k; - } catch (PKCS11Exception e) { - handleException(e); - throw new ProviderException("doFinal() failed", e); } finally { - reset(doCancel); + NIO_ACCESS.releaseSession(outBuffer); } } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java index 1c667ae58e9..5a0aec89aa1 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Digest.java @@ -25,13 +25,14 @@ package sun.security.pkcs11; -import java.util.*; import java.nio.ByteBuffer; import java.security.*; import javax.crypto.SecretKey; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.util.MessageDigestSpi2; @@ -55,6 +56,8 @@ final class P11Digest extends MessageDigestSpi implements Cloneable, MessageDigestSpi2 { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + /* fields initialized, no session acquired */ private static final int S_BLANK = 1; @@ -268,13 +271,12 @@ protected void engineUpdate(ByteBuffer byteBuffer) { return; } - if (!(byteBuffer instanceof DirectBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { super.engineUpdate(byteBuffer); return; } fetchSession(); - long addr = ((DirectBuffer)byteBuffer).address(); int ofs = byteBuffer.position(); try { if (state == S_BUFFERED) { @@ -285,7 +287,12 @@ protected void engineUpdate(ByteBuffer byteBuffer) { token.p11.C_DigestUpdate(session.id(), 0, buffer, 0, bufOfs); bufOfs = 0; } - token.p11.C_DigestUpdate(session.id(), addr + ofs, null, 0, len); + NIO_ACCESS.acquireSession(byteBuffer); + try { + token.p11.C_DigestUpdate(session.id(), dByteBuffer.address() + ofs, null, 0, len); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); + } byteBuffer.position(ofs + len); } catch (PKCS11Exception e) { engineReset(); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java index 12dfcf6004e..cdd01d6f5fc 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java @@ -37,13 +37,14 @@ import java.util.HexFormat; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.jca.JCAUtil; import sun.security.pkcs11.wrapper.*; import static sun.security.pkcs11.wrapper.PKCS11Constants.*; import static sun.security.pkcs11.wrapper.PKCS11Exception.RV.*; import static sun.security.pkcs11.TemplateManager.*; -import static sun.security.pkcs11.P11Cipher.*; /** * P11 KeyWrap Cipher implementation class for native impl which only support @@ -58,6 +59,8 @@ */ final class P11KeyWrapCipher extends CipherSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private static final int BLK_SIZE = 8; // supported mode and padding with AES cipher @@ -552,78 +555,88 @@ private int implDoFinal(ByteBuffer inBuffer, ByteBuffer outBuffer) boolean doCancel = true; int k = 0; + NIO_ACCESS.acquireSession(inBuffer); try { - ensureInitialized(); - - long inAddr = 0; - byte[] in = null; - int inOfs = 0; - - if (dataBuffer.size() > 0) { - if (inBuffer != null && inLen > 0) { - byte[] temp = new byte[inLen]; - inBuffer.get(temp); - dataBuffer.write(temp, 0, temp.length); - } - - in = dataBuffer.toByteArray(); - inOfs = 0; - inLen = in.length; - } else { - if (inBuffer instanceof DirectBuffer) { - inAddr = ((DirectBuffer) inBuffer).address(); - inOfs = inBuffer.position(); - } else { - if (inBuffer.hasArray()) { - in = inBuffer.array(); - inOfs = inBuffer.position() + inBuffer.arrayOffset(); + NIO_ACCESS.acquireSession(outBuffer); + try { + try { + ensureInitialized(); + + long inAddr = 0; + byte[] in = null; + int inOfs = 0; + + if (dataBuffer.size() > 0) { + if (inBuffer != null && inLen > 0) { + byte[] temp = new byte[inLen]; + inBuffer.get(temp); + dataBuffer.write(temp, 0, temp.length); + } + + in = dataBuffer.toByteArray(); + inOfs = 0; + inLen = in.length; } else { - in = new byte[inLen]; - inBuffer.get(in); + if (inBuffer instanceof DirectBuffer dInBuffer) { + inAddr = dInBuffer.address(); + inOfs = inBuffer.position(); + } else { + if (inBuffer.hasArray()) { + in = inBuffer.array(); + inOfs = inBuffer.position() + inBuffer.arrayOffset(); + } else { + in = new byte[inLen]; + inBuffer.get(in); + } + } + } + long outAddr = 0; + byte[] outArray = null; + int outOfs = 0; + if (outBuffer instanceof DirectBuffer dOutBuffer) { + outAddr = dOutBuffer.address(); + outOfs = outBuffer.position(); + } else { + if (outBuffer.hasArray()) { + outArray = outBuffer.array(); + outOfs = outBuffer.position() + outBuffer.arrayOffset(); + } else { + outArray = new byte[outLen]; + } } - } - } - long outAddr = 0; - byte[] outArray = null; - int outOfs = 0; - if (outBuffer instanceof DirectBuffer) { - outAddr = ((DirectBuffer) outBuffer).address(); - outOfs = outBuffer.position(); - } else { - if (outBuffer.hasArray()) { - outArray = outBuffer.array(); - outOfs = outBuffer.position() + outBuffer.arrayOffset(); - } else { - outArray = new byte[outLen]; - } - } - if (opmode == Cipher.ENCRYPT_MODE) { - k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; - } else { - // Special handling to match SunJCE provider behavior - if (inLen == 0) { - return 0; + if (opmode == Cipher.ENCRYPT_MODE) { + k = token.p11.C_Encrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } else { + // Special handling to match SunJCE provider behavior + if (inLen == 0) { + return 0; + } + k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, + outAddr, outArray, outOfs, outLen); + doCancel = false; + } + inBuffer.position(inBuffer.limit()); + outBuffer.position(outBuffer.position() + k); + } catch (PKCS11Exception e) { + // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only + // keep the operation active on CKR_BUFFER_TOO_SMALL errors or + // successful calls to determine the output length. However, + // these cases are not expected here because the output length + // is checked in the OpenJDK side before making the PKCS#11 call. + // Thus, doCancel can safely be 'false'. + doCancel = false; + handleEncException("doFinal() failed", e); + } finally { + reset(doCancel); } - k = token.p11.C_Decrypt(session.id(), inAddr, in, inOfs, inLen, - outAddr, outArray, outOfs, outLen); - doCancel = false; + } finally { + NIO_ACCESS.releaseSession(outBuffer); } - inBuffer.position(inBuffer.limit()); - outBuffer.position(outBuffer.position() + k); - } catch (PKCS11Exception e) { - // As per the PKCS#11 standard, C_Encrypt and C_Decrypt may only - // keep the operation active on CKR_BUFFER_TOO_SMALL errors or - // successful calls to determine the output length. However, - // these cases are not expected here because the output length - // is checked in the OpenJDK side before making the PKCS#11 call. - // Thus, doCancel can safely be 'false'. - doCancel = false; - handleEncException("doFinal() failed", e); } finally { - reset(doCancel); + NIO_ACCESS.releaseSession(inBuffer); } return k; } diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java index 54a1986f6a8..cbf40bd39b4 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Mac.java @@ -32,6 +32,8 @@ import javax.crypto.MacSpi; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.pkcs11.wrapper.*; @@ -55,6 +57,8 @@ */ final class P11Mac extends MacSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // token instance private final Token token; @@ -246,13 +250,17 @@ protected void engineUpdate(ByteBuffer byteBuffer) { if (len <= 0) { return; } - if (!(byteBuffer instanceof DirectBuffer directBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { super.engineUpdate(byteBuffer); return; } - long addr = directBuffer.address(); int ofs = byteBuffer.position(); - token.p11.C_SignUpdate(session.id(), addr + ofs, null, 0, len); + NIO_ACCESS.acquireSession(byteBuffer); + try { + token.p11.C_SignUpdate(session.id(), dByteBuffer.address() + ofs, null, 0, len); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); + } byteBuffer.position(ofs + len); } catch (PKCS11Exception e) { throw new ProviderException("update() failed", e); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java index e90a4d2a6da..b7df5fd352a 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11PSSSignature.java @@ -25,13 +25,13 @@ package sun.security.pkcs11; -import java.io.ByteArrayOutputStream; -import java.io.IOException; import java.nio.ByteBuffer; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import java.util.Hashtable; -import java.util.Arrays; import java.security.*; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.MGF1ParameterSpec; @@ -68,6 +68,8 @@ */ final class P11PSSSignature extends SignatureSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private static final boolean DEBUG = false; // mappings of digest algorithms and their output length in bytes @@ -613,14 +615,15 @@ protected void engineUpdate(ByteBuffer byteBuffer) { isActive = true; switch (type) { case T_UPDATE -> { - if (byteBuffer instanceof DirectBuffer == false) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { // cannot do better than default impl super.engineUpdate(byteBuffer); return; } - long addr = ((DirectBuffer) byteBuffer).address(); int ofs = byteBuffer.position(); + NIO_ACCESS.acquireSession(byteBuffer); try { + long addr = dByteBuffer.address(); if (mode == M_SIGN) { if (DEBUG) System.out.println(this + ": Calling C_SignUpdate"); token.p11.C_SignUpdate @@ -635,6 +638,8 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } catch (PKCS11Exception e) { reset(false); throw new ProviderException("Update failed", e); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); } } case T_DIGEST -> { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java index e262d95c67f..23386daf29e 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Signature.java @@ -32,10 +32,12 @@ import java.security.*; import java.security.interfaces.*; import java.security.spec.AlgorithmParameterSpec; + +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.nio.ch.DirectBuffer; import sun.security.util.*; -import sun.security.x509.AlgorithmId; import sun.security.rsa.RSAUtil; import sun.security.rsa.RSAPadding; @@ -98,6 +100,8 @@ */ final class P11Signature extends SignatureSpi { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + // token instance private final Token token; @@ -575,14 +579,15 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } switch (type) { case T_UPDATE -> { - if (!(byteBuffer instanceof DirectBuffer)) { + if (!(byteBuffer instanceof DirectBuffer dByteBuffer)) { // cannot do better than default impl super.engineUpdate(byteBuffer); return; } - long addr = ((DirectBuffer) byteBuffer).address(); int ofs = byteBuffer.position(); + NIO_ACCESS.acquireSession(byteBuffer); try { + long addr = dByteBuffer.address(); if (mode == M_SIGN) { token.p11.C_SignUpdate (session.id(), addr + ofs, null, 0, len); @@ -595,6 +600,8 @@ protected void engineUpdate(ByteBuffer byteBuffer) { } catch (PKCS11Exception e) { reset(false); throw new ProviderException("Update failed", e); + } finally { + NIO_ACCESS.releaseSession(byteBuffer); } } case T_DIGEST -> { diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 348c9e8a668..6ad541b36a3 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -53,6 +53,8 @@ import com.sun.nio.sctp.NotificationHandler; import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpSocketOption; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.net.util.IPAddressUtil; import sun.nio.ch.DirectBuffer; import sun.nio.ch.IOStatus; @@ -74,6 +76,9 @@ public class SctpChannelImpl extends SctpChannel implements SelChImpl { + + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private final FileDescriptor fd; private final int fdVal; @@ -839,11 +844,16 @@ private int receiveIntoNativeBuffer(int fd, boolean peek) throws IOException { - int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek); + NIO_ACCESS.acquireSession(bb); + try { + int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem, peek); - if (n > 0) - bb.position(pos + n); - return n; + if (n > 0) + bb.position(pos + n); + return n; + } finally { + NIO_ACCESS.releaseSession(bb); + } } private InternalNotificationHandler internalNotificationHandler = @@ -1028,11 +1038,16 @@ private int sendFromNativeBuffer(int fd, assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, - port, -1 /*121*/, streamNumber, unordered, ppid); - if (written > 0) - bb.position(pos + written); - return written; + NIO_ACCESS.acquireSession(bb); + try { + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, -1 /*121*/, streamNumber, unordered, ppid); + if (written > 0) + bb.position(pos + written); + return written; + } finally { + NIO_ACCESS.releaseSession(bb); + } } @Override diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index ad708d0e71b..ca55e553e6a 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -53,6 +53,8 @@ import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpMultiChannel; import com.sun.nio.sctp.SctpSocketOption; +import jdk.internal.access.JavaNioAccess; +import jdk.internal.access.SharedSecrets; import sun.net.util.IPAddressUtil; import sun.nio.ch.DirectBuffer; import sun.nio.ch.NativeThread; @@ -71,6 +73,8 @@ public class SctpMultiChannelImpl extends SctpMultiChannel implements SelChImpl { + private static final JavaNioAccess NIO_ACCESS = SharedSecrets.getJavaNioAccess(); + private final FileDescriptor fd; private final int fdVal; @@ -583,10 +587,15 @@ private int receiveIntoNativeBuffer(int fd, int rem, int pos) throws IOException { - int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem); - if (n > 0) - bb.position(pos + n); - return n; + NIO_ACCESS.acquireSession(bb); + try { + int n = receive0(fd, resultContainer, ((DirectBuffer)bb).address() + pos, rem); + if (n > 0) + bb.position(pos + n); + return n; + } finally { + NIO_ACCESS.releaseSession(bb); + } } private InternalNotificationHandler internalNotificationHandler = @@ -908,11 +917,16 @@ private int sendFromNativeBuffer(int fd, assert (pos <= lim); int rem = (pos <= lim ? lim - pos : 0); - int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, - port, assocId, streamNumber, unordered, ppid); - if (written > 0) - bb.position(pos + written); - return written; + NIO_ACCESS.acquireSession(bb); + try { + int written = send0(fd, ((DirectBuffer)bb).address() + pos, rem, addr, + port, assocId, streamNumber, unordered, ppid); + if (written > 0) + bb.position(pos + written); + return written; + } finally { + NIO_ACCESS.releaseSession(bb); + } } @Override From 2243646fe35226e6d12d478483264270537a83cc Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 6 Dec 2022 12:26:06 +0000 Subject: [PATCH 071/494] 8298145: Remove ContiguousSpace::capacity Reviewed-by: tschatzl --- src/hotspot/share/gc/shared/space.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 17be87aa6ac..88706fc2be0 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -468,7 +468,6 @@ class ContiguousSpace: public CompactibleSpace { void check_mangled_unused_area_complete() PRODUCT_RETURN; // Size computations: sizes in bytes. - size_t capacity() const { return byte_size(bottom(), end()); } size_t used() const override { return byte_size(bottom(), top()); } size_t free() const override { return byte_size(top(), end()); } From b0e54328c530faf8aae2f48a37ff378215142689 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Tue, 6 Dec 2022 12:46:01 +0000 Subject: [PATCH 072/494] 8297687: new URI(S,S,S,S) throws exception with incorrect index position reported in the error message Reviewed-by: jpai --- src/java.base/share/classes/java/net/URI.java | 5 +- test/jdk/java/net/URI/Test.java | 49 ++++++++++++++++++- 2 files changed, 51 insertions(+), 3 deletions(-) diff --git a/src/java.base/share/classes/java/net/URI.java b/src/java.base/share/classes/java/net/URI.java index 9c2daae3ce2..27824076e80 100644 --- a/src/java.base/share/classes/java/net/URI.java +++ b/src/java.base/share/classes/java/net/URI.java @@ -3239,6 +3239,7 @@ private int parseAuthority(int start, int n) { int p = start; int q = p; + int qreg = p; URISyntaxException ex = null; boolean serverChars; @@ -3250,7 +3251,7 @@ private int parseAuthority(int start, int n) } else { serverChars = (scan(p, n, L_SERVER, H_SERVER) == n); } - regChars = (scan(p, n, L_REG_NAME, H_REG_NAME) == n); + regChars = ((qreg = scan(p, n, L_REG_NAME, H_REG_NAME)) == n); if (regChars && !serverChars) { // Must be a registry-based authority @@ -3294,7 +3295,7 @@ private int parseAuthority(int start, int n) // a malformed IPv6 address throw ex; } else { - fail("Illegal character in authority", q); + fail("Illegal character in authority", serverChars ? q : qreg); } } diff --git a/test/jdk/java/net/URI/Test.java b/test/jdk/java/net/URI/Test.java index f48c8d84dc9..00d473f87be 100644 --- a/test/jdk/java/net/URI/Test.java +++ b/test/jdk/java/net/URI/Test.java @@ -24,7 +24,7 @@ /* @test * @summary Unit test for java.net.URI * @bug 4464135 4505046 4503239 4438319 4991359 4866303 7023363 7041800 - * 7171415 6339649 6933879 8037396 8272072 8051627 + * 7171415 6339649 6933879 8037396 8272072 8051627 8297687 * @author Mark Reinhold */ @@ -1619,6 +1619,53 @@ static void bugs() { b8037396(); b8051627(); b8272072(); + b8297687(); + } + + private static void b8297687() { + // constructors that take a hostname should fail + test("ftps", "p.e.local|SIT@p.e.local", "/path", null) + .x().z(); + test("ftps", null,"p.e.local|SIT@p.e.local", -1, "/path", null, null) + .x().z(); + // constructors that take an authority component should succeed + test("ftps", "p.e.local|SIT@p.e.local", "/path", null,null) + .s("ftps") + .sp("//p.e.local%7CSIT@p.e.local/path") + .spd("//p.e.local|SIT@p.e.local/path") + .u("p.e.local%7CSIT") + .ud("p.e.local|SIT") + .h("p.e.local") + .n(-1) + .p("/path") + .pd("/path") + .z(); + + // check index in exception for constructors that should fail + try { + URI uri = new URI("ftps", "p.e.local|SIT@p.e.local", "/path", null); + throw new AssertionError("Expected URISyntaxException not thrown for " + uri); + } catch (URISyntaxException ex) { + if (ex.getMessage().contains("at index 16")) { + System.out.println("Got expected exception: " + ex); + } else { + throw new AssertionError("Exception does not point at index 16", ex); + } + } + testCount++; + + // check index in exception for constructors that should fail + try { + URI uri = new URI("ftps", null, "p.e.local|SIT@p.e.local", -1, "/path", null, null); + throw new AssertionError("Expected URISyntaxException not thrown for " + uri); + } catch (URISyntaxException ex) { + if (ex.getMessage().contains("at index 16")) { + System.out.println("Got expected exception: " + ex); + } else { + throw new AssertionError("Exception does not point at index 16", ex); + } + } + testCount++; } // 6339649 - include detail message from nested exception From 1e468320dc6e495343dbdf392cbcbda79672c7ad Mon Sep 17 00:00:00 2001 From: Aggelos Biboudis Date: Tue, 6 Dec 2022 13:00:10 +0000 Subject: [PATCH 073/494] 8297602: Compiler crash with type annotation and generic record during pattern matching Reviewed-by: jlahoda --- .../sun/tools/javac/code/TypeAnnotations.java | 6 ++- test/langtools/tools/javac/T8297602.java | 52 +++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/T8297602.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java index 9523d7dc433..90566406680 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/TypeAnnotations.java @@ -1086,7 +1086,11 @@ private Attribute.TypeCompound toTypeCompound(Attribute.Compound a, TypeAnnotati newPath, currentLambda, outer_type_index, location); } - + case DECONSTRUCTION_PATTERN: { + // TODO: Treat case labels as full type contexts for complete type annotation support in Record Patterns + // https://bugs.openjdk.org/browse/JDK-8298154 + return TypeAnnotationPosition.unknown; + } default: throw new AssertionError("Unresolved frame: " + frame + " of kind: " + frame.getKind() + diff --git a/test/langtools/tools/javac/T8297602.java b/test/langtools/tools/javac/T8297602.java new file mode 100644 index 00000000000..5d7519d0318 --- /dev/null +++ b/test/langtools/tools/javac/T8297602.java @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2022, 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 8297602 + * @summary Compiler crash with type annotation and generic record during pattern matching + * @enablePreview + * @compile --enable-preview -source ${jdk.version} -XDrawDiagnostics T8297602.java + */ +import java.lang.annotation.ElementType; +import java.lang.annotation.Target; + +public class T8297602 +{ + void meth(Foo p) { + switch(p) { + case Foo<@Annot(field = "") Integer>(): {} + }; + + if (p instanceof Foo<@Annot(field = "") Integer>()) { + + } + } + + @Target({ElementType.TYPE_USE}) + @interface Annot { + String field(); + } + + record Foo() { } +} From 203251ffc0ea8b9bb9c8b95c50434e4185020d84 Mon Sep 17 00:00:00 2001 From: Volodymyr Paprotski Date: Tue, 6 Dec 2022 16:47:45 +0000 Subject: [PATCH 074/494] 8297379: Enable the ByteBuffer path of Poly1305 optimizations Reviewed-by: sviswanathan, ascarpino, jnimeh --- .../com/sun/crypto/provider/Poly1305.java | 29 ++++++++--- .../provider/Poly1305IntrinsicFuzzTest.java | 51 +++++++++++++++---- .../crypto/full/Poly1305DigestBench.java | 22 +++++++- 3 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java b/src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java index d24b29cedbf..1752bb8dddd 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/Poly1305.java @@ -124,10 +124,10 @@ void engineUpdate(ByteBuffer buf) { BLOCK_LENGTH - blockOffset); if (bytesToWrite >= BLOCK_LENGTH) { - // If bytes to write == BLOCK_LENGTH, then we have no - // left-over data from previous updates and we can create - // the IntegerModuloP directly from the input buffer. - processBlock(buf, bytesToWrite); + // Have at least one full block in the buf, process all full blocks + int blockMultipleLength = remaining & (~(BLOCK_LENGTH-1)); + processMultipleBlocks(buf, blockMultipleLength); + remaining -= blockMultipleLength; } else { // We have some left-over data from previous updates, so // copy that into the holding block until we get a full block. @@ -138,9 +138,8 @@ void engineUpdate(ByteBuffer buf) { processBlock(block, 0, BLOCK_LENGTH); blockOffset = 0; } + remaining -= bytesToWrite; } - - remaining -= bytesToWrite; } } @@ -255,6 +254,24 @@ private void processMultipleBlocks(byte[] input, int offset, int length, long[] } } + private void processMultipleBlocks(ByteBuffer buf, int blockMultipleLength) { + if (buf.hasArray()) { + byte[] input = buf.array(); + int offset = buf.arrayOffset() + buf.position(); + long[] aLimbs = a.getLimbs(); + long[] rLimbs = r.getLimbs(); + + processMultipleBlocksCheck(input, offset, blockMultipleLength, aLimbs, rLimbs); + processMultipleBlocks(input, offset, blockMultipleLength, aLimbs, rLimbs); + buf.position(offset + blockMultipleLength); + } else { + while (blockMultipleLength >= BLOCK_LENGTH) { + processBlock(buf, BLOCK_LENGTH); + blockMultipleLength -= BLOCK_LENGTH; + } + } + } + private static void processMultipleBlocksCheck(byte[] input, int offset, int length, long[] aLimbs, long[] rLimbs) { Objects.checkFromIndexSize(offset, length, input.length); final int numLimbs = 5; // Intrinsic expects exactly 5 limbs diff --git a/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java index 3e7ecbad62e..dba3dcdacef 100644 --- a/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java +++ b/test/jdk/com/sun/crypto/provider/Cipher/ChaCha20/unittest/java.base/com/sun/crypto/provider/Poly1305IntrinsicFuzzTest.java @@ -26,6 +26,7 @@ import java.nio.ByteBuffer; import java.util.Arrays; +import java.util.Random; import javax.crypto.spec.SecretKeySpec; @@ -36,7 +37,7 @@ public class Poly1305IntrinsicFuzzTest { public static void main(String[] args) throws Exception { //Note: it might be useful to increase this number during development of new Poly1305 intrinsics - final int repeat = 100; + final int repeat = 1000; for (int i = 0; i < repeat; i++) { run(); } @@ -44,7 +45,7 @@ public static void main(String[] args) throws Exception { } public static void run() throws Exception { - java.util.Random rnd = new java.util.Random(); + Random rnd = new Random(); long seed = rnd.nextLong(); rnd.setSeed(seed); @@ -52,6 +53,7 @@ public static void run() throws Exception { rnd.nextBytes(key); int msgLen = rnd.nextInt(128, 4096); // x86_64 intrinsic requires 256 bytes minimum byte[] message = new byte[msgLen]; + rnd.nextBytes(message); Poly1305 authenticator = new Poly1305(); Poly1305 authenticatorSlow = new Poly1305(); @@ -62,20 +64,22 @@ public static void run() throws Exception { authenticator.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null); authenticatorSlow.engineInit(new SecretKeySpec(key, 0, 32, "Poly1305"), null); - if (rnd.nextBoolean()) { + if (rnd.nextBoolean() && message.length > 16) { // Prime just the buffer and/or accumulator (buffer can keep at most 16 bytes from previous engineUpdate) - int initDataLen = rnd.nextInt(8, 24); - authenticator.engineUpdate(message, 0, initDataLen); - slowUpdate(authenticatorSlow, message, 0, initDataLen); + int initDataLen = rnd.nextInt(1, 16); + int initDataOffset = rnd.nextInt(0, message.length - initDataLen); + fastUpdate(authenticator, rnd, message, initDataOffset, initDataLen); + slowUpdate(authenticatorSlow, message, initDataOffset, initDataLen); } if (rnd.nextBoolean()) { // Multiple calls to engineUpdate - authenticator.engineUpdate(message, 0, message.length); - slowUpdate(authenticatorSlow, message, 0, message.length); + int initDataOffset = rnd.nextInt(0, message.length); + fastUpdate(authenticator, rnd, message, initDataOffset, message.length - initDataOffset); + slowUpdate(authenticatorSlow, message, initDataOffset, message.length - initDataOffset); } - authenticator.engineUpdate(message, 0, message.length); + fastUpdate(authenticator, rnd, message, 0, message.length); slowUpdate(authenticatorSlow, message, 0, message.length); byte[] tag = authenticator.engineDoFinal(); @@ -87,9 +91,34 @@ public static void run() throws Exception { } static void slowUpdate(Poly1305 authenticator, byte[] message, int offset, int len) { - len = Math.min(message.length, offset + len); - for (int i = offset; i < len; i++) { + for (int i = offset; i < offset + len; i++) { authenticator.engineUpdate(message[i]); } } + + static void fastUpdate(Poly1305 authenticator, Random rnd, byte[] message, int offset, int len) { + ByteBuffer buf; + switch(rnd.nextInt(4)) { + case 0: // byte[] + authenticator.engineUpdate(message, offset, len); + break; + case 1: // ByteArray with backing array + buf = ByteBuffer.wrap(message, offset, len) + .order(java.nio.ByteOrder.LITTLE_ENDIAN); + authenticator.engineUpdate(buf); + break; + case 2: // ByteArray with backing array (non-zero position) + buf = ByteBuffer.wrap(message, 0, len+offset) + .order(java.nio.ByteOrder.LITTLE_ENDIAN) + .position(offset); + authenticator.engineUpdate(buf); + break; + case 3: // ByteArray without backing array (wont be sent to intrinsic) + buf = ByteBuffer.wrap(message, offset, len) + .asReadOnlyBuffer() + .order(java.nio.ByteOrder.LITTLE_ENDIAN); + authenticator.engineUpdate(buf); + break; + } + } } diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java b/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java index aa45aa2e398..15613557fb9 100644 --- a/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java +++ b/test/micro/org/openjdk/bench/javax/crypto/full/Poly1305DigestBench.java @@ -37,6 +37,7 @@ import org.openjdk.jmh.annotations.Fork; import org.openjdk.jmh.annotations.Warmup; import org.openjdk.jmh.annotations.Measurement; +import java.nio.ByteBuffer; @Measurement(iterations = 3, time = 10) @Warmup(iterations = 3, time = 10) @@ -49,7 +50,7 @@ public class Poly1305DigestBench extends CryptoBase { private byte[][] data; int index = 0; - private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineFinal; + private static MethodHandle polyEngineInit, polyEngineUpdate, polyEngineUpdateBuf, polyEngineFinal; private static Object polyObj; static { @@ -68,6 +69,10 @@ public class Poly1305DigestBench extends CryptoBase { m.setAccessible(true); polyEngineUpdate = lookup.unreflect(m); + m = polyClazz.getDeclaredMethod("engineUpdate", ByteBuffer.class); + m.setAccessible(true); + polyEngineUpdateBuf = lookup.unreflect(m); + m = polyClazz.getDeclaredMethod("engineDoFinal"); m.setAccessible(true); polyEngineFinal = lookup.unreflect(m); @@ -83,7 +88,7 @@ public void setup() { } @Benchmark - public byte[] digest() { + public byte[] digestBytes() { try { byte[] d = data[index]; index = (index +1) % SET_SIZE; @@ -94,4 +99,17 @@ public byte[] digest() { throw new RuntimeException(ex); } } + + @Benchmark + public byte[] digestBuffer() { + try { + byte[] d = data[index]; + index = (index +1) % SET_SIZE; + polyEngineInit.invoke(polyObj, new SecretKeySpec(d, 0, 32, "Poly1305"), null); + polyEngineUpdateBuf.invoke(polyObj, ByteBuffer.wrap(d, 0, d.length)); + return (byte[])polyEngineFinal.invoke(polyObj); + } catch (Throwable ex) { + throw new RuntimeException(ex); + } + } } From 0d2a9ee5287779c2e33fc0bfda84aa6128d8f479 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 6 Dec 2022 16:55:12 +0000 Subject: [PATCH 075/494] 8298142: Update internal comment on language features in SourceVersion Reviewed-by: sundar, jlahoda --- .../share/classes/javax/lang/model/SourceVersion.java | 4 ++++ .../share/classes/com/sun/tools/javac/code/Source.java | 10 +++++----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index 26be8fbfc32..be3fb580de7 100644 --- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -69,6 +69,8 @@ public enum SourceVersion { * 18: no changes (pattern matching for switch in second preview) * 19: no changes (pattern matching for switch in third preview, * record patterns in preview) + * 20: no changes (pattern matching for switch in fourth preview, + * record patterns in second preview) */ /** @@ -362,6 +364,8 @@ public enum SourceVersion { * The version recognized by the Java Platform, Standard Edition * 20. * + * No major changes from the prior release. + * * @since 20 * * @see Date: Tue, 6 Dec 2022 18:32:42 +0000 Subject: [PATCH 076/494] 8297958: NMT: Display peak values Reviewed-by: jsjolen, sjohanss --- .../share/services/mallocSiteTable.hpp | 4 ++ src/hotspot/share/services/mallocTracker.cpp | 33 +++------- src/hotspot/share/services/mallocTracker.hpp | 33 ++++++---- src/hotspot/share/services/memReporter.cpp | 62 +++++++++++++------ src/hotspot/share/services/memReporter.hpp | 6 +- 5 files changed, 81 insertions(+), 57 deletions(-) diff --git a/src/hotspot/share/services/mallocSiteTable.hpp b/src/hotspot/share/services/mallocSiteTable.hpp index 75baad30615..74cc579dd30 100644 --- a/src/hotspot/share/services/mallocSiteTable.hpp +++ b/src/hotspot/share/services/mallocSiteTable.hpp @@ -46,8 +46,12 @@ class MallocSite : public AllocationSite { // Memory allocated from this code path size_t size() const { return _c.size(); } + // Peak memory ever allocated from this code path + size_t peak_size() const { return _c.peak_size(); } // The number of calls were made size_t count() const { return _c.count(); } + + const MemoryCounter* counter() const { return &_c; } }; // Malloc site hashtable entry diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index 9ecc7505452..4d2eca4f587 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -27,6 +27,7 @@ #include "jvm_io.h" #include "logging/log.hpp" #include "runtime/arguments.hpp" +#include "runtime/atomic.hpp" #include "runtime/os.hpp" #include "runtime/safefetch.hpp" #include "services/mallocHeader.inline.hpp" @@ -42,34 +43,20 @@ size_t MallocMemorySummary::_limits_per_category[mt_number_of_types] = { 0 }; size_t MallocMemorySummary::_total_limit = 0; #ifdef ASSERT -void MemoryCounter::update_peak_count(size_t count) { - size_t peak_cnt = peak_count(); - while (peak_cnt < count) { - size_t old_cnt = Atomic::cmpxchg(&_peak_count, peak_cnt, count, memory_order_relaxed); - if (old_cnt != peak_cnt) { - peak_cnt = old_cnt; - } - } -} - -void MemoryCounter::update_peak_size(size_t sz) { +void MemoryCounter::update_peak(size_t size, size_t cnt) { size_t peak_sz = peak_size(); - while (peak_sz < sz) { - size_t old_sz = Atomic::cmpxchg(&_peak_size, peak_sz, sz, memory_order_relaxed); - if (old_sz != peak_sz) { + while (peak_sz < size) { + size_t old_sz = Atomic::cmpxchg(&_peak_size, peak_sz, size, memory_order_relaxed); + if (old_sz == peak_sz) { + // I won + _peak_count = cnt; + break; + } else { peak_sz = old_sz; } } } - -size_t MemoryCounter::peak_count() const { - return Atomic::load(&_peak_count); -} - -size_t MemoryCounter::peak_size() const { - return Atomic::load(&_peak_size); -} -#endif +#endif // ASSERT // Total malloc'd memory used by arenas size_t MallocMemorySnapshot::total_arena() const { diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 575bc21ee08..556467d4aa3 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -45,8 +45,13 @@ class MemoryCounter { volatile size_t _count; volatile size_t _size; - DEBUG_ONLY(volatile size_t _peak_count;) - DEBUG_ONLY(volatile size_t _peak_size; ) +#ifdef ASSERT + // Peak size and count. Note: Peak count is the count at the point + // peak size was reached, not the absolute highest peak count. + volatile size_t _peak_count; + volatile size_t _peak_size; + void update_peak(size_t size, size_t cnt); +#endif // ASSERT public: MemoryCounter() : _count(0), _size(0) { @@ -58,9 +63,8 @@ class MemoryCounter { size_t cnt = Atomic::add(&_count, size_t(1), memory_order_relaxed); if (sz > 0) { size_t sum = Atomic::add(&_size, sz, memory_order_relaxed); - DEBUG_ONLY(update_peak_size(sum);) + DEBUG_ONLY(update_peak(sum, cnt);) } - DEBUG_ONLY(update_peak_count(cnt);) } inline void deallocate(size_t sz) { @@ -76,19 +80,20 @@ class MemoryCounter { if (sz != 0) { assert(sz >= 0 || size() >= size_t(-sz), "Must be"); size_t sum = Atomic::add(&_size, size_t(sz), memory_order_relaxed); - DEBUG_ONLY(update_peak_size(sum);) + DEBUG_ONLY(update_peak(sum, _count);) } } inline size_t count() const { return Atomic::load(&_count); } inline size_t size() const { return Atomic::load(&_size); } -#ifdef ASSERT - void update_peak_count(size_t cnt); - void update_peak_size(size_t sz); - size_t peak_count() const; - size_t peak_size() const; -#endif // ASSERT + inline size_t peak_count() const { + return DEBUG_ONLY(Atomic::load(&_peak_count)) NOT_DEBUG(0); + } + + inline size_t peak_size() const { + return DEBUG_ONLY(Atomic::load(&_peak_size)) NOT_DEBUG(0); + } }; /* @@ -125,12 +130,14 @@ class MallocMemory { } inline size_t malloc_size() const { return _malloc.size(); } + inline size_t malloc_peak_size() const { return _malloc.peak_size(); } inline size_t malloc_count() const { return _malloc.count();} inline size_t arena_size() const { return _arena.size(); } + inline size_t arena_peak_size() const { return _arena.peak_size(); } inline size_t arena_count() const { return _arena.count(); } - DEBUG_ONLY(inline const MemoryCounter& malloc_counter() const { return _malloc; }) - DEBUG_ONLY(inline const MemoryCounter& arena_counter() const { return _arena; }) + const MemoryCounter* malloc_counter() const { return &_malloc; } + const MemoryCounter* arena_counter() const { return &_arena; } }; class MallocMemorySummary; diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp index b910bc0b34c..4ef40ad196c 100644 --- a/src/hotspot/share/services/memReporter.cpp +++ b/src/hotspot/share/services/memReporter.cpp @@ -45,11 +45,14 @@ void MemReporterBase::print_total(size_t reserved, size_t committed) const { amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale); } -void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) const { +void MemReporterBase::print_malloc(const MemoryCounter* c, MEMFLAGS flag) const { const char* scale = current_scale(); outputStream* out = output(); const char* alloc_type = (flag == mtThreadStack) ? "" : "malloc="; + const size_t amount = c->size(); + const size_t count = c->count(); + if (flag != mtNone) { out->print("(%s" SIZE_FORMAT "%s type=%s", alloc_type, amount_in_current_scale(amount), scale, NMTUtil::flag_to_name(flag)); @@ -58,11 +61,21 @@ void MemReporterBase::print_malloc(size_t amount, size_t count, MEMFLAGS flag) c amount_in_current_scale(amount), scale); } + // blends out mtChunk count number if (count > 0) { out->print(" #" SIZE_FORMAT "", count); } out->print(")"); + + size_t pk_amount = c->peak_size(); + if (pk_amount == amount) { + out->print_raw(" (at peak)"); + } else if (pk_amount > amount) { + size_t pk_count = c->peak_count(); + out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", + amount_in_current_scale(pk_amount), scale, pk_count); + } } void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) const { @@ -71,9 +84,9 @@ void MemReporterBase::print_virtual_memory(size_t reserved, size_t committed) co amount_in_current_scale(reserved), scale, amount_in_current_scale(committed), scale); } -void MemReporterBase::print_malloc_line(size_t amount, size_t count) const { +void MemReporterBase::print_malloc_line(const MemoryCounter* c) const { output()->print("%28s", " "); - print_malloc(amount, count); + print_malloc(c); output()->print_cr(" "); } @@ -83,10 +96,26 @@ void MemReporterBase::print_virtual_memory_line(size_t reserved, size_t committe output()->print_cr(" "); } -void MemReporterBase::print_arena_line(size_t amount, size_t count) const { +void MemReporterBase::print_arena_line(const MemoryCounter* c) const { const char* scale = current_scale(); - output()->print_cr("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", " ", + outputStream* out = output(); + + const size_t amount = c->size(); + const size_t count = c->count(); + + out->print("%27s (arena=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", "", amount_in_current_scale(amount), scale, count); + + size_t pk_amount = c->peak_size(); + if (pk_amount == amount) { + out->print_raw(" (at peak)"); + } else if (pk_amount > amount) { + size_t pk_count = c->peak_count(); + out->print(" (peak=" SIZE_FORMAT "%s #" SIZE_FORMAT ")", + amount_in_current_scale(pk_amount), scale, pk_count); + } + + out->cr(); } void MemReporterBase::print_virtual_memory_region(const char* type, address base, size_t size) const { @@ -195,18 +224,18 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, } // report malloc'd memory - if (amount_in_current_scale(malloc_memory->malloc_size()) > 0) { - // We don't know how many arena chunks are in used, so don't report the count - size_t count = (flag == mtChunk) ? 0 : malloc_memory->malloc_count(); - print_malloc_line(malloc_memory->malloc_size(), count); + if (amount_in_current_scale(malloc_memory->malloc_size()) > 0 + DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->malloc_peak_size()) > 0)) { + print_malloc_line(malloc_memory->malloc_counter()); } if (amount_in_current_scale(virtual_memory->reserved()) > 0) { print_virtual_memory_line(virtual_memory->reserved(), virtual_memory->committed()); } - if (amount_in_current_scale(malloc_memory->arena_size()) > 0) { - print_arena_line(malloc_memory->arena_size(), malloc_memory->arena_count()); + if (amount_in_current_scale(malloc_memory->arena_size()) > 0 + DEBUG_ONLY(|| amount_in_current_scale(malloc_memory->arena_peak_size()) > 0)) { + print_arena_line(malloc_memory->arena_counter()); } if (flag == mtNMT && @@ -271,12 +300,9 @@ int MemDetailReporter::report_malloc_sites() { const MallocSite* malloc_site; int num_omitted = 0; while ((malloc_site = malloc_itr.next()) != NULL) { - // Don't report free sites; does not count toward omitted count. - if (malloc_site->size() == 0) { - continue; - } - // Don't report if site has allocated less than one unit of whatever our scale is - if (scale() > 1 && amount_in_current_scale(malloc_site->size()) == 0) { + // Don't report if site has never allocated less than one unit of whatever our scale is + if (scale() > 1 && amount_in_current_scale(malloc_site->size()) == 0 + DEBUG_ONLY(&& amount_in_current_scale(malloc_site->peak_size()) == 0)) { num_omitted ++; continue; } @@ -286,7 +312,7 @@ int MemDetailReporter::report_malloc_sites() { MEMFLAGS flag = malloc_site->flag(); assert(NMTUtil::flag_is_valid(flag) && flag != mtNone, "Must have a valid memory type"); - print_malloc(malloc_site->size(), malloc_site->count(),flag); + print_malloc(malloc_site->counter(), flag); out->print_cr("\n"); } return num_omitted; diff --git a/src/hotspot/share/services/memReporter.hpp b/src/hotspot/share/services/memReporter.hpp index 1642ce8376f..30dee6797e0 100644 --- a/src/hotspot/share/services/memReporter.hpp +++ b/src/hotspot/share/services/memReporter.hpp @@ -80,12 +80,12 @@ class MemReporterBase : public StackObj { // Print summary total, malloc and virtual memory void print_total(size_t reserved, size_t committed) const; - void print_malloc(size_t amount, size_t count, MEMFLAGS flag = mtNone) const; + void print_malloc(const MemoryCounter* c, MEMFLAGS flag = mtNone) const; void print_virtual_memory(size_t reserved, size_t committed) const; - void print_malloc_line(size_t amount, size_t count) const; + void print_malloc_line(const MemoryCounter* c) const; void print_virtual_memory_line(size_t reserved, size_t committed) const; - void print_arena_line(size_t amount, size_t count) const; + void print_arena_line(const MemoryCounter* c) const; void print_virtual_memory_region(const char* type, address base, size_t size) const; }; From ea83cb960d07ffa9384aad6a1e2a0233e3ebbdd1 Mon Sep 17 00:00:00 2001 From: Rajat Mahajan Date: Tue, 6 Dec 2022 18:43:02 +0000 Subject: [PATCH 077/494] 8297450: ScaledTextFieldBorderTest.java fails when run with -show parameter Reviewed-by: aivanov, honkar --- .../border/LineBorder/ScaledTextFieldBorderTest.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java index 5e2868ed506..ea8254c401a 100644 --- a/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java +++ b/test/jdk/javax/swing/border/LineBorder/ScaledTextFieldBorderTest.java @@ -246,6 +246,8 @@ private static JComponent createUI() { childPanel.add(Box.createHorizontalStrut(4)); contentPanel.add(childPanel); + contentPanel.add(Box.createVerticalStrut(4)); + if (textFieldSize == null) { textFieldSize = textField.getPreferredSize(); borderColor = tfBorder.getLineColor().getRGB(); @@ -254,6 +256,7 @@ private static JComponent createUI() { textField.setBounds(i, 0, textFieldSize.width, textFieldSize.height); childPanel.setBounds(0, (textFieldSize.height + 4) * i, textFieldSize.width + i + 4, textFieldSize.height); + panelLocations.add(childPanel.getLocation()); } contentPanel.setSize(textFieldSize.width + 4, @@ -261,11 +264,6 @@ private static JComponent createUI() { panelColor = contentPanel.getBackground().getRGB(); - // Save coordinates of the panels - for (Component comp : contentPanel.getComponents()) { - panelLocations.add(comp.getLocation()); - } - return contentPanel; } From 79d163d4994d235266117b425498b0df3d16c3c4 Mon Sep 17 00:00:00 2001 From: Mark Powers Date: Tue, 6 Dec 2022 20:36:50 +0000 Subject: [PATCH 078/494] 8293412: Remove unnecessary java.security.egd overrides Reviewed-by: xuelei, djelinski --- .../provider/SeedGenerator/SeedGeneratorChoice.java | 4 ++-- .../tools/jarsigner/compatibility/Compatibility.java | 10 ++-------- test/lib/jdk/test/lib/SecurityTools.java | 6 +----- 3 files changed, 5 insertions(+), 15 deletions(-) diff --git a/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java b/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java index 581dc54216b..01c3dfd06a1 100644 --- a/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java +++ b/test/jdk/sun/security/provider/SeedGenerator/SeedGeneratorChoice.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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 6998583 8141039 * @summary NativeSeedGenerator is making 8192 byte read requests from * entropy pool on each init. - * @run main/othervm -Djava.security.egd=file:/dev/random SeedGeneratorChoice + * @run main/othervm -Djava.security.egd=file:/dev/urandom SeedGeneratorChoice * @run main/othervm -Djava.security.egd=file:filename SeedGeneratorChoice */ diff --git a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java index 87fa6483009..b0e65f17441 100644 --- a/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java +++ b/test/jdk/sun/security/tools/jarsigner/compatibility/Compatibility.java @@ -1036,15 +1036,9 @@ private static OutputAnalyzer execTool(String toolPath, String... args) long start = System.currentTimeMillis(); try { String[] cmd; - if (Platform.isWindows()) { - cmd = new String[args.length + 3]; - System.arraycopy(args, 0, cmd, 3, args.length); - } else { - cmd = new String[args.length + 4]; - cmd[3] = "-J-Djava.security.egd=file:/dev/./urandom"; - System.arraycopy(args, 0, cmd, 4, args.length); - } + cmd = new String[args.length + 3]; + System.arraycopy(args, 0, cmd, 3, args.length); cmd[0] = toolPath; cmd[1] = "-J-Duser.language=en"; cmd[2] = "-J-Duser.country=US"; diff --git a/test/lib/jdk/test/lib/SecurityTools.java b/test/lib/jdk/test/lib/SecurityTools.java index 6e3a55f7e5c..ff13343ad32 100644 --- a/test/lib/jdk/test/lib/SecurityTools.java +++ b/test/lib/jdk/test/lib/SecurityTools.java @@ -40,8 +40,7 @@ /** * Run security tools (including jarsigner and keytool) in a new process. * The en_US locale is always used so a test can always match output to - * English text. {@code /dev/urandom} is used as entropy source so tool will - * not block because of entropy scarcity. An argument can be a normal string, + * English text. An argument can be a normal string, * {@code -Jvm-options}, or {@code $sysProp}. */ public class SecurityTools { @@ -58,9 +57,6 @@ public static ProcessBuilder getProcessBuilder(String tool, List args) { JDKToolLauncher launcher = JDKToolLauncher.createUsingTestJDK(tool) .addVMArg("-Duser.language=en") .addVMArg("-Duser.country=US"); - if (!Platform.isWindows()) { - launcher.addVMArg("-Djava.security.egd=file:/dev/./urandom"); - } for (String arg : args) { if (arg.startsWith("-J")) { launcher.addVMArg(arg.substring(2)); From 2cdc0195655317cb0b04f76fd8dce5e40bf52774 Mon Sep 17 00:00:00 2001 From: Christian Stein Date: Tue, 6 Dec 2022 20:51:06 +0000 Subject: [PATCH 079/494] 8298178: Update to use jtreg 7.1.1 Reviewed-by: erikj --- make/autoconf/lib-tests.m4 | 2 +- make/conf/github-actions.conf | 2 +- make/conf/jib-profiles.js | 4 ++-- test/hotspot/jtreg/TEST.ROOT | 2 +- test/jaxp/TEST.ROOT | 2 +- test/jdk/TEST.ROOT | 2 +- test/langtools/TEST.ROOT | 2 +- test/lib-test/TEST.ROOT | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/make/autoconf/lib-tests.m4 b/make/autoconf/lib-tests.m4 index 0b4b138ccd7..9d3080d2050 100644 --- a/make/autoconf/lib-tests.m4 +++ b/make/autoconf/lib-tests.m4 @@ -28,7 +28,7 @@ ################################################################################ # Minimum supported version -JTREG_MINIMUM_VERSION=7.1 +JTREG_MINIMUM_VERSION=7.1.1 ############################################################################### # diff --git a/make/conf/github-actions.conf b/make/conf/github-actions.conf index fa7062b6fa9..b7c27797034 100644 --- a/make/conf/github-actions.conf +++ b/make/conf/github-actions.conf @@ -26,7 +26,7 @@ # Versions and download locations for dependencies used by GitHub Actions (GHA) GTEST_VERSION=1.8.1 -JTREG_VERSION=7.1+1 +JTREG_VERSION=7.1.1+1 LINUX_X64_BOOT_JDK_EXT=tar.gz LINUX_X64_BOOT_JDK_URL=https://download.java.net/java/GA/jdk19/877d6127e982470ba2a7faa31cc93d04/36/GPL/openjdk-19_linux-x64_bin.tar.gz diff --git a/make/conf/jib-profiles.js b/make/conf/jib-profiles.js index 4ffc7e50259..6ddd13067ad 100644 --- a/make/conf/jib-profiles.js +++ b/make/conf/jib-profiles.js @@ -1135,9 +1135,9 @@ var getJibProfilesDependencies = function (input, common) { jtreg: { server: "jpg", product: "jtreg", - version: "7.1", + version: "7.1.1", build_number: "1", - file: "bundles/jtreg-7.1+1.zip", + file: "bundles/jtreg-7.1.1+1.zip", environment_name: "JT_HOME", environment_path: input.get("jtreg", "home_path") + "/bin", configure_args: "--with-jtreg=" + input.get("jtreg", "home_path"), diff --git a/test/hotspot/jtreg/TEST.ROOT b/test/hotspot/jtreg/TEST.ROOT index aa34e37488a..8b16798e3d7 100644 --- a/test/hotspot/jtreg/TEST.ROOT +++ b/test/hotspot/jtreg/TEST.ROOT @@ -80,7 +80,7 @@ requires.properties= \ jdk.containerized # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../../ notation to reach them diff --git a/test/jaxp/TEST.ROOT b/test/jaxp/TEST.ROOT index 8a5f37a5c05..fe569a3b5d1 100644 --- a/test/jaxp/TEST.ROOT +++ b/test/jaxp/TEST.ROOT @@ -23,7 +23,7 @@ modules=java.xml groups=TEST.groups # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/jdk/TEST.ROOT b/test/jdk/TEST.ROOT index 13f0d6249ad..2dbf5cd7822 100644 --- a/test/jdk/TEST.ROOT +++ b/test/jdk/TEST.ROOT @@ -71,7 +71,7 @@ requires.properties= \ jdk.containerized # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them diff --git a/test/langtools/TEST.ROOT b/test/langtools/TEST.ROOT index 465e412b21b..04485c0d7ed 100644 --- a/test/langtools/TEST.ROOT +++ b/test/langtools/TEST.ROOT @@ -15,7 +15,7 @@ keys=intermittent randomness needs-src needs-src-jdk_javadoc groups=TEST.groups # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Use new module options useNewOptions=true diff --git a/test/lib-test/TEST.ROOT b/test/lib-test/TEST.ROOT index cbda44ae379..306d2bd7c6e 100644 --- a/test/lib-test/TEST.ROOT +++ b/test/lib-test/TEST.ROOT @@ -29,7 +29,7 @@ keys=randomness # Minimum jtreg version -requiredVersion=7.1+1 +requiredVersion=7.1.1+1 # Path to libraries in the topmost test directory. This is needed so @library # does not need ../../ notation to reach them From cd2182a9967917e733e486d918e9aeba3bd35ee8 Mon Sep 17 00:00:00 2001 From: Martin Doerr Date: Tue, 6 Dec 2022 20:56:48 +0000 Subject: [PATCH 080/494] 8295724: VirtualMachineError: Out of space in CodeCache for method handle intrinsic Reviewed-by: kvn, dlong --- src/hotspot/share/code/nmethod.cpp | 53 +++++++++++- src/hotspot/share/code/nmethod.hpp | 4 + src/hotspot/share/gc/shared/gcBehaviours.cpp | 5 ++ src/hotspot/share/oops/method.hpp | 3 +- .../MHIntrinsicAllocFailureTest.java | 85 +++++++++++++++++++ 5 files changed, 147 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/codecache/MHIntrinsicAllocFailureTest.java diff --git a/src/hotspot/share/code/nmethod.cpp b/src/hotspot/share/code/nmethod.cpp index e03ab23c4c6..5ec7f71b826 100644 --- a/src/hotspot/share/code/nmethod.cpp +++ b/src/hotspot/share/code/nmethod.cpp @@ -451,6 +451,42 @@ void nmethod::init_defaults() { #endif } +#ifdef ASSERT +class CheckForOopsClosure : public OopClosure { + bool _found_oop = false; + public: + virtual void do_oop(oop* o) { _found_oop = true; } + virtual void do_oop(narrowOop* o) { _found_oop = true; } + bool found_oop() { return _found_oop; } +}; +class CheckForMetadataClosure : public MetadataClosure { + bool _found_metadata = false; + Metadata* _ignore = nullptr; + public: + CheckForMetadataClosure(Metadata* ignore) : _ignore(ignore) {} + virtual void do_metadata(Metadata* md) { if (md != _ignore) _found_metadata = true; } + bool found_metadata() { return _found_metadata; } +}; + +static void assert_no_oops_or_metadata(nmethod* nm) { + if (nm == nullptr) return; + assert(nm->oop_maps() == nullptr, "expectation"); + + CheckForOopsClosure cfo; + nm->oops_do(&cfo); + assert(!cfo.found_oop(), "no oops allowed"); + + // We allow an exception for the own Method, but require its class to be permanent. + Method* own_method = nm->method(); + CheckForMetadataClosure cfm(/* ignore reference to own Method */ own_method); + nm->metadata_do(&cfm); + assert(!cfm.found_metadata(), "no metadata allowed"); + + assert(own_method->method_holder()->class_loader_data()->is_permanent_class_loader_data(), + "Method's class needs to be permanent"); +} +#endif + nmethod* nmethod::new_native_nmethod(const methodHandle& method, int compile_id, CodeBuffer *code_buffer, @@ -474,14 +510,19 @@ nmethod* nmethod::new_native_nmethod(const methodHandle& method, if (exception_handler != -1) { offsets.set_value(CodeOffsets::Exceptions, exception_handler); } - nm = new (native_nmethod_size, CompLevel_none) + + // MH intrinsics are dispatch stubs which are compatible with NonNMethod space. + // IsUnloadingBehaviour::is_unloading needs to handle them separately. + bool allow_NonNMethod_space = method->can_be_allocated_in_NonNMethod_space(); + nm = new (native_nmethod_size, allow_NonNMethod_space) nmethod(method(), compiler_none, native_nmethod_size, compile_id, &offsets, code_buffer, frame_size, basic_lock_owner_sp_offset, basic_lock_sp_offset, oop_maps); - NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); + DEBUG_ONLY( if (allow_NonNMethod_space) assert_no_oops_or_metadata(nm); ) + NOT_PRODUCT(if (nm != NULL) native_nmethod_stats.note_native_nmethod(nm)); } if (nm != NULL) { @@ -716,6 +757,14 @@ void* nmethod::operator new(size_t size, int nmethod_size, int comp_level) throw return CodeCache::allocate(nmethod_size, CodeCache::get_code_blob_type(comp_level)); } +void* nmethod::operator new(size_t size, int nmethod_size, bool allow_NonNMethod_space) throw () { + // Try MethodNonProfiled and MethodProfiled. + void* return_value = CodeCache::allocate(nmethod_size, CodeBlobType::MethodNonProfiled); + if (return_value != nullptr || !allow_NonNMethod_space) return return_value; + // Try NonNMethod or give up. + return CodeCache::allocate(nmethod_size, CodeBlobType::NonNMethod); +} + nmethod::nmethod( Method* method, CompilerType type, diff --git a/src/hotspot/share/code/nmethod.hpp b/src/hotspot/share/code/nmethod.hpp index bd2af1053a0..d9b792e0ef6 100644 --- a/src/hotspot/share/code/nmethod.hpp +++ b/src/hotspot/share/code/nmethod.hpp @@ -298,6 +298,10 @@ class nmethod : public CompiledMethod { // helper methods void* operator new(size_t size, int nmethod_size, int comp_level) throw(); + // For method handle intrinsics: Try MethodNonProfiled, MethodProfiled and NonNMethod. + // Attention: Only allow NonNMethod space for special nmethods which don't need to be + // findable by nmethod iterators! In particular, they must not contain oops! + void* operator new(size_t size, int nmethod_size, bool allow_NonNMethod_space) throw(); const char* reloc_string_for(u_char* begin, u_char* end); diff --git a/src/hotspot/share/gc/shared/gcBehaviours.cpp b/src/hotspot/share/gc/shared/gcBehaviours.cpp index d0a4eb79a40..3b5136f74f0 100644 --- a/src/hotspot/share/gc/shared/gcBehaviours.cpp +++ b/src/hotspot/share/gc/shared/gcBehaviours.cpp @@ -30,6 +30,11 @@ IsUnloadingBehaviour* IsUnloadingBehaviour::_current = NULL; bool IsUnloadingBehaviour::is_unloading(CompiledMethod* cm) { + if (cm->method()->can_be_allocated_in_NonNMethod_space()) { + // When the nmethod is in NonNMethod space, we may reach here without IsUnloadingBehaviour. + // However, we only allow this for special methods which never get unloaded. + return false; + } return _current->has_dead_oop(cm) || cm->as_nmethod()->is_cold(); } diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 0ce9b768b53..1fc28c86df3 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -722,7 +722,8 @@ class Method : public Metadata { static methodHandle make_method_handle_intrinsic(vmIntrinsicID iid, // _invokeBasic, _linkToVirtual Symbol* signature, //anything at all TRAPS); - + // Some special methods don't need to be findable by nmethod iterators and are permanent. + bool can_be_allocated_in_NonNMethod_space() const { return is_method_handle_intrinsic(); } // Continuation inline bool is_continuation_enter_intrinsic() const; diff --git a/test/hotspot/jtreg/compiler/codecache/MHIntrinsicAllocFailureTest.java b/test/hotspot/jtreg/compiler/codecache/MHIntrinsicAllocFailureTest.java new file mode 100644 index 00000000000..06fda8e2e91 --- /dev/null +++ b/test/hotspot/jtreg/compiler/codecache/MHIntrinsicAllocFailureTest.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022 SAP SE. All rights reserved.ights reserved. + * 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 MHIntrinsicAllocFailureTest + * @bug 8295724 + * @requires vm.compMode == "Xmixed" + * @requires vm.opt.TieredCompilation == null | vm.opt.TieredCompilation == true + * @summary test allocation failure of method handle intrinsic in profiled/non-profiled space + * @library /test/lib + * @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 -XX:CompileCommand=compileonly,null::* + * -XX:ReservedCodeCacheSize=16m -XX:+SegmentedCodeCache + * compiler.codecache.MHIntrinsicAllocFailureTest + */ + +package compiler.codecache; + +import jdk.test.lib.Asserts; +import jdk.test.whitebox.WhiteBox; +import jdk.test.whitebox.code.BlobType; + +import java.lang.management.MemoryPoolMXBean; + +public class MHIntrinsicAllocFailureTest { + private static final WhiteBox WHITE_BOX = WhiteBox.getWhiteBox(); + + private interface TestInterface { + int testMethod(int a, int b, Object c); + } + + private static void fillCodeCacheSegment(BlobType type) { + // Fill with large blobs. + MemoryPoolMXBean bean = type.getMemoryPool(); + int size = (int) (bean.getUsage().getMax() >> 7); + while (WHITE_BOX.allocateCodeBlob(size, type.id) != 0) {} + // Fill rest with minimal blobs. + while (WHITE_BOX.allocateCodeBlob(1, type.id) != 0) {} + } + + public static void main(String[] args) { + // Lock compilation to be able to better control code cache space + WHITE_BOX.lockCompilation(); + fillCodeCacheSegment(BlobType.MethodNonProfiled); + fillCodeCacheSegment(BlobType.MethodProfiled); + // JIT compilers should be off, now. + Asserts.assertNotEquals(WHITE_BOX.getCompilationActivityMode(), 1); + System.out.println("Code cache segments for non-profiled and profiled nmethods are full."); + // Generate and use a MH itrinsic. Should not trigger one of the following: + // - VirtualMachineError: Out of space in CodeCache for method handle intrinsic + // - InternalError: java.lang.NoSuchMethodException: no such method: + // java.lang.invoke.MethodHandle.linkToStatic(int,int,Object,MemberName)int/invokeStatic + TestInterface add2ints = (a, b, c) -> a + b; + System.out.println("Result of lambda expression: " + add2ints.testMethod(1, 2, null)); + // Let GC check the code cache. + WHITE_BOX.unlockCompilation(); + WHITE_BOX.fullGC(); + } +} From b4da0ee706b6a274e6ba4e5483ef972f45c9f81e Mon Sep 17 00:00:00 2001 From: Anthony Scarpino Date: Tue, 6 Dec 2022 21:37:12 +0000 Subject: [PATCH 081/494] 8296507: GCM using more memory than necessary with in-place operations Reviewed-by: jnimeh --- .../crypto/provider/GaloisCounterMode.java | 113 +++++++++++++----- 1 file changed, 80 insertions(+), 33 deletions(-) diff --git a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java index d55aff35499..f676c4dd1a6 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/GaloisCounterMode.java @@ -576,36 +576,58 @@ private static byte[] getJ0(byte[] iv, byte[] subkeyH, int blockSize) { return j0; } - // Wrapper function around AES-GCM interleaved intrinsic that splits - // large chunks of data into 1MB sized chunks. This is to place - // an upper limit on the number of blocks encrypted in the intrinsic. + /** + * Wrapper function around Combined AES-GCM intrinsic method that splits + * large chunks of data into 1MB sized chunks. This is to place + * an upper limit on the number of blocks encrypted in the intrinsic. + * + * The combined intrinsic is not used when decrypting in-place heap + * bytebuffers because 'ct' will be the same as 'in' and overwritten by + * GCTR before GHASH calculates the encrypted tag. + */ private static int implGCMCrypt(byte[] in, int inOfs, int inLen, byte[] ct, int ctOfs, byte[] out, int outOfs, GCTR gctr, GHASH ghash) { int len = 0; - if (inLen > SPLIT_LEN) { + // Loop if input length is greater than the SPLIT_LEN + if (inLen > SPLIT_LEN && ct != null) { + int partlen; while (inLen >= SPLIT_LEN) { - int partlen = implGCMCrypt0(in, inOfs + len, SPLIT_LEN, ct, + partlen = implGCMCrypt0(in, inOfs + len, SPLIT_LEN, ct, ctOfs + len, out, outOfs + len, gctr, ghash); len += partlen; inLen -= partlen; } } + + // Finish any remaining data if (inLen > 0) { - len += implGCMCrypt0(in, inOfs + len, inLen, ct, - ctOfs + len, out, outOfs + len, gctr, ghash); + if (ct == null) { + ghash.update(in, inOfs + len, inLen); + len += gctr.update(in, inOfs + len, inLen, out, outOfs); + } else { + len += implGCMCrypt0(in, inOfs + len, inLen, ct, + ctOfs + len, out, outOfs + len, gctr, ghash); + } } return len; } + /** - * Intrinsic for Vector AES Galois Counter Mode implementation. - * AES and GHASH operations are interleaved in the intrinsic implementation. - * return - number of processed bytes + * Intrinsic for the combined AES Galois Counter Mode implementation. + * AES and GHASH operations are combined in the intrinsic implementation. * * Requires 768 bytes (48 AES blocks) to efficiently use the intrinsic. * inLen that is less than 768 size block sizes, before or after this * intrinsic is used, will be done by the calling method + * + * Note: + * Only Intel processors with AVX512 that support vaes, vpclmulqdq, + * avx512dq, and avx512vl trigger this intrinsic. + * Other processors will always use GHASH and GCTR which may have their own + * intrinsic support + * * @param in input buffer * @param inOfs input offset * @param inLen input length @@ -614,7 +636,7 @@ private static int implGCMCrypt(byte[] in, int inOfs, int inLen, byte[] ct, * @param out output buffer * @param outOfs output offset * @param gctr object for the GCTR operation - * @param ghash object for the ghash operation + * @param ghash object for the GHASH operation * @return number of processed bytes */ @IntrinsicCandidate @@ -670,6 +692,11 @@ abstract class GCMEngine { byte[] originalOut = null; int originalOutOfs = 0; + // True if ops is an in-place array decryption with the offset between + // input & output the same or the input greater. This is to + // avoid the AVX512 intrinsic. + boolean inPlaceArray = false; + GCMEngine(SymmetricCipher blockCipher) { blockSize = blockCipher.getBlockSize(); byte[] subkeyH = new byte[blockSize]; @@ -736,7 +763,8 @@ int implGCMCrypt(ByteBuffer src, ByteBuffer dst) { ByteBuffer ct = (encryption ? dst : src); len = GaloisCounterMode.implGCMCrypt(src.array(), src.arrayOffset() + src.position(), srcLen, - ct.array(), ct.arrayOffset() + ct.position(), + inPlaceArray ? null : ct.array(), + ct.arrayOffset() + ct.position(), dst.array(), dst.arrayOffset() + dst.position(), gctr, ghash); src.position(src.position() + len); @@ -948,10 +976,13 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { // from the passed object. That gives up the true offset from // the base address. As long as the src side is >= the dst // side, we are not in overlap. + // NOTE: inPlaceArray does not apply here as direct buffers run + // through a byte[] to get to the combined intrinsic if (((DirectBuffer) src).address() - srcaddr + src.position() >= ((DirectBuffer) dst).address() - dstaddr + dst.position()) { return dst; } + } else if (!src.isDirect() && !dst.isDirect()) { // if src is read only, then we need a copy if (!src.isReadOnly()) { @@ -964,10 +995,12 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { // from the underlying byte[] address. // If during encryption and the input offset is behind or // the same as the output offset, the same buffer can be - // used. But during decryption always create a new - // buffer in case of a bad auth tag. - if (encryption && src.position() + src.arrayOffset() >= + // used. + // Set 'inPlaceArray' true for decryption operations to + // avoid the AVX512 combined intrinsic + if (src.position() + src.arrayOffset() >= dst.position() + dst.arrayOffset()) { + inPlaceArray = (!encryption); return dst; } } @@ -989,7 +1022,7 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { } /** - * This is used for both overlap detection for the data or decryption + * This is used for both overlap detection for the data or decryption * during in-place crypto, so to not overwrite the input if the auth tag * is invalid. * @@ -997,10 +1030,13 @@ ByteBuffer overlapDetection(ByteBuffer src, ByteBuffer dst) { * allocated because for code simplicity. */ byte[] overlapDetection(byte[] in, int inOfs, byte[] out, int outOfs) { - if (in == out && (!encryption || inOfs < outOfs)) { - originalOut = out; - originalOutOfs = outOfs; - return new byte[out.length]; + if (in == out) { + if (inOfs < outOfs) { + originalOut = out; + originalOutOfs = outOfs; + return new byte[out.length]; + } + inPlaceArray = (!encryption); } return out; } @@ -1501,8 +1537,11 @@ public int doFinal(byte[] in, int inOfs, int inLen, byte[] out, } if (mismatch != 0) { - // Clear output data - Arrays.fill(out, outOfs, outOfs + len, (byte) 0); + // If this is an in-place array, don't zero the input + if (!inPlaceArray) { + // Clear output data + Arrays.fill(out, outOfs, outOfs + len, (byte) 0); + } throw new AEADBadTagException("Tag mismatch"); } @@ -1586,16 +1625,21 @@ public int doFinal(ByteBuffer src, ByteBuffer dst) if (mismatch != 0) { // Clear output data dst.reset(); - if (dst.hasArray()) { - int ofs = dst.arrayOffset() + dst.position(); - Arrays.fill(dst.array(), ofs , ofs + len, (byte)0); - } else { - NIO_ACCESS.acquireSession(dst); - try { - Unsafe.getUnsafe().setMemory(((DirectBuffer)dst).address(), + // If this is an in-place array, don't zero the src + if (!inPlaceArray) { + if (dst.hasArray()) { + int ofs = dst.arrayOffset() + dst.position(); + Arrays.fill(dst.array(), ofs, ofs + len, + (byte) 0); + } else { + NIO_ACCESS.acquireSession(dst); + try { + Unsafe.getUnsafe().setMemory( + ((DirectBuffer)dst).address(), len + dst.position(), (byte) 0); - } finally { - NIO_ACCESS.releaseSession(dst); + } finally { + NIO_ACCESS.releaseSession(dst); + } } } throw new AEADBadTagException("Tag mismatch"); @@ -1807,8 +1851,11 @@ public int doFinal(byte[] in, int inOfs, int inLen, byte[] out, int outOfs) { int len = 0; if (inLen >= PARALLEL_LEN) { - len += implGCMCrypt(in, inOfs, inLen, in, inOfs, out, outOfs, - gctr, ghash); + // Since GCMDecrypt.inPlaceArray cannot be accessed, check that + // 'in' and 'out' are the same. All other in-place situations + // have been resolved by overlapDetection() + len += implGCMCrypt(in, inOfs, inLen, (in == out ? null : in), + inOfs, out, outOfs, gctr, ghash); } ghash.doFinal(in, inOfs + len, inLen - len); return len + gctr.doFinal(in, inOfs + len, inLen - len, out, From 16a5901845de170e2e6f9ea13f19bb2a34c1da85 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Tue, 6 Dec 2022 22:01:45 +0000 Subject: [PATCH 082/494] 8298214: ProblemList java/util/concurrent/forkjoin/AsyncShutdownNow.java 8298218: ProblemList java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java on windows-x64 8298222: ProblemList java/awt/Mixing/AWT_Mixing/ViewportOverlapping.java on windows-x64 8298220: ProblemList java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java on windows-x64 Reviewed-by: rriggs --- test/jdk/ProblemList.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 7532f3550d7..26b21389474 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -670,6 +670,9 @@ javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8297296 macosx-all javax/swing/JFileChooser/8046391/bug8046391.java 8293862 windows-x64 +java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392 windows-x64 +java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8294264 windows-x64 +java/awt/Mixing/AWT_Mixing/ViewportOverlapping.java 8253184,8295813 windows-x64 sanity/client/SwingSet/src/ToolTipDemoTest.java 8293001 linux-all sanity/client/SwingSet/src/ButtonDemoScreenshotTest.java 8265770 macosx-all @@ -711,6 +714,7 @@ com/sun/jdi/AfterThreadDeathTest.java 8232839 linux-al java/util/Locale/LocaleProvidersRun.java 8268379 macosx-x64 sun/util/locale/provider/CalendarDataRegression.java 8268379 macosx-x64 +java/util/concurrent/forkjoin/AsyncShutdownNow.java 8286352 linux-all,windows-x64 ############################################################################ From 62baff503ef5562e02e1900525acffa5d4ca8534 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Tue, 6 Dec 2022 22:45:53 +0000 Subject: [PATCH 083/494] 8298221: Problem list gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java on macosx-aarch64 Reviewed-by: dcubed --- test/hotspot/jtreg/ProblemList.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 125f3ccaf3b..4e188102701 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -80,7 +80,7 @@ gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293 macosx-x64 +gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293,8298073 macosx-x64,macosx-aarch64 gc/stress/TestStressG1Humongous.java 8286554 windows-x64 ############################################################################# From ce896731d38866c2bf99cd49525062e150d94160 Mon Sep 17 00:00:00 2001 From: Andrew John Hughes Date: Wed, 7 Dec 2022 00:34:00 +0000 Subject: [PATCH 084/494] 8297804: (tz) Update Timezone Data to 2022g Reviewed-by: naoto --- make/data/cldr/common/bcp47/timezone.xml | 1 + make/data/cldr/common/main/root.xml | 12 ++ .../cldr/common/supplemental/metaZones.xml | 9 +- .../sun/util/resources/TimeZoneNames.java | 1 + src/java.base/share/data/tzdata/VERSION | 2 +- src/java.base/share/data/tzdata/africa | 4 + src/java.base/share/data/tzdata/asia | 2 +- src/java.base/share/data/tzdata/backward | 1 + src/java.base/share/data/tzdata/europe | 28 ++- src/java.base/share/data/tzdata/iso3166.tab | 6 +- src/java.base/share/data/tzdata/northamerica | 161 ++++++++++-------- src/java.base/share/data/tzdata/southamerica | 9 +- src/java.base/share/data/tzdata/zone.tab | 26 +-- .../util/resources/ext/TimeZoneNames_de.java | 1 + .../util/resources/ext/TimeZoneNames_es.java | 1 + .../util/resources/ext/TimeZoneNames_fr.java | 1 + .../util/resources/ext/TimeZoneNames_it.java | 1 + .../util/resources/ext/TimeZoneNames_ja.java | 1 + .../util/resources/ext/TimeZoneNames_ko.java | 1 + .../resources/ext/TimeZoneNames_pt_BR.java | 1 + .../util/resources/ext/TimeZoneNames_sv.java | 1 + .../resources/ext/TimeZoneNames_zh_CN.java | 1 + .../resources/ext/TimeZoneNames_zh_TW.java | 1 + .../java/util/TimeZone/TimeZoneData/VERSION | 2 +- .../util/TimeZone/TimeZoneData/aliases.txt | 1 + .../TimeZone/TimeZoneData/displaynames.txt | 4 +- 26 files changed, 183 insertions(+), 96 deletions(-) diff --git a/make/data/cldr/common/bcp47/timezone.xml b/make/data/cldr/common/bcp47/timezone.xml index ddbccff077c..57d81ed48ec 100644 --- a/make/data/cldr/common/bcp47/timezone.xml +++ b/make/data/cldr/common/bcp47/timezone.xml @@ -280,6 +280,7 @@ For terms of use, see http://www.unicode.org/copyright.html + diff --git a/make/data/cldr/common/main/root.xml b/make/data/cldr/common/main/root.xml index 411a316f8ed..44c80ff1348 100644 --- a/make/data/cldr/common/main/root.xml +++ b/make/data/cldr/common/main/root.xml @@ -2994,6 +2994,18 @@ Warnings: All cp values have U+FE0F characters removed. See /annotationsDerived/ Ho Chi Minh + + Bahía de Banderas + + + Cancún + + + Ciudad Juárez + + + Mérida + diff --git a/make/data/cldr/common/supplemental/metaZones.xml b/make/data/cldr/common/supplemental/metaZones.xml index 1c363cbe7aa..0beb757cacb 100644 --- a/make/data/cldr/common/supplemental/metaZones.xml +++ b/make/data/cldr/common/supplemental/metaZones.xml @@ -333,6 +333,12 @@ For terms of use, see http://www.unicode.org/copyright.html + + + + + + @@ -621,8 +627,7 @@ For terms of use, see http://www.unicode.org/copyright.html - - + diff --git a/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java b/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java index db892dbb595..bf7918659ae 100644 --- a/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java +++ b/src/java.base/share/classes/sun/util/resources/TimeZoneNames.java @@ -430,6 +430,7 @@ protected final Object[][] getContents() { "French Guiana Time", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/java.base/share/data/tzdata/VERSION b/src/java.base/share/data/tzdata/VERSION index b8d9ae74fbd..0f328a4a7ff 100644 --- a/src/java.base/share/data/tzdata/VERSION +++ b/src/java.base/share/data/tzdata/VERSION @@ -21,4 +21,4 @@ # or visit www.oracle.com if you need additional information or have any # questions. # -tzdata2022f +tzdata2022g diff --git a/src/java.base/share/data/tzdata/africa b/src/java.base/share/data/tzdata/africa index cbf6322c4ee..830d7d10b7e 100644 --- a/src/java.base/share/data/tzdata/africa +++ b/src/java.base/share/data/tzdata/africa @@ -611,6 +611,10 @@ Zone Indian/Mauritius 3:50:00 - LMT 1907 # Port Louis # Agalega Is, Rodriguez # no information; probably like Indian/Mauritius + +# Morocco +# See Africa/Ceuta for Spanish Morocco. + # From Alex Krivenyshev (2008-05-09): # Here is an article that Morocco plan to introduce Daylight Saving Time between # 1 June, 2008 and 27 September, 2008. diff --git a/src/java.base/share/data/tzdata/asia b/src/java.base/share/data/tzdata/asia index 89784bf4c33..ff81978bc47 100644 --- a/src/java.base/share/data/tzdata/asia +++ b/src/java.base/share/data/tzdata/asia @@ -3608,7 +3608,7 @@ Zone Asia/Singapore 6:55:25 - LMT 1901 Jan 1 7:20 - +0720 1941 Sep 1 7:30 - +0730 1942 Feb 16 9:00 - +09 1945 Sep 12 - 7:30 - +0730 1982 Jan 1 + 7:30 - +0730 1981 Dec 31 16:00u 8:00 - +08 # Spratly Is diff --git a/src/java.base/share/data/tzdata/backward b/src/java.base/share/data/tzdata/backward index 1fb087a6d87..fa44f655009 100644 --- a/src/java.base/share/data/tzdata/backward +++ b/src/java.base/share/data/tzdata/backward @@ -290,6 +290,7 @@ Link America/Tijuana America/Ensenada Link America/Indiana/Indianapolis America/Fort_Wayne Link America/Toronto America/Montreal Link America/Toronto America/Nipigon +Link America/Iqaluit America/Pangnirtung Link America/Rio_Branco America/Porto_Acre Link America/Winnipeg America/Rainy_River Link America/Argentina/Cordoba America/Rosario diff --git a/src/java.base/share/data/tzdata/europe b/src/java.base/share/data/tzdata/europe index f88730002ca..acc5da3ec79 100644 --- a/src/java.base/share/data/tzdata/europe +++ b/src/java.base/share/data/tzdata/europe @@ -1126,7 +1126,30 @@ Zone Atlantic/Faroe -0:27:04 - LMT 1908 Jan 11 # Tórshavn # "National Park" by Executive Order: # http://naalakkersuisut.gl/~/media/Nanoq/Files/Attached%20Files/Engelske-tekster/Legislation/Executive%20Order%20National%20Park.rtf # It is their only National Park. -# + +# From Jonas Nyrup (2022-11-24): +# On last Saturday in October 2023 when DST ends America/Nuuk will switch +# from -03/-02 to -02/-01 +# https://sermitsiaq.ag/forslagtidsforskel-danmark-mindskes-sommertid-beholdes +# ... +# https://sermitsiaq.ag/groenland-skifte-tidszone-trods-bekymringer +# +# From Jürgen Appel (2022-11-25): +# https://ina.gl/samlinger/oversigt-over-samlinger/samling/dagsordener/dagsorden.aspx?lang=da&day=24-11-2022 +# If I understand this correctly, from the next planned switch to +# summer time, Greenland will permanently stay at that time, i.e. no +# switch back to winter time in 2023 will occur. +# +# From Paul Eggert (2022-11-28): +# The official document in Danish +# https://naalakkersuisut.gl/-/media/naalakkersuisut/filer/kundgoerelser/2022/11/2511/31_da_inatsisartutlov-om-tidens-bestemmelse.pdf?la=da&hash=A33597D8A38CC7038465241119EF34F3 +# says standard time for Greenland is -02, that Naalakkersuisut can lay down +# rules for DST and can require some areas to use a different time zone, +# and that this all takes effect 2023-03-25 22:00. The abovementioned +# "bekymringer" URL says the intent is no transition March 25, that +# Greenland will not go back to winter time in fall 2023, and that +# only America/Nuuk is affected (though further changes may occur). + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Thule 1991 1992 - Mar lastSun 2:00 1:00 D Rule Thule 1991 1992 - Sep lastSun 2:00 0 S @@ -1149,7 +1172,8 @@ Zone America/Scoresbysund -1:27:52 - LMT 1916 Jul 28 # Ittoqqortoormiit -1:00 EU -01/+00 Zone America/Nuuk -3:26:56 - LMT 1916 Jul 28 # Godthåb -3:00 - -03 1980 Apr 6 2:00 - -3:00 EU -03/-02 + -3:00 EU -03/-02 2023 Mar 25 22:00 + -2:00 - -02 Zone America/Thule -4:35:08 - LMT 1916 Jul 28 # Pituffik -4:00 Thule A%sT diff --git a/src/java.base/share/data/tzdata/iso3166.tab b/src/java.base/share/data/tzdata/iso3166.tab index 544b3034c17..fbfb74bec45 100644 --- a/src/java.base/share/data/tzdata/iso3166.tab +++ b/src/java.base/share/data/tzdata/iso3166.tab @@ -26,13 +26,13 @@ # This file is in the public domain, so clarified as of # 2009-05-17 by Arthur David Olson. # -# From Paul Eggert (2015-05-02): +# From Paul Eggert (2022-11-18): # This file contains a table of two-letter country codes. Columns are # separated by a single tab. Lines beginning with '#' are comments. # All text uses UTF-8 encoding. The columns of the table are as follows: # # 1. ISO 3166-1 alpha-2 country code, current as of -# ISO 3166-1 N976 (2018-11-06). See: Updates on ISO 3166-1 +# ISO 3166-1 N1087 (2022-09-02). See: Updates on ISO 3166-1 # https://isotc.iso.org/livelink/livelink/Open/16944257 # 2. The usual English name for the coded region, # chosen so that alphabetic sorting of subsets produces helpful lists. @@ -261,7 +261,7 @@ SY Syria SZ Eswatini (Swaziland) TC Turks & Caicos Is TD Chad -TF French Southern & Antarctic Lands +TF French Southern Territories TG Togo TH Thailand TJ Tajikistan diff --git a/src/java.base/share/data/tzdata/northamerica b/src/java.base/share/data/tzdata/northamerica index 465e8c234ed..a5fd701f88c 100644 --- a/src/java.base/share/data/tzdata/northamerica +++ b/src/java.base/share/data/tzdata/northamerica @@ -1992,6 +1992,37 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884 # Northwest Territories, Nunavut, Yukon +# From Chris Walton (2022-11-06): +# Whitehorse Star - Thursday April 22, 1965 - page 1 +# title: DST Starts Monday ... +# https://www.newspapers.com/image/578587481/ +# The title of this first article is wrong and/or misleading. +# Also, the start time shown in the article is vague; it simply says "after +# midnight" when it probably should have stated 2:00a.m.... +# +# Whitehorse Star - Monday October 25, 1965 - page 15 ... +# https://www.newspapers.com/image/578589147/ +# The 1965 Yukon Council minutes can be found here: +# http://assets.yukonarchives.ca/PER_YG_06_1965_C20_S02_v1.pdf +# ... I do not currently believe that NWT touched any of its clocks in 1965.... +# +# Whitehorse Star - Thursday Feb 24,1966 - page 2 +# title: It's Time for YDT ... +# https://www.newspapers.com/image/578575979/ ... +# America/Whitehorse as a permanent change from UTC-9(YST) to +# UTC-8(PST) at 00:00 on Sunday February 27, 1966.... +# +# Whitehorse Star - Friday April 28,1972 - page 6 +# title: Daylight Saving Time for N.W.T.... +# https://www.newspapers.com/image/578701610/ ... +# Nunavut and NWT zones ... DST starting in 1972.... Start and End ... +# should be the same as the rest of Canada +# +# +# From Paul Eggert (2022-11-06): +# For now, assume Yukon's 1965-04-22 spring forward was 00:00 -> 02:00, as this +# seems likely than 02:00 -> 04:00 and matches "after midnight". + # From Paul Eggert (2006-03-22): # Dawson switched to PST in 1973. Inuvik switched to MST in 1979. # Mathew Englander (1996-10-07) gives the following refs: @@ -2106,6 +2137,13 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884 # * Interpretation Act, RSY 2002, c 125 # https://www.canlii.org/en/yk/laws/stat/rsy-2002-c-125/latest/rsy-2002-c-125.html +# From Chris Walton (2022-11-06): +# The 5th edition of the Atlas of Canada contains a time zone map that +# shows both legislated and observed time zone boundaries. +# All communities on Baffin Island are shown to be observing Eastern time. +# The date on the map is 1984. +# https://ftp.maps.canada.ca/pub/nrcan_rncan/raster/atlas_5_ed/eng/other/referencemaps/mcr4056.pdf + # From Rives McDow (1999-09-04): # Nunavut ... moved ... to incorporate the whole territory into one time zone. # Nunavut moves to single time zone Oct. 31 @@ -2118,40 +2156,7 @@ Zone America/Fort_Nelson -8:10:47 - LMT 1884 # From Paul Eggert (1999-09-20): # Basic Facts: The New Territory # http://www.nunavut.com/basicfacts/english/basicfacts_1territory.html -# (1999) reports that Pangnirtung operates on eastern time, -# and that Coral Harbour does not observe DST. We don't know when -# Pangnirtung switched to eastern time; we'll guess 1995. - -# From Rives McDow (1999-11-08): -# On October 31, when the rest of Nunavut went to Central time, -# Pangnirtung wobbled. Here is the result of their wobble: -# -# The following businesses and organizations in Pangnirtung use Central Time: -# -# First Air, Power Corp, Nunavut Construction, Health Center, RCMP, -# Eastern Arctic National Parks, A & D Specialist -# -# The following businesses and organizations in Pangnirtung use Eastern Time: -# -# Hamlet office, All other businesses, Both schools, Airport operator -# -# This has made for an interesting situation there, which warranted the news. -# No one there that I spoke with seems concerned, or has plans to -# change the local methods of keeping time, as it evidently does not -# really interfere with any activities or make things difficult locally. -# They plan to celebrate New Year's turn-over twice, one hour apart, -# so it appears that the situation will last at least that long. -# The Nunavut Intergovernmental Affairs hopes that they will "come to -# their senses", but the locals evidently don't see any problem with -# the current state of affairs. - -# From Michaela Rodrigue, writing in the -# Nunatsiaq News (1999-11-19): -# http://www.nunatsiaqonline.ca/archives/nunavut991130/nvt91119_17.html -# Clyde River, Pangnirtung and Sanikiluaq now operate with two time zones, -# central - or Nunavut time - for government offices, and eastern time -# for municipal offices and schools.... Igloolik [was similar but then] -# made the switch to central time on Saturday, Nov. 6. +# (1999) reports that ... Coral Harbour does not observe DST. # From Paul Eggert (2000-10-02): # Matthews and Vincent (1998) say the following, but we lack histories @@ -2310,18 +2315,12 @@ Rule NT_YK 1919 only - Nov 1 0:00 0 S Rule NT_YK 1942 only - Feb 9 2:00 1:00 W # War Rule NT_YK 1945 only - Aug 14 23:00u 1:00 P # Peace Rule NT_YK 1945 only - Sep 30 2:00 0 S -Rule NT_YK 1965 only - Apr lastSun 0:00 2:00 DD -Rule NT_YK 1965 only - Oct lastSun 2:00 0 S -Rule NT_YK 1980 1986 - Apr lastSun 2:00 1:00 D -Rule NT_YK 1980 2006 - Oct lastSun 2:00 0 S +Rule NT_YK 1972 1986 - Apr lastSun 2:00 1:00 D +Rule NT_YK 1972 2006 - Oct lastSun 2:00 0 S Rule NT_YK 1987 2006 - Apr Sun>=1 2:00 1:00 D +Rule Yukon 1965 only - Apr lastSun 0:00 2:00 DD +Rule Yukon 1965 only - Oct lastSun 2:00 0 S # Zone NAME STDOFF RULES FORMAT [UNTIL] -# aka Panniqtuuq -Zone America/Pangnirtung 0 - -00 1921 # trading post est. - -4:00 NT_YK A%sT 1995 Apr Sun>=1 2:00 - -5:00 Canada E%sT 1999 Oct 31 2:00 - -6:00 Canada C%sT 2000 Oct 29 2:00 - -5:00 Canada E%sT # formerly Frobisher Bay Zone America/Iqaluit 0 - -00 1942 Aug # Frobisher Bay est. -5:00 NT_YK E%sT 1999 Oct 31 2:00 @@ -2354,13 +2353,15 @@ Zone America/Inuvik 0 - -00 1953 # Inuvik founded -7:00 NT_YK M%sT 1980 -7:00 Canada M%sT Zone America/Whitehorse -9:00:12 - LMT 1900 Aug 20 - -9:00 NT_YK Y%sT 1967 May 28 0:00 - -8:00 NT_YK P%sT 1980 + -9:00 NT_YK Y%sT 1965 + -9:00 Yukon Y%sT 1966 Feb 27 0:00 + -8:00 - PST 1980 -8:00 Canada P%sT 2020 Nov 1 -7:00 - MST Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 - -9:00 NT_YK Y%sT 1973 Oct 28 0:00 - -8:00 NT_YK P%sT 1980 + -9:00 NT_YK Y%sT 1965 + -9:00 Yukon Y%sT 1973 Oct 28 0:00 + -8:00 - PST 1980 -8:00 Canada P%sT 2020 Nov 1 -7:00 - MST @@ -2582,6 +2583,14 @@ Zone America/Dawson -9:17:40 - LMT 1900 Aug 20 # This abolishes DST except where US DST rules are observed, # and in addition changes all of Chihuahua to -06 with no DST. +# From Heitor David Pinto (2022-11-28): +# Now the northern municipalities want to have the same time zone as the +# respective neighboring cities in the US, for example Juárez in UTC-7 with +# DST, matching El Paso, and Ojinaga in UTC-6 with DST, matching Presidio.... +# the president authorized the publication of the decree for November 29, +# so the time change would occur on November 30 at 0:00. +# http://puentelibre.mx/noticia/ciudad_juarez_cambio_horario_noviembre_2022/ + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S Rule Mexico 1931 only - May 1 23:00 1:00 D Rule Mexico 1931 only - Oct 1 0:00 0 S @@ -2613,14 +2622,12 @@ Zone America/Merida -5:58:28 - LMT 1922 Jan 1 6:00u -6:00 Mexico C%sT # Coahuila, Nuevo León, Tamaulipas (near US border) # This includes the following municipalities: -# in Coahuila: Ocampo, Acuña, Zaragoza, Jiménez, Piedras Negras, Nava, -# Guerrero, Hidalgo. -# in Nuevo León: Anáhuac, Los Aldama. +# in Coahuila: Acuña, Allende, Guerrero, Hidalgo, Jiménez, Morelos, Nava, +# Ocampo, Piedras Negras, Villa Unión, Zaragoza +# in Nuevo León: Anáhuac # in Tamaulipas: Nuevo Laredo, Guerrero, Mier, Miguel Alemán, Camargo, # Gustavo Díaz Ordaz, Reynosa, Río Bravo, Valle Hermoso, Matamoros. -# See: Inicia mañana Horario de Verano en zona fronteriza, El Universal, -# 2016-03-12 -# http://www.eluniversal.com.mx/articulo/estados/2016/03/12/inicia-manana-horario-de-verano-en-zona-fronteriza +# https://www.dof.gob.mx/nota_detalle.php?codigo=5670045&fecha=28/10/2022 Zone America/Matamoros -6:30:00 - LMT 1922 Jan 1 6:00u -6:00 - CST 1988 -6:00 US C%sT 1989 @@ -2639,10 +2646,24 @@ Zone America/Mexico_City -6:36:36 - LMT 1922 Jan 1 7:00u -6:00 Mexico C%sT 2001 Sep 30 2:00 -6:00 - CST 2002 Feb 20 -6:00 Mexico C%sT -# Chihuahua (near US border) +# Chihuahua (near US border - western side) # This includes the municipalities of Janos, Ascensión, Juárez, Guadalupe, -# Práxedis G Guerrero, Coyame del Sotol, Ojinaga, and Manuel Benavides. -# (See the 2016-03-12 El Universal source mentioned above.) +# and Práxedis G Guerrero. +# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf +Zone America/Ciudad_Juarez -7:05:56 - LMT 1922 Jan 1 7:00u + -7:00 - MST 1927 Jun 10 23:00 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1996 + -6:00 Mexico C%sT 1998 + -6:00 - CST 1998 Apr Sun>=1 3:00 + -7:00 Mexico M%sT 2010 + -7:00 US M%sT 2022 Oct 30 2:00 + -6:00 - CST 2022 Nov 30 0:00 + -7:00 US M%sT +# Chihuahua (near US border - eastern side) +# The municipalities of Coyame del Sotol, Ojinaga, and Manuel Benavides. +# http://gaceta.diputados.gob.mx/PDF/65/2a022/nov/20221124-VII.pdf Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u -7:00 - MST 1927 Jun 10 23:00 -6:00 - CST 1930 Nov 15 @@ -2652,7 +2673,8 @@ Zone America/Ojinaga -6:57:40 - LMT 1922 Jan 1 7:00u -6:00 - CST 1998 Apr Sun>=1 3:00 -7:00 Mexico M%sT 2010 -7:00 US M%sT 2022 Oct 30 2:00 - -6:00 - CST + -6:00 - CST 2022 Nov 30 0:00 + -6:00 US C%sT # Chihuahua (away from US border) Zone America/Chihuahua -7:04:20 - LMT 1922 Jan 1 7:00u -7:00 - MST 1927 Jun 10 23:00 @@ -2674,6 +2696,18 @@ Zone America/Hermosillo -7:23:52 - LMT 1922 Jan 1 7:00u -7:00 Mexico M%sT 1999 -7:00 - MST +# Baja California Sur, Nayarit (except Bahía de Banderas), Sinaloa +Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u + -7:00 - MST 1927 Jun 10 23:00 + -6:00 - CST 1930 Nov 15 + -7:00 Mexico M%sT 1932 Apr 1 + -6:00 - CST 1942 Apr 24 + -7:00 - MST 1949 Jan 14 + -8:00 - PST 1970 + -7:00 Mexico M%sT + +# Bahía de Banderas + # From Alexander Krivenyshev (2010-04-21): # According to news, Bahía de Banderas (Mexican state of Nayarit) # changed time zone UTC-7 to new time zone UTC-6 on April 4, 2010 (to @@ -2701,17 +2735,6 @@ Zone America/Hermosillo -7:23:52 - LMT 1922 Jan 1 7:00u # From Arthur David Olson (2010-05-01): # Use "Bahia_Banderas" to keep the name to fourteen characters. -# Mazatlán -Zone America/Mazatlan -7:05:40 - LMT 1922 Jan 1 7:00u - -7:00 - MST 1927 Jun 10 23:00 - -6:00 - CST 1930 Nov 15 - -7:00 Mexico M%sT 1932 Apr 1 - -6:00 - CST 1942 Apr 24 - -7:00 - MST 1949 Jan 14 - -8:00 - PST 1970 - -7:00 Mexico M%sT - -# Bahía de Banderas Zone America/Bahia_Banderas -7:01:00 - LMT 1922 Jan 1 7:00u -7:00 - MST 1927 Jun 10 23:00 -6:00 - CST 1930 Nov 15 diff --git a/src/java.base/share/data/tzdata/southamerica b/src/java.base/share/data/tzdata/southamerica index 982ad09c408..81fdd793df4 100644 --- a/src/java.base/share/data/tzdata/southamerica +++ b/src/java.base/share/data/tzdata/southamerica @@ -1441,9 +1441,14 @@ Zone Antarctica/Palmer 0 - -00 1965 # Milne gives 4:56:16.4 for Bogotá time in 1899. He writes, # "A variation of fifteen minutes in the public clocks of Bogota is not rare." +# From Alois Treindl (2022-11-10): +# End of time change in Colombia 1993 ... should be 6 February 24h ... +# DECRETO 267 DE 1993 +# https://www.suin-juriscol.gov.co/viewDocument.asp?ruta=Decretos/1061335 + # Rule NAME FROM TO - IN ON AT SAVE LETTER/S -Rule CO 1992 only - May 3 0:00 1:00 - -Rule CO 1993 only - Apr 4 0:00 0 - +Rule CO 1992 only - May 3 0:00 1:00 - +Rule CO 1993 only - Feb 6 24:00 0 - # Zone NAME STDOFF RULES FORMAT [UNTIL] #STDOFF -4:56:16.4 Zone America/Bogota -4:56:16 - LMT 1884 Mar 13 diff --git a/src/java.base/share/data/tzdata/zone.tab b/src/java.base/share/data/tzdata/zone.tab index 535d1c94af1..939432d3456 100644 --- a/src/java.base/share/data/tzdata/zone.tab +++ b/src/java.base/share/data/tzdata/zone.tab @@ -137,8 +137,7 @@ CA +4606-06447 America/Moncton Atlantic - New Brunswick CA +5320-06025 America/Goose_Bay Atlantic - Labrador (most areas) CA +5125-05707 America/Blanc-Sablon AST - QC (Lower North Shore) CA +4339-07923 America/Toronto Eastern - ON, QC (most areas) -CA +6344-06828 America/Iqaluit Eastern - NU (most east areas) -CA +6608-06544 America/Pangnirtung Eastern - NU (Pangnirtung) +CA +6344-06828 America/Iqaluit Eastern - NU (most areas) CA +484531-0913718 America/Atikokan EST - ON (Atikokan); NU (Coral H) CA +4953-09709 America/Winnipeg Central - ON (west); Manitoba CA +744144-0944945 America/Resolute Central - NU (Resolute) @@ -300,17 +299,18 @@ MT +3554+01431 Europe/Malta MU -2010+05730 Indian/Mauritius MV +0410+07330 Indian/Maldives MW -1547+03500 Africa/Blantyre -MX +1924-09909 America/Mexico_City Central Time -MX +2105-08646 America/Cancun Eastern Standard Time - Quintana Roo -MX +2058-08937 America/Merida Central Time - Campeche, Yucatan -MX +2540-10019 America/Monterrey Central Time - Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas) -MX +2550-09730 America/Matamoros Central Time US - Coahuila, Nuevo Leon, Tamaulipas (US border) -MX +2313-10625 America/Mazatlan Mountain Time - Baja California Sur, Nayarit, Sinaloa -MX +2838-10605 America/Chihuahua Mountain Time - Chihuahua (most areas) -MX +2934-10425 America/Ojinaga Mountain Time US - Chihuahua (US border) -MX +2904-11058 America/Hermosillo Mountain Standard Time - Sonora -MX +3232-11701 America/Tijuana Pacific Time US - Baja California -MX +2048-10515 America/Bahia_Banderas Central Time - Bahia de Banderas +MX +1924-09909 America/Mexico_City Central Mexico +MX +2105-08646 America/Cancun Quintana Roo +MX +2058-08937 America/Merida Campeche, Yucatan +MX +2540-10019 America/Monterrey Durango; Coahuila, Nuevo Leon, Tamaulipas (most areas) +MX +2550-09730 America/Matamoros Coahuila, Nuevo Leon, Tamaulipas (US border) +MX +2838-10605 America/Chihuahua Chihuahua (most areas) +MX +3144-10629 America/Ciudad_Juarez Chihuahua (US border - west) +MX +2934-10425 America/Ojinaga Chihuahua (US border - east) +MX +2313-10625 America/Mazatlan Baja California Sur, Nayarit (most areas), Sinaloa +MX +2048-10515 America/Bahia_Banderas Bahia de Banderas +MX +2904-11058 America/Hermosillo Sonora +MX +3232-11701 America/Tijuana Baja California MY +0310+10142 Asia/Kuala_Lumpur Malaysia (peninsula) MY +0133+11020 Asia/Kuching Sabah, Sarawak MZ -2558+03235 Africa/Maputo diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java index 08550acd037..1f437ae8ec2 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_de.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Franz\u00F6sisch-Guiana Zeit", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java index a12dedb94e9..126010ba396 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_es.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Hora de la Guayana Francesa", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java index f2064397e5e..bd6bceb6ddd 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_fr.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Heure de Guyane fran\u00E7aise", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java index b7fb55286f7..7f55e19fff5 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_it.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Ora della Guyana Francese", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java index 3ccf8c2514c..fe00a00404d 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ja.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "\u30D5\u30E9\u30F3\u30B9\u9818\u30AE\u30A2\u30CA\u6642\u9593", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java index 9bf7c119d52..3b0f44a2e4e 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_ko.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "\uD504\uB791\uC2A4\uB839 \uAE30\uC544\uB098 \uD45C\uC900\uC2DC", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java index c0cae47bd97..557e0bf9001 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_pt_BR.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Hor\u00E1rio da Guiana Francesa", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java index afcdcd348bf..d4b1377b430 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_sv.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "Franska Guyana-tid", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java index e6328ee8347..8224549464f 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_CN.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "\u6CD5\u5C5E\u572D\u4E9A\u90A3\u65F6\u95F4", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java index 236959b8a69..3d28bfa2cd6 100644 --- a/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java +++ b/src/jdk.localedata/share/classes/sun/util/resources/ext/TimeZoneNames_zh_TW.java @@ -428,6 +428,7 @@ protected final Object[][] getContents() { "\u6CD5\u5C6C\u572D\u4E9E\u90A3\u6642\u9593", "GFT"}}, {"America/Cayman", EST}, {"America/Chihuahua", CST}, + {"America/Ciudad_Juarez", MST}, {"America/Creston", MST}, {"America/Coral_Harbour", EST}, {"America/Cordoba", AGT}, diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION index f29d2d938b1..0f66ee12c94 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/VERSION +++ b/test/jdk/java/util/TimeZone/TimeZoneData/VERSION @@ -1 +1 @@ -tzdata2022f +tzdata2022g diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt index 24cec5af700..d495743b268 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt +++ b/test/jdk/java/util/TimeZone/TimeZoneData/aliases.txt @@ -204,6 +204,7 @@ Link America/Tijuana America/Ensenada Link America/Indiana/Indianapolis America/Fort_Wayne Link America/Toronto America/Montreal Link America/Toronto America/Nipigon +Link America/Iqaluit America/Pangnirtung Link America/Rio_Branco America/Porto_Acre Link America/Winnipeg America/Rainy_River Link America/Argentina/Cordoba America/Rosario diff --git a/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt b/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt index a1cd41d283d..44db4dbdb81 100644 --- a/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt +++ b/test/jdk/java/util/TimeZone/TimeZoneData/displaynames.txt @@ -25,6 +25,7 @@ America/Cambridge_Bay MST MDT America/Cancun EST America/Chicago CST CDT America/Chihuahua CST +America/Ciudad_Juarez MST MDT America/Costa_Rica CST CDT America/Danmarkshavn GMT America/Dawson MST @@ -71,9 +72,8 @@ America/Nome AKST AKDT America/North_Dakota/Beulah CST CDT America/North_Dakota/Center CST CDT America/North_Dakota/New_Salem CST CDT -America/Ojinaga CST +America/Ojinaga CST CDT America/Panama EST -America/Pangnirtung EST EDT America/Phoenix MST America/Port-au-Prince EST EDT America/Puerto_Rico AST From acf96c64b750b1a7badbb2cd1c7021dad36aae1e Mon Sep 17 00:00:00 2001 From: Yi Yang Date: Wed, 7 Dec 2022 03:08:07 +0000 Subject: [PATCH 085/494] 8290432: C2 compilation fails with assert(node->_last_del == _last) failed: must have deleted the edge just produced Reviewed-by: kvn, thartmann, chagedorn --- src/hotspot/share/opto/loopnode.cpp | 22 +++-- .../compiler/c2/TestUnexpectedParallelIV.java | 95 +++++++++++++++++++ 2 files changed, 111 insertions(+), 6 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/c2/TestUnexpectedParallelIV.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 5f43a344a3c..a05798dcd0c 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -3657,11 +3657,13 @@ bool PhaseIdealLoop::is_deleteable_safept(Node* sfpt) { void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { assert(loop->_head->is_CountedLoop(), ""); CountedLoopNode *cl = loop->_head->as_CountedLoop(); - if (!cl->is_valid_counted_loop(T_INT)) + if (!cl->is_valid_counted_loop(T_INT)) { return; // skip malformed counted loop + } Node *incr = cl->incr(); - if (incr == NULL) + if (incr == NULL) { return; // Dead loop? + } Node *init = cl->init_trip(); Node *phi = cl->phi(); int stride_con = cl->stride_con(); @@ -3670,25 +3672,33 @@ void PhaseIdealLoop::replace_parallel_iv(IdealLoopTree *loop) { for (DUIterator i = cl->outs(); cl->has_out(i); i++) { Node *out = cl->out(i); // Look for other phis (secondary IVs). Skip dead ones - if (!out->is_Phi() || out == phi || !has_node(out)) + if (!out->is_Phi() || out == phi || !has_node(out)) { continue; + } + PhiNode* phi2 = out->as_Phi(); - Node *incr2 = phi2->in( LoopNode::LoopBackControl ); + Node* incr2 = phi2->in(LoopNode::LoopBackControl); // Look for induction variables of the form: X += constant if (phi2->region() != loop->_head || incr2->req() != 3 || incr2->in(1)->uncast() != phi2 || incr2 == incr || incr2->Opcode() != Op_AddI || - !incr2->in(2)->is_Con()) + !incr2->in(2)->is_Con()) { continue; + } + if (incr2->in(1)->is_ConstraintCast() && + !(incr2->in(1)->in(0)->is_IfProj() && incr2->in(1)->in(0)->in(0)->is_RangeCheck())) { + // Skip AddI->CastII->Phi case if CastII is not controlled by local RangeCheck + continue; + } // Check for parallel induction variable (parallel to trip counter) // via an affine function. In particular, count-down loops with // count-up array indices are common. We only RCE references off // the trip-counter, so we need to convert all these to trip-counter // expressions. - Node *init2 = phi2->in( LoopNode::EntryControl ); + Node* init2 = phi2->in(LoopNode::EntryControl); int stride_con2 = incr2->in(2)->get_int(); // The ratio of the two strides cannot be represented as an int diff --git a/test/hotspot/jtreg/compiler/c2/TestUnexpectedParallelIV.java b/test/hotspot/jtreg/compiler/c2/TestUnexpectedParallelIV.java new file mode 100644 index 00000000000..7d1008a3d09 --- /dev/null +++ b/test/hotspot/jtreg/compiler/c2/TestUnexpectedParallelIV.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022, 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. + * + */ + +/** + * @test + * @bug 8290432 + * @summary Unexpected parallel induction variable pattern was recongized + * + * @run main/othervm -XX:-TieredCompilation -Xcomp + * -XX:CompileCommand=compileonly,compiler.c2.TestUnexpectedParallelIV::test + * -XX:CompileCommand=compileonly,compiler.c2.TestUnexpectedParallelIV::test2 + * -XX:CompileCommand=quiet + * -XX:CompileCommand=dontinline,compiler.c2.TestUnexpectedParallelIV::* compiler.c2.TestUnexpectedParallelIV + */ + +package compiler.c2; + +public class TestUnexpectedParallelIV { + + static boolean bFld; + + static int dontInline() { + return 0; + } + + static int test2(int i1) { + int i2, i3 = 0, i4, i5 = 0, i6; + for (i2 = 0; 4 > i2; ++i2) { + for (i4 = 1; i4 < 5; ++i4) { + i3 -= --i1; + i6 = 1; + while (++i6 < 2) { + dontInline(); + if (bFld) { + i1 = 5; + } + } + if (bFld) { + break; + } + } + } + return i3; + } + + static long test(int val, boolean b) { + long ret = 0; + long dArr[] = new long[100]; + for (int i = 15; 293 > i; ++i) { + ret = val; + int j = 1; + while (++j < 6) { + int k = (val--); + for (long l = i; 1 > l; ) { + if (k != 0) { + ret += dontInline(); + } + } + if (b) { + break; + } + } + } + return ret; + } + + public static void main(String[] args) { + for (int i = 0; i < 1000; i++) { + test(0, false); + } + + test2(5); + } +} From 8ea369afe6b23618086d074f1fad61effce3beec Mon Sep 17 00:00:00 2001 From: Denghui Dong Date: Wed, 7 Dec 2022 06:37:54 +0000 Subject: [PATCH 086/494] 8298171: Missing newline in the example output of -Xlog:help Reviewed-by: dholmes --- src/hotspot/share/logging/logConfiguration.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/logging/logConfiguration.cpp b/src/hotspot/share/logging/logConfiguration.cpp index a35b42016db..d37393f287b 100644 --- a/src/hotspot/share/logging/logConfiguration.cpp +++ b/src/hotspot/share/logging/logConfiguration.cpp @@ -675,6 +675,7 @@ void LogConfiguration::print_command_line_help(outputStream* out) { out->print_cr(" -Xlog:disable -Xlog:safepoint=trace:safepointtrace.txt"); out->print_cr("\t Turn off all logging, including warnings and errors,"); out->print_cr("\t and then enable messages tagged with 'safepoint' up to 'trace' level to file 'safepointtrace.txt'."); + out->cr(); out->print_cr(" -Xlog:async -Xlog:gc=debug:file=gc.log -Xlog:safepoint=trace"); out->print_cr("\t Write logs asynchronously. Enable messages tagged with 'safepoint' up to 'trace' level to stdout "); From 1c2a093988c69ae0b2c0030835d11469fa9fb852 Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 7 Dec 2022 07:31:29 +0000 Subject: [PATCH 087/494] 8298147: Clang warns about pointless comparisons Reviewed-by: dholmes --- .../os/linux/cgroupV1Subsystem_linux.cpp | 3 --- .../os/linux/cgroupV2Subsystem_linux.cpp | 24 ------------------- 2 files changed, 27 deletions(-) diff --git a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp index e62dcf4f759..d7dda076966 100644 --- a/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV1Subsystem_linux.cpp @@ -287,9 +287,6 @@ int CgroupV1Subsystem::cpu_shares() { char* CgroupV1Subsystem::pids_max_val() { GET_CONTAINER_INFO_CPTR(cptr, _pids, "/pids.max", "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); - if (pidsmax == NULL) { - return NULL; - } return os::strdup(pidsmax); } diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index 25ab8f55f38..eebff376711 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -92,27 +92,18 @@ int CgroupV2Subsystem::cpu_quota() { char * CgroupV2Subsystem::cpu_cpuset_cpus() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.cpus", "cpuset.cpus is: %s", "%1023s", cpus, 1024); - if (cpus == NULL) { - return NULL; - } return os::strdup(cpus); } char* CgroupV2Subsystem::cpu_quota_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpu.max", "Raw value for CPU quota is: %s", "%s %*d", quota, 1024); - if (quota == NULL) { - return NULL; - } return os::strdup(quota); } char * CgroupV2Subsystem::cpu_cpuset_memory_nodes() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpuset.mems", "cpuset.mems is: %s", "%1023s", mems, 1024); - if (mems == NULL) { - return NULL; - } return os::strdup(mems); } @@ -151,9 +142,6 @@ jlong CgroupV2Subsystem::memory_max_usage_in_bytes() { char* CgroupV2Subsystem::mem_soft_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", "Memory Soft Limit is: %s", "%s", mem_soft_limit_str, 1024); - if (mem_soft_limit_str == NULL) { - return NULL; - } return os::strdup(mem_soft_limit_str); } @@ -176,9 +164,6 @@ jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() { char* CgroupV2Subsystem::mem_swp_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.max", "Memory and Swap Limit is: %s", "%s", mem_swp_limit_str, 1024); - if (mem_swp_limit_str == NULL) { - return NULL; - } return os::strdup(mem_swp_limit_str); } @@ -186,9 +171,6 @@ char* CgroupV2Subsystem::mem_swp_limit_val() { char* CgroupV2Subsystem::mem_swp_current_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.current", "Swap currently used is: %s", "%s", mem_swp_current_str, 1024); - if (mem_swp_current_str == NULL) { - return NULL; - } return os::strdup(mem_swp_current_str); } @@ -216,9 +198,6 @@ jlong CgroupV2Subsystem::read_memory_limit_in_bytes() { char* CgroupV2Subsystem::mem_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max", "Raw value for memory limit is: %s", "%s", mem_limit_str, 1024); - if (mem_limit_str == NULL) { - return NULL; - } return os::strdup(mem_limit_str); } @@ -245,9 +224,6 @@ char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { char* CgroupV2Subsystem::pids_max_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/pids.max", "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); - if (pidsmax == NULL) { - return NULL; - } return os::strdup(pidsmax); } From 085f96cb1a9be3e55da5801069a800e322649a8f Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 7 Dec 2022 08:28:20 +0000 Subject: [PATCH 088/494] 8295258: Add BasicType argument to AccessInternal::decorator_fixup Reviewed-by: stefank, eosterlund --- src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp | 4 ++-- src/hotspot/cpu/arm/macroAssembler_arm.cpp | 4 ++-- src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp | 4 ++-- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 4 ++-- src/hotspot/cpu/s390/macroAssembler_s390.cpp | 4 ++-- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 4 ++-- src/hotspot/share/gc/shared/c1/barrierSetC1.hpp | 2 +- src/hotspot/share/gc/shared/c2/barrierSetC2.cpp | 2 +- src/hotspot/share/oops/accessDecorators.hpp | 8 +++++--- 9 files changed, 19 insertions(+), 17 deletions(-) diff --git a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp index ff88e9487ef..b16140dac67 100644 --- a/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp @@ -4387,7 +4387,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register tmp2) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2); @@ -4400,7 +4400,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); diff --git a/src/hotspot/cpu/arm/macroAssembler_arm.cpp b/src/hotspot/cpu/arm/macroAssembler_arm.cpp index 1c7ae0f54f3..8744ac6dedd 100644 --- a/src/hotspot/cpu/arm/macroAssembler_arm.cpp +++ b/src/hotspot/cpu/arm/macroAssembler_arm.cpp @@ -1643,7 +1643,7 @@ void MacroAssembler::store_heap_oop_null(Address obj, Register new_val, Register void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Address src, Register dst, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2, tmp3); @@ -1655,7 +1655,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address obj, Register new_val, Register tmp1, Register tmp2, Register tmp3, bool is_null) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, obj, new_val, tmp1, tmp2, tmp3, is_null); diff --git a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp index 5be76916b21..d4a08310dd9 100644 --- a/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp +++ b/src/hotspot/cpu/ppc/macroAssembler_ppc.inline.hpp @@ -357,7 +357,7 @@ inline void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorat ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); bool as_raw = (decorators & AS_RAW) != 0; - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, base, ind_or_offs, val, @@ -377,7 +377,7 @@ inline void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorato assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 3c613d8c09b..90032696513 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -1993,7 +1993,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register tmp2) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, tmp2); @@ -2018,7 +2018,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler *bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); diff --git a/src/hotspot/cpu/s390/macroAssembler_s390.cpp b/src/hotspot/cpu/s390/macroAssembler_s390.cpp index 5a26adf5ec9..46897266b20 100644 --- a/src/hotspot/cpu/s390/macroAssembler_s390.cpp +++ b/src/hotspot/cpu/s390/macroAssembler_s390.cpp @@ -3858,7 +3858,7 @@ void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_UNKNOWN_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, @@ -3877,7 +3877,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, assert((decorators & ~(AS_RAW | IN_HEAP | IN_NATIVE | IS_ARRAY | IS_NOT_NULL | ON_PHANTOM_OOP_REF | ON_WEAK_OOP_REF)) == 0, "unsupported decorator"); BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 387a63c804a..76d348b6a05 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -5108,7 +5108,7 @@ void MacroAssembler::store_klass(Register dst, Register src, Register tmp) { void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Register dst, Address src, Register tmp1, Register thread_tmp) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::load_at(this, decorators, type, dst, src, tmp1, thread_tmp); @@ -5120,7 +5120,7 @@ void MacroAssembler::access_load_at(BasicType type, DecoratorSet decorators, Reg void MacroAssembler::access_store_at(BasicType type, DecoratorSet decorators, Address dst, Register val, Register tmp1, Register tmp2, Register tmp3) { BarrierSetAssembler* bs = BarrierSet::barrier_set()->barrier_set_assembler(); - decorators = AccessInternal::decorator_fixup(decorators); + decorators = AccessInternal::decorator_fixup(decorators, type); bool as_raw = (decorators & AS_RAW) != 0; if (as_raw) { bs->BarrierSetAssembler::store_at(this, decorators, type, dst, val, tmp1, tmp2, tmp3); diff --git a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp index 777d68ff872..bc0a9a7e57b 100644 --- a/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp +++ b/src/hotspot/share/gc/shared/c1/barrierSetC1.hpp @@ -76,7 +76,7 @@ class LIRAccess: public StackObj { LIRAddressOpr base, LIRAddressOpr offset, BasicType type, CodeEmitInfo* patch_emit_info = NULL, CodeEmitInfo* access_emit_info = NULL) : _gen(gen), - _decorators(AccessInternal::decorator_fixup(decorators)), + _decorators(AccessInternal::decorator_fixup(decorators, type)), _base(base), _offset(offset), _type(type), diff --git a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp index c518ad4216a..f41cd0e2ac3 100644 --- a/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp +++ b/src/hotspot/share/gc/shared/c2/barrierSetC2.cpp @@ -358,7 +358,7 @@ void C2Access::fixup_decorators() { _decorators |= MO_RELAXED; // Force the MO_RELAXED decorator with AlwaysAtomicAccess } - _decorators = AccessInternal::decorator_fixup(_decorators); + _decorators = AccessInternal::decorator_fixup(_decorators, _type); if (is_read && !is_write && anonymous) { // To be valid, unsafe loads may depend on other conditions than diff --git a/src/hotspot/share/oops/accessDecorators.hpp b/src/hotspot/share/oops/accessDecorators.hpp index 4235b4b2e9a..9b571e0e297 100644 --- a/src/hotspot/share/oops/accessDecorators.hpp +++ b/src/hotspot/share/oops/accessDecorators.hpp @@ -236,10 +236,12 @@ namespace AccessInternal { // This function implements the above DecoratorFixup rules, but without meta // programming for code generation that does not use templates. - inline DecoratorSet decorator_fixup(DecoratorSet input_decorators) { + inline DecoratorSet decorator_fixup(DecoratorSet input_decorators, BasicType type) { + // Some call-sites don't specify that the access is performed on oops + DecoratorSet with_oop_decorators = input_decorators |= (is_reference_type(type) ? INTERNAL_VALUE_IS_OOP : 0); // If no reference strength has been picked, then strong will be picked - DecoratorSet ref_strength_default = input_decorators | - (((ON_DECORATOR_MASK & input_decorators) == 0 && (INTERNAL_VALUE_IS_OOP & input_decorators) != 0) ? + DecoratorSet ref_strength_default = with_oop_decorators | + (((ON_DECORATOR_MASK & with_oop_decorators) == 0 && (INTERNAL_VALUE_IS_OOP & input_decorators) != 0) ? ON_STRONG_OOP_REF : DECORATORS_NONE); // If no memory ordering has been picked, unordered will be picked DecoratorSet memory_ordering_default = ref_strength_default | From 27bbe7be2c43a22e8cf55aa403d8018346ae3e37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Wed, 7 Dec 2022 08:56:10 +0000 Subject: [PATCH 089/494] 8297976: Remove sun.net.ProgressMonitor and related classes 8240275: Occasional errors in HttpURLConnection due to race with GC Reviewed-by: jpai, dfuchs, michaelm --- .../share/classes/sun/net/ProgressEvent.java | 113 ------- .../classes/sun/net/ProgressListener.java | 51 --- .../sun/net/ProgressMeteringPolicy.java | 45 --- .../classes/sun/net/ProgressMonitor.java | 246 --------------- .../share/classes/sun/net/ProgressSource.java | 210 ------------- .../classes/sun/net/www/MeteredStream.java | 27 +- .../classes/sun/net/www/http/HttpClient.java | 48 +-- .../sun/net/www/http/KeepAliveStream.java | 8 +- .../www/protocol/file/FileURLConnection.java | 11 +- .../www/protocol/ftp/FtpURLConnection.java | 14 +- .../www/protocol/http/HttpURLConnection.java | 34 +- .../reflect/Proxy/ProxyModuleMapping.java | 4 +- ...hunkedEncodingWithProgressMonitorTest.java | 103 ------ .../KeepAliveStreamFinalizer.java | 293 ++++++++++++++++++ 14 files changed, 313 insertions(+), 894 deletions(-) delete mode 100644 src/java.base/share/classes/sun/net/ProgressEvent.java delete mode 100644 src/java.base/share/classes/sun/net/ProgressListener.java delete mode 100644 src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java delete mode 100644 src/java.base/share/classes/sun/net/ProgressMonitor.java delete mode 100644 src/java.base/share/classes/sun/net/ProgressSource.java delete mode 100644 test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java create mode 100644 test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java diff --git a/src/java.base/share/classes/sun/net/ProgressEvent.java b/src/java.base/share/classes/sun/net/ProgressEvent.java deleted file mode 100644 index 00ef84e5cc9..00000000000 --- a/src/java.base/share/classes/sun/net/ProgressEvent.java +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2004, 2008, 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. - */ -package sun.net; - -import java.util.EventObject; -import java.net.URL; - -/** - * ProgressEvent represents an progress event in monitering network input stream. - * - * @author Stanley Man-Kit Ho - */ -@SuppressWarnings("serial") // never serialized -public class ProgressEvent extends EventObject { - // URL of the stream - private URL url; - // content type of the stream - private String contentType; - // method associated with URL - private String method; - // bytes read - private long progress; - // bytes expected - private long expected; - // the last thing to happen - private ProgressSource.State state; - - /** - * Construct a ProgressEvent object. - */ - public ProgressEvent(ProgressSource source, URL url, String method, String contentType, ProgressSource.State state, long progress, long expected) { - super(source); - this.url = url; - this.method = method; - this.contentType = contentType; - this.progress = progress; - this.expected = expected; - this.state = state; - } - - /** - * Return URL related to the progress. - */ - public URL getURL() - { - return url; - } - - /** - * Return method associated with URL. - */ - public String getMethod() - { - return method; - } - - /** - * Return content type of the URL. - */ - public String getContentType() - { - return contentType; - } - - /** - * Return current progress value. - */ - public long getProgress() - { - return progress; - } - - /** - * Return expected maximum progress value; -1 if expected is unknown. - */ - public long getExpected() { - return expected; - } - - /** - * Return state. - */ - public ProgressSource.State getState() { - return state; - } - - public String toString() { - return getClass().getName() + "[url=" + url + ", method=" + method + ", state=" + state - + ", content-type=" + contentType + ", progress=" + progress + ", expected=" + expected + "]"; - } -} diff --git a/src/java.base/share/classes/sun/net/ProgressListener.java b/src/java.base/share/classes/sun/net/ProgressListener.java deleted file mode 100644 index 140744bd605..00000000000 --- a/src/java.base/share/classes/sun/net/ProgressListener.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright (c) 2004, 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. - */ -package sun.net; - -import java.util.EventListener; - -/** - * ProgressListener is an interface to be implemented by parties - * interested to be notified of progress in network input stream. - * - * @author Stanley Man-Kit Ho - */ -public interface ProgressListener extends EventListener -{ - /** - * Start progress. - */ - public void progressStart(ProgressEvent evt); - - /** - * Update progress. - */ - public void progressUpdate(ProgressEvent evt); - - /** - * Finish progress. - */ - public void progressFinish(ProgressEvent evt); -} diff --git a/src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java b/src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java deleted file mode 100644 index f6e3ea9465e..00000000000 --- a/src/java.base/share/classes/sun/net/ProgressMeteringPolicy.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2004, 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. - */ -package sun.net; - -import java.net.URL; - -/** - * ProgressMeteringPolicy is an interface for determining progress metering policy. - * - * @author Stanley Man-Kit Ho - */ -public interface ProgressMeteringPolicy -{ - /** - * Return true if metering should be turned on for a particular network input stream. - */ - public boolean shouldMeterInput(URL url, String method); - - /** - * Return update notification threshold. - */ - public int getProgressUpdateThreshold(); -} diff --git a/src/java.base/share/classes/sun/net/ProgressMonitor.java b/src/java.base/share/classes/sun/net/ProgressMonitor.java deleted file mode 100644 index d92a0ff1c38..00000000000 --- a/src/java.base/share/classes/sun/net/ProgressMonitor.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright (c) 2004, 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. - */ - -package sun.net; - -import java.util.ArrayList; -import java.util.Iterator; -import java.net.URL; - -/** - * ProgressMonitor is a class for monitoring progress in network input stream. - * - * @author Stanley Man-Kit Ho - */ -public class ProgressMonitor -{ - /** - * Return default ProgressMonitor. - */ - public static synchronized ProgressMonitor getDefault() { - return pm; - } - - /** - * Change default ProgressMonitor implementation. - */ - public static synchronized void setDefault(ProgressMonitor m) { - if (m != null) - pm = m; - } - - /** - * Change progress metering policy. - */ - public static synchronized void setMeteringPolicy(ProgressMeteringPolicy policy) { - if (policy != null) - meteringPolicy = policy; - } - - - /** - * Return a snapshot of the ProgressSource list - */ - public ArrayList getProgressSources() { - ArrayList snapshot = new ArrayList<>(); - - try { - synchronized(progressSourceList) { - for (ProgressSource pi : progressSourceList) { - // Clone ProgressSource and add to snapshot - snapshot.add((ProgressSource)pi.clone()); - } - } - } - catch(CloneNotSupportedException e) { - e.printStackTrace(); - } - - return snapshot; - } - - /** - * Return update notification threshold - */ - public synchronized int getProgressUpdateThreshold() { - return meteringPolicy.getProgressUpdateThreshold(); - } - - /** - * Return true if metering should be turned on - * for a particular URL input stream. - */ - public boolean shouldMeterInput(URL url, String method) { - return meteringPolicy.shouldMeterInput(url, method); - } - - /** - * Register progress source when progress is began. - */ - public void registerSource(ProgressSource pi) { - - synchronized(progressSourceList) { - if (progressSourceList.contains(pi)) - return; - - progressSourceList.add(pi); - } - - // Notify only if there is at least one listener - if (progressListenerList.size() > 0) - { - // Notify progress listener if there is progress change - ArrayList listeners; - - // Copy progress listeners to another list to avoid holding locks - synchronized(progressListenerList) { - listeners = new ArrayList<>(progressListenerList); - } - - // Fire event on each progress listener - for (ProgressListener pl : listeners) { - ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected()); - pl.progressStart(pe); - } - } - } - - /** - * Unregister progress source when progress is finished. - */ - public void unregisterSource(ProgressSource pi) { - - synchronized(progressSourceList) { - // Return if ProgressEvent does not exist - if (progressSourceList.contains(pi) == false) - return; - - // Close entry and remove from map - pi.close(); - progressSourceList.remove(pi); - } - - // Notify only if there is at least one listener - if (progressListenerList.size() > 0) - { - // Notify progress listener if there is progress change - ArrayList listeners; - - // Copy progress listeners to another list to avoid holding locks - synchronized(progressListenerList) { - listeners = new ArrayList<>(progressListenerList); - } - - // Fire event on each progress listener - for (ProgressListener pl : listeners) { - ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected()); - pl.progressFinish(pe); - } - } - } - - /** - * Progress source is updated. - */ - public void updateProgress(ProgressSource pi) { - - synchronized (progressSourceList) { - if (progressSourceList.contains(pi) == false) - return; - } - - // Notify only if there is at least one listener - if (progressListenerList.size() > 0) - { - // Notify progress listener if there is progress change - ArrayList listeners; - - // Copy progress listeners to another list to avoid holding locks - synchronized(progressListenerList) { - listeners = new ArrayList<>(progressListenerList); - } - - // Fire event on each progress listener - for (ProgressListener pl : listeners) { - ProgressEvent pe = new ProgressEvent(pi, pi.getURL(), pi.getMethod(), pi.getContentType(), pi.getState(), pi.getProgress(), pi.getExpected()); - pl.progressUpdate(pe); - } - } - } - - /** - * Add progress listener in progress monitor. - */ - public void addProgressListener(ProgressListener l) { - synchronized(progressListenerList) { - progressListenerList.add(l); - } - } - - /** - * Remove progress listener from progress monitor. - */ - public void removeProgressListener(ProgressListener l) { - synchronized(progressListenerList) { - progressListenerList.remove(l); - } - } - - // Metering policy - private static ProgressMeteringPolicy meteringPolicy = new DefaultProgressMeteringPolicy(); - - // Default implementation - private static ProgressMonitor pm = new ProgressMonitor(); - - // ArrayList for outstanding progress sources - private ArrayList progressSourceList = new ArrayList(); - - // ArrayList for progress listeners - private ArrayList progressListenerList = new ArrayList(); -} - - -/** - * Default progress metering policy. - */ -class DefaultProgressMeteringPolicy implements ProgressMeteringPolicy { - /** - * Return true if metering should be turned on for a particular network input stream. - */ - public boolean shouldMeterInput(URL url, String method) - { - // By default, no URL input stream is metered for - // performance reason. - return false; - } - - /** - * Return update notification threshold. - */ - public int getProgressUpdateThreshold() { - // 8K - same as default I/O buffer size - return 8192; - } -} diff --git a/src/java.base/share/classes/sun/net/ProgressSource.java b/src/java.base/share/classes/sun/net/ProgressSource.java deleted file mode 100644 index 9bbd14143cd..00000000000 --- a/src/java.base/share/classes/sun/net/ProgressSource.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2004, 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. - */ -package sun.net; - -import java.net.URL; - -/** - * ProgressSource represents the source of progress changes. - * - * @author Stanley Man-Kit Ho - */ -public class ProgressSource -{ - public enum State { NEW, CONNECTED, UPDATE, DELETE }; - - // URL - private URL url; - // URL method - private String method; - // Content type - private String contentType; - // bytes read - private long progress = 0; - // last bytes read - private long lastProgress = 0; - //bytes expected - private long expected = -1; - // the last thing to happen with this source - private State state; - // connect flag - private boolean connected = false; - // threshold for notification - private int threshold = 8192; - // progress monitor - private ProgressMonitor progressMonitor; - - /** - * Construct progress source object. - */ - public ProgressSource(URL url, String method) { - this(url, method, -1); - } - - /** - * Construct progress source object. - */ - public ProgressSource(URL url, String method, long expected) { - this.url = url; - this.method = method; - this.contentType = "content/unknown"; - this.progress = 0; - this.lastProgress = 0; - this.expected = expected; - this.state = State.NEW; - this.progressMonitor = ProgressMonitor.getDefault(); - this.threshold = progressMonitor.getProgressUpdateThreshold(); - } - - public boolean connected() { - if (!connected) { - connected = true; - state = State.CONNECTED; - return false; - } - return true; - } - - /** - * Close progress source. - */ - public void close() { - state = State.DELETE; - } - - /** - * Return URL of progress source. - */ - public URL getURL() { - return url; - } - - /** - * Return method of URL. - */ - public String getMethod() { - return method; - } - - /** - * Return content type of URL. - */ - public String getContentType() { - return contentType; - } - - // Change content type - public void setContentType(String ct) { - contentType = ct; - } - - /** - * Return current progress. - */ - public long getProgress() { - return progress; - } - - /** - * Return expected maximum progress; -1 if expected is unknown. - */ - public long getExpected() { - return expected; - } - - /** - * Return state. - */ - public State getState() { - return state; - } - - /** - * Begin progress tracking. - */ - public void beginTracking() { - progressMonitor.registerSource(this); - } - - /** - * Finish progress tracking. - */ - public void finishTracking() { - progressMonitor.unregisterSource(this); - } - - /** - * Update progress. - */ - public void updateProgress(long latestProgress, long expectedProgress) { - lastProgress = progress; - progress = latestProgress; - expected = expectedProgress; - - if (connected() == false) - state = State.CONNECTED; - else - state = State.UPDATE; - - // The threshold effectively divides the progress into - // different set of ranges: - // - // Range 0: 0..threshold-1, - // Range 1: threshold .. 2*threshold-1 - // .... - // Range n: n*threshold .. (n+1)*threshold-1 - // - // To determine which range the progress belongs to, it - // would be calculated as follow: - // - // range number = progress / threshold - // - // Notification should only be triggered when the current - // progress and the last progress are in different ranges, - // i.e. they have different range numbers. - // - // Using this range scheme, notification will be generated - // only once when the progress reaches each range. - // - if (lastProgress / threshold != progress / threshold) { - progressMonitor.updateProgress(this); - } - - // Detect read overrun - if (expected != -1) { - if (progress >= expected && progress != 0) - close(); - } - } - - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - public String toString() { - return getClass().getName() + "[url=" + url + ", method=" + method + ", state=" + state - + ", content-type=" + contentType + ", progress=" + progress + ", expected=" + expected + "]"; - } -} diff --git a/src/java.base/share/classes/sun/net/www/MeteredStream.java b/src/java.base/share/classes/sun/net/www/MeteredStream.java index a03440e66f7..d12389416fc 100644 --- a/src/java.base/share/classes/sun/net/www/MeteredStream.java +++ b/src/java.base/share/classes/sun/net/www/MeteredStream.java @@ -27,7 +27,6 @@ import java.io.*; import java.util.concurrent.locks.ReentrantLock; -import sun.net.ProgressSource; import sun.net.www.http.ChunkedInputStream; @@ -42,19 +41,13 @@ public class MeteredStream extends FilterInputStream { protected long count = 0; protected long markedCount = 0; protected int markLimit = -1; - protected ProgressSource pi; private final ReentrantLock readLock = new ReentrantLock(); - public MeteredStream(InputStream is, ProgressSource pi, long expected) + public MeteredStream(InputStream is, long expected) { super(is); - this.pi = pi; this.expected = expected; - - if (pi != null) { - pi.updateProgress(0, expected); - } } private final void justRead(long n) throws IOException { @@ -81,9 +74,6 @@ private final void justRead(long n) throws IOException { markLimit = -1; } - if (pi != null) - pi.updateProgress(count, expected); - if (isMarked()) { return; } @@ -170,8 +160,6 @@ public void close() throws IOException { lock(); try { if (closed) return; - if (pi != null) - pi.finishTracking(); closed = true; in.close(); @@ -241,17 +229,4 @@ public final void unlock() { public final boolean isLockHeldByCurrentThread() { return readLock.isHeldByCurrentThread(); } - - @SuppressWarnings("removal") - protected void finalize() throws Throwable { - try { - close(); - if (pi != null) - pi.close(); - } - finally { - // Call super class - super.finalize(); - } - } } diff --git a/src/java.base/share/classes/sun/net/www/http/HttpClient.java b/src/java.base/share/classes/sun/net/www/http/HttpClient.java index e6dd88c15b9..31f32b44da6 100644 --- a/src/java.base/share/classes/sun/net/www/http/HttpClient.java +++ b/src/java.base/share/classes/sun/net/www/http/HttpClient.java @@ -34,7 +34,6 @@ import java.util.concurrent.locks.ReentrantLock; import sun.net.NetworkClient; -import sun.net.ProgressSource; import sun.net.www.MessageHeader; import sun.net.www.HeaderParser; import sun.net.www.MeteredStream; @@ -741,7 +740,7 @@ public void writeRequests(MessageHeader head, /** Parse the first line of the HTTP request. It usually looks something like: {@literal "HTTP/1.0 comment\r\n"}. */ - public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc) + public boolean parseHTTP(MessageHeader responses, HttpURLConnection httpuc) throws IOException { /* If "HTTP/*" is found in the beginning, return true. Let * HttpURLConnection parse the mime header itself. @@ -758,7 +757,7 @@ public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConn serverInput = new HttpCaptureInputStream(serverInput, capture); } serverInput = new BufferedInputStream(serverInput); - return (parseHTTPHeader(responses, pi, httpuc)); + return (parseHTTPHeader(responses, httpuc)); } catch (SocketTimeoutException stex) { // We don't want to retry the request when the app. sets a timeout // but don't close the server if timeout while waiting for 100-continue @@ -785,7 +784,7 @@ public boolean parseHTTP(MessageHeader responses, ProgressSource pi, HttpURLConn checkTunneling(httpuc); afterConnect(); writeRequests(requests, poster); - return parseHTTP(responses, pi, httpuc); + return parseHTTP(responses, httpuc); } } throw e; @@ -805,7 +804,7 @@ private void checkTunneling(HttpURLConnection httpuc) throws IOException { } } - private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, HttpURLConnection httpuc) + private boolean parseHTTPHeader(MessageHeader responses, HttpURLConnection httpuc) throws IOException { /* If "HTTP/*" is found in the beginning, return true. Let * HttpURLConnection parse the mime header itself. @@ -951,7 +950,7 @@ private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, Http checkTunneling(httpuc); afterConnect(); writeRequests(requests, poster); - return parseHTTP(responses, pi, httpuc); + return parseHTTP(responses, httpuc); } } throw new SocketException("Unexpected end of file from server"); @@ -994,7 +993,7 @@ private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, Http || (code >= 102 && code <= 199)) { logFinest("Ignoring interim informational 1xx response: " + code); responses.reset(); - return parseHTTPHeader(responses, pi, httpuc); + return parseHTTPHeader(responses, httpuc); } long cl = -1; @@ -1067,11 +1066,6 @@ private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, Http // In this case, content length is well known, so it is okay // to wrap the input stream with KeepAliveStream/MeteredStream. - if (pi != null) { - // Progress monitor is enabled - pi.setContentType(responses.findValue("content-type")); - } - // If disableKeepAlive == true, the client will not be returned // to the cache. But we still need to use a keepalive stream to // allow the multi-message authentication exchange on the connection @@ -1079,39 +1073,13 @@ private boolean parseHTTPHeader(MessageHeader responses, ProgressSource pi, Http if (useKeepAliveStream) { // Wrap KeepAliveStream if keep alive is enabled. logFinest("KeepAlive stream used: " + url); - serverInput = new KeepAliveStream(serverInput, pi, cl, this); + serverInput = new KeepAliveStream(serverInput, cl, this); failedOnce = false; } else { - serverInput = new MeteredStream(serverInput, pi, cl); + serverInput = new MeteredStream(serverInput, cl); } } - else if (cl == -1) { - // In this case, content length is unknown - the input - // stream would simply be a regular InputStream or - // ChunkedInputStream. - - if (pi != null) { - // Progress monitoring is enabled. - - pi.setContentType(responses.findValue("content-type")); - - // Wrap MeteredStream for tracking indeterministic - // progress, even if the input stream is ChunkedInputStream. - serverInput = new MeteredStream(serverInput, pi, cl); - } - else { - // Progress monitoring is disabled, and there is no - // need to wrap an unknown length input stream. - - // ** This is an no-op ** - } - } - else { - if (pi != null) - pi.finishTracking(); - } - return ret; } diff --git a/src/java.base/share/classes/sun/net/www/http/KeepAliveStream.java b/src/java.base/share/classes/sun/net/www/http/KeepAliveStream.java index 852fda2165c..2006dc71de2 100644 --- a/src/java.base/share/classes/sun/net/www/http/KeepAliveStream.java +++ b/src/java.base/share/classes/sun/net/www/http/KeepAliveStream.java @@ -27,7 +27,6 @@ import java.io.*; -import sun.net.ProgressSource; import sun.net.www.MeteredStream; import jdk.internal.misc.InnocuousThread; @@ -56,8 +55,8 @@ class KeepAliveStream extends MeteredStream implements Hurryable { /** * Constructor */ - public KeepAliveStream(InputStream is, ProgressSource pi, long expected, HttpClient hc) { - super(is, pi, expected); + public KeepAliveStream(InputStream is, long expected, HttpClient hc) { + super(is, expected); this.hc = hc; } @@ -101,9 +100,6 @@ public void close() throws IOException { hc.finished(); } } finally { - if (pi != null) - pi.finishTracking(); - if (!queuedForCleanup) { // nulling out the underlying inputstream as well as // httpClient to let gc collect the memories faster diff --git a/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java index 603e8300ffc..a9ce7cee9a1 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/file/FileURLConnection.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1995, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1995, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,7 +36,6 @@ import java.io.*; import java.text.Collator; import java.security.Permission; -import sun.net.*; import sun.net.www.*; import java.util.*; import java.text.SimpleDateFormat; @@ -82,15 +81,7 @@ public void connect() throws IOException { throw new FileNotFoundException(filename + " exists, but is not accessible"); files = Arrays.asList(fileList); } else { - is = new BufferedInputStream(new FileInputStream(filename)); - - // Check if URL should be metered - boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET"); - if (meteredInput) { - ProgressSource pi = new ProgressSource(url, "GET", file.length()); - is = new MeteredStream(is, pi, file.length()); - } } } catch (IOException e) { throw e; diff --git a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java index d1254c6a76e..ecc17ea85ec 100644 --- a/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java +++ b/src/java.base/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java @@ -56,8 +56,6 @@ import sun.net.www.protocol.http.HttpURLConnection; import sun.net.ftp.FtpClient; import sun.net.ftp.FtpProtocolException; -import sun.net.ProgressSource; -import sun.net.ProgressMonitor; import sun.net.www.ParseUtil; import sun.security.action.GetPropertyAction; @@ -466,17 +464,7 @@ public InputStream getInputStream() throws IOException { // Wrap input stream with MeteredStream to ensure read() will always return -1 // at expected length. - - // Check if URL should be metered - boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET"); - ProgressSource pi = null; - - if (meteredInput) { - pi = new ProgressSource(url, "GET", l); - pi.beginTracking(); - } - - is = new MeteredStream(is, pi, l); + is = new MeteredStream(is, l); } } catch (Exception e) { e.printStackTrace(); 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 5cf29194789..7fa3c249a4a 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 @@ -67,7 +67,8 @@ import java.util.StringJoiner; import jdk.internal.access.JavaNetHttpCookieAccess; import jdk.internal.access.SharedSecrets; -import sun.net.*; +import sun.net.NetProperties; +import sun.net.NetworkClient; import sun.net.util.IPAddressUtil; import sun.net.www.*; import sun.net.www.http.HttpClient; @@ -384,9 +385,6 @@ private static Set schemesListToSet(String list) { String serverAuthKey, proxyAuthKey; - /* Progress source */ - protected ProgressSource pi; - /* all the response headers we get back */ private MessageHeader responses; /* the stream _from_ the server */ @@ -1331,7 +1329,7 @@ private void expect100Continue() throws IOException { } try { - http.parseHTTP(responses, pi, this); + http.parseHTTP(responses, this); } catch (SocketTimeoutException se) { if (!enforceTimeOut) { throw se; @@ -1662,14 +1660,6 @@ private InputStream getInputStream0() throws IOException { return cachedInputStream; } - // Check if URL should be metered - boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, method); - - if (meteredInput) { - pi = new ProgressSource(url, method); - pi.beginTracking(); - } - /* REMIND: This exists to fix the HttpsURLConnection subclass. * Hotjava needs to run on JDK1.1FCS. Do proper fix once a * proper solution for SSL can be found. @@ -1679,7 +1669,7 @@ private InputStream getInputStream0() throws IOException { if (!streaming()) { writeRequests(); } - http.parseHTTP(responses, pi, this); + http.parseHTTP(responses, this); if (logger.isLoggable(PlatformLogger.Level.FINE)) { logger.fine(responses.toString()); } @@ -1943,10 +1933,6 @@ private InputStream getInputStream0() throws IOException { respCode == HTTP_NOT_MODIFIED || respCode == HTTP_NO_CONTENT) { - if (pi != null) { - pi.finishTracking(); - pi = null; - } http.finished(); http = null; inputStream = new EmptyInputStream(); @@ -2166,9 +2152,7 @@ private void doTunneling0() throws IOException { sendCONNECTRequest(); responses.reset(); - // There is no need to track progress in HTTP Tunneling, - // so ProgressSource is null. - http.parseHTTP(responses, null, this); + http.parseHTTP(responses, this); /* Log the response to the CONNECT */ if (logger.isLoggable(PlatformLogger.Level.FINE)) { @@ -3045,10 +3029,6 @@ private void disconnectWeb() throws IOException { private void disconnectInternal() { responseCode = -1; inputStream = null; - if (pi != null) { - pi.finishTracking(); - pi = null; - } if (http != null) { http.closeServer(); http = null; @@ -3062,10 +3042,6 @@ private void disconnectInternal() { public void disconnect() { responseCode = -1; - if (pi != null) { - pi.finishTracking(); - pi = null; - } if (http != null) { /* diff --git a/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java b/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java index 86403c3378f..4e263d000a4 100644 --- a/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java +++ b/test/jdk/java/lang/reflect/Proxy/ProxyModuleMapping.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 static void main(String... args) throws Exception { // unnamed module gets access to sun.invoke package (e.g. via --add-exports) new ProxyModuleMapping(sun.invoke.WrapperInstance.class).test(); - Class modulePrivateIntf = Class.forName("sun.net.ProgressListener"); + Class modulePrivateIntf = Class.forName("sun.net.PlatformSocketImpl"); new ProxyModuleMapping(modulePrivateIntf).test(); } diff --git a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java b/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java deleted file mode 100644 index 38c00e68c87..00000000000 --- a/test/jdk/sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2004, 2019, 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 4333920 4994372 - * @summary ChunkedEncoding unit test; MeteredStream/ProgressData problem - * @modules java.base/sun.net - * jdk.httpserver - * @library /test/lib - * @run main ChunkedEncodingWithProgressMonitorTest - */ - -import java.net.*; -import java.util.BitSet; -import sun.net.ProgressMeteringPolicy; -import sun.net.ProgressMonitor; -import sun.net.ProgressListener; -import sun.net.ProgressEvent; - -public class ChunkedEncodingWithProgressMonitorTest { - public static void main (String[] args) throws Exception { - ProgressMonitor.setMeteringPolicy(new MyProgressMeteringPolicy()); - ProgressListener listener = new MyProgressListener(); - ProgressMonitor.getDefault().addProgressListener(listener); - ChunkedEncodingTest.test(); - ProgressMonitor.getDefault().removeProgressListener(listener); - - if (flag.cardinality() != 3) { - throw new RuntimeException("All three methods in ProgressListener"+ - " should be called. Yet the number of"+ - " methods actually called are "+ - flag.cardinality()); - } - } - - static class MyProgressMeteringPolicy implements ProgressMeteringPolicy { - /** - * Return true if metering should be turned on for a particular network input stream. - */ - public boolean shouldMeterInput(URL url, String method) { - return true; - } - - /** - * Return update notification threshold. - */ - public int getProgressUpdateThreshold() { - return 8192; - } - } - - static BitSet flag = new BitSet(3); - - static class MyProgressListener implements ProgressListener { - /** - * Start progress. - */ - public void progressStart(ProgressEvent evt) { - System.out.println("start: received progressevent "+evt); - if (flag.nextSetBit(0) == -1) - flag.set(0); - } - - /** - * Update progress. - */ - public void progressUpdate(ProgressEvent evt) { - System.out.println("update: received progressevent "+evt); - if (flag.nextSetBit(1) == -1) - flag.set(1); - } - - /** - * Finish progress. - */ - public void progressFinish(ProgressEvent evt) { - System.out.println("finish: received progressevent "+evt); - if (flag.nextSetBit(2) == -1) - flag.set(2); - } - } -} diff --git a/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java new file mode 100644 index 00000000000..16325c893c8 --- /dev/null +++ b/test/jdk/sun/net/www/http/KeepAliveStream/KeepAliveStreamFinalizer.java @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2022, 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 8240275 + * @library /test/lib + * @run main/othervm KeepAliveStreamFinalizer + * @summary HttpsURLConnection: connection must not be reused after finalization + */ + +import javax.net.ssl.HandshakeCompletedListener; +import javax.net.ssl.HttpsURLConnection; +import javax.net.ssl.SSLSession; +import javax.net.ssl.SSLSocket; +import javax.net.ssl.SSLSocketFactory; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.ServerSocket; +import java.net.Socket; +import java.net.URL; +import java.net.UnknownHostException; + +public class KeepAliveStreamFinalizer { + + static Server server; + private static volatile String failureReason; + + static class Server extends Thread { + final ServerSocket srv; + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n'}; + + Server(ServerSocket s) { + srv = s; + } + + boolean readOneRequest(InputStream is) throws IOException { + int requestEndCount = 0, r; + while ((r = is.read()) != -1) { + if (r == requestEnd[requestEndCount]) { + requestEndCount++; + if (requestEndCount == 4) { + return true; + } + } else { + requestEndCount = 0; + } + } + return false; + } + + public void run() { + try { + while (true) { + Socket ss = srv.accept(); + Thread t1 = new Thread(new Runnable() { + public void run() { + try { + InputStream in = ss.getInputStream(); + OutputStream out = ss.getOutputStream(); + while (readOneRequest(in)) { + out.write("HTTP/1.1 200 OK\r\nConnection: Keep-Alive\r\nContent-Length: 1\r\n\r\na".getBytes()); + out.flush(); + } + in.close(); + out.close(); + ss.close(); + } catch (Exception e) { + e.printStackTrace(); + } + } + }); + t1.setDaemon(true); + t1.start(); + } + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + public static void main(String[] args) throws Exception { + InetSocketAddress address = startHttpServer(); + clientHttpCalls(address); + if (failureReason != null) { + throw new RuntimeException(failureReason); + } + } + + public static InetSocketAddress startHttpServer() throws Exception { + InetAddress localHost = InetAddress.getLoopbackAddress(); + InetSocketAddress address = new InetSocketAddress(localHost, 0); + ServerSocket serverSocket = new ServerSocket(); + serverSocket.bind(address); + server = new Server(serverSocket); + server.setDaemon(true); + server.start(); + return (InetSocketAddress) serverSocket.getLocalSocketAddress(); + } + + public static void doRequest(URL url) throws IOException { + HttpsURLConnection c = (HttpsURLConnection)url.openConnection(); + c.setRequestMethod("POST"); + c.setDoOutput(true); + OutputStreamWriter out = new OutputStreamWriter(c.getOutputStream()); + out.write("test"); + out.close(); + int responseCode = c.getResponseCode(); + // Fully reading the body causes the HttpsClient to be added to the KeepAliveCache immediately, + // which avoids this issue since GC will not finalize the HttpsClient. + } + + public static void clientHttpCalls(InetSocketAddress address) throws Exception { + try { + System.err.println("http server listen on: " + address.getPort()); + String hostAddr = address.getAddress().getHostAddress(); + if (hostAddr.indexOf(':') > -1) hostAddr = "[" + hostAddr + "]"; + String baseURLStr = "https://" + hostAddr + ":" + address.getPort() + "/"; + + URL testUrl = new URL(baseURLStr); + + // CheckFinalizeSocketFactory is not a real SSLSocketFactory; + // it produces regular non-SSL sockets. Effectively, the request + // is made over http. + HttpsURLConnection.setDefaultSSLSocketFactory(new CheckFinalizeSocketFactory()); + // now perform up to 3 requests; with the broken KeepAliveStream finalizer, + // the second request usually attempts to use a finalized socket + for (int i = 0; i < 3; i++) { + System.err.println("Request #" + (i + 1)); + doRequest(testUrl); + System.gc(); + Thread.sleep(100); + if (failureReason != null) break; + } + } finally { + server.srv.close(); + } + } + + static class CheckFinalizeSocket extends SSLSocket { + private volatile boolean finalized; + public void finalize() throws Throwable { + System.err.println("In finalize"); + super.finalize(); + finalized = true; + } + + @Override + public InputStream getInputStream() throws IOException { + if (finalized) { + System.err.println(failureReason = "getInputStream called after finalize"); + Thread.dumpStack(); + } + return super.getInputStream(); + } + + @Override + public OutputStream getOutputStream() throws IOException { + if (finalized) { + System.err.println(failureReason = "getOutputStream called after finalize"); + Thread.dumpStack(); + } + return super.getOutputStream(); + } + + @Override + public synchronized void close() throws IOException { + if (finalized) { + System.err.println(failureReason = "close called after finalize"); + Thread.dumpStack(); + } + super.close(); + } + + // required abstract method overrides + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public String[] getEnabledCipherSuites() { + return new String[0]; + } + @Override + public void setEnabledCipherSuites(String[] suites) { } + @Override + public String[] getSupportedProtocols() { + return new String[0]; + } + @Override + public String[] getEnabledProtocols() { + return new String[0]; + } + @Override + public void setEnabledProtocols(String[] protocols) { } + @Override + public SSLSession getSession() { + return null; + } + @Override + public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { } + @Override + public void startHandshake() throws IOException { } + @Override + public void setUseClientMode(boolean mode) { } + @Override + public boolean getUseClientMode() { + return false; + } + @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) { } + @Override + public boolean getEnableSessionCreation() { + return false; + } + } + + static class CheckFinalizeSocketFactory extends SSLSocketFactory { + + @Override + public Socket createSocket() throws IOException { + return new CheckFinalizeSocket(); + } + // required abstract method overrides + @Override + public Socket createSocket(String host, int port) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress host, int port) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { + throw new UnsupportedOperationException(); + } + @Override + public String[] getDefaultCipherSuites() { + return new String[0]; + } + @Override + public String[] getSupportedCipherSuites() { + return new String[0]; + } + @Override + public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { + throw new UnsupportedOperationException(); + } + } +} + From 5a3439db9fef3e54650df4019e31311b60a0ec1d Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Wed, 7 Dec 2022 09:35:26 +0000 Subject: [PATCH 090/494] 4677581: ColorModel.getComponentSize()-wrong conditions for ArrayIndexOutOfBoundsExceptio Reviewed-by: prr --- .../classes/java/awt/image/ColorModel.java | 5 +- .../ColorModel/GetComponentSizeAIOBE.java | 54 +++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) create mode 100644 test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java diff --git a/src/java.desktop/share/classes/java/awt/image/ColorModel.java b/src/java.desktop/share/classes/java/awt/image/ColorModel.java index 94af9edac77..6c14d425cc6 100644 --- a/src/java.desktop/share/classes/java/awt/image/ColorModel.java +++ b/src/java.desktop/share/classes/java/awt/image/ColorModel.java @@ -465,9 +465,8 @@ public int getPixelSize() { * @param componentIdx the index of the color/alpha component * @return the number of bits for the color/alpha component at the * specified index. - * @throws ArrayIndexOutOfBoundsException if {@code componentIdx} - * is greater than the number of components or - * less than zero + * @throws ArrayIndexOutOfBoundsException if {@code componentIdx} is greater + * than or equal to the number of components or less than zero * @throws NullPointerException if the number of bits array is * {@code null} */ diff --git a/test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java b/test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java new file mode 100644 index 00000000000..e2274497256 --- /dev/null +++ b/test/jdk/java/awt/image/ColorModel/GetComponentSizeAIOBE.java @@ -0,0 +1,54 @@ +/* + * 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.image.ColorModel; + +/** + * @test + * @bug 4677581 + * @summary checks when the ColorModel#getComponentSize() throws AIOBE + */ +public final class GetComponentSizeAIOBE { + + public static void main(String[] args) { + ColorModel cm = ColorModel.getRGBdefault(); + for (int i = 0; i < cm.getNumComponents(); ++i) { + cm.getComponentSize(i); + } + + testAIOBE(cm, Integer.MIN_VALUE); + testAIOBE(cm, -1); + testAIOBE(cm, cm.getNumComponents()); + testAIOBE(cm, cm.getNumComponents() + 1); + testAIOBE(cm, Integer.MAX_VALUE); + } + + private static void testAIOBE(ColorModel cm, int componentIdx) { + try { + cm.getComponentSize(componentIdx); + throw new RuntimeException("AIOBE is not thrown"); + } catch (ArrayIndexOutOfBoundsException ignore) { + // expected + } + } +} From ccc69af966cf4395d75b2018490cafc47dcad90f Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Wed, 7 Dec 2022 10:12:40 +0000 Subject: [PATCH 091/494] 8296672: Implementation of Virtual Threads (Second Preview) Reviewed-by: mchung, jpai --- .../share/classes/jdk/internal/javac/PreviewFeature.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java index 26e2a92ea4a..f02db39ad65 100644 --- a/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java +++ b/src/java.base/share/classes/jdk/internal/javac/PreviewFeature.java @@ -68,7 +68,7 @@ public enum Feature { SWITCH_PATTERN_MATCHING(), @JEP(number=432, title="Record Patterns", status="Second Preview") RECORD_PATTERNS, - @JEP(number=425, title="Virtual Threads") + @JEP(number=436, title="Virtual Threads", status="Second Preview") VIRTUAL_THREADS, @JEP(number=434, title="Foreign Function & Memory API", status="Second Preview") FOREIGN, From 221e1a426070088b819ddc37b7ca77d9d8626eb4 Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Wed, 7 Dec 2022 10:14:06 +0000 Subject: [PATCH 092/494] 8286666: JEP 429: Implementation of Scoped Values (Incubator) Reviewed-by: psandoz, dlong, alanb, mcimadamore --- make/data/hotspot-symbols/symbols-unix | 8 +- src/hotspot/cpu/aarch64/aarch64.ad | 5 + src/hotspot/cpu/x86/x86_64.ad | 8 +- src/hotspot/share/c1/c1_Compiler.cpp | 2 +- src/hotspot/share/c1/c1_LIRGenerator.cpp | 6 +- src/hotspot/share/c1/c1_LIRGenerator.hpp | 2 +- src/hotspot/share/classfile/javaClasses.cpp | 9 +- src/hotspot/share/classfile/javaClasses.hpp | 6 +- src/hotspot/share/classfile/vmIntrinsics.cpp | 10 +- src/hotspot/share/classfile/vmIntrinsics.hpp | 20 +- src/hotspot/share/classfile/vmSymbols.hpp | 4 + src/hotspot/share/include/jvm.h | 9 +- .../share/interpreter/interpreterRuntime.cpp | 6 + src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 4 +- src/hotspot/share/jvmci/vmStructs_jvmci.cpp | 2 +- src/hotspot/share/oops/oopHandle.hpp | 1 - src/hotspot/share/opto/c2compiler.cpp | 4 +- src/hotspot/share/opto/library_call.cpp | 30 +- src/hotspot/share/opto/library_call.hpp | 6 +- src/hotspot/share/opto/memnode.cpp | 2 +- src/hotspot/share/prims/jvm.cpp | 72 +- src/hotspot/share/runtime/deoptimization.cpp | 7 +- .../flags/jvmFlagConstraintsRuntime.cpp | 12 - .../flags/jvmFlagConstraintsRuntime.hpp | 1 - src/hotspot/share/runtime/globals.hpp | 5 - src/hotspot/share/runtime/javaThread.cpp | 33 +- src/hotspot/share/runtime/javaThread.hpp | 9 +- src/hotspot/share/runtime/sharedRuntime.cpp | 7 +- src/hotspot/share/runtime/vframe_hp.cpp | 4 +- src/hotspot/share/runtime/vmStructs.cpp | 2 +- src/hotspot/share/utilities/exceptions.cpp | 10 +- .../share/classes/java/lang/System.java | 26 +- .../share/classes/java/lang/Thread.java | 79 +- .../classes/java/lang/VirtualThread.java | 19 +- .../util/concurrent/ThreadLocalRandom.java | 2 +- .../jdk/internal/access/JavaLangAccess.java | 20 +- .../jdk/internal/misc/ThreadFlock.java | 31 +- .../classes/jdk/internal/vm/Continuation.java | 18 +- ...ntainer.java => ScopedValueContainer.java} | 45 +- .../jdk/internal/vm/ThreadContainer.java | 4 +- src/java.base/share/classes/module-info.java | 6 +- src/java.base/share/native/libjava/Thread.c | 9 +- .../jdk/incubator/concurrent/ScopedValue.java | 838 ++++++++++++++++++ .../concurrent/StructuredTaskScope.java | 94 +- .../GetFrameCount/framecnt01/framecnt01.java | 13 +- .../libGetStackTraceCurrentThreadTest.cpp | 6 +- .../getstacktr03/libgetstacktr03.cpp | 4 +- .../getstacktr04/libgetstacktr04.cpp | 2 + .../getstacktr05/libgetstacktr05.cpp | 2 + .../getstacktr06/libgetstacktr06.cpp | 2 + .../getstacktr07/libgetstacktr07.cpp | 2 + .../getstacktr08/libgetstacktr08.cpp | 2 + test/jdk/ProblemList.txt | 1 + .../concurrent/ScopedValue/ManyBindings.java | 164 ++++ .../concurrent/ScopedValue/ScopeValueAPI.java | 442 +++++++++ .../ScopedValue/StressStackOverflow.java | 213 +++++ .../StructuredTaskScope/WithScopedValue.java | 216 +++++ .../misc/ThreadFlock/WithScopedValue.java | 220 +++++ .../incubator/concurrent/ScopedValues.java | 217 +++++ .../concurrent/ScopedValuesData.java | 72 ++ .../ScopedValuesExecutorService.java | 44 + 61 files changed, 2889 insertions(+), 230 deletions(-) rename src/java.base/share/classes/jdk/internal/vm/{ExtentLocalContainer.java => ScopedValueContainer.java} (81%) create mode 100644 src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/ScopedValue.java create mode 100644 test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java create mode 100644 test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java create mode 100644 test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java create mode 100644 test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java create mode 100644 test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java create mode 100644 test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java diff --git a/make/data/hotspot-symbols/symbols-unix b/make/data/hotspot-symbols/symbols-unix index de2babed51a..ae49a992f54 100644 --- a/make/data/hotspot-symbols/symbols-unix +++ b/make/data/hotspot-symbols/symbols-unix @@ -194,8 +194,6 @@ JVM_RegisterLambdaProxyClassForArchiving JVM_RegisterSignal JVM_ReleaseUTF JVM_ReportFinalizationComplete -JVM_ExtentLocalCache -JVM_SetExtentLocalCache JVM_SetArrayElement JVM_SetClassSigners JVM_SetNativeThreadName @@ -225,4 +223,10 @@ JVM_VirtualThreadMountEnd JVM_VirtualThreadUnmountBegin JVM_VirtualThreadUnmountEnd JVM_VirtualThreadHideFrames + +# Scoped values +JVM_EnsureMaterializedForStackWalk_func +JVM_FindScopedValueBindings +JVM_ScopedValueCache +JVM_SetScopedValueCache # diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index e6d39248ac4..c162baad936 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -3632,6 +3632,11 @@ encode %{ ciEnv::current()->record_failure("CodeCache is full"); return; } + } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) { + // The NOP here is purely to ensure that eliding a call to + // JVM_EnsureMaterializedForStackWalk doesn't change the code size. + __ nop(); + __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); } else { int method_index = resolved_method_index(cbuf); RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index 995ed35de0c..e78d416a044 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -2164,13 +2164,19 @@ encode %{ // determine who we intended to call. MacroAssembler _masm(&cbuf); cbuf.set_insts_mark(); - $$$emit8$primary; if (!_method) { + $$$emit8$primary; emit_d32_reloc(cbuf, (int) ($meth$$method - ((intptr_t) cbuf.insts_end()) - 4), runtime_call_Relocation::spec(), RELOC_DISP32); + } else if (_method->intrinsic_id() == vmIntrinsicID::_ensureMaterializedForStackWalk) { + // The NOP here is purely to ensure that eliding a call to + // JVM_EnsureMaterializedForStackWalk doesn't change the code size. + __ addr_nop_5(); + __ block_comment("call JVM_EnsureMaterializedForStackWalk (elided)"); } else { + $$$emit8$primary; int method_index = resolved_method_index(cbuf); RelocationHolder rspec = _optimized_virtual ? opt_virtual_call_Relocation::spec(method_index) : static_call_Relocation::spec(method_index); diff --git a/src/hotspot/share/c1/c1_Compiler.cpp b/src/hotspot/share/c1/c1_Compiler.cpp index ef741e82943..819ee6adeb9 100644 --- a/src/hotspot/share/c1/c1_Compiler.cpp +++ b/src/hotspot/share/c1/c1_Compiler.cpp @@ -154,7 +154,7 @@ bool Compiler::is_intrinsic_supported(const methodHandle& method) { case vmIntrinsics::_getModifiers: case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: - case vmIntrinsics::_extentLocalCache: + case vmIntrinsics::_scopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_dsqrt: case vmIntrinsics::_dsqrt_strict: diff --git a/src/hotspot/share/c1/c1_LIRGenerator.cpp b/src/hotspot/share/c1/c1_LIRGenerator.cpp index f6f0a6ac28b..eb28d07ce24 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.cpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.cpp @@ -1428,8 +1428,8 @@ void LIRGenerator::do_getObjectSize(Intrinsic* x) { __ branch_destination(L_done->label()); } -void LIRGenerator::do_extentLocalCache(Intrinsic* x) { - do_JavaThreadField(x, JavaThread::extentLocalCache_offset()); +void LIRGenerator::do_scopedValueCache(Intrinsic* x) { + do_JavaThreadField(x, JavaThread::scopedValueCache_offset()); } // Example: Thread.currentCarrierThread() @@ -2948,7 +2948,7 @@ void LIRGenerator::do_Intrinsic(Intrinsic* x) { case vmIntrinsics::_getObjectSize: do_getObjectSize(x); break; case vmIntrinsics::_currentCarrierThread: do_currentCarrierThread(x); break; case vmIntrinsics::_currentThread: do_vthread(x); break; - case vmIntrinsics::_extentLocalCache: do_extentLocalCache(x); break; + case vmIntrinsics::_scopedValueCache: do_scopedValueCache(x); break; case vmIntrinsics::_dlog: // fall through case vmIntrinsics::_dlog10: // fall through diff --git a/src/hotspot/share/c1/c1_LIRGenerator.hpp b/src/hotspot/share/c1/c1_LIRGenerator.hpp index aedba60e973..7f4b25e89f1 100644 --- a/src/hotspot/share/c1/c1_LIRGenerator.hpp +++ b/src/hotspot/share/c1/c1_LIRGenerator.hpp @@ -257,7 +257,7 @@ class LIRGenerator: public InstructionVisitor, public BlockClosure { void do_getClass(Intrinsic* x); void do_getObjectSize(Intrinsic* x); void do_currentCarrierThread(Intrinsic* x); - void do_extentLocalCache(Intrinsic* x); + void do_scopedValueCache(Intrinsic* x); void do_vthread(Intrinsic* x); void do_JavaThreadField(Intrinsic* x, ByteSize offset); void do_FmaIntrinsic(Intrinsic* x); diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 117e5be1c28..c133a8346eb 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1683,7 +1683,7 @@ int java_lang_Thread::_interrupted_offset; int java_lang_Thread::_tid_offset; int java_lang_Thread::_continuation_offset; int java_lang_Thread::_park_blocker_offset; -int java_lang_Thread::_extentLocalBindings_offset; +int java_lang_Thread::_scopedValueBindings_offset; JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;) #define THREAD_FIELDS_DO(macro) \ @@ -1696,7 +1696,7 @@ JFR_ONLY(int java_lang_Thread::_jfr_epoch_offset;) macro(_tid_offset, k, "tid", long_signature, false); \ macro(_park_blocker_offset, k, "parkBlocker", object_signature, false); \ macro(_continuation_offset, k, "cont", continuation_signature, false); \ - macro(_extentLocalBindings_offset, k, "extentLocalBindings", object_signature, false); + macro(_scopedValueBindings_offset, k, "scopedValueBindings", object_signature, false); void java_lang_Thread::compute_offsets() { assert(_holder_offset == 0, "offsets should be initialized only once"); @@ -1729,8 +1729,9 @@ void java_lang_Thread::set_jvmti_thread_state(oop java_thread, JvmtiThreadState* java_thread->address_field_put(_jvmti_thread_state_offset, (address)state); } -void java_lang_Thread::clear_extentLocalBindings(oop java_thread) { - java_thread->obj_field_put(_extentLocalBindings_offset, NULL); +void java_lang_Thread::clear_scopedValueBindings(oop java_thread) { + assert(java_thread != NULL, "need a java_lang_Thread pointer here"); + java_thread->obj_field_put(_scopedValueBindings_offset, NULL); } oop java_lang_Thread::holder(oop java_thread) { diff --git a/src/hotspot/share/classfile/javaClasses.hpp b/src/hotspot/share/classfile/javaClasses.hpp index 7d159dbcc63..665d6aa97ec 100644 --- a/src/hotspot/share/classfile/javaClasses.hpp +++ b/src/hotspot/share/classfile/javaClasses.hpp @@ -352,7 +352,7 @@ class java_lang_Thread : AllStatic { static int _tid_offset; static int _continuation_offset; static int _park_blocker_offset; - static int _extentLocalBindings_offset; + static int _scopedValueBindings_offset; JFR_ONLY(static int _jfr_epoch_offset;) static void compute_offsets(); @@ -398,8 +398,8 @@ class java_lang_Thread : AllStatic { static JvmtiThreadState* jvmti_thread_state(oop java_thread); static void set_jvmti_thread_state(oop java_thread, JvmtiThreadState* state); - // Clear all extent local bindings on error - static void clear_extentLocalBindings(oop java_thread); + // Clear all scoped value bindings on error + static void clear_scopedValueBindings(oop java_thread); // Blocker object responsible for thread parking static oop park_blocker(oop java_thread); diff --git a/src/hotspot/share/classfile/vmIntrinsics.cpp b/src/hotspot/share/classfile/vmIntrinsics.cpp index 0c3364a8c94..3dafc8f235f 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.cpp +++ b/src/hotspot/share/classfile/vmIntrinsics.cpp @@ -77,7 +77,7 @@ bool vmIntrinsics::preserves_state(vmIntrinsics::ID id) { case vmIntrinsics::_isInstance: case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: - case vmIntrinsics::_extentLocalCache: + case vmIntrinsics::_scopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: @@ -127,8 +127,8 @@ bool vmIntrinsics::can_trap(vmIntrinsics::ID id) { case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: case vmIntrinsics::_setCurrentThread: - case vmIntrinsics::_extentLocalCache: - case vmIntrinsics::_setExtentLocalCache: + case vmIntrinsics::_scopedValueCache: + case vmIntrinsics::_setScopedValueCache: case vmIntrinsics::_dabs: case vmIntrinsics::_fabs: case vmIntrinsics::_iabs: @@ -265,8 +265,8 @@ bool vmIntrinsics::disabled_by_jvm_flags(vmIntrinsics::ID id) { if (!InlineThreadNatives) return true; break; case vmIntrinsics::_setCurrentThread: - case vmIntrinsics::_extentLocalCache: - case vmIntrinsics::_setExtentLocalCache: + case vmIntrinsics::_scopedValueCache: + case vmIntrinsics::_setScopedValueCache: case vmIntrinsics::_floatToRawIntBits: case vmIntrinsics::_intBitsToFloat: case vmIntrinsics::_doubleToRawLongBits: diff --git a/src/hotspot/share/classfile/vmIntrinsics.hpp b/src/hotspot/share/classfile/vmIntrinsics.hpp index 70604efe1dc..fb9d9ec9c95 100644 --- a/src/hotspot/share/classfile/vmIntrinsics.hpp +++ b/src/hotspot/share/classfile/vmIntrinsics.hpp @@ -270,7 +270,7 @@ class methodHandle; do_intrinsic(_identityHashCode, java_lang_System, identityHashCode_name, object_int_signature, F_SN) \ do_name( identityHashCode_name, "identityHashCode") \ do_intrinsic(_currentTimeMillis, java_lang_System, currentTimeMillis_name, void_long_signature, F_SN) \ - \ + \ do_name( currentTimeMillis_name, "currentTimeMillis") \ do_intrinsic(_nanoTime, java_lang_System, nanoTime_name, void_long_signature, F_SN) \ do_name( nanoTime_name, "nanoTime") \ @@ -286,12 +286,15 @@ class methodHandle; do_intrinsic(_currentThread, java_lang_Thread, currentThread_name, currentThread_signature, F_SN) \ do_name( currentThread_name, "currentThread") \ do_signature(currentThread_signature, "()Ljava/lang/Thread;") \ - do_intrinsic(_extentLocalCache, java_lang_Thread, extentLocalCache_name, extentLocalCache_signature, F_SN) \ - do_name( extentLocalCache_name, "extentLocalCache") \ - do_signature(extentLocalCache_signature, "()[Ljava/lang/Object;") \ - do_intrinsic(_setExtentLocalCache, java_lang_Thread, setExtentLocalCache_name, setExtentLocalCache_signature, F_SN) \ - do_name( setExtentLocalCache_name, "setExtentLocalCache") \ - do_signature(setExtentLocalCache_signature, "([Ljava/lang/Object;)V") \ + do_intrinsic(_scopedValueCache, java_lang_Thread, scopedValueCache_name, scopedValueCache_signature, F_SN) \ + do_name( scopedValueCache_name, "scopedValueCache") \ + do_signature(scopedValueCache_signature, "()[Ljava/lang/Object;") \ + do_intrinsic(_setScopedValueCache, java_lang_Thread, setScopedValueCache_name, setScopedValueCache_signature, F_SN) \ + do_name( setScopedValueCache_name, "setScopedValueCache") \ + do_signature(setScopedValueCache_signature, "([Ljava/lang/Object;)V") \ + do_intrinsic(_findScopedValueBindings, java_lang_Thread, findScopedValueBindings_name, void_object_signature, F_SN) \ + do_name( findScopedValueBindings_name, "findScopedValueBindings") \ + \ do_intrinsic(_setCurrentThread, java_lang_Thread, setCurrentThread_name, thread_void_signature, F_RN) \ do_name( setCurrentThread_name, "setCurrentThread") \ \ @@ -331,6 +334,9 @@ class methodHandle; do_name( onSpinWait_name, "onSpinWait") \ do_alias( onSpinWait_signature, void_method_signature) \ \ + do_intrinsic(_ensureMaterializedForStackWalk, java_lang_Thread, ensureMaterializedForStackWalk_name, object_void_signature, F_SN) \ + do_name( ensureMaterializedForStackWalk_name, "ensureMaterializedForStackWalk") \ + \ do_intrinsic(_copyOf, java_util_Arrays, copyOf_name, copyOf_signature, F_S) \ do_name( copyOf_name, "copyOf") \ do_signature(copyOf_signature, "([Ljava/lang/Object;ILjava/lang/Class;)[Ljava/lang/Object;") \ diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 00ff8e732d2..6804c49fb2c 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -156,6 +156,8 @@ template(jdk_internal_loader_BuiltinClassLoader, "jdk/internal/loader/BuiltinClassLoader") \ template(jdk_internal_loader_ClassLoaders_AppClassLoader, "jdk/internal/loader/ClassLoaders$AppClassLoader") \ template(jdk_internal_loader_ClassLoaders_PlatformClassLoader, "jdk/internal/loader/ClassLoaders$PlatformClassLoader") \ + template(jdk_incubator_concurrent_ScopedValue, "jdk/incubator/concurrent/ScopedValue") \ + template(jdk_incubator_concurrent_ScopedValue_Carrier, "jdk/incubator/concurrent/ScopedValue$Carrier") \ \ /* Java runtime version access */ \ template(java_lang_VersionProps, "java/lang/VersionProps") \ @@ -396,6 +398,7 @@ template(group_name, "group") \ template(daemon_name, "daemon") \ template(run_method_name, "run") \ + template(runWith_method_name, "runWith") \ template(interrupt_method_name, "interrupt") \ template(exit_method_name, "exit") \ template(remove_method_name, "remove") \ @@ -601,6 +604,7 @@ template(string_array_string_array_void_signature, "([Ljava/lang/String;[Ljava/lang/String;)V") \ template(thread_throwable_void_signature, "(Ljava/lang/Thread;Ljava/lang/Throwable;)V") \ template(thread_void_signature, "(Ljava/lang/Thread;)V") \ + template(runnable_void_signature, "(Ljava/lang/Runnable;)V") \ template(threadgroup_runnable_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/Runnable;)V") \ template(threadgroup_string_void_signature, "(Ljava/lang/ThreadGroup;Ljava/lang/String;)V") \ template(void_threadgroup_array_signature, "()[Ljava/lang/ThreadGroup;") \ diff --git a/src/hotspot/share/include/jvm.h b/src/hotspot/share/include/jvm.h index 07dd0513b96..98e0233887c 100644 --- a/src/hotspot/share/include/jvm.h +++ b/src/hotspot/share/include/jvm.h @@ -310,10 +310,13 @@ JNIEXPORT jobjectArray JNICALL JVM_DumpThreads(JNIEnv *env, jclass threadClass, jobjectArray threads); JNIEXPORT jobject JNICALL -JVM_ExtentLocalCache(JNIEnv *env, jclass threadClass); +JVM_ScopedValueCache(JNIEnv *env, jclass threadClass); JNIEXPORT void JNICALL -JVM_SetExtentLocalCache(JNIEnv *env, jclass threadClass, jobject theCache); +JVM_SetScopedValueCache(JNIEnv *env, jclass threadClass, jobject theCache); + +JNIEXPORT jobject JNICALL +JVM_FindScopedValueBindings(JNIEnv *env, jclass threadClass); JNIEXPORT jlong JNICALL JVM_GetNextThreadIdOffset(JNIEnv *env, jclass threadClass); @@ -742,6 +745,8 @@ JVM_GetInheritedAccessControlContext(JNIEnv *env, jclass cls); #define JVM_EnsureMaterializedForStackWalk(env, value) \ do {} while(0) // Nothing to do. The fact that the value escaped // through a native method is enough. +JNIEXPORT void JNICALL +JVM_EnsureMaterializedForStackWalk_func(JNIEnv* env, jobject vthread, jobject value); JNIEXPORT jobject JNICALL JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls); diff --git a/src/hotspot/share/interpreter/interpreterRuntime.cpp b/src/hotspot/share/interpreter/interpreterRuntime.cpp index 6c169ea4317..9ce2c1e37fc 100644 --- a/src/hotspot/share/interpreter/interpreterRuntime.cpp +++ b/src/hotspot/share/interpreter/interpreterRuntime.cpp @@ -372,6 +372,9 @@ JRT_ENTRY(void, InterpreterRuntime::throw_StackOverflowError(JavaThread* current CHECK); // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); + // Remove the ScopedValue bindings in case we got a StackOverflowError + // while we were trying to manipulate ScopedValue bindings. + current->clear_scopedValueBindings(); THROW_HANDLE(exception); JRT_END @@ -383,6 +386,9 @@ JRT_ENTRY(void, InterpreterRuntime::throw_delayed_StackOverflowError(JavaThread* Universe::delayed_stack_overflow_error_message()); // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); + // Remove the ScopedValue bindings in case we got a StackOverflowError + // while we were trying to manipulate ScopedValue bindings. + current->clear_scopedValueBindings(); THROW_HANDLE(exception); JRT_END diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index daee5bf677c..ca37d3e3e1c 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -1609,12 +1609,12 @@ C2V_VMENTRY(void, materializeVirtualObjects, (JNIEnv* env, jobject, jobject _hs_ for (int frame_index = 0; frame_index < virtualFrames->length(); frame_index++) { compiledVFrame* cvf = virtualFrames->at(frame_index); - GrowableArray* extentLocals = cvf->scope()->locals(); + GrowableArray* scopedValues = cvf->scope()->locals(); StackValueCollection* locals = cvf->locals(); if (locals != NULL) { for (int i2 = 0; i2 < locals->size(); i2++) { StackValue* var = locals->at(i2); - if (var->type() == T_OBJECT && extentLocals->at(i2)->is_object()) { + if (var->type() == T_OBJECT && scopedValues->at(i2)->is_object()) { jvalue val; val.l = cast_from_oop(locals->at(i2)->get_obj()()); cvf->update_local(T_OBJECT, i2, val); diff --git a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp index 74d65514bc1..916577d913c 100644 --- a/src/hotspot/share/jvmci/vmStructs_jvmci.cpp +++ b/src/hotspot/share/jvmci/vmStructs_jvmci.cpp @@ -174,7 +174,7 @@ \ nonstatic_field(JavaThread, _threadObj, OopHandle) \ nonstatic_field(JavaThread, _vthread, OopHandle) \ - nonstatic_field(JavaThread, _extentLocalCache, OopHandle) \ + nonstatic_field(JavaThread, _scopedValueCache, OopHandle) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _vm_result, oop) \ nonstatic_field(JavaThread, _stack_overflow_state._stack_overflow_limit, address) \ diff --git a/src/hotspot/share/oops/oopHandle.hpp b/src/hotspot/share/oops/oopHandle.hpp index fd4c9679219..77bdbfd8f9a 100644 --- a/src/hotspot/share/oops/oopHandle.hpp +++ b/src/hotspot/share/oops/oopHandle.hpp @@ -70,7 +70,6 @@ class OopHandle { inline oop xchg(oop new_value); - // Used only for removing handle. oop* ptr_raw() const { return _obj; } }; diff --git a/src/hotspot/share/opto/c2compiler.cpp b/src/hotspot/share/opto/c2compiler.cpp index a4e997513f4..5af1cbe4aa1 100644 --- a/src/hotspot/share/opto/c2compiler.cpp +++ b/src/hotspot/share/opto/c2compiler.cpp @@ -680,8 +680,8 @@ bool C2Compiler::is_intrinsic_supported(const methodHandle& method, bool is_virt case vmIntrinsics::_currentCarrierThread: case vmIntrinsics::_currentThread: case vmIntrinsics::_setCurrentThread: - case vmIntrinsics::_extentLocalCache: - case vmIntrinsics::_setExtentLocalCache: + case vmIntrinsics::_scopedValueCache: + case vmIntrinsics::_setScopedValueCache: #ifdef JFR_HAVE_INTRINSICS case vmIntrinsics::_counterTime: case vmIntrinsics::_getEventWriter: diff --git a/src/hotspot/share/opto/library_call.cpp b/src/hotspot/share/opto/library_call.cpp index 365a2065c85..0051bed3314 100644 --- a/src/hotspot/share/opto/library_call.cpp +++ b/src/hotspot/share/opto/library_call.cpp @@ -472,8 +472,8 @@ bool LibraryCallKit::try_to_inline(int predicate) { case vmIntrinsics::_currentThread: return inline_native_currentThread(); case vmIntrinsics::_setCurrentThread: return inline_native_setCurrentThread(); - case vmIntrinsics::_extentLocalCache: return inline_native_extentLocalCache(); - case vmIntrinsics::_setExtentLocalCache: return inline_native_setExtentLocalCache(); + case vmIntrinsics::_scopedValueCache: return inline_native_scopedValueCache(); + case vmIntrinsics::_setScopedValueCache: return inline_native_setScopedValueCache(); #ifdef JFR_HAVE_INTRINSICS case vmIntrinsics::_counterTime: return inline_native_time_funcs(CAST_FROM_FN_PTR(address, JfrTime::time_function()), "counterTime"); @@ -3357,38 +3357,42 @@ bool LibraryCallKit::inline_native_setCurrentThread() { return true; } -Node* LibraryCallKit::extentLocalCache_helper() { +Node* LibraryCallKit::scopedValueCache_helper() { ciKlass *objects_klass = ciObjArrayKlass::make(env()->Object_klass()); const TypeOopPtr *etype = TypeOopPtr::make_from_klass(env()->Object_klass()); bool xk = etype->klass_is_exact(); Node* thread = _gvn.transform(new ThreadLocalNode()); - Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::extentLocalCache_offset())); - return _gvn.transform(LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), - TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered)); + Node* p = basic_plus_adr(top()/*!oop*/, thread, in_bytes(JavaThread::scopedValueCache_offset())); + // We cannot use immutable_memory() because we might flip onto a + // different carrier thread, at which point we'll need to use that + // carrier thread's cache. + // return _gvn.transform(LoadNode::make(_gvn, NULL, immutable_memory(), p, p->bottom_type()->is_ptr(), + // TypeRawPtr::NOTNULL, T_ADDRESS, MemNode::unordered)); + return make_load(NULL, p, p->bottom_type()->is_ptr(), T_ADDRESS, MemNode::unordered); } -//------------------------inline_native_extentLocalCache------------------ -bool LibraryCallKit::inline_native_extentLocalCache() { +//------------------------inline_native_scopedValueCache------------------ +bool LibraryCallKit::inline_native_scopedValueCache() { ciKlass *objects_klass = ciObjArrayKlass::make(env()->Object_klass()); const TypeOopPtr *etype = TypeOopPtr::make_from_klass(env()->Object_klass()); const TypeAry* arr0 = TypeAry::make(etype, TypeInt::POS); - // Because we create the extentLocal cache lazily we have to make the + // Because we create the scopedValue cache lazily we have to make the // type of the result BotPTR. bool xk = etype->klass_is_exact(); const Type* objects_type = TypeAryPtr::make(TypePtr::BotPTR, arr0, objects_klass, xk, 0); - Node* cache_obj_handle = extentLocalCache_helper(); + Node* cache_obj_handle = scopedValueCache_helper(); set_result(access_load(cache_obj_handle, objects_type, T_OBJECT, IN_NATIVE)); return true; } -//------------------------inline_native_setExtentLocalCache------------------ -bool LibraryCallKit::inline_native_setExtentLocalCache() { +//------------------------inline_native_setScopedValueCache------------------ +bool LibraryCallKit::inline_native_setScopedValueCache() { Node* arr = argument(0); - Node* cache_obj_handle = extentLocalCache_helper(); + Node* cache_obj_handle = scopedValueCache_helper(); const TypePtr *adr_type = _gvn.type(cache_obj_handle)->isa_ptr(); store_to_memory(control(), cache_obj_handle, arr, T_OBJECT, adr_type, diff --git a/src/hotspot/share/opto/library_call.hpp b/src/hotspot/share/opto/library_call.hpp index 405a5bfd01c..8cc6f00fdf7 100644 --- a/src/hotspot/share/opto/library_call.hpp +++ b/src/hotspot/share/opto/library_call.hpp @@ -239,9 +239,9 @@ class LibraryCallKit : public GraphKit { bool inline_native_currentThread(); bool inline_native_setCurrentThread(); - bool inline_native_extentLocalCache(); - Node* extentLocalCache_helper(); - bool inline_native_setExtentLocalCache(); + bool inline_native_scopedValueCache(); + Node* scopedValueCache_helper(); + bool inline_native_setScopedValueCache(); bool inline_native_time_funcs(address method, const char* funcName); #ifdef JFR_HAVE_INTRINSICS diff --git a/src/hotspot/share/opto/memnode.cpp b/src/hotspot/share/opto/memnode.cpp index 6cb8b742dfb..603f82c6309 100644 --- a/src/hotspot/share/opto/memnode.cpp +++ b/src/hotspot/share/opto/memnode.cpp @@ -865,7 +865,7 @@ bool LoadNode::is_immutable_value(Node* adr) { in_bytes(JavaThread::osthread_offset()), in_bytes(JavaThread::threadObj_offset()), in_bytes(JavaThread::vthread_offset()), - in_bytes(JavaThread::extentLocalCache_offset()), + in_bytes(JavaThread::scopedValueCache_offset()), }; for (size_t i = 0; i < sizeof offsets / sizeof offsets[0]; i++) { diff --git a/src/hotspot/share/prims/jvm.cpp b/src/hotspot/share/prims/jvm.cpp index 6bf6b5ae31c..d79b31bdb30 100644 --- a/src/hotspot/share/prims/jvm.cpp +++ b/src/hotspot/share/prims/jvm.cpp @@ -1363,6 +1363,54 @@ JVM_ENTRY(jobject, JVM_GetStackAccessControlContext(JNIEnv *env, jclass cls)) return JNIHandles::make_local(THREAD, result); JVM_END +class ScopedValueBindingsResolver { +public: + InstanceKlass* Carrier_klass; + ScopedValueBindingsResolver(JavaThread* THREAD) { + Klass *k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_incubator_concurrent_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()) { + int loc = -1; + // get method of frame + Method* method = vfst.method(); + + Symbol *name = method->name(); + + InstanceKlass* holder = method->method_holder(); + if (name == vmSymbols::runWith_method_name()) { + if ((holder == resolver.Carrier_klass + || holder == vmClasses::VirtualThread_klass() + || holder == vmClasses::Thread_klass())) { + loc = 1; + } + } + + if (loc != -1) { + javaVFrame *frame = vfst.asJavaVFrame(); + StackValueCollection* locals = frame->locals(); + StackValue* head_sv = locals->at(loc); // jdk/incubator/concurrent/ScopedValue$Snapshot + Handle result = head_sv->get_obj(); + assert(!head_sv->obj_is_scalar_replaced(), "found scalar-replaced object"); + if (result() != NULL) { + return JNIHandles::make_local(THREAD, result()); + } + } + } + + return NULL; +JVM_END JVM_ENTRY(jboolean, JVM_IsArrayClass(JNIEnv *env, jclass cls)) Klass* k = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(cls)); @@ -3114,22 +3162,15 @@ JVM_ENTRY(void, JVM_SetNativeThreadName(JNIEnv* env, jobject jthread, jstring na } JVM_END -JVM_ENTRY(jobject, JVM_ExtentLocalCache(JNIEnv* env, jclass threadClass)) - oop theCache = thread->extentLocalCache(); - if (theCache) { - arrayOop objs = arrayOop(theCache); - assert(objs->length() == ExtentLocalCacheSize * 2, "wrong length"); - } +JVM_ENTRY(jobject, JVM_ScopedValueCache(JNIEnv* env, jclass threadClass)) + oop theCache = thread->scopedValueCache(); return JNIHandles::make_local(THREAD, theCache); JVM_END -JVM_ENTRY(void, JVM_SetExtentLocalCache(JNIEnv* env, jclass threadClass, +JVM_ENTRY(void, JVM_SetScopedValueCache(JNIEnv* env, jclass threadClass, jobject theCache)) arrayOop objs = arrayOop(JNIHandles::resolve(theCache)); - if (objs != NULL) { - assert(objs->length() == ExtentLocalCacheSize * 2, "wrong length"); - } - thread->set_extentLocalCache(objs); + thread->set_scopedValueCache(objs); JVM_END // java.lang.SecurityManager /////////////////////////////////////////////////////////////////////// @@ -4019,3 +4060,12 @@ JVM_ENTRY(jint, JVM_GetClassFileVersion(JNIEnv* env, jclass current)) InstanceKlass* ik = InstanceKlass::cast(c); return (ik->minor_version() << 16) | ik->major_version(); JVM_END + +/* + * Ensure that code doing a stackwalk and using javaVFrame::locals() to + * get the value will see a materialized value and not a scalar-replaced + * null value. + */ +JVM_ENTRY(void, JVM_EnsureMaterializedForStackWalk_func(JNIEnv* env, jobject vthread, jobject value)) + JVM_EnsureMaterializedForStackWalk(env, value); +JVM_END diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index b63038b2b5d..61ad39dba3a 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -441,11 +441,8 @@ Deoptimization::UnrollBlock* Deoptimization::fetch_unroll_info_helper(JavaThread vframeArray* array = create_vframeArray(current, deoptee, &map, chunk, realloc_failures); #if COMPILER2_OR_JVMCI if (realloc_failures) { - // FIXME: This very crudely destroys all ExtentLocal bindings. This - // is better than a bound value escaping, but far from ideal. - oop java_thread = current->threadObj(); - current->set_extentLocalCache(NULL); - java_lang_Thread::clear_extentLocalBindings(java_thread); + // This destroys all ScopedValue bindings. + current->clear_scopedValueBindings(); pop_frames_failed_reallocs(current, array); } #endif diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp index 968830cd4a4..78dc81fda67 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.cpp @@ -92,18 +92,6 @@ JVMFlag::Error VMPageSizeConstraintFunc(uintx value, bool verbose) { return JVMFlag::SUCCESS; } -JVMFlag::Error ExtentLocalCacheSizeConstraintFunc(intx value, bool verbose) { - if (!is_power_of_2(value)) { - JVMFlag::printError(verbose, - "ExtentLocalCacheSize (" INTX_FORMAT ") must be " - "power of 2\n", - value); - return JVMFlag::VIOLATES_CONSTRAINT; - } - - return JVMFlag::SUCCESS; -} - JVMFlag::Error NUMAInterleaveGranularityConstraintFunc(size_t value, bool verbose) { size_t min = os::vm_allocation_granularity(); size_t max = NOT_LP64(2*G) LP64_ONLY(8192*G); diff --git a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp index c3c8ad94e1d..689e5d875f3 100644 --- a/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp +++ b/src/hotspot/share/runtime/flags/jvmFlagConstraintsRuntime.hpp @@ -37,7 +37,6 @@ f(int, ObjectAlignmentInBytesConstraintFunc) \ f(intx, ContendedPaddingWidthConstraintFunc) \ f(intx, PerfDataSamplingIntervalFunc) \ - f(intx, ExtentLocalCacheSizeConstraintFunc) \ f(uintx, VMPageSizeConstraintFunc) \ f(size_t, NUMAInterleaveGranularityConstraintFunc) diff --git a/src/hotspot/share/runtime/globals.hpp b/src/hotspot/share/runtime/globals.hpp index 1e2b8753ed8..4e90449d78c 100644 --- a/src/hotspot/share/runtime/globals.hpp +++ b/src/hotspot/share/runtime/globals.hpp @@ -1947,11 +1947,6 @@ const int ObjectAlignmentInBytes = 8; develop(bool, UseContinuationFastPath, true, \ "Use fast-path frame walking in continuations") \ \ - product(intx, ExtentLocalCacheSize, 16, \ - "Size of the cache for scoped values") \ - range(0, max_intx) \ - constraint(ExtentLocalCacheSizeConstraintFunc, AtParse) \ - \ develop(int, VerifyMetaspaceInterval, DEBUG_ONLY(500) NOT_DEBUG(0), \ "Run periodic metaspace verifications (0 - none, " \ "1 - always, >1 every nth interval)") \ diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 19bd3e657af..20bba7d4848 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -157,7 +157,7 @@ void JavaThread::set_threadOopHandles(oop p) { _threadObj = OopHandle(_thread_oop_storage, p); _vthread = OopHandle(_thread_oop_storage, p); _jvmti_vthread = OopHandle(_thread_oop_storage, NULL); - _extentLocalCache = OopHandle(_thread_oop_storage, NULL); + _scopedValueCache = OopHandle(_thread_oop_storage, NULL); } oop JavaThread::threadObj() const { @@ -186,13 +186,26 @@ void JavaThread::set_jvmti_vthread(oop p) { _jvmti_vthread.replace(p); } -oop JavaThread::extentLocalCache() const { - return _extentLocalCache.resolve(); +oop JavaThread::scopedValueCache() const { + return _scopedValueCache.resolve(); } -void JavaThread::set_extentLocalCache(oop p) { - assert(_thread_oop_storage != NULL, "not yet initialized"); - _extentLocalCache.replace(p); +void JavaThread::set_scopedValueCache(oop p) { + if (_scopedValueCache.ptr_raw() != NULL) { // i.e. if the OopHandle has been allocated + _scopedValueCache.replace(p); + } else { + assert(p == NULL, "not yet initialized"); + } +} + +void JavaThread::clear_scopedValueBindings() { + set_scopedValueCache(NULL); + oop vthread_oop = vthread(); + // vthread may be null here if we get a VM error during startup, + // before the java.lang.Thread instance has been created. + if (vthread_oop != NULL) { + java_lang_Thread::clear_scopedValueBindings(vthread_oop); + } } void JavaThread::allocate_threadObj(Handle thread_group, const char* thread_name, @@ -1040,11 +1053,7 @@ void JavaThread::handle_async_exception(oop java_throwable) { // We cannot call Exceptions::_throw(...) here because we cannot block set_pending_exception(java_throwable, __FILE__, __LINE__); - // Clear any extent-local bindings - set_extentLocalCache(NULL); - oop threadOop = threadObj(); - assert(threadOop != NULL, "must be"); - java_lang_Thread::clear_extentLocalBindings(threadOop); + clear_scopedValueBindings(); LogTarget(Info, exceptions) lt; if (lt.is_enabled()) { @@ -2097,7 +2106,7 @@ void JavaThread::add_oop_handles_for_release() { new_head->add(_threadObj); new_head->add(_vthread); new_head->add(_jvmti_vthread); - new_head->add(_extentLocalCache); + new_head->add(_scopedValueCache); _oop_handle_list = new_head; Service_lock->notify_all(); } diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 02e646c8d77..750903d44be 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -92,7 +92,7 @@ class JavaThread: public Thread { OopHandle _threadObj; // The Java level thread object OopHandle _vthread; // the value returned by Thread.currentThread(): the virtual thread, if mounted, otherwise _threadObj OopHandle _jvmti_vthread; - OopHandle _extentLocalCache; + OopHandle _scopedValueCache; static OopStorage* _thread_oop_storage; @@ -520,8 +520,9 @@ class JavaThread: public Thread { void set_threadOopHandles(oop p); oop vthread() const; void set_vthread(oop p); - oop extentLocalCache() const; - void set_extentLocalCache(oop p); + oop scopedValueCache() const; + void set_scopedValueCache(oop p); + void clear_scopedValueBindings(); oop jvmti_vthread() const; void set_jvmti_vthread(oop p); @@ -744,7 +745,7 @@ class JavaThread: public Thread { void clr_do_not_unlock(void) { _do_not_unlock_if_synchronized = false; } bool do_not_unlock(void) { return _do_not_unlock_if_synchronized; } - static ByteSize extentLocalCache_offset() { return byte_offset_of(JavaThread, _extentLocalCache); } + static ByteSize scopedValueCache_offset() { return byte_offset_of(JavaThread, _scopedValueCache); } // For assembly stub generation static ByteSize threadObj_offset() { return byte_offset_of(JavaThread, _threadObj); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index db2acd25772..369790dff3a 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -884,9 +884,10 @@ void SharedRuntime::throw_StackOverflowError_common(JavaThread* current, bool de if (StackTraceInThrowable) { java_lang_Throwable::fill_in_stack_trace(exception); } - // Remove the ExtentLocal cache in case we got a StackOverflowError - // while we were trying to remove ExtentLocal bindings. - current->set_extentLocalCache(NULL); + // Remove the ScopedValue bindings in case we got a + // StackOverflowError while we were trying to remove ScopedValue + // bindings. + current->clear_scopedValueBindings(); // Increment counter for hs_err file reporting Atomic::inc(&Exceptions::_stack_overflow_errors); throw_and_post_jvmti_exception(current, exception); diff --git a/src/hotspot/share/runtime/vframe_hp.cpp b/src/hotspot/share/runtime/vframe_hp.cpp index d5458d3bea2..54d0fd97b23 100644 --- a/src/hotspot/share/runtime/vframe_hp.cpp +++ b/src/hotspot/share/runtime/vframe_hp.cpp @@ -145,12 +145,12 @@ void compiledVFrame::update_deferred_value(BasicType type, int index, jvalue val // original update is kept. void compiledVFrame::create_deferred_updates_after_object_deoptimization() { // locals - GrowableArray* extentLocals = scope()->locals(); + GrowableArray* scopedValues = scope()->locals(); StackValueCollection* lcls = locals(); if (lcls != NULL) { for (int i2 = 0; i2 < lcls->size(); i2++) { StackValue* var = lcls->at(i2); - if (var->type() == T_OBJECT && extentLocals->at(i2)->is_object()) { + if (var->type() == T_OBJECT && scopedValues->at(i2)->is_object()) { jvalue val; val.l = cast_from_oop(lcls->at(i2)->get_obj()()); update_local(T_OBJECT, i2, val); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index 06d420e47f6..aeb2d640648 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -710,7 +710,7 @@ nonstatic_field(JavaThread, _threadObj, OopHandle) \ nonstatic_field(JavaThread, _vthread, OopHandle) \ nonstatic_field(JavaThread, _jvmti_vthread, OopHandle) \ - nonstatic_field(JavaThread, _extentLocalCache, OopHandle) \ + nonstatic_field(JavaThread, _scopedValueCache, OopHandle) \ nonstatic_field(JavaThread, _anchor, JavaFrameAnchor) \ nonstatic_field(JavaThread, _vm_result, oop) \ nonstatic_field(JavaThread, _vm_result_2, Metadata*) \ diff --git a/src/hotspot/share/utilities/exceptions.cpp b/src/hotspot/share/utilities/exceptions.cpp index a131eb501a7..7aa331f32ae 100644 --- a/src/hotspot/share/utilities/exceptions.cpp +++ b/src/hotspot/share/utilities/exceptions.cpp @@ -160,8 +160,14 @@ void Exceptions::_throw(JavaThread* thread, const char* file, int line, Handle h return; } - if (h_exception->is_a(vmClasses::OutOfMemoryError_klass())) { - count_out_of_memory_exceptions(h_exception); + if (h_exception->is_a(vmClasses::VirtualMachineError_klass())) { + // Remove the ScopedValue bindings in case we got a virtual machine + // Error while we were trying to manipulate ScopedValue bindings. + thread->clear_scopedValueBindings(); + + if (h_exception->is_a(vmClasses::OutOfMemoryError_klass())) { + count_out_of_memory_exceptions(h_exception); + } } if (h_exception->is_a(vmClasses::LinkageError_klass())) { diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index f429a041e3d..455a521d11e 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -86,6 +86,7 @@ import jdk.internal.vm.ContinuationScope; import jdk.internal.vm.StackableScope; import jdk.internal.vm.ThreadContainer; +import jdk.internal.vm.annotation.ForceInline; import jdk.internal.vm.annotation.IntrinsicCandidate; import jdk.internal.vm.annotation.Stable; import jdk.internal.vm.annotation.ChangesCurrentThread; @@ -2578,20 +2579,29 @@ public boolean isCarrierThreadLocalPresent(CarrierThreadLocal local) { return ((ThreadLocal)local).isCarrierThreadLocalPresent(); } - public Object[] extentLocalCache() { - return Thread.extentLocalCache(); + public Object[] scopedValueCache() { + return Thread.scopedValueCache(); } - public void setExtentLocalCache(Object[] cache) { - Thread.setExtentLocalCache(cache); + public void setScopedValueCache(Object[] cache) { + Thread.setScopedValueCache(cache); } - public Object extentLocalBindings() { - return Thread.extentLocalBindings(); + public Object scopedValueBindings() { + return Thread.scopedValueBindings(); } - public void setExtentLocalBindings(Object bindings) { - Thread.setExtentLocalBindings(bindings); + public Object findScopedValueBindings() { + return Thread.findScopedValueBindings(); + } + + public void setScopedValueBindings(Object bindings) { + Thread.setScopedValueBindings(bindings); + } + + @ForceInline + public void ensureMaterializedForStackWalk(Object value) { + Thread.ensureMaterializedForStackWalk(value); } public Continuation getContinuation(Thread thread) { diff --git a/src/java.base/share/classes/java/lang/Thread.java b/src/java.base/share/classes/java/lang/Thread.java index 61da2ebf6f2..668c81471d1 100644 --- a/src/java.base/share/classes/java/lang/Thread.java +++ b/src/java.base/share/classes/java/lang/Thread.java @@ -25,6 +25,7 @@ package java.lang; +import java.lang.ref.Reference; import java.lang.reflect.Field; import java.security.AccessController; import java.security.AccessControlContext; @@ -49,9 +50,11 @@ import jdk.internal.reflect.CallerSensitive; import jdk.internal.reflect.Reflection; import jdk.internal.vm.Continuation; -import jdk.internal.vm.ExtentLocalContainer; +import jdk.internal.vm.ScopedValueContainer; import jdk.internal.vm.StackableScope; import jdk.internal.vm.ThreadContainer; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Hidden; import jdk.internal.vm.annotation.IntrinsicCandidate; import sun.nio.ch.Interruptible; import sun.security.util.SecurityConstants; @@ -279,34 +282,44 @@ private static class FieldHolder { ThreadLocal.ThreadLocalMap inheritableThreadLocals; /* - * Extent locals binding are maintained by the ExtentLocal class. + * Scoped value bindings are maintained by the ScopedValue class. */ - private Object extentLocalBindings; + private Object scopedValueBindings; - static Object extentLocalBindings() { - return currentThread().extentLocalBindings; + // Special value to indicate this is a newly-created Thread + // Note that his must match the declaration in ScopedValue. + private static final Object NEW_THREAD_BINDINGS = Thread.class; + + static Object scopedValueBindings() { + return currentThread().scopedValueBindings; } - static void setExtentLocalBindings(Object bindings) { - currentThread().extentLocalBindings = bindings; + static void setScopedValueBindings(Object bindings) { + currentThread().scopedValueBindings = bindings; } /** - * Inherit the extent-local bindings from the given container. + * Search the stack for the most recent scoped-value bindings. + */ + @IntrinsicCandidate + static native Object findScopedValueBindings(); + + /** + * Inherit the scoped-value bindings from the given container. * Invoked when starting a thread. */ - void inheritExtentLocalBindings(ThreadContainer container) { - ExtentLocalContainer.BindingsSnapshot snapshot; + void inheritScopedValueBindings(ThreadContainer container) { + ScopedValueContainer.BindingsSnapshot snapshot; if (container.owner() != null - && (snapshot = container.extentLocalBindings()) != null) { + && (snapshot = container.scopedValueBindings()) != null) { // bindings established for running/calling an operation - Object bindings = snapshot.extentLocalBindings(); - if (currentThread().extentLocalBindings != bindings) { - StructureViolationExceptions.throwException("Extent local bindings have changed"); + Object bindings = snapshot.scopedValueBindings(); + if (currentThread().scopedValueBindings != bindings) { + StructureViolationExceptions.throwException("Scoped value bindings have changed"); } - this.extentLocalBindings = bindings; + this.scopedValueBindings = bindings; } } @@ -393,13 +406,16 @@ void setContinuation(Continuation cont) { @IntrinsicCandidate native void setCurrentThread(Thread thread); - // ExtentLocal support: + // ScopedValue support: + + @IntrinsicCandidate + static native Object[] scopedValueCache(); @IntrinsicCandidate - static native Object[] extentLocalCache(); + static native void setScopedValueCache(Object[] cache); @IntrinsicCandidate - static native void setExtentLocalCache(Object[] cache); + static native void ensureMaterializedForStackWalk(Object o); /** * A hint to the scheduler that the current thread is willing to yield @@ -728,6 +744,10 @@ private static ClassLoader contextClassLoader(Thread parent) { this.contextClassLoader = ClassLoader.getSystemClassLoader(); } } + + // Special value to indicate this is a newly-created Thread + // Note that his must match the declaration in ScopedValue. + this.scopedValueBindings = NEW_THREAD_BINDINGS; } /** @@ -767,6 +787,9 @@ private static ClassLoader contextClassLoader(Thread parent) { this.contextClassLoader = ClassLoader.getSystemClassLoader(); } + // Special value to indicate this is a newly-created Thread + this.scopedValueBindings = NEW_THREAD_BINDINGS; + // create a FieldHolder object, needed when bound to an OS thread if (bound) { ThreadGroup g = Constants.VTHREAD_GROUP; @@ -1564,8 +1587,8 @@ void start(ThreadContainer container) { boolean started = false; container.onStart(this); // may throw try { - // extent locals may be inherited - inheritExtentLocalBindings(container); + // scoped values may be inherited + inheritScopedValueBindings(container); start0(); started = true; @@ -1596,10 +1619,24 @@ void start(ThreadContainer container) { public void run() { Runnable task = holder.task; if (task != null) { - task.run(); + Object bindings = scopedValueBindings(); + runWith(bindings, task); } } + /** + * The VM recognizes this method as special, so any changes to the + * name or signature require corresponding changes in + * JVM_FindScopedValueBindings(). + */ + @Hidden + @ForceInline + private void runWith(Object bindings, Runnable op) { + ensureMaterializedForStackWalk(bindings); + op.run(); + Reference.reachabilityFence(bindings); + } + /** * Null out reference after Thread termination. */ diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 704910c3c36..3dd722739e3 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -24,6 +24,7 @@ */ package java.lang; +import java.lang.ref.Reference; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.Locale; @@ -53,6 +54,8 @@ import jdk.internal.vm.ThreadContainer; import jdk.internal.vm.ThreadContainers; import jdk.internal.vm.annotation.ChangesCurrentThread; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Hidden; import jdk.internal.vm.annotation.JvmtiMountTransition; import sun.nio.ch.Interruptible; import sun.security.action.GetPropertyAction; @@ -283,13 +286,13 @@ private void run(Runnable task) { event.commit(); } + Object bindings = scopedValueBindings(); try { - task.run(); + runWith(bindings, task); } catch (Throwable exc) { dispatchUncaughtException(exc); } finally { try { - // pop any remaining scopes from the stack, this may block StackableScope.popAll(); @@ -311,6 +314,14 @@ private void run(Runnable task) { } } + @Hidden + @ForceInline + private void runWith(Object bindings, Runnable op) { + ensureMaterializedForStackWalk(bindings); + op.run(); + Reference.reachabilityFence(bindings); + } + /** * Mounts this virtual thread onto the current platform thread. On * return, the current thread is the virtual thread. @@ -488,8 +499,8 @@ void start(ThreadContainer container) { boolean started = false; container.onStart(this); // may throw try { - // extent locals may be inherited - inheritExtentLocalBindings(container); + // scoped values may be inherited + inheritScopedValueBindings(container); // submit task to run thread submitRunContinuation(); diff --git a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java index 2bb0bdd00b6..bebf00d7ec6 100644 --- a/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java +++ b/src/java.base/share/classes/java/util/concurrent/ThreadLocalRandom.java @@ -401,7 +401,7 @@ private Object readResolve() { = new AtomicLong(RandomSupport.mixMurmur64(System.currentTimeMillis()) ^ RandomSupport.mixMurmur64(System.nanoTime())); - // used by ExtentLocal + // used by ScopedValue private static class Access { static { SharedSecrets.setJavaUtilConcurrentTLRAccess( diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index be8ee9d91f6..261be6bbe13 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -476,24 +476,28 @@ public interface JavaLangAccess { boolean isCarrierThreadLocalPresent(CarrierThreadLocal local); /** - * Returns the current thread's extent locals cache + * Returns the current thread's scoped values cache */ - Object[] extentLocalCache(); + Object[] scopedValueCache(); /** - * Sets the current thread's extent locals cache + * Sets the current thread's scoped values cache */ - void setExtentLocalCache(Object[] cache); + void setScopedValueCache(Object[] cache); /** - * Return the current thread's extent local bindings. + * Return the current thread's scoped value bindings. */ - Object extentLocalBindings(); + Object scopedValueBindings(); /** - * Set the current thread's extent local bindings. + * Set the current thread's scoped value bindings. */ - void setExtentLocalBindings(Object bindings); + void setScopedValueBindings(Object bindings); + + Object findScopedValueBindings(); + + void ensureMaterializedForStackWalk(Object value); /** * Returns the innermost mounted continuation diff --git a/src/java.base/share/classes/jdk/internal/misc/ThreadFlock.java b/src/java.base/share/classes/jdk/internal/misc/ThreadFlock.java index 9a3e2953d38..90e84d8ddfa 100644 --- a/src/java.base/share/classes/jdk/internal/misc/ThreadFlock.java +++ b/src/java.base/share/classes/jdk/internal/misc/ThreadFlock.java @@ -35,7 +35,7 @@ import java.util.stream.Stream; import jdk.internal.access.JavaLangAccess; import jdk.internal.access.SharedSecrets; -import jdk.internal.vm.ExtentLocalContainer; +import jdk.internal.vm.ScopedValueContainer; import jdk.internal.vm.ThreadContainer; import jdk.internal.vm.ThreadContainers; import static java.util.concurrent.TimeUnit.NANOSECONDS; @@ -99,7 +99,7 @@ public class ThreadFlock implements AutoCloseable { private volatile int threadCount; private final String name; - private final ExtentLocalContainer.BindingsSnapshot extentLocalBindings; + private final ScopedValueContainer.BindingsSnapshot scopedValueBindings; private final ThreadContainerImpl container; // encapsulate for now // state @@ -111,7 +111,7 @@ public class ThreadFlock implements AutoCloseable { ThreadFlock(String name) { this.name = name; - this.extentLocalBindings = ExtentLocalContainer.captureBindings(); + this.scopedValueBindings = ScopedValueContainer.captureBindings(); this.container = new ThreadContainerImpl(this); } @@ -119,8 +119,8 @@ private long threadCount() { return threadCount; } - private ExtentLocalContainer.BindingsSnapshot extentLocalBindings() { - return extentLocalBindings; + private ScopedValueContainer.BindingsSnapshot scopedValueBindings() { + return scopedValueBindings; } private void incrementThreadCount() { @@ -210,7 +210,7 @@ private void ensureOwnerOrContainsThread() { * Opens a new thread flock. The flock is owned by the current thread. It can be * named to aid debugging. * - *

    This method captures the current thread's {@linkplain ExtentLocal extent-local} + *

    This method captures the current thread's {@linkplain ScopedValue scoped value} * bindings for inheritance by threads created in the flock. * *

    For the purposes of containment, monitoring, and debugging, the parent @@ -250,7 +250,7 @@ public Thread owner() { /** * Starts the given unstarted thread in this flock. * - *

    The thread is started with the extent-local bindings that were captured + *

    The thread is started with the scoped value bindings that were captured * when opening the flock. The bindings must match the current thread's bindings. * *

    This method may only be invoked by the flock owner or threads {@linkplain @@ -263,7 +263,7 @@ public Thread owner() { * @throws WrongThreadException if the current thread is not the owner or a thread * contained in the flock * @throws jdk.incubator.concurrent.StructureViolationException if the current - * extent-local bindings are not the same as when the flock was created + * scoped value bindings are not the same as when the flock was created */ public Thread start(Thread thread) { ensureOwnerOrContainsThread(); @@ -398,12 +398,11 @@ public void wakeup() { *

    A ThreadFlock is intended to be used in a structured manner. If * this method is called to close a flock before nested flocks are closed then it * closes the nested flocks (in the reverse order that they were created in), - * closes this flock, and then throws {@link - * jdk.incubator.concurrent.StructureViolationException}. - * Similarly, if called to close a flock that encloses {@linkplain - * jdk.incubator.concurrent.ExtentLocal.Carrier#run(Runnable) operations} with - * extent-local bindings then it also throws {@code StructureViolationException} - * after closing the flock. + * closes this flock, and then throws {@code StructureViolationException}. + * Similarly, if this method is called to close a thread flock while executing with + * scoped value bindings, and the thread flock was created before the scoped values + * were bound, then {@code StructureViolationException} is thrown after closing the + * thread flock. * * @throws WrongThreadException if invoked by a thread that is not the owner * @throws jdk.incubator.concurrent.StructureViolationException if a structure @@ -585,8 +584,8 @@ public String toString() { return flock.toString(); } @Override - public ExtentLocalContainer.BindingsSnapshot extentLocalBindings() { - return flock.extentLocalBindings(); + public ScopedValueContainer.BindingsSnapshot scopedValueBindings() { + return flock.scopedValueBindings(); } } } diff --git a/src/java.base/share/classes/jdk/internal/vm/Continuation.java b/src/java.base/share/classes/jdk/internal/vm/Continuation.java index d0e9433b869..cfb386227e1 100644 --- a/src/java.base/share/classes/jdk/internal/vm/Continuation.java +++ b/src/java.base/share/classes/jdk/internal/vm/Continuation.java @@ -46,7 +46,7 @@ */ public class Continuation { private static final Unsafe U = Unsafe.getUnsafe(); - private static final boolean PRESERVE_EXTENT_LOCAL_CACHE; + private static final boolean PRESERVE_SCOPED_VALUE_CACHE; private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); static { ContinuationSupport.ensureSupported(); @@ -54,8 +54,8 @@ public class Continuation { StackChunk.init(); // ensure StackChunk class is initialized - String value = GetPropertyAction.privilegedGetProperty("jdk.preserveExtentLocalCache"); - PRESERVE_EXTENT_LOCAL_CACHE = (value == null) || Boolean.parseBoolean(value); + String value = GetPropertyAction.privilegedGetProperty("jdk.preserveScopedValueCache"); + PRESERVE_SCOPED_VALUE_CACHE = (value == null) || Boolean.parseBoolean(value); } private static final VarHandle MOUNTED; @@ -129,7 +129,7 @@ private static Thread currentCarrierThread() { private Object yieldInfo; private boolean preempted; - private Object[] extentLocalCache; + private Object[] scopedValueCache; /** * Constructs a continuation @@ -238,7 +238,7 @@ private void unmount() { public final void run() { while (true) { mount(); - JLA.setExtentLocalCache(extentLocalCache); + JLA.setScopedValueCache(scopedValueCache); if (done) throw new IllegalStateException("Continuation terminated"); @@ -270,12 +270,12 @@ public final void run() { postYieldCleanup(); unmount(); - if (PRESERVE_EXTENT_LOCAL_CACHE) { - extentLocalCache = JLA.extentLocalCache(); + if (PRESERVE_SCOPED_VALUE_CACHE) { + scopedValueCache = JLA.scopedValueCache(); } else { - extentLocalCache = null; + scopedValueCache = null; } - JLA.setExtentLocalCache(null); + JLA.setScopedValueCache(null); } catch (Throwable e) { e.printStackTrace(); System.exit(1); } } // we're now in the parent continuation diff --git a/src/java.base/share/classes/jdk/internal/vm/ExtentLocalContainer.java b/src/java.base/share/classes/jdk/internal/vm/ScopedValueContainer.java similarity index 81% rename from src/java.base/share/classes/jdk/internal/vm/ExtentLocalContainer.java rename to src/java.base/share/classes/jdk/internal/vm/ScopedValueContainer.java index c31707eb586..e798d7e95e1 100644 --- a/src/java.base/share/classes/jdk/internal/vm/ExtentLocalContainer.java +++ b/src/java.base/share/classes/jdk/internal/vm/ScopedValueContainer.java @@ -33,26 +33,26 @@ import jdk.internal.vm.annotation.ReservedStackAccess; /** - * A StackableScope to represent extent-local bindings. + * A StackableScope to represent scoped-value bindings. * - * This class defines static methods to run an operation with a ExtentLocalContainer - * on the scope stack. It also defines a method to get the latest ExtentLocalContainer - * and a method to return a snapshot of the extent local bindings. + * This class defines static methods to run an operation with a ScopedValueContainer + * on the scope stack. It also defines a method to get the latest ScopedValueContainer + * and a method to return a snapshot of the scoped value bindings. */ -public class ExtentLocalContainer extends StackableScope { +public class ScopedValueContainer extends StackableScope { private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); static { Unsafe.getUnsafe().ensureClassInitialized(StructureViolationExceptions.class); } - private ExtentLocalContainer() { + private ScopedValueContainer() { } /** - * Returns the "latest" ExtentLocalContainer for the current Thread. This may be on - * the current thread's scope task or ma require walking up the tree to find it. + * Returns the "latest" ScopedValueContainer for the current Thread. This may be on + * the current thread's scope task or may require walking up the tree to find it. */ - public static T latest(Class containerClass) { + public static T latest(Class containerClass) { StackableScope scope = head(); if (scope == null) { scope = JLA.threadContainer(Thread.currentThread()); @@ -69,37 +69,37 @@ public static T latest(Class containerClass) } /** - * Returns the "latest" ExtentLocalContainer for the current Thread. This + * Returns the "latest" ScopedValueContainer for the current Thread. This * may be on the current thread's scope task or may require walking up the * tree to find it. */ - public static ExtentLocalContainer latest() { - return latest(ExtentLocalContainer.class); + public static ScopedValueContainer latest() { + return latest(ScopedValueContainer.class); } /** - * A snapshot of the extent local bindings. The snapshot includes the bindings - * established for the current thread and extent local container. + * A snapshot of the scoped value bindings. The snapshot includes the bindings + * established for the current thread and scoped value container. */ - public record BindingsSnapshot(Object extentLocalBindings, - ExtentLocalContainer container) { } + public record BindingsSnapshot(Object scopedValueBindings, + ScopedValueContainer container) { } /** - * Returns the extent local bindings for the current thread. + * Returns the scoped value bindings for the current thread. */ public static BindingsSnapshot captureBindings() { - return new BindingsSnapshot(JLA.extentLocalBindings(), latest()); + return new BindingsSnapshot(JLA.scopedValueBindings(), latest()); } /** - * For use by ExtentLocal to run an operation in a structured context. + * For use by ScopedValue to run an operation in a structured context. */ public static void run(Runnable op) { if (head() == null) { // no need to push scope when stack is empty runWithoutScope(op); } else { - new ExtentLocalContainer().doRun(op); + new ScopedValueContainer().doRun(op); } } @@ -141,14 +141,14 @@ private void doRun(Runnable op) { } /** - * For use by ExtentLocal to call a value returning operation in a structured context. + * For use by ScopedValue to call a value returning operation in a structured context. */ public static V call(Callable op) throws Exception { if (head() == null) { // no need to push scope when stack is empty return callWithoutScope(op); } else { - return new ExtentLocalContainer().doCall(op); + return new ScopedValueContainer().doCall(op); } } @@ -199,7 +199,6 @@ private V doCall(Callable op) { * Throws {@code ex} if not null. StructureViolationException is thrown or added * as a suppressed exception when {@code atTop} is false. */ - @DontInline @ReservedStackAccess private static void throwIfFailed(Throwable ex, boolean atTop) { if (ex != null || !atTop) { if (!atTop) { diff --git a/src/java.base/share/classes/jdk/internal/vm/ThreadContainer.java b/src/java.base/share/classes/jdk/internal/vm/ThreadContainer.java index cf6dc94aea7..45bd013ecab 100644 --- a/src/java.base/share/classes/jdk/internal/vm/ThreadContainer.java +++ b/src/java.base/share/classes/jdk/internal/vm/ThreadContainer.java @@ -89,9 +89,9 @@ public void onExit(Thread thread) { } /** - * The extent locals captured when the thread container was created. + * The scoped values captured when the thread container was created. */ - public ExtentLocalContainer.BindingsSnapshot extentLocalBindings() { + public ScopedValueContainer.BindingsSnapshot scopedValueBindings() { return null; } } diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index 86d8866049c..a042ecc22dd 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -167,6 +167,7 @@ jdk.jlink, jdk.jfr, jdk.net, + jdk.incubator.concurrent, jdk.sctp, jdk.crypto.cryptoki; exports jdk.internal.foreign to @@ -247,12 +248,14 @@ jdk.unsupported; exports jdk.internal.vm to java.management, + jdk.incubator.concurrent, jdk.internal.jvmstat, jdk.management, jdk.management.agent; exports jdk.internal.vm.annotation to java.instrument, jdk.internal.vm.ci, + jdk.incubator.concurrent, jdk.incubator.vector, jdk.jfr, jdk.unsupported; @@ -307,7 +310,8 @@ exports sun.security.action to java.desktop, java.security.jgss, - jdk.crypto.ec; + jdk.crypto.ec, + jdk.incubator.concurrent; exports sun.security.internal.interfaces to jdk.crypto.cryptoki; exports sun.security.internal.spec to diff --git a/src/java.base/share/native/libjava/Thread.c b/src/java.base/share/native/libjava/Thread.c index 6014feedcb8..4230d167cdc 100644 --- a/src/java.base/share/native/libjava/Thread.c +++ b/src/java.base/share/native/libjava/Thread.c @@ -50,9 +50,12 @@ static JNINativeMethod methods[] = { {"dumpThreads", "([" THD ")[[" STE, (void *)&JVM_DumpThreads}, {"getStackTrace0", "()" OBJ, (void *)&JVM_GetStackTrace}, {"setNativeName", "(" STR ")V", (void *)&JVM_SetNativeThreadName}, - {"extentLocalCache", "()[" OBJ, (void *)&JVM_ExtentLocalCache}, - {"setExtentLocalCache", "([" OBJ ")V",(void *)&JVM_SetExtentLocalCache}, - {"getNextThreadIdOffset", "()J", (void *)&JVM_GetNextThreadIdOffset} + {"scopedValueCache", "()[" OBJ, (void *)&JVM_ScopedValueCache}, + {"setScopedValueCache", "([" OBJ ")V",(void *)&JVM_SetScopedValueCache}, + {"getNextThreadIdOffset", "()J", (void *)&JVM_GetNextThreadIdOffset}, + {"findScopedValueBindings", "()" OBJ, (void *)&JVM_FindScopedValueBindings}, + {"ensureMaterializedForStackWalk", + "(" OBJ ")V", (void*)&JVM_EnsureMaterializedForStackWalk_func}, }; #undef THD diff --git a/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/ScopedValue.java b/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/ScopedValue.java new file mode 100644 index 00000000000..882bc8eb219 --- /dev/null +++ b/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/ScopedValue.java @@ -0,0 +1,838 @@ +/* + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Red Hat Inc. + * 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.incubator.concurrent; + +import java.util.NoSuchElementException; +import java.util.Objects; +import java.lang.ref.Reference; +import java.util.concurrent.Callable; +import java.util.function.Supplier; +import jdk.internal.access.JavaLangAccess; +import jdk.internal.access.JavaUtilConcurrentTLRAccess; +import jdk.internal.access.SharedSecrets; +import jdk.internal.vm.annotation.ForceInline; +import jdk.internal.vm.annotation.Hidden; +import jdk.internal.vm.annotation.Stable; +import jdk.internal.vm.ScopedValueContainer; +import sun.security.action.GetPropertyAction; + +/** + * A value that is set once and is then available for reading for a bounded period of + * execution by a thread. A {@code ScopedValue} allows for safely and efficiently sharing + * data for a bounded period of execution without passing the data as method arguments. + * + *

    {@code ScopedValue} defines the {@link #where(ScopedValue, Object, Runnable)} + * method to set the value of a {@code ScopedValue} for the bouned period of execution by + * a thread of the runnable's {@link Runnable#run() run} method. The unfolding execution of + * the methods executed by {@code run} defines a dynamic scope. The scoped + * value is {@linkplain #isBound() bound} while executing in the dynamic scope, it reverts + * to being unbound when the {@code run} method completes (normally or with an + * exception). Code executing in the dynamic scope uses the {@code ScopedValue} {@link + * #get() get} method to read its value. + * + *

    Like a {@linkplain ThreadLocal thread-local variable}, a scoped value has multiple + * incarnations, one per thread. The particular incarnation that is used depends on which + * thread calls its methods. + * + *

    Consider the following example with a scoped value {@code USERNAME} that is + * bound to the value "{@code duke}" for the execution, by a thread, of a run + * method that invokes {@code doSomething()}. + * {@snippet lang=java : + * // @link substring="newInstance" target="#newInstance" : + * private static final ScopedValue USERNAME = ScopedValue.newInstance(); + * + * ScopedValue.where(USERNAME, "duke", () -> doSomething()); + * } + * Code executed directly or indirectly by {@code doSomething()} that invokes {@code + * USERNAME.get()} will read the value "{@code duke}". The scoped value is bound while + * executing {@code doSomething()} and becomes unbound when {@code doSomething()} + * completes (normally or with an exception). If one thread were to call {@code + * doSomething()} with {@code USERNAME} bound to "{@code duke1}", and another thread + * were to call the method with {@code USERNAME} bound to "{@code duke2}", then + * {@code USERNAME.get()} would read the value "{@code duke1}" or "{@code duke2}", + * depending on which thread is executing. + * + *

    In addition to the {@code where} method that executes a {@code run} method, {@code + * ScopedValue} defines the {@link #where(ScopedValue, Object, Callable)} method to execute + * a method that returns a result. It also defines the {@link #where(ScopedValue, Object)} + * method for cases where it is useful to accumulate mappings of {@code ScopedValue} to + * value. + * + *

    A {@code ScopedValue} will typically be declared in a {@code final} and {@code + * static} field. The accessibility of the field will determine which components can + * bind or read its value. + * + *

    Unless otherwise specified, passing a {@code null} argument to a method in this + * class will cause a {@link NullPointerException} to be thrown. + * + *

    Rebinding

    + * + * The {@code ScopedValue} API allows a new binding to be established for nested + * dynamic scopes. This is known as rebinding. A {@code ScopedValue} that + * is bound to some value may be bound to a new value for the bounded execution of some + * method. The unfolding execution of code executed by that method defines the nested + * dynamic scope. When the method completes (normally or with an exception), the value of + * the {@code ScopedValue} reverts to its previous value. + * + *

    In the above example, suppose that code executed by {@code doSomething()} binds + * {@code USERNAME} to a new value with: + * {@snippet lang=java : + * ScopedValue.where(USERNAME, "duchess", () -> doMore()); + * } + * Code executed directly or indirectly by {@code doMore()} that invokes {@code + * USERNAME.get()} will read the value "{@code duchess}". When {@code doMore()} completes + * (normally or with an exception), the value of {@code USERNAME} reverts to + * "{@code duke}". + * + *

    Inheritance

    + * + * {@code ScopedValue} supports sharing data across threads. This sharing is limited to + * structured cases where child threads are started and terminate within the bounded + * period of execution by a parent thread. More specifically, when using a {@link + * StructuredTaskScope}, scoped value bindings are captured when creating a + * {@code StructuredTaskScope} and inherited by all threads started in that scope with + * the {@link StructuredTaskScope#fork(Callable) fork} method. + * + *

    In the following example, the {@code ScopedValue} {@code USERNAME} is bound to the + * value "{@code duke}" for the execution of a runnable operation. The code in the {@code + * run} method creates a {@code StructuredTaskScope} and forks three child threads. Code + * executed directly or indirectly by these threads running {@code childTask1()}, + * {@code childTask2()}, and {@code childTask3()} will read the value "{@code duke}". + * + * {@snippet lang=java : + * private static final ScopedValue USERNAME = ScopedValue.newInstance(); + + * ScopedValue.where(USERNAME, "duke", () -> { + * try (var scope = new StructuredTaskScope()) { + * + * scope.fork(() -> childTask1()); + * scope.fork(() -> childTask2()); + * scope.fork(() -> childTask3()); + * + * ... + * } + * }); + * } + * + * @implNote + * Scoped values are designed to be used in fairly small + * numbers. {@link #get} initially performs a search through enclosing + * scopes to find a scoped value's innermost binding. It + * then caches the result of the search in a small thread-local + * cache. Subsequent invocations of {@link #get} for that scoped value + * will almost always be very fast. However, if a program has many + * scoped values that it uses cyclically, the cache hit rate + * will be low and performance will be poor. This design allows + * scoped-value inheritance by {@link StructuredTaskScope} threads to + * be very fast: in essence, no more than copying a pointer, and + * leaving a scoped-value binding also requires little more than + * updating a pointer. + * + *

    Because the scoped-value per-thread cache is small, clients + * should minimize the number of bound scoped values in use. For + * example, if it is necessary to pass a number of values in this way, + * it makes sense to create a record class to hold those values, and + * then bind a single {@code ScopedValue} to an instance of that record. + * + *

    For this incubator release, the reference implementation + * provides some system properties to tune the performance of scoped + * values. + * + *

    The system property {@code jdk.incubator.concurrent.ScopedValue.cacheSize} + * controls the size of the (per-thread) scoped-value cache. This cache is crucial + * for the performance of scoped values. If it is too small, + * the runtime library will repeatedly need to scan for each + * {@link #get}. If it is too large, memory will be unnecessarily + * consumed. The default scoped-value cache size is 16 entries. It may + * be varied from 2 to 16 entries in size. {@code ScopedValue.cacheSize} + * must be an integer power of 2. + * + *

    For example, you could use {@code -Djdk.incubator.concurrent.ScopedValue.cacheSize=8}. + * + *

    The other system property is {@code jdk.preserveScopedValueCache}. + * This property determines whether the per-thread scoped-value + * cache is preserved when a virtual thread is blocked. By default + * this property is set to {@code true}, meaning that every virtual + * thread preserves its scoped-value cache when blocked. Like {@code + * ScopedValue.cacheSize}, this is a space versus speed trade-off: in + * situations where many virtual threads are blocked most of the time, + * setting this property to {@code false} might result in a useful + * memory saving, but each virtual thread's scoped-value cache would + * have to be regenerated after a blocking operation. + * + * @param the type of the object bound to this {@code ScopedValue} + * @since 20 + */ +public final class ScopedValue { + private static final JavaLangAccess JLA = SharedSecrets.getJavaLangAccess(); + + private final @Stable int hash; + + @Override + public int hashCode() { return hash; } + + /** + * An immutable map from {@code ScopedValue} to values. + * + *

    Unless otherwise specified, passing a {@code null} argument to a constructor + * or method in this class will cause a {@link NullPointerException} to be thrown. + */ + static final class Snapshot { + final Snapshot prev; + final Carrier bindings; + final int bitmask; + + private static final Object NIL = new Object(); + + static final Snapshot EMPTY_SNAPSHOT = new Snapshot(); + + Snapshot(Carrier bindings, Snapshot prev) { + this.prev = prev; + this.bindings = bindings; + this.bitmask = bindings.bitmask | prev.bitmask; + } + + protected Snapshot() { + this.prev = null; + this.bindings = null; + this.bitmask = 0; + } + + Object find(ScopedValue key) { + int bits = key.bitmask(); + for (Snapshot snapshot = this; + containsAll(snapshot.bitmask, bits); + snapshot = snapshot.prev) { + for (Carrier carrier = snapshot.bindings; + carrier != null && containsAll(carrier.bitmask, bits); + carrier = carrier.prev) { + if (carrier.getKey() == key) { + Object value = carrier.get(); + return value; + } + } + } + return NIL; + } + } + + /** + * A mapping of scoped values, as keys, to values. + * + *

    A {@code Carrier} is used to accumlate mappings so that an operation (a + * {@link Runnable} or {@link Callable}) can be executed with all scoped values in the + * mapping bound to values. The following example runs an operation with {@code k1} + * bound (or rebound) to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}. + * {@snippet lang=java : + * // @link substring="where" target="#where(ScopedValue, Object)" : + * ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... ); + * } + * + *

    A {@code Carrier} is immutable and thread-safe. The {@link + * #where(ScopedValue, Object) where} method returns a new {@code Carrier} object, + * it does not mutate an existing mapping. + * + *

    Unless otherwise specified, passing a {@code null} argument to a method in + * this class will cause a {@link NullPointerException} to be thrown. + * + * @since 20 + */ + public static final class Carrier { + // Bit masks: a 1 in postion n indicates that this set of bound values + // hits that slot in the cache. + final int bitmask; + final ScopedValue key; + final Object value; + final Carrier prev; + + Carrier(ScopedValue key, Object value, Carrier prev) { + this.key = key; + this.value = value; + this.prev = prev; + int bits = key.bitmask(); + if (prev != null) { + bits |= prev.bitmask; + } + this.bitmask = bits; + } + + /** + * Add a binding to this map, returning a new Carrier instance. + */ + private static final Carrier where(ScopedValue key, T value, + Carrier prev) { + return new Carrier(key, value, prev); + } + + /** + * Returns a new {@code Carrier} with the mappings from this carrier plus a + * new mapping from {@code key} to {@code value}. If this carrier already has a + * mapping for the scoped value {@code key} then it will map to the new + * {@code value}. The current carrier is immutable, so it is not changed by this + * method. + * + * @param key the {@code ScopedValue} key + * @param value the value, can be {@code null} + * @param the type of the value + * @return a new {@code Carrier} with the mappings from this carrier plus the new mapping + */ + public Carrier where(ScopedValue key, T value) { + return where(key, value, this); + } + + /* + * Return a new set consisting of a single binding. + */ + static Carrier of(ScopedValue key, T value) { + return where(key, value, null); + } + + final Object get() { + return value; + } + + final ScopedValue getKey() { + return key; + } + + /** + * Returns the value of a {@link ScopedValue} in this mapping. + * + * @param key the {@code ScopedValue} key + * @param the type of the value + * @return the value + * @throws NoSuchElementException if the key is not present in this mapping + */ + @SuppressWarnings("unchecked") + public T get(ScopedValue key) { + var bits = key.bitmask(); + for (Carrier carrier = this; + carrier != null && containsAll(carrier.bitmask, bits); + carrier = carrier.prev) { + if (carrier.getKey() == key) { + Object value = carrier.get(); + return (T)value; + } + } + throw new NoSuchElementException(); + } + + /** + * Calls a value-returning operation with each scoped value in this mapping bound + * to its value in the current thread. + * When the operation completes (normally or with an exception), each scoped value + * in the mapping will revert to being unbound, or revert to its previous value + * when previously bound, in the current thread. + * + *

    Scoped values are intended to be used in a structured manner. + * If {@code op} creates a {@link StructuredTaskScope} but does not {@linkplain + * StructuredTaskScope#close() close} it, then exiting {@code op} causes the + * underlying construct of each {@code StructuredTaskScope} created in the + * dynamic scope to be closed. This may require blocking until all child threads + * have completed their sub-tasks. The closing is done in the reverse order that + * they were created. Once closed, {@link StructureViolationException} is thrown. + * + * @param op the operation to run + * @param the type of the result of the operation + * @return the result + * @throws Exception if {@code op} completes with an exception + * @see ScopedValue#where(ScopedValue, Object, Callable) + */ + public R call(Callable op) throws Exception { + Objects.requireNonNull(op); + Cache.invalidate(bitmask); + var prevSnapshot = scopedValueBindings(); + var newSnapshot = new Snapshot(this, prevSnapshot); + return runWith(newSnapshot, op); + } + + /** + * Execute the action with a set of ScopedValue bindings. + * + * The VM recognizes this method as special, so any changes to the + * name or signature require corresponding changes in + * JVM_FindScopedValueBindings(). + */ + @Hidden + @ForceInline + private R runWith(Snapshot newSnapshot, Callable op) throws Exception { + try { + JLA.setScopedValueBindings(newSnapshot); + JLA.ensureMaterializedForStackWalk(newSnapshot); + return ScopedValueContainer.call(op); + } finally { + Reference.reachabilityFence(newSnapshot); + JLA.setScopedValueBindings(newSnapshot.prev); + Cache.invalidate(bitmask); + } + } + + /** + * Runs an operation with each scoped value in this mapping bound to its value + * in the current thread. + * When the operation completes (normally or with an exception), each scoped value + * in the mapping will revert to being unbound, or revert to its previous value + * when previously bound, in the current thread. + * + *

    Scoped values are intended to be used in a structured manner. + * If {@code op} creates a {@link StructuredTaskScope} but does not {@linkplain + * StructuredTaskScope#close() close} it, then exiting {@code op} causes the + * underlying construct of each {@code StructuredTaskScope} created in the + * dynamic scope to be closed. This may require blocking until all child threads + * have completed their sub-tasks. The closing is done in the reverse order that + * they were created. Once closed, {@link StructureViolationException} is thrown. + * + * @param op the operation to run + * @see ScopedValue#where(ScopedValue, Object, Runnable) + */ + public void run(Runnable op) { + Objects.requireNonNull(op); + Cache.invalidate(bitmask); + var prevSnapshot = scopedValueBindings(); + var newSnapshot = new Snapshot(this, prevSnapshot); + runWith(newSnapshot, op); + } + + /** + * Execute the action with a set of {@code ScopedValue} bindings. + * + * The VM recognizes this method as special, so any changes to the + * name or signature require corresponding changes in + * JVM_FindScopedValueBindings(). + */ + @Hidden + @ForceInline + private void runWith(Snapshot newSnapshot, Runnable op) { + try { + JLA.setScopedValueBindings(newSnapshot); + JLA.ensureMaterializedForStackWalk(newSnapshot); + ScopedValueContainer.run(op); + } finally { + Reference.reachabilityFence(newSnapshot); + JLA.setScopedValueBindings(newSnapshot.prev); + Cache.invalidate(bitmask); + } + } + } + + /** + * Creates a new {@code Carrier} with a single mapping of a {@code ScopedValue} + * key to a value. The {@code Carrier} can be used to accumlate mappings so + * that an operation can be executed with all scoped values in the mapping bound to + * values. The following example runs an operation with {@code k1} bound (or rebound) + * to {@code v1}, and {@code k2} bound (or rebound) to {@code v2}. + * {@snippet lang=java : + * // @link substring="run" target="Carrier#run(Runnable)" : + * ScopedValue.where(k1, v1).where(k2, v2).run(() -> ... ); + * } + * + * @param key the {@code ScopedValue} key + * @param value the value, can be {@code null} + * @param the type of the value + * @return a new {@code Carrier} with a single mapping + */ + public static Carrier where(ScopedValue key, T value) { + return Carrier.of(key, value); + } + + /** + * Calls a value-returning operation with a {@code ScopedValue} bound to a value + * in the current thread. When the operation completes (normally or with an + * exception), the {@code ScopedValue} will revert to being unbound, or revert to + * its previous value when previously bound, in the current thread. + * + *

    Scoped values are intended to be used in a structured manner. + * If {@code op} creates a {@link StructuredTaskScope} but does not {@linkplain + * StructuredTaskScope#close() close} it, then exiting {@code op} causes the + * underlying construct of each {@code StructuredTaskScope} created in the + * dynamic scope to be closed. This may require blocking until all child threads + * have completed their sub-tasks. The closing is done in the reverse order that + * they were created. Once closed, {@link StructureViolationException} is thrown. + * + * @implNote + * This method is implemented to be equivalent to: + * {@snippet lang=java : + * // @link substring="call" target="Carrier#call(Callable)" : + * ScopedValue.where(key, value).call(op); + * } + * + * @param key the {@code ScopedValue} key + * @param value the value, can be {@code null} + * @param the type of the value + * @param the result type + * @param op the operation to call + * @return the result + * @throws Exception if the operation completes with an exception + */ + public static R where(ScopedValue key, + T value, + Callable op) throws Exception { + return where(key, value).call(op); + } + + /** + * Run an operation with a {@code ScopedValue} bound to a value in the current + * thread. When the operation completes (normally or with an exception), the + * {@code ScopedValue} will revert to being unbound, or revert to its previous value + * when previously bound, in the current thread. + * + *

    Scoped values are intended to be used in a structured manner. + * If {@code op} creates a {@link StructuredTaskScope} but does not {@linkplain + * StructuredTaskScope#close() close} it, then exiting {@code op} causes the + * underlying construct of each {@code StructuredTaskScope} created in the + * dynamic scope to be closed. This may require blocking until all child threads + * have completed their sub-tasks. The closing is done in the reverse order that + * they were created. Once closed, {@link StructureViolationException} is thrown. + * + * @implNote + * This method is implemented to be equivalent to: + * {@snippet lang=java : + * // @link substring="run" target="Carrier#run(Runnable)" : + * ScopedValue.where(key, value).run(op); + * } + * + * @param key the {@code ScopedValue} key + * @param value the value, can be {@code null} + * @param the type of the value + * @param op the operation to call + */ + public static void where(ScopedValue key, T value, Runnable op) { + where(key, value).run(op); + } + + private ScopedValue() { + this.hash = generateKey(); + } + + /** + * Creates a scoped value that is initially unbound for all threads. + * + * @param the type of the value + * @return a new {@code ScopedValue} + */ + public static ScopedValue newInstance() { + return new ScopedValue(); + } + + /** + * {@return the value of the scoped value if bound in the current thread} + * + * @throws NoSuchElementException if the scoped value is not bound + */ + @ForceInline + @SuppressWarnings("unchecked") + public T get() { + Object[] objects; + if ((objects = scopedValueCache()) != null) { + // This code should perhaps be in class Cache. We do it + // here because the generated code is small and fast and + // we really want it to be inlined in the caller. + int n = (hash & Cache.SLOT_MASK) * 2; + if (objects[n] == this) { + return (T)objects[n + 1]; + } + n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2; + if (objects[n] == this) { + return (T)objects[n + 1]; + } + } + return slowGet(); + } + + @SuppressWarnings("unchecked") + private T slowGet() { + var value = findBinding(); + if (value == Snapshot.NIL) { + throw new NoSuchElementException(); + } + Cache.put(this, value); + return (T)value; + } + + /** + * {@return {@code true} if this scoped value is bound in the current thread} + */ + public boolean isBound() { + Object[] objects = scopedValueCache(); + if (objects != null) { + int n = (hash & Cache.SLOT_MASK) * 2; + if (objects[n] == this) { + return true; + } + n = ((hash >>> Cache.INDEX_BITS) & Cache.SLOT_MASK) * 2; + if (objects[n] == this) { + return true; + } + } + var value = findBinding(); + boolean result = (value != Snapshot.NIL); + if (result) Cache.put(this, value); + return result; + } + + /** + * Return the value of the scoped value or NIL if not bound. + */ + private Object findBinding() { + Object value = scopedValueBindings().find(this); + return value; + } + + /** + * Returns the value of this scoped value if bound in the current thread, otherwise + * returns {@code other}. + * + * @param other the value to return if not bound, can be {@code null} + * @return the value of the scoped value if bound, otherwise {@code other} + */ + public T orElse(T other) { + Object obj = findBinding(); + if (obj != Snapshot.NIL) { + @SuppressWarnings("unchecked") + T value = (T) obj; + return value; + } else { + return other; + } + } + + /** + * Returns the value of this scoped value if bound in the current thread, otherwise + * throws an exception produced by the exception supplying function. + * + * @param the type of the exception that may be thrown + * @param exceptionSupplier the supplying function that produces the exception to throw + * @return the value of the scoped value if bound in the current thread + * @throws X if the scoped value is not bound in the current thread + */ + public T orElseThrow(Supplier exceptionSupplier) throws X { + Objects.requireNonNull(exceptionSupplier); + Object obj = findBinding(); + if (obj != Snapshot.NIL) { + @SuppressWarnings("unchecked") + T value = (T) obj; + return value; + } else { + throw exceptionSupplier.get(); + } + } + + private static Object[] scopedValueCache() { + return JLA.scopedValueCache(); + } + + private static void setScopedValueCache(Object[] cache) { + JLA.setScopedValueCache(cache); + } + + // Special value to indicate this is a newly-created Thread + // Note that his must match the declaration in j.l.Thread. + private static final Object NEW_THREAD_BINDINGS = Thread.class; + + private static Snapshot scopedValueBindings() { + // Bindings can be in one of four states: + // + // 1: class Thread: this is a new Thread instance, and no + // scoped values have ever been bound in this Thread. + // 2: EmptySnapshot.SINGLETON: This is effectively an empty binding. + // 3: A Snapshot instance: this contains one or more scoped value + // bindings. + // 4: null: there may be some bindings in this Thread, but we don't know + // where they are. We must invoke JLA.findScopedValueBindings() to walk + // the stack to find them. + + Object bindings = JLA.scopedValueBindings(); + if (bindings == NEW_THREAD_BINDINGS) { + // This must be a new thread + return Snapshot.EMPTY_SNAPSHOT; + } + if (bindings == null) { + // Search the stack + bindings = JLA.findScopedValueBindings(); + if (bindings == null) { + // Nothing on the stack. + bindings = Snapshot.EMPTY_SNAPSHOT; + } + } + assert (bindings != null); + JLA.setScopedValueBindings(bindings); + return (Snapshot) bindings; + } + + private static int nextKey = 0xf0f0_f0f0; + + // A Marsaglia xor-shift generator used to generate hashes. This one has full period, so + // it generates 2**32 - 1 hashes before it repeats. We're going to use the lowest n bits + // and the next n bits as cache indexes, so we make sure that those indexes map + // to different slots in the cache. + private static synchronized int generateKey() { + int x = nextKey; + do { + x ^= x >>> 12; + x ^= x << 9; + x ^= x >>> 23; + } while (Cache.primarySlot(x) == Cache.secondarySlot(x)); + return (nextKey = x); + } + + /** + * Return a bit mask that may be used to determine if this ScopedValue is + * bound in the current context. Each Carrier holds a bit mask which is + * the OR of all the bit masks of the bound ScopedValues. + * @return the bitmask + */ + int bitmask() { + return (1 << Cache.primaryIndex(this)) | (1 << (Cache.secondaryIndex(this) + Cache.TABLE_SIZE)); + } + + // Return true iff bitmask, considered as a set of bits, contains all + // of the bits in targetBits. + static boolean containsAll(int bitmask, int targetBits) { + return (bitmask & targetBits) == targetBits; + } + + // A small fixed-size key-value cache. When a scoped value's get() method + // is invoked, we record the result of the lookup in this per-thread cache + // for fast access in future. + private static final class Cache { + static final int INDEX_BITS = 4; // Must be a power of 2 + static final int TABLE_SIZE = 1 << INDEX_BITS; + static final int TABLE_MASK = TABLE_SIZE - 1; + static final int PRIMARY_MASK = (1 << TABLE_SIZE) - 1; + + // The number of elements in the cache array, and a bit mask used to + // select elements from it. + private static final int CACHE_TABLE_SIZE, SLOT_MASK; + // The largest cache we allow. Must be a power of 2 and greater than + // or equal to 2. + private static final int MAX_CACHE_SIZE = 16; + + static { + final String propertyName = "jdk.incubator.concurrent.ScopedValue.cacheSize"; + var sizeString = GetPropertyAction.privilegedGetProperty(propertyName, "16"); + var cacheSize = Integer.valueOf(sizeString); + if (cacheSize < 2 || cacheSize > MAX_CACHE_SIZE) { + cacheSize = MAX_CACHE_SIZE; + System.err.println(propertyName + " is out of range: is " + sizeString); + } + if ((cacheSize & (cacheSize - 1)) != 0) { // a power of 2 + cacheSize = MAX_CACHE_SIZE; + System.err.println(propertyName + " must be an integer power of 2: is " + sizeString); + } + CACHE_TABLE_SIZE = cacheSize; + SLOT_MASK = cacheSize - 1; + } + + static int primaryIndex(ScopedValue key) { + return key.hash & TABLE_MASK; + } + + static int secondaryIndex(ScopedValue key) { + return (key.hash >> INDEX_BITS) & TABLE_MASK; + } + + private static int primarySlot(ScopedValue key) { + return key.hashCode() & SLOT_MASK; + } + + private static int secondarySlot(ScopedValue key) { + return (key.hash >> INDEX_BITS) & SLOT_MASK; + } + + static int primarySlot(int hash) { + return hash & SLOT_MASK; + } + + static int secondarySlot(int hash) { + return (hash >> INDEX_BITS) & SLOT_MASK; + } + + static void put(ScopedValue key, Object value) { + Object[] theCache = scopedValueCache(); + if (theCache == null) { + theCache = new Object[CACHE_TABLE_SIZE * 2]; + setScopedValueCache(theCache); + } + // Update the cache to replace one entry with the value we just looked up. + // Each value can be in one of two possible places in the cache. + // Pick a victim at (pseudo-)random. + int k1 = primarySlot(key); + int k2 = secondarySlot(key); + var usePrimaryIndex = chooseVictim(); + int victim = usePrimaryIndex ? k1 : k2; + int other = usePrimaryIndex ? k2 : k1; + setKeyAndObjectAt(victim, key, value); + if (getKey(theCache, other) == key) { + setKeyAndObjectAt(other, key, value); + } + } + + private static void setKeyAndObjectAt(int n, Object key, Object value) { + var cache = scopedValueCache(); + cache[n * 2] = key; + cache[n * 2 + 1] = value; + } + + private static void setKeyAndObjectAt(Object[] cache, int n, Object key, Object value) { + cache[n * 2] = key; + cache[n * 2 + 1] = value; + } + + private static Object getKey(Object[] objs, int n) { + return objs[n * 2]; + } + + private static void setKey(Object[] objs, int n, Object key) { + objs[n * 2] = key; + } + + private static final JavaUtilConcurrentTLRAccess THREAD_LOCAL_RANDOM_ACCESS + = SharedSecrets.getJavaUtilConcurrentTLRAccess(); + + // Return either true or false, at pseudo-random, with a bias towards true. + // This chooses either the primary or secondary cache slot, but the + // primary slot is approximately twice as likely to be chosen as the + // secondary one. + private static boolean chooseVictim() { + int r = THREAD_LOCAL_RANDOM_ACCESS.nextSecondaryThreadLocalRandomSeed(); + return (r & 15) >= 5; + } + + // Null a set of cache entries, indicated by the 1-bits given + static void invalidate(int toClearBits) { + toClearBits = (toClearBits >>> TABLE_SIZE) | (toClearBits & PRIMARY_MASK); + Object[] objects; + if ((objects = scopedValueCache()) != null) { + for (int bits = toClearBits; bits != 0; ) { + int index = Integer.numberOfTrailingZeros(bits); + setKeyAndObjectAt(objects, index & SLOT_MASK, null, null); + bits &= ~1 << index; + } + } + } + } +} diff --git a/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java b/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java index a64af2393a2..2f983d52372 100644 --- a/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java +++ b/src/jdk.incubator.concurrent/share/classes/jdk/incubator/concurrent/StructuredTaskScope.java @@ -210,8 +210,8 @@ * *

    Tree structure

    * - * StructuredTaskScopes form a tree where parent-child relations are established - * implicitly when opening a new task scope: + * Task scopes form a tree where parent-child relations are established implicitly when + * opening a new task scope: *
      *
    • A parent-child relation is established when a thread started in a task scope * opens its own task scope. A thread started in task scope "A" that opens task scope @@ -222,10 +222,45 @@ * scope "B" is the parent of the nested task scope "C". *
    * - *

    The tree structure supports confinement checks. The phrase "threads contained in - * the task scope" in method descriptions means threads started in the task scope or - * descendant scopes. {@code StructuredTaskScope} does not define APIs that exposes the - * tree structure at this time. + * The descendants of a task scope are the child task scopes that it is a parent + * of, plus the descendants of the child task scopes, recursively. + * + *

    The tree structure supports: + *

      + *
    • Inheritance of {@linkplain ScopedValue scoped values} across threads. + *
    • Confinement checks. The phrase "threads contained in the task scope" in method + * descriptions means threads started in the task scope or descendant scopes. + *
    + * + *

    The following example demonstrates the inheritance of a scoped value. A scoped + * value {@code USERNAME} is bound to the value "{@code duke}". A {@code StructuredTaskScope} + * is created and its {@code fork} method invoked to start a thread to execute {@code + * childTask}. The thread inherits the scoped value bindings captured when + * creating the task scope. The code in {@code childTask} uses the value of the scoped + * value and so reads the value "{@code duke}". + * {@snippet lang=java : + * private static final ScopedValue USERNAME = ScopedValue.newInstance(); + * + * // @link substring="where" target="ScopedValue#where(ScopedValue, Object, Runnable)" : + * ScopedValue.where(USERNAME, "duke", () -> { + * try (var scope = new StructuredTaskScope()) { + * + * scope.fork(() -> childTask()); // @highlight substring="fork" + * ... + * } + * }); + * + * ... + * + * String childTask() { + * // @link substring="get" target="ScopedValue#get()" : + * String name = USERNAME.get(); // "duke" + * ... + * } + * } + * + *

    {@code StructuredTaskScope} does not define APIs that exposes the tree structure + * at this time. * *

    Unless otherwise specified, passing a {@code null} argument to a constructor * or method in this class will cause a {@link NullPointerException} to be thrown. @@ -234,7 +269,7 @@ * *

    Actions in the owner thread of, or a thread contained in, the task scope prior to * {@linkplain #fork forking} of a {@code Callable} task - * + * * happen-before any actions taken by that task, which in turn happen-before * the task result is retrieved via its {@code Future}, or happen-before any actions * taken in a thread after {@linkplain #join() joining} of the task scope. @@ -280,6 +315,12 @@ public class StructuredTaskScope implements AutoCloseable { * tasks are {@linkplain #fork(Callable) forked}. The task scope is owned by the * current thread. * + *

    This method captures the current thread's {@linkplain ScopedValue scoped value} + * bindings for inheritance by threads created in the task scope. The + * Tree Structure section in the class description + * details how parent-child relations are established implicitly for the purpose of + * inheritance of scoped value bindings. + * * @param name the name of the task scope, can be null * @param factory the thread factory */ @@ -367,16 +408,19 @@ protected void handleComplete(Future future) { } /** * Starts a new thread to run the given task. * - *

    The new thread is created with the task scope's {@link ThreadFactory}. + *

    The new thread is created with the task scope's {@link ThreadFactory}. It + * inherits the current thread's {@linkplain ScopedValue scoped value} bindings. The + * bindings must match the bindings captured when the task scope was created. * *

    If the task completes before the task scope is {@link #shutdown() shutdown} - * then the {@link #handleComplete(Future) handle} method is invoked to consume the - * completed task. The {@code handleComplete} method is run when the task completes - * with a result or exception. If the {@code Future} {@link Future#cancel(boolean) - * cancel} method is used the cancel a task before the task scope is shut down, then - * the {@code handleComplete} method is run by the thread that invokes {@code cancel}. - * If the task scope shuts down at or around the same time that the task completes or - * is cancelled then the {@code handleComplete} method may or may not be invoked. + * then the {@link #handleComplete(Future) handleComplete} method is invoked to + * consume the completed task. The {@code handleComplete} method is run when the task + * completes with a result or exception. If the {@code Future}'s {@link + * Future#cancel(boolean) cancel} method is used to cancel a task before the task scope + * is shut down, then the {@code handleComplete} method is run by the thread that + * invokes {@code cancel}. If the task scope shuts down at or around the same time + * that the task completes or is cancelled then the {@code handleComplete} method may + * or may not be invoked. * *

    If this task scope is {@linkplain #shutdown() shutdown} (or in the process * of shutting down) then {@code fork} returns a {@code Future} representing a {@link @@ -395,6 +439,8 @@ protected void handleComplete(Future future) { } * @throws IllegalStateException if this task scope is closed * @throws WrongThreadException if the current thread is not the owner or a thread * contained in the task scope + * @throws StructureViolationException if the current scoped value bindings are not + * the same as when the task scope was created * @throws RejectedExecutionException if the thread factory rejected creating a * thread to run the task */ @@ -628,6 +674,12 @@ public void shutdown() { * scopes are closed then it closes the underlying construct of each nested task scope * (in the reverse order that they were created in), closes this task scope, and then * throws {@link StructureViolationException}. + * + * Similarly, if this method is called to close a task scope while executing with + * {@linkplain ScopedValue scoped value} bindings, and the task scope was created + * before the scoped values were bound, then {@code StructureViolationException} is + * thrown after closing the task scope. + * * If a thread terminates without first closing task scopes that it owns then * termination will cause the underlying construct of each of its open tasks scopes to * be closed. Closing is performed in the reverse order that the task scopes were @@ -824,6 +876,12 @@ public static final class ShutdownOnSuccess extends StructuredTaskScope { * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope is * owned by the current thread. * + *

    This method captures the current thread's {@linkplain ScopedValue scoped value} + * bindings for inheritance by threads created in the task scope. The + * Tree Structure section in + * the class description details how parent-child relations are established + * implicitly for the purpose of inheritance of scoped value bindings. + * * @param name the name of the task scope, can be null * @param factory the thread factory */ @@ -1000,6 +1058,12 @@ public static final class ShutdownOnFailure extends StructuredTaskScope * threads when tasks are {@linkplain #fork(Callable) forked}. The task scope * is owned by the current thread. * + *

    This method captures the current thread's {@linkplain ScopedValue scoped value} + * bindings for inheritance by threads created in the task scope. The + * Tree Structure section in + * the class description details how parent-child relations are established + * implicitly for the purpose of inheritance of scoped value bindings. + * * @param name the name of the task scope, can be null * @param factory the thread factory */ diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java b/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java index 5a88fcc5b25..922cad26735 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetFrameCount/framecnt01/framecnt01.java @@ -61,7 +61,7 @@ public static void main(String args[]) throws Exception { // Test GetFrameCount on virtual live thread Thread vThread = Thread.ofVirtual().name("VirtualThread-Live").start(() -> { - checkFrames(Thread.currentThread(), false, 9); + checkFrames(Thread.currentThread(), false, 10); }); vThread.join(); @@ -79,13 +79,13 @@ public static void main(String args[]) throws Exception { } // this is too fragile, implementation can change at any time. - checkFrames(vThread1, false, 14); + checkFrames(vThread1, false, 15); LockSupport.unpark(vThread1); vThread1.join(); // Test GetFrameCount on live platform thread Thread pThread = Thread.ofPlatform().name("PlatformThread-Live").start(() -> { - checkFrames(Thread.currentThread(), false, 5); + checkFrames(Thread.currentThread(), false, 6); }); pThread.join(); @@ -101,7 +101,7 @@ public static void main(String args[]) throws Exception { while(pThread1.getState() != Thread.State.WAITING) { Thread.sleep(1); } - checkFrames(pThread1, false, 5); + checkFrames(pThread1, false, 6); LockSupport.unpark(pThread1); pThread1.join(); @@ -118,10 +118,11 @@ class FixedDepthThread implements Runnable { Object checkFlag; Thread thread; - // Each stack has 2 frames additional to expected depth + // Each stack has 3 frames additional to expected depth // 0: FixedDepthThread: run()V // 1: java/lang/Thread: run()V - static final int ADDITIONAL_STACK_COUNT = 2; + // 2: java/lang/Thread: runWith()V + static final int ADDITIONAL_STACK_COUNT = 3; private FixedDepthThread(String name, int depth, Object checkFlag) { this.thread = Thread.ofPlatform().name(name).unstarted(this); diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp index 1e3b6211400..deb494dd0aa 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/GetStackTraceCurrentThreadTest/libGetStackTraceCurrentThreadTest.cpp @@ -36,7 +36,8 @@ static frame_info expected_virtual_frames[] = { {"LGetStackTraceCurrentThreadTest;", "dummy", "()V"}, {"LGetStackTraceCurrentThreadTest;", "chain", "()V"}, {"LTask;", "run", "()V"}, - {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"} + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, }; static frame_info expected_platform_frames[] = { @@ -44,7 +45,8 @@ static frame_info expected_platform_frames[] = { {"LGetStackTraceCurrentThreadTest;", "dummy", "()V"}, {"LGetStackTraceCurrentThreadTest;", "chain", "()V"}, {"LTask;", "run", "()V"}, - {"Ljava/lang/Thread;", "run", "()V"} + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/Thread;", "run", "()V"}, }; JNIEXPORT jint JNICALL diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp index 1f1bce5bb01..2b1c2385491 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr03/libgetstacktr03.cpp @@ -35,7 +35,8 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr03;", "dummy", "()V"}, {"Lgetstacktr03;", "chain", "()V"}, {"Lgetstacktr03$Task;", "run", "()V"}, - {"Ljava/lang/Thread;", "run", "()V"} + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, + {"Ljava/lang/Thread;", "run", "()V"}, }; static frame_info expected_virtual_frames[] = { @@ -43,6 +44,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr03;", "dummy", "()V"}, {"Lgetstacktr03;", "chain", "()V"}, {"Lgetstacktr03$Task;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda$31.0x0000000800098810;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp index d15c4112757..873522ab531 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr04/libgetstacktr04.cpp @@ -38,6 +38,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr04$TestThread;", "chain2", "()V"}, {"Lgetstacktr04$TestThread;", "chain1", "()V"}, {"Lgetstacktr04$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -48,6 +49,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr04$TestThread;", "chain2", "()V"}, {"Lgetstacktr04$TestThread;", "chain1", "()V"}, {"Lgetstacktr04$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp index 3e228886538..d4d4b2447ab 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr05/libgetstacktr05.cpp @@ -39,6 +39,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr05$TestThread;", "chain2", "()V"}, {"Lgetstacktr05$TestThread;", "chain1", "()V"}, {"Lgetstacktr05$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -48,6 +49,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr05$TestThread;", "chain2", "()V"}, {"Lgetstacktr05$TestThread;", "chain1", "()V"}, {"Lgetstacktr05$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp index 21568a64226..0fd52c697f4 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr06/libgetstacktr06.cpp @@ -43,6 +43,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr06$TestThread;", "chain2", "()V"}, {"Lgetstacktr06$TestThread;", "chain1", "()V"}, {"Lgetstacktr06$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -52,6 +53,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr06$TestThread;", "chain2", "()V"}, {"Lgetstacktr06$TestThread;", "chain1", "()V"}, {"Lgetstacktr06$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp index 7bf22883f55..a422fc0782f 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr07/libgetstacktr07.cpp @@ -45,6 +45,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr07$TestThread;", "chain2", "()V"}, {"Lgetstacktr07$TestThread;", "chain1", "()V"}, {"Lgetstacktr07$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -55,6 +56,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr07$TestThread;", "chain2", "()V"}, {"Lgetstacktr07$TestThread;", "chain1", "()V"}, {"Lgetstacktr07$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp index af71c61b0c4..977bbf00b04 100644 --- a/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp +++ b/test/hotspot/jtreg/serviceability/jvmti/thread/GetStackTrace/getstacktr08/libgetstacktr08.cpp @@ -44,6 +44,7 @@ static frame_info expected_platform_frames[] = { {"Lgetstacktr08$TestThread;", "chain2", "()V"}, {"Lgetstacktr08$TestThread;", "chain1", "()V"}, {"Lgetstacktr08$TestThread;", "run", "()V"}, + {"Ljava/lang/Thread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/Thread;", "run", "()V"}, }; @@ -56,6 +57,7 @@ static frame_info expected_virtual_frames[] = { {"Lgetstacktr08$TestThread;", "chain2", "()V"}, {"Lgetstacktr08$TestThread;", "chain1", "()V"}, {"Lgetstacktr08$TestThread;", "run", "()V"}, + {"Ljava/lang/VirtualThread;", "runWith", "(Ljava/lang/Object;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread;", "run", "(Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation;", "lambda$new$0", "(Ljava/lang/VirtualThread;Ljava/lang/Runnable;)V"}, {"Ljava/lang/VirtualThread$VThreadContinuation$$Lambda;", "run", "()V"}, diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 26b21389474..71001d0e76a 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -794,3 +794,4 @@ java/awt/event/MouseEvent/SpuriousExitEnter/SpuriousExitEnter.java 8254841 macos java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.java 8256289 windows-x64 java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java 8258103 linux-all java/awt/Focus/FrameMinimizeTest/FrameMinimizeTest.java 8016266 linux-x64 + diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java new file mode 100644 index 00000000000..f2b2c470ae7 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/ManyBindings.java @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2022, 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 Stress test ScopedValue with many bindings and rebinings + * @enablePreview + * @modules jdk.incubator.concurrent + * @library /test/lib + * @key randomness + * @run testng ManyBindings + */ + +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.ScopedValue.Carrier; +import java.util.Arrays; +import java.util.Objects; +import java.util.Random; + +import jdk.test.lib.RandomFactory; +import jdk.test.lib.thread.VThreadRunner; + +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class ManyBindings { + private static final Random RND = RandomFactory.getRandom(); + + // number of scoped values to create + private static final int SCOPED_VALUE_COUNT = 16; + + // recursive depth to test + private static final int MAX_DEPTH = 24; + + /** + * Stress test bindings on platform thread. + */ + public void testPlatformThread() { + test(); + } + + /** + * Stress test bindings on virtual thread. + */ + public void testVirtualThread() throws Exception { + VThreadRunner.run(() -> test()); + } + + /** + * Scoped value and its expected value (or null if not bound). + */ + record KeyAndValue(ScopedValue key, T value) { + KeyAndValue() { + this(ScopedValue.newInstance(), null); + } + } + + /** + * Stress test bindings on current thread. + */ + private void test() { + KeyAndValue[] array = new KeyAndValue[SCOPED_VALUE_COUNT]; + for (int i = 0; i < array.length; i++) { + array[i] = new KeyAndValue<>(); + } + test(array, 1); + } + + /** + * Test that the scoped values in the array have the expected value, then + * recursively call this method with some of the scoped values bound to a + * new value. + * + * @param array the scoped values and their expected value + * @param depth current recurive depth + */ + private void test(KeyAndValue[] array, int depth) { + if (depth > MAX_DEPTH) + return; + + // check that the scoped values have the expected values + check(array); + + // try to pollute the cache + lotsOfReads(array); + + // create a Carrier to bind/rebind some of the scoped values + int len = array.length; + Carrier carrier = null; + + KeyAndValue[] newArray = Arrays.copyOf(array, len); + int n = Math.max(1, RND.nextInt(len / 2)); + while (n > 0) { + int index = RND.nextInt(len); + ScopedValue key = array[index].key; + int newValue = RND.nextInt(); + if (carrier == null) { + carrier = ScopedValue.where(key, newValue); + } else { + carrier = carrier.where(key, newValue); + } + newArray[index] = new KeyAndValue<>(key, newValue); + n--; + } + + // invoke recursively + carrier.run(() -> { + test(newArray, depth+1); + }); + + // check that the scoped values have the origina values + check(array); + } + + /** + * Check that the given scoped values have the expected value. + */ + private void check(KeyAndValue[] array) { + for (int i = 0; i < array.length; i++) { + ScopedValue key = array[i].key; + Integer value = array[i].value; + if (value == null) { + assertFalse(key.isBound()); + } else { + assertEquals(key.get(), value); + } + } + } + + /** + * Do lots of reads of the scoped values, to pollute the SV cache. + */ + private void lotsOfReads(KeyAndValue[] array) { + for (int k = 0; k < 1000; k++) { + int index = RND.nextInt(array.length); + Integer value = array[index].value; + if (value != null) { + ScopedValue key = array[index].key; + assertEquals(key.get(), value); + } + } + } +} diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java new file mode 100644 index 00000000000..690f974a539 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/ScopeValueAPI.java @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2021, 2022, 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 Test ScopedValue API + * @enablePreview + * @modules jdk.incubator.concurrent + * @run testng ScopeValueAPI + */ + +import jdk.incubator.concurrent.ScopedValue; +import java.util.NoSuchElementException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class ScopeValueAPI { + + @DataProvider + public Object[][] factories() { + return new Object[][] { + { Thread.ofPlatform().factory() }, + { Thread.ofVirtual().factory() }, + }; + } + + /** + * Test that the run method is invoked. + */ + @Test(dataProvider = "factories") + public void testRun(ThreadFactory factory) throws Exception { + test(factory, () -> { + class Box { static boolean executed; } + ScopedValue name = ScopedValue.newInstance(); + ScopedValue.where(name, "duke", () -> { Box.executed = true; }); + assertTrue(Box.executed); + }); + } + + /** + * Test the run method throwing an exception. + */ + @Test(dataProvider = "factories") + public void testRunThrows(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + Runnable op = () -> { throw new FooException(); }; + assertThrows(FooException.class, () -> ScopedValue.where(name, "duke", op)); + assertFalse(name.isBound()); + }); + } + + /** + * Test that the call method is invoked. + */ + @Test(dataProvider = "factories") + public void testCall(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + String result = ScopedValue.where(name, "duke", name::get); + assertEquals(result, "duke"); + }); + } + + /** + * Test the call method throwing an exception. + */ + @Test(dataProvider = "factories") + public void testCallThrows(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + Callable op = () -> { throw new FooException(); }; + assertThrows(FooException.class, () -> ScopedValue.where(name, "duke", op)); + assertFalse(name.isBound()); + }); + } + + /** + * Test get method. + */ + @Test(dataProvider = "factories") + public void testGet(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + + // run + ScopedValue.where(name1, "duke", () -> { + assertEquals(name1.get(), "duke"); + assertThrows(NoSuchElementException.class, name2::get); + + }); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + + // call + ScopedValue.where(name1, "duke", () -> { + assertEquals(name1.get(), "duke"); + assertThrows(NoSuchElementException.class, name2::get); + return null; + }); + assertThrows(NoSuchElementException.class, name1::get); + assertThrows(NoSuchElementException.class, name2::get); + }); + } + + /** + * Test isBound method. + */ + @Test(dataProvider = "factories") + public void testIsBound(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + + // run + ScopedValue.where(name1, "duke", () -> { + assertTrue(name1.isBound()); + assertFalse(name2.isBound()); + }); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + + // call + ScopedValue.where(name1, "duke", () -> { + assertTrue(name1.isBound()); + assertFalse(name2.isBound()); + return null; + }); + assertFalse(name1.isBound()); + assertFalse(name2.isBound()); + }); + } + + /** + * Test orElse method. + */ + @Test(dataProvider = "factories") + public void testOrElse(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + assertTrue(name.orElse(null) == null); + assertEquals(name.orElse("default"), "default"); + + // run + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElse(null), "duke"); + assertEquals(name.orElse("default"), "duke"); + }); + + // call + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElse(null), "duke"); + assertEquals(name.orElse("default"), "duke"); + return null; + }); + }); + } + + /** + * Test orElseThrow method. + */ + @Test(dataProvider = "factories") + public void testOrElseThrow(ThreadFactory factory) throws Exception { + test(factory, () -> { + class FooException extends RuntimeException { } + ScopedValue name = ScopedValue.newInstance(); + assertThrows(FooException.class, () -> name.orElseThrow(FooException::new)); + + // run + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElseThrow(FooException::new), "duke"); + }); + + // call + ScopedValue.where(name, "duke", () -> { + assertEquals(name.orElseThrow(FooException::new), "duke"); + return null; + }); + }); + } + + /** + * Test two bindings. + */ + @Test(dataProvider = "factories") + public void testTwoBindings(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue age = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke").where(age, 100).run(() -> { + assertTrue(name.isBound()); + assertTrue(age.isBound()); + assertEquals(name.get(), "duke"); + assertEquals((int) age.get(), 100); + }); + assertFalse(name.isBound()); + assertFalse(age.isBound()); + + // call + ScopedValue.where(name, "duke").where(age, 100).call(() -> { + assertTrue(name.isBound()); + assertTrue(age.isBound()); + assertEquals(name.get(), "duke"); + assertEquals((int) age.get(), 100); + return null; + }); + assertFalse(name.isBound()); + assertFalse(age.isBound()); + + }); + } + + /** + * Test rebinding. + */ + @Test(dataProvider = "factories") + public void testRebinding(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + return null; + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test rebinding from null vaue to another value. + */ + @Test(dataProvider = "factories") + public void testRebindingFromNull(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), null); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + }); + + assertTrue(name.isBound()); + assertTrue(name.get() == null); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), null); + + ScopedValue.where(name, "duchess", () -> { + assertTrue(name.isBound()); + assertTrue("duchess".equals(name.get())); + return null; + }); + + assertTrue(name.isBound()); + assertTrue(name.get() == null); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test rebinding to null value. + */ + @Test(dataProvider = "factories") + public void testRebindingToNull(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + + // run + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertTrue(name.get() == null); + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + }); + assertFalse(name.isBound()); + + // call + ScopedValue.where(name, "duke", () -> { + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + + ScopedValue.where(name, null, () -> { + assertTrue(name.isBound()); + assertTrue(name.get() == null); + return null; + }); + + assertTrue(name.isBound()); + assertEquals(name.get(), "duke"); + return null; + }); + assertFalse(name.isBound()); + }); + } + + /** + * Test Carrier.get. + */ + @Test(dataProvider = "factories") + public void testCarrierGet(ThreadFactory factory) throws Exception { + test(factory, () -> { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue age = ScopedValue.newInstance(); + + // one scoped value + var carrier1 = ScopedValue.where(name, "duke"); + assertEquals(carrier1.get(name), "duke"); + assertThrows(NoSuchElementException.class, () -> carrier1.get(age)); + + // two scoped values + var carrier2 = carrier1.where(age, 20); + assertEquals(carrier2.get(name), "duke"); + assertEquals((int) carrier2.get(age), 20); + }); + } + + /** + * Test NullPointerException. + */ + public void testNullPointerException() { + ScopedValue name = ScopedValue.newInstance(); + + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value")); + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value", () -> { })); + assertThrows(NullPointerException.class, () -> ScopedValue.where(null, "value", () -> null)); + + assertThrows(NullPointerException.class, () -> name.orElseThrow(null)); + + var carrier = ScopedValue.where(name, "duke"); + assertThrows(NullPointerException.class, () -> carrier.where(null, "value")); + assertThrows(NullPointerException.class, () -> carrier.get(null)); + assertThrows(NullPointerException.class, () -> carrier.run(null)); + assertThrows(NullPointerException.class, () -> carrier.call(null)); + } + + @FunctionalInterface + private interface ThrowingRunnable { + void run() throws Exception; + } + + /** + * Run the given task in a thread created with the given thread factory. + * @throws Exception if the task throws an exception + */ + private static void test(ThreadFactory factory, ThrowingRunnable task) throws Exception { + try (var executor = Executors.newThreadPerTaskExecutor(factory)) { + var future = executor.submit(() -> { + task.run(); + return null; + }); + try { + future.get(); + } catch (ExecutionException ee) { + Throwable cause = ee.getCause(); + if (cause instanceof Exception e) + throw e; + if (cause instanceof Error e) + throw e; + throw new RuntimeException(cause); + } + } + } +} diff --git a/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java b/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java new file mode 100644 index 00000000000..c5e6cd54589 --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/ScopedValue/StressStackOverflow.java @@ -0,0 +1,213 @@ +/* + * Copyright (c) 2021, 2022 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 + * @summary StressStackOverflow the recovery path for ScopedValue + * @modules jdk.incubator.concurrent + * @compile --enable-preview -source ${jdk.version} StressStackOverflow.java + * @run main/othervm/timeout=300 -XX:-TieredCompilation --enable-preview StressStackOverflow + * @run main/othervm/timeout=300 -XX:TieredStopAtLevel=1 --enable-preview StressStackOverflow + * @run main/othervm/timeout=300 --enable-preview StressStackOverflow + */ + +import java.util.concurrent.Callable; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.ThreadLocalRandom; +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructureViolationException; +import jdk.incubator.concurrent.StructuredTaskScope; + +public class StressStackOverflow { + public static final ScopedValue el = ScopedValue.newInstance(); + + public static final ScopedValue inheritedValue = ScopedValue.newInstance(); + + final ThreadLocalRandom tlr = ThreadLocalRandom.current(); + static final TestFailureException testFailureException = new TestFailureException("Unexpected value for ScopedValue"); + int ITERS = 1_000_000; + + static class TestFailureException extends RuntimeException { + TestFailureException(String s) { super(s); } + } + + // Test the ScopedValue recovery mechanism for stack overflows. We implement both Callable + // and Runnable interfaces. Which one gets tested depends on the constructor argument. + class DeepRecursion implements Callable, Runnable { + + static enum Behaviour {CALL, RUN} + final Behaviour behaviour; + + public DeepRecursion(Behaviour behaviour) { + this.behaviour = behaviour; + } + + public void run() { + final var last = el.get(); + ITERS--; + var nextRandomFloat = tlr.nextFloat(); + try { + switch (behaviour) { + case CALL -> + ScopedValue.where(el, el.get() + 1).call(() -> fibonacci_pad(20, this)); + case RUN -> + ScopedValue.where(el, el.get() + 1).run(() -> fibonacci_pad(20, this)); + } + if (!last.equals(el.get())) { + throw testFailureException; + } + } catch (StackOverflowError e) { + if (nextRandomFloat <= 0.1) { + ScopedValue.where(el, el.get() + 1).run(this); + } + } catch (TestFailureException e) { + throw e; + } catch (Throwable throwable) { + // StackOverflowErrors cause many different failures. These include + // StructureViolationExceptions and InvocationTargetExceptions. This test + // checks that, no matter what the failure mode, scoped values are handled + // correctly. + } finally { + if (!last.equals(el.get())) { + throw testFailureException; + } + } + + Thread.yield(); + } + + public Object call() { + run(); + return null; + } + } + + static final Runnable nop = new Runnable() { + public void run() { } + }; + + // Consume some stack. + // + + // The double recursion used here prevents an optimizing JIT from + // inlining all the recursive calls, which would make it + // ineffective. + private long fibonacci_pad1(int n, Runnable op) { + if (n <= 1) { + op.run(); + return n; + } + return fibonacci_pad1(n - 1, op) + fibonacci_pad1(n - 2, nop); + } + + private static final Integer I_42 = 42; + + long fibonacci_pad(int n, Runnable op) { + final var last = el.get(); + try { + return fibonacci_pad1(tlr.nextInt(n), op); + } catch (StackOverflowError err) { + if (!inheritedValue.get().equals(I_42)) { + throw testFailureException; + } + if (!last.equals(el.get())) { + throw testFailureException; + } + throw err; + } + } + + // Run op in a new thread. Platform or virtual threads are chosen at random. + void runInNewThread(Runnable op) { + var threadFactory + = (tlr.nextBoolean() ? Thread.ofPlatform() : Thread.ofVirtual()).factory(); + try (var scope = new StructuredTaskScope("", threadFactory)) { + var future = scope.fork(() -> { + op.run(); + return null; + }); + future.get(); + scope.join(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public void run() { + try { + ScopedValue.where(inheritedValue, 42).where(el, 0).run(() -> { + try (var scope = new StructuredTaskScope()) { + try { + if (tlr.nextBoolean()) { + // Repeatedly test Scoped Values set by ScopedValue::call() and ScopedValue::run() + final var deepRecursion + = new DeepRecursion(tlr.nextBoolean() ? DeepRecursion.Behaviour.CALL : DeepRecursion.Behaviour.RUN); + deepRecursion.run(); + } else { + // Recursively run ourself until we get a stack overflow + // Catch the overflow and make sure the recovery path works + // for values inherited from a StructuredTaskScope. + Runnable op = new Runnable() { + public void run() { + try { + fibonacci_pad(20, this); + } catch (StackOverflowError e) { + } catch (TestFailureException e) { + throw e; + } catch (Throwable throwable) { + // StackOverflowErrors cause many different failures. These include + // StructureViolationExceptions and InvocationTargetExceptions. This test + // checks that, no matter what the failure mode, scoped values are handled + // correctly. + } finally { + if (!inheritedValue.get().equals(I_42)) { + throw testFailureException; + } + } + } + }; + runInNewThread(op); + } + scope.join(); + } catch (StructureViolationException structureViolationException) { + // Can happen if a stack overflow prevented a StackableScope from + // being removed. We can continue. + } catch (Exception e) { + throw new RuntimeException(e); + } + } + }); + } catch (StructureViolationException structureViolationException) { + // Can happen if a stack overflow prevented a StackableScope from + // being removed. We can continue. + } + } + + public static void main(String[] args) { + var torture = new StressStackOverflow(); + while (torture.ITERS > 0) { + torture.run(); + } + System.out.println("OK"); + } +} diff --git a/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java b/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java new file mode 100644 index 00000000000..a6917ccf6ab --- /dev/null +++ b/test/jdk/jdk/incubator/concurrent/StructuredTaskScope/WithScopedValue.java @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2022, 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 Basic tests for StructuredTaskScope with scoped values + * @enablePreview + * @modules jdk.incubator.concurrent + * @run testng WithScopedValue + */ + +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructuredTaskScope; +import jdk.incubator.concurrent.StructureViolationException; +import java.util.concurrent.Future; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class WithScopedValue { + + @DataProvider + public Object[][] factories() { + return new Object[][] { + { Thread.ofPlatform().factory() }, + { Thread.ofVirtual().factory() }, + }; + } + + /** + * Test that fork inherits a scoped value into a child thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue1(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope = new StructuredTaskScope(null, factory)) { + Future future = scope.fork(() -> { + return name.get(); // child should read "x" + }); + scope.join(); + return future.resultNow(); + } + }); + assertEquals(value, "x"); + } + + /** + * Test that fork inherits a scoped value into a grandchild thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue2(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope1 = new StructuredTaskScope(null, factory)) { + Future future1 = scope1.fork(() -> { + try (var scope2 = new StructuredTaskScope(null, factory)) { + Future future2 = scope2.fork(() -> { + return name.get(); // grandchild should read "x" + }); + scope2.join(); + return future2.resultNow(); + } + }); + scope1.join(); + return future1.resultNow(); + } + }); + assertEquals(value, "x"); + } + + /** + * Test that fork inherits a rebound scoped value into a grandchild thread. + */ + @Test(dataProvider = "factories") + public void testForkInheritsScopedValue3(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "x", () -> { + try (var scope1 = new StructuredTaskScope(null, factory)) { + Future future1 = scope1.fork(() -> { + assertEquals(name.get(), "x"); // child should read "x" + + // rebind name to "y" + String grandchildValue = ScopedValue.where(name, "y", () -> { + try (var scope2 = new StructuredTaskScope(null, factory)) { + Future future2 = scope2.fork(() -> { + return name.get(); // grandchild should read "y" + }); + scope2.join(); + return future2.resultNow(); + } + }); + + assertEquals(name.get(), "x"); // child should read "x" + return grandchildValue; + }); + scope1.join(); + return future1.resultNow(); + } + }); + assertEquals(value, "y"); + } + + /** + * Test exiting a dynamic scope with an open task scope. + */ + public void testStructureViolation1() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + class Box { + StructuredTaskScope scope; + } + var box = new Box(); + try { + try { + ScopedValue.where(name, "x", () -> { + box.scope = new StructuredTaskScope(); + }); + fail(); + } catch (StructureViolationException expected) { } + + // underlying flock should be closed, fork should return a cancelled task + StructuredTaskScope scope = box.scope; + AtomicBoolean ran = new AtomicBoolean(); + Future future = scope.fork(() -> { + ran.set(true); + return null; + }); + assertTrue(future.isCancelled()); + scope.join(); + assertFalse(ran.get()); + + } finally { + StructuredTaskScope scope = box.scope; + if (scope != null) { + scope.close(); + } + } + } + + /** + * Test closing a StructuredTaskScope while executing in a dynamic scope. + */ + public void testStructureViolation2() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name, "x", () -> { + assertThrows(StructureViolationException.class, scope::close); + }); + } + } + + /** + * Test fork when a scoped value is bound after a StructuredTaskScope is created. + */ + public void testStructureViolation3() throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name, "x", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + } + + /** + * Test fork when a scoped value is re-bound after a StructuredTaskScope is created. + */ + public void testStructureViolation4() throws Exception { + ScopedValue name1 = ScopedValue.newInstance(); + ScopedValue name2 = ScopedValue.newInstance(); + + // rebind + ScopedValue.where(name1, "x", () -> { + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name1, "y", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + }); + + // new binding + ScopedValue.where(name1, "x", () -> { + try (var scope = new StructuredTaskScope()) { + ScopedValue.where(name2, "y", () -> { + assertThrows(StructureViolationException.class, + () -> scope.fork(() -> "foo")); + }); + } + }); + } +} diff --git a/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java new file mode 100644 index 00000000000..7bb45bd6f79 --- /dev/null +++ b/test/jdk/jdk/internal/misc/ThreadFlock/WithScopedValue.java @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2021, 2022, 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 Test ThreadFlock with scoped values + * @enablePreview + * @modules java.base/jdk.internal.misc + * @modules jdk.incubator.concurrent + * @run testng WithScopedValue + */ + +import jdk.internal.misc.ThreadFlock; +import jdk.incubator.concurrent.ScopedValue; +import jdk.incubator.concurrent.StructureViolationException; +import java.util.concurrent.Executors; +import java.util.concurrent.ThreadFactory; +import java.util.concurrent.atomic.AtomicReference; + +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; +import static org.testng.Assert.*; + +@Test +public class WithScopedValue { + + @DataProvider(name = "factories") + public Object[][] factories() { + var defaultThreadFactory = Executors.defaultThreadFactory(); + var virtualThreadFactory = Thread.ofVirtual().factory(); + return new Object[][]{ + { defaultThreadFactory, }, + { virtualThreadFactory, }, + }; + } + + /** + * Test inheritance of a scoped value. + */ + @Test(dataProvider = "factories") + public void testInheritsScopedValue(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + String value = ScopedValue.where(name, "duke", () -> { + var result = new AtomicReference(); + try (var flock = ThreadFlock.open(null)) { + Thread thread = factory.newThread(() -> { + // child + result.set(name.get()); + }); + flock.start(thread); + } + return result.get(); + }); + assertEquals(value, "duke"); + } + + /** + * Test exiting a dynamic scope with open thread flocks. + */ + public void testStructureViolation1() { + ScopedValue name = ScopedValue.newInstance(); + class Box { + ThreadFlock flock1; + ThreadFlock flock2; + } + var box = new Box(); + try { + ScopedValue.where(name, "x1", () -> { + box.flock1 = ThreadFlock.open(null); + box.flock2 = ThreadFlock.open(null); + }); + fail(); + } catch (StructureViolationException expected) { } + assertTrue(box.flock1.isClosed()); + assertTrue(box.flock2.isClosed()); + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock1. + */ + public void testStructureViolation2() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock1.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertTrue(flock1.isClosed()); + assertTrue(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock2. + */ + public void testStructureViolation3() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock2.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertFalse(flock1.isClosed()); + assertTrue(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test closing a thread flock while in a dynamic scope and with enclosing thread + * flocks. This test closes enclosing flock3. + */ + public void testStructureViolation4() { + ScopedValue name = ScopedValue.newInstance(); + try (var flock1 = ThreadFlock.open("flock1")) { + ScopedValue.where(name, "x1", () -> { + try (var flock2 = ThreadFlock.open("flock2")) { + ScopedValue.where(name, "x2", () -> { + try (var flock3 = ThreadFlock.open("flock3")) { + ScopedValue.where(name, "x3", () -> { + var flock4 = ThreadFlock.open("flock4"); + + try { + flock3.close(); + fail(); + } catch (StructureViolationException expected) { } + + assertFalse(flock1.isClosed()); + assertFalse(flock2.isClosed()); + assertTrue(flock3.isClosed()); + assertTrue(flock4.isClosed()); + }); + } + }); + } + }); + } + } + + /** + * Test start when a scoped value is bound after a thread flock is created. + */ + @Test(dataProvider = "factories") + public void testStructureViolation5(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + try (var flock = ThreadFlock.open(null)) { + ScopedValue.where(name, "duke", () -> { + Thread thread = factory.newThread(() -> { }); + expectThrows(StructureViolationException.class, () -> flock.start(thread)); + }); + } + } + + /** + * Test start when a scoped value is re-bound after a thread flock is created. + */ + @Test(dataProvider = "factories") + public void testStructureViolation6(ThreadFactory factory) throws Exception { + ScopedValue name = ScopedValue.newInstance(); + ScopedValue.where(name, "duke", () -> { + try (var flock = ThreadFlock.open(null)) { + ScopedValue.where(name, "duchess", () -> { + Thread thread = factory.newThread(() -> { }); + expectThrows(StructureViolationException.class, () -> flock.start(thread)); + }); + } + }); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java new file mode 100644 index 00000000000..ab08dc8919c --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValues.java @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2022, 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. + */ + + +package org.openjdk.bench.jdk.incubator.concurrent; + +import jdk.incubator.concurrent.ScopedValue; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.*; +import org.openjdk.jmh.infra.Blackhole; + +import static org.openjdk.bench.jdk.incubator.concurrent.ScopedValuesData.*; + +/** + * Tests ScopedValue + */ +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Warmup(iterations=4, time=1) +@Measurement(iterations=10, time=1) +@Threads(1) +@Fork(value = 1, + jvmArgsPrepend = {"-Djmh.executor.class=org.openjdk.bench.jdk.incubator.concurrent.ScopedValuesExecutorService", + "-Djmh.executor=CUSTOM", + "-Djmh.blackhole.mode=COMPILER", + "--add-modules=jdk.incubator.concurrent", + "--enable-preview"}) +@State(Scope.Thread) +@SuppressWarnings("preview") +public class ScopedValues { + + private static final Integer THE_ANSWER = 42; + + // Test 1: make sure ScopedValue.get() is hoisted out of loops. + + @Benchmark + public void thousandAdds_ScopedValue(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.sl1.get(); + } + bh.consume(result); + } + + @Benchmark + public void thousandAdds_ThreadLocal(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.tl1.get(); + } + bh.consume(result); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int thousandIsBoundQueries(Blackhole bh) throws Exception { + var result = 0; + for (int i = 0; i < 1_000; i++) { + result += ScopedValuesData.sl1.isBound() ? 1 : 0; + } + return result; + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int thousandMaybeGets(Blackhole bh) throws Exception { + int result = 0; + for (int i = 0; i < 1_000; i++) { + if (ScopedValuesData.sl1.isBound()) { + result += ScopedValuesData.sl1.get(); + } + } + return result; + } + + // Test 2: stress the ScopedValue cache. + // The idea here is to use a bunch of bound values cyclically, which + // stresses the ScopedValue cache. + + int combine(int n, int i1, int i2, int i3, int i4, int i5, int i6) { + return n + ((i1 ^ i2 >>> 6) + (i3 << 7) + i4 - i5 | i6); + } + + @Benchmark + public int sixValues_ScopedValue() throws Exception { + int result = 0; + for (int i = 0 ; i < 166; i++) { + result = combine(result, sl1.get(), sl2.get(), sl3.get(), sl4.get(), sl5.get(), sl6.get()); + } + return result; + } + + @Benchmark + public int sixValues_ThreadLocal() throws Exception { + int result = 0; + for (int i = 0 ; i < 166; i++) { + result = combine(result, tl1.get(), tl2.get(), tl3.get(), tl4.get(), tl5.get(), tl6.get()); + } + return result; + } + + // Test 3: The cost of bind, then get + // This is the worst case for ScopedValues because we have to create + // a binding, link it in, then search the current bindings. In addition, we + // create a cache entry for the bound value, then we immediately have to + // destroy it. + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int CreateBindThenGetThenRemove_ScopedValue() throws Exception { + return ScopedValue.where(sl1, THE_ANSWER).call(sl1::get); + } + + + // Create a Carrier ahead of time: might be slightly faster + private static final ScopedValue.Carrier HOLD_42 = ScopedValue.where(sl1, 42); + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetThenRemove_ScopedValue() throws Exception { + return HOLD_42.call(sl1::get); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetThenRemove_ThreadLocal() throws Exception { + try { + tl1.set(THE_ANSWER); + return tl1.get(); + } finally { + tl1.remove(); + } + } + + // This has no exact equivalent in ScopedValue, but it's provided here for + // information. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public int bindThenGetNoRemove_ThreadLocal() throws Exception { + tl1.set(THE_ANSWER); + return tl1.get(); + } + + // Test 4: The cost of binding, but not using any result + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Object bind_ScopedValue() throws Exception { + return HOLD_42.call(this::getClass); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public Object bind_ThreadLocal() throws Exception { + try { + tl1.set(THE_ANSWER); + return this.getClass(); + } finally { + tl1.remove(); + } + } + + // Simply set a ThreadLocal so that the caller can see it + // This has no exact equivalent in ScopedValue, but it's provided here for + // information. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void setNoRemove_ThreadLocal() throws Exception { + tl1.set(THE_ANSWER); + } + + // This is the closest I can think of to setNoRemove_ThreadLocal in that it + // returns a value in a ScopedValue container. The container must already + // be bound to an AtomicReference for this to work. + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void setNoRemove_ScopedValue() throws Exception { + sl_atomicRef.get().setPlain(THE_ANSWER); + } + + // Test 5: A simple counter + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void counter_ScopedValue() { + sl_atomicInt.get().setPlain( + sl_atomicInt.get().getPlain() + 1); + } + + @Benchmark + @OutputTimeUnit(TimeUnit.NANOSECONDS) + public void counter_ThreadLocal() { + // Very slow: + // tl1.set(tl1.get() + 1); + var ctr = tl_atomicInt.get(); + ctr.setPlain(ctr.getPlain() + 1); + } +} diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java new file mode 100644 index 00000000000..29e007d3483 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesData.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2021, 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. + */ + +package org.openjdk.bench.jdk.incubator.concurrent; + +import jdk.incubator.concurrent.ScopedValue; +import java.util.concurrent.atomic.AtomicInteger; +import java.util.concurrent.atomic.AtomicReference; + +@SuppressWarnings("preview") +public class ScopedValuesData { + + static final ScopedValue sl1 = ScopedValue.newInstance(); + static final ThreadLocal tl1 = new ThreadLocal<>(); + + static final ScopedValue sl2 = ScopedValue.newInstance(); + static final ScopedValue sl3 = ScopedValue.newInstance(); + static final ScopedValue sl4 = ScopedValue.newInstance(); + static final ScopedValue sl5 = ScopedValue.newInstance(); + static final ScopedValue sl6 = ScopedValue.newInstance(); + static final ScopedValue sl_atomicInt = ScopedValue.newInstance(); + + static final ScopedValue unbound = ScopedValue.newInstance(); + + static final ScopedValue> sl_atomicRef = ScopedValue.newInstance(); + + static final ThreadLocal tl2 = new ThreadLocal<>(); + static final ThreadLocal tl3 = new ThreadLocal<>(); + static final ThreadLocal tl4 = new ThreadLocal<>(); + static final ThreadLocal tl5 = new ThreadLocal<>(); + static final ThreadLocal tl6 = new ThreadLocal<>(); + static final ThreadLocal tl_atomicInt = new ThreadLocal<>(); + + static final ScopedValue.Carrier VALUES = ScopedValue + .where(sl1, 42).where(sl2, 2).where(sl3, 3) + .where(sl4, 4).where(sl5, 5).where(sl6, 6); + + public static void run(Runnable action) { + try { + tl1.set(42); tl2.set(2); tl3.set(3); tl4.set(4); tl5.set(5); tl6.set(6); + tl1.get(); // Create the ScopedValue cache as a side effect + tl_atomicInt.set(new AtomicInteger()); + VALUES.where(sl_atomicInt, new AtomicInteger()) + .where(sl_atomicRef, new AtomicReference<>()) + .run(action); + } finally { + tl1.remove(); tl2.remove(); tl3.remove(); tl4.remove(); tl5.remove(); tl6.remove(); + tl_atomicInt.remove(); + } + } +} + diff --git a/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java new file mode 100644 index 00000000000..5238dbcc665 --- /dev/null +++ b/test/micro/org/openjdk/bench/jdk/incubator/concurrent/ScopedValuesExecutorService.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 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.jdk.incubator.concurrent; + +import java.util.concurrent.*; + +public class ScopedValuesExecutorService extends ThreadPoolExecutor { + public ScopedValuesExecutorService(int corePoolSize, String prefix) { + super(1, 1, 0, TimeUnit.MILLISECONDS, new LinkedBlockingQueue(), + new AThreadFactory(), new ThreadPoolExecutor.AbortPolicy()); + } +} + +class AThreadFactory implements ThreadFactory { + public Thread newThread(Runnable action) { + return new Thread() { + public void run() { + ScopedValuesData.run(action); + } + }; + } +} From 80cbfab928eaace71c16a7a1d430980a730383ba Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 7 Dec 2022 10:35:43 +0000 Subject: [PATCH 093/494] 8298169: Remove unused methods in space.hpp Reviewed-by: stefank --- src/hotspot/share/gc/shared/space.hpp | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 88706fc2be0..211dc51125c 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -132,7 +132,6 @@ class Space: public CHeapObj { // Testers bool is_empty() const { return used() == 0; } - bool not_empty() const { return used() > 0; } // Returns true iff the given the space contains the // given address as part of an allocated object. For @@ -285,15 +284,6 @@ class DirtyCardToOopClosure: public MemRegionClosureRO { } void do_MemRegion(MemRegion mr) override; - - void set_min_done(HeapWord* min_done) { - _min_done = min_done; - } -#ifndef PRODUCT - void set_last_bottom(HeapWord* last_bottom) { - _last_bottom = last_bottom; - } -#endif }; // A structure to represent a point at which objects are being copied @@ -396,13 +386,6 @@ class CompactibleSpace: public Space { // space. virtual HeapWord* forward(oop q, size_t size, CompactPoint* cp, HeapWord* compact_top); - - // Return a size with adjustments as required of the space. - virtual size_t adjust_object_size_v(size_t size) const { return size; } - - void set_first_dead(HeapWord* value) { _first_dead = value; } - void set_end_of_live(HeapWord* value) { _end_of_live = value; } - protected: // Used during compaction. HeapWord* _first_dead; From 4da8411674b7515310000bd8243860bc73f9a03d Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 7 Dec 2022 10:46:53 +0000 Subject: [PATCH 094/494] 8298108: Add a regression test for JDK-8297684 Reviewed-by: mullan --- .../spi-calendar-provider/TestSPISigned.java | 124 ++++++++++++++++++ .../baz/CalendarDataProviderImpl.java | 50 +++++++ .../java.util.spi.CalendarDataProvider | 7 + 3 files changed, 181 insertions(+) create mode 100644 test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java create mode 100644 test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java create mode 100644 test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java new file mode 100644 index 00000000000..e7cf5146252 --- /dev/null +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. + * 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 jdk.test.lib.util.JarUtils; +import jdk.test.lib.SecurityTools; +import jdk.test.lib.Asserts; +import jdk.test.lib.process.ProcessTools; +import jdk.test.lib.process.OutputAnalyzer; +import java.util.Calendar; +import java.util.Locale; +import java.util.List; +import java.util.ArrayList; +import java.nio.file.Paths; +import java.nio.file.Path; +import java.nio.file.Files; +import static java.util.Calendar.WEDNESDAY; + +/* + * @test + * @bug 8297684 8269039 + * @summary Checking custom CalendarDataProvider with SPI contained in signed jar does + * not produce NPE. + * @modules java.base/sun.security.pkcs + * java.base/sun.security.timestamp + * java.base/sun.security.x509 + * java.base/sun.security.util + * java.base/sun.security.tools.keytool + * jdk.jartool/jdk.security.jarsigner + * @library /test/lib + * @library provider + * @build baz.CalendarDataProviderImpl + * @run main/timeout=600 TestSPISigned + */ +public class TestSPISigned { + + private static final String TEST_CLASSES = System.getProperty("test.classes", "."); + private static final String TEST_SRC = System.getProperty("test.src", "."); + + private static final Path META_INF_DIR = Paths.get(TEST_SRC, "provider", "meta"); + private static final Path PROVIDER_PARENT = Paths.get(TEST_CLASSES, ".."); + private static final Path PROVIDER_DIR = PROVIDER_PARENT.resolve("provider"); + private static final Path MODS_DIR = Paths.get("mods"); + private static final Path UNSIGNED_JAR = MODS_DIR.resolve("unsigned-with-locale.jar"); + private static final Path SIGNED_JAR = MODS_DIR.resolve("signed-with-locale.jar"); + + public static void main(String[] args) throws Throwable { + if (args.length == 1) { + String arg = args[0]; + if ("run-test".equals(arg)) { + System.out.println("Debug: Running test"); + String provProp = System.getProperty("java.locale.providers"); + if (!"SPI".equals(provProp)) { + throw new RuntimeException("Test failed! Expected -Djava.locale.providers=SPI to be set for test run"); + } + doRunTest(); + } else { + throw new RuntimeException("Test failed! Expected 'run-test' arg for test run"); + } + } else { + // Set up signed jar with custom calendar data provider + // + // 1. Create jar with custom CalendarDataProvider + JarUtils.createJarFile(UNSIGNED_JAR, PROVIDER_DIR); + JarUtils.updateJarFile(UNSIGNED_JAR, META_INF_DIR); + // create signer's keypair + SecurityTools.keytool("-genkeypair -keyalg RSA -keystore ks " + + "-storepass changeit -dname CN=test -alias test") + .shouldHaveExitValue(0); + // sign jar + SecurityTools.jarsigner("-keystore ks -storepass changeit " + + "-signedjar " + SIGNED_JAR + " " + UNSIGNED_JAR + " test") + .shouldHaveExitValue(0); + // run test, which must not throw a NPE + List testRun = new ArrayList<>(); + testRun.add("-Djava.locale.providers=SPI"); + testRun.add("-cp"); + String classPath = System.getProperty("java.class.path"); + classPath = classPath + ":" + SIGNED_JAR.toAbsolutePath().toString(); + testRun.add(classPath); + testRun.add(TestSPISigned.class.getSimpleName()); + testRun.add("run-test"); + OutputAnalyzer out = ProcessTools.executeTestJvm(testRun); + out.shouldHaveExitValue(0); + out.shouldContain("DEBUG: Getting xx language"); + } + } + + private static void doRunTest() { + Locale locale = new Locale("xx", "YY"); + Calendar kcal = Calendar.getInstance(locale); + try { + check(WEDNESDAY, kcal.getFirstDayOfWeek()); + check(7, kcal.getMinimalDaysInFirstWeek()); + } catch (Throwable ex) { + throw new RuntimeException("Test failed with signed jar and " + + " argument java.locale.providers=SPI", ex); + } + } + + private static void check(T expected, T actual) { + Asserts.assertEquals(expected, actual, "Expected calendar from SPI to be in effect"); + } + +} diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java new file mode 100644 index 00000000000..958aa128e93 --- /dev/null +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/baz/CalendarDataProviderImpl.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, Red Hat, Inc. + * 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 baz; + +import static java.util.Calendar.*; +import java.util.Locale; +import java.util.spi.CalendarDataProvider; + +public class CalendarDataProviderImpl extends CalendarDataProvider { + private static final Locale[] locales = { new Locale("xx", "YY") }; + + @Override + public int getFirstDayOfWeek(Locale locale) { + return WEDNESDAY; + } + + @Override + public int getMinimalDaysInFirstWeek(Locale locale) { + if (locale.getLanguage().equals("xx")) { + System.out.println("DEBUG: Getting xx language"); + } + return 7; + } + + @Override + public Locale[] getAvailableLocales() { + return locales; + } +} diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider new file mode 100644 index 00000000000..1563e3b3086 --- /dev/null +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/provider/meta/META-INF/services/java.util.spi.CalendarDataProvider @@ -0,0 +1,7 @@ +# +# +# +# fully-qualified name of the java.util.spi.CalendarDataProvider +# implementation class +# +baz.CalendarDataProviderImpl From 3e041eb9093275bc658c02ae74cd39b4a74684ee Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Wed, 7 Dec 2022 11:12:51 +0000 Subject: [PATCH 095/494] 8298248: Limit sscanf output width in cgroup file parsers Reviewed-by: dholmes, sgehwolf --- src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp index eebff376711..d200704e978 100644 --- a/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp +++ b/src/hotspot/os/linux/cgroupV2Subsystem_linux.cpp @@ -97,7 +97,7 @@ char * CgroupV2Subsystem::cpu_cpuset_cpus() { char* CgroupV2Subsystem::cpu_quota_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/cpu.max", - "Raw value for CPU quota is: %s", "%s %*d", quota, 1024); + "Raw value for CPU quota is: %s", "%1023s %*d", quota, 1024); return os::strdup(quota); } @@ -141,7 +141,7 @@ jlong CgroupV2Subsystem::memory_max_usage_in_bytes() { char* CgroupV2Subsystem::mem_soft_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.low", - "Memory Soft Limit is: %s", "%s", mem_soft_limit_str, 1024); + "Memory Soft Limit is: %s", "%1023s", mem_soft_limit_str, 1024); return os::strdup(mem_soft_limit_str); } @@ -163,14 +163,14 @@ jlong CgroupV2Subsystem::memory_and_swap_limit_in_bytes() { char* CgroupV2Subsystem::mem_swp_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.max", - "Memory and Swap Limit is: %s", "%s", mem_swp_limit_str, 1024); + "Memory and Swap Limit is: %s", "%1023s", mem_swp_limit_str, 1024); return os::strdup(mem_swp_limit_str); } // memory.swap.current : total amount of swap currently used by the cgroup and its descendants char* CgroupV2Subsystem::mem_swp_current_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.swap.current", - "Swap currently used is: %s", "%s", mem_swp_current_str, 1024); + "Swap currently used is: %s", "%1023s", mem_swp_current_str, 1024); return os::strdup(mem_swp_current_str); } @@ -197,7 +197,7 @@ jlong CgroupV2Subsystem::read_memory_limit_in_bytes() { char* CgroupV2Subsystem::mem_limit_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/memory.max", - "Raw value for memory limit is: %s", "%s", mem_limit_str, 1024); + "Raw value for memory limit is: %s", "%1023s", mem_limit_str, 1024); return os::strdup(mem_limit_str); } @@ -223,7 +223,7 @@ char* CgroupV2Controller::construct_path(char* mount_path, char *cgroup_path) { char* CgroupV2Subsystem::pids_max_val() { GET_CONTAINER_INFO_CPTR(cptr, _unified, "/pids.max", - "Maximum number of tasks is: %s", "%s %*d", pidsmax, 1024); + "Maximum number of tasks is: %s", "%1023s %*d", pidsmax, 1024); return os::strdup(pidsmax); } From bfcc238ed09cb432e4a003b89a803c3c10e8ac80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Wed, 7 Dec 2022 11:25:37 +0000 Subject: [PATCH 096/494] 8297964: Jetty.java fails "assert(_no_handle_mark_nesting == 0) failed: allocating handle inside NoHandleMark" Reviewed-by: egahlin --- src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp index fd306fe2525..dd3b834727a 100644 --- a/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp +++ b/src/hotspot/share/jfr/recorder/stacktrace/jfrStackTrace.cpp @@ -274,7 +274,10 @@ bool JfrStackTrace::record(JavaThread* jt, const frame& frame, int skip) { assert(jt != NULL, "invariant"); assert(jt == Thread::current(), "invariant"); assert(!_lineno, "invariant"); - HandleMark hm(jt); // RegisterMap uses Handles to support continuations. + // Must use ResetNoHandleMark here to bypass if any NoHandleMark exist on stack. + // This is because RegisterMap uses Handles to support continuations. + ResetNoHandleMark rnhm; + HandleMark hm(jt); JfrVframeStream vfs(jt, frame, false, false); u4 count = 0; _reached_root = true; From 58170f657c2ccc7afd1e9056d7630a3b564207ef Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Wed, 7 Dec 2022 11:57:42 +0000 Subject: [PATCH 097/494] 8298035: Provide better descriptions for JIT compiler JFR events Reviewed-by: clanger, stuefe --- src/hotspot/share/jfr/metadata/metadata.xml | 28 +++++++++++++++------ 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 8ae6f289481..9e81561b196 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -566,12 +566,16 @@ - + - + @@ -582,13 +586,17 @@ - + - + @@ -599,7 +607,9 @@ - + @@ -608,7 +618,9 @@ - + @@ -621,7 +633,9 @@ - + From cf63f2e3ea93cf339d08e2865034e128d683e515 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 7 Dec 2022 12:03:50 +0000 Subject: [PATCH 098/494] 8298184: Incorrect record component type in record patterns Reviewed-by: vromero --- .../share/classes/com/sun/tools/javac/comp/Attr.java | 6 ++++-- .../patterns/GenericRecordDeconstructionPattern.java | 10 ++++++++++ 2 files changed, 14 insertions(+), 2 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 02f2c7e500a..513122317f1 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 @@ -4204,13 +4204,15 @@ public void visitRecordPattern(JCRecordPattern tree) { } } tree.type = tree.deconstructor.type = type; - Type site = types.removeWildcards(tree.type); + Type site = types.capture(tree.type); List expectedRecordTypes; if (site.tsym.kind == Kind.TYP && ((ClassSymbol) site.tsym).isRecord()) { ClassSymbol record = (ClassSymbol) site.tsym; expectedRecordTypes = record.getRecordComponents() .stream() - .map(rc -> types.memberType(site, rc)).collect(List.collector()); + .map(rc -> types.memberType(site, rc)) + .map(t -> types.upward(t, types.captures(t)).baseType()) + .collect(List.collector()); tree.record = record; } else { log.error(tree.pos(), Errors.DeconstructionPatternOnlyRecords(site.tsym)); diff --git a/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java b/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java index 9b9a7dcccba..fa59657970e 100644 --- a/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java +++ b/test/langtools/tools/javac/patterns/GenericRecordDeconstructionPattern.java @@ -23,7 +23,10 @@ /** * @test + * @bug 8298184 * @enablePreview + * @compile GenericRecordDeconstructionPattern.java + * @run main GenericRecordDeconstructionPattern */ import java.util.List; import java.util.Objects; @@ -46,6 +49,8 @@ void run() { testInference3(); assertEquals(0, forEachInference(List.of(new Box("")))); assertEquals(1, forEachInference(List.of(new Box(null)))); + assertEquals(1, runIfSuperBound(new Box<>(new StringBuilder()))); + assertEquals(1, runIfSuperBound(new Box<>(0))); } void runTest(Function, Integer> test) { @@ -120,6 +125,11 @@ int runSwitchInferenceNested(I> b) { } } + int runIfSuperBound(I b) { + if (b instanceof Box(var v)) return 1; + return -1; + } + sealed interface I {} record Box(V v) implements I { } From 86270e3068d3b2e80710227ae2dc79719df35788 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 7 Dec 2022 14:16:50 +0000 Subject: [PATCH 099/494] 8269820: C2 PhaseIdealLoop::do_unroll get wrong opaque node Reviewed-by: kvn, thartmann, chagedorn --- src/hotspot/share/opto/cfgnode.cpp | 2 +- src/hotspot/share/opto/classes.hpp | 1 + src/hotspot/share/opto/loopTransform.cpp | 6 +- src/hotspot/share/opto/loopnode.cpp | 4 +- src/hotspot/share/opto/opaquenode.hpp | 7 +++ src/hotspot/share/opto/split_if.cpp | 19 ++++++ src/hotspot/share/opto/subnode.cpp | 2 +- .../TestCanonicalLoopEntryOpaqueOrder.java | 59 +++++++++++++++++++ 8 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCanonicalLoopEntryOpaqueOrder.java diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index fdee440cf47..8afc4d5d844 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -619,7 +619,7 @@ Node *RegionNode::Ideal(PhaseGVN *phase, bool can_reshape) { if (opaq != NULL) { // This is not a loop anymore. No need to keep the Opaque1 node on the test that guards the loop as it won't be // subject to further loop opts. - assert(opaq->Opcode() == Op_Opaque1, ""); + assert(opaq->Opcode() == Op_OpaqueZeroTripGuard, ""); igvn->replace_node(opaq, opaq->in(1)); } } diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index ba50d559d99..45b7f8f2f85 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -268,6 +268,7 @@ macro(OnSpinWait) macro(Opaque1) macro(OpaqueLoopInit) macro(OpaqueLoopStride) +macro(OpaqueZeroTripGuard) macro(Opaque3) macro(Opaque4) macro(ProfileBoolean) diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index e636440d8cb..ddcb8dbd15e 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -1300,7 +1300,7 @@ void PhaseIdealLoop::ensure_zero_trip_guard_proj(Node* node, bool is_main_loop) assert(zer_cmp != NULL && zer_cmp->Opcode() == Op_CmpI, "must be CmpI"); // For the main loop, the opaque node is the second input to zer_cmp, for the post loop it's the first input node Node* zer_opaq = zer_cmp->in(is_main_loop ? 2 : 1); - assert(zer_opaq != NULL && zer_opaq->Opcode() == Op_Opaque1, "must be Opaque1"); + assert(zer_opaq != NULL && zer_opaq->Opcode() == Op_OpaqueZeroTripGuard, "must be OpaqueZeroTripGuard"); } #endif @@ -1705,7 +1705,7 @@ void PhaseIdealLoop::insert_pre_post_loops(IdealLoopTree *loop, Node_List &old_n // pre-loop, the main-loop may not execute at all. Later in life this // zero-trip guard will become the minimum-trip guard when we unroll // the main-loop. - Node *min_opaq = new Opaque1Node(C, limit); + Node *min_opaq = new OpaqueZeroTripGuardNode(C, limit); Node *min_cmp = new CmpINode(pre_incr, min_opaq); Node *min_bol = new BoolNode(min_cmp, b_test); register_new_node(min_opaq, new_pre_exit); @@ -1994,7 +1994,7 @@ Node *PhaseIdealLoop::insert_post_loop(IdealLoopTree* loop, Node_List& old_new, // (the previous loop trip-counter exit value) because we will be changing // the exit value (via additional unrolling) so we cannot constant-fold away the zero // trip guard until all unrolling is done. - Node *zer_opaq = new Opaque1Node(C, incr); + Node *zer_opaq = new OpaqueZeroTripGuardNode(C, incr); Node *zer_cmp = new CmpINode(zer_opaq, limit); Node *zer_bol = new BoolNode(zer_cmp, main_end->test_trip()); register_new_node(zer_opaq, new_main_exit); diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index a05798dcd0c..2c244496727 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -5480,12 +5480,12 @@ Node* CountedLoopNode::is_canonical_loop_entry() { if (input >= cmpzm->req() || cmpzm->in(input) == NULL) { return NULL; } - bool res = cmpzm->in(input)->Opcode() == Op_Opaque1; + bool res = cmpzm->in(input)->Opcode() == Op_OpaqueZeroTripGuard; #ifdef ASSERT bool found_opaque = false; for (uint i = 1; i < cmpzm->req(); i++) { Node* opnd = cmpzm->in(i); - if (opnd && opnd->Opcode() == Op_Opaque1) { + if (opnd && opnd->is_Opaque1()) { found_opaque = true; break; } diff --git a/src/hotspot/share/opto/opaquenode.hpp b/src/hotspot/share/opto/opaquenode.hpp index 11a79f8a478..2fb57d51187 100644 --- a/src/hotspot/share/opto/opaquenode.hpp +++ b/src/hotspot/share/opto/opaquenode.hpp @@ -70,6 +70,13 @@ class OpaqueLoopStrideNode : public Opaque1Node { virtual int Opcode() const; }; +class OpaqueZeroTripGuardNode : public Opaque1Node { +public: + OpaqueZeroTripGuardNode(Compile* C, Node *n) : Opaque1Node(C, n) { + } + virtual int Opcode() const; +}; + //------------------------------Opaque3Node------------------------------------ // A node to prevent unwanted optimizations. Will be optimized only during // macro nodes expansion. diff --git a/src/hotspot/share/opto/split_if.cpp b/src/hotspot/share/opto/split_if.cpp index c40240c68a3..6f0a526361d 100644 --- a/src/hotspot/share/opto/split_if.cpp +++ b/src/hotspot/share/opto/split_if.cpp @@ -27,6 +27,7 @@ #include "opto/callnode.hpp" #include "opto/loopnode.hpp" #include "opto/movenode.hpp" +#include "opto/opaquenode.hpp" //------------------------------split_thru_region------------------------------ @@ -220,6 +221,24 @@ bool PhaseIdealLoop::split_up( Node *n, Node *blk1, Node *blk2 ) { } } + if (n->Opcode() == Op_OpaqueZeroTripGuard) { + // If this Opaque1 is part of the zero trip guard for a loop: + // 1- it can't be shared + // 2- the zero trip guard can't be the if that's being split + // As a consequence, this node could be assigned control anywhere between its current control and the zero trip guard. + // Move it down to get it out of the way of split if and avoid breaking the zero trip guard shape. + Node* cmp = n->unique_out(); + assert(cmp->Opcode() == Op_CmpI, "bad zero trip guard shape"); + Node* bol = cmp->unique_out(); + assert(bol->Opcode() == Op_Bool, "bad zero trip guard shape"); + Node* iff = bol->unique_out(); + assert(iff->Opcode() == Op_If, "bad zero trip guard shape"); + set_ctrl(n, iff->in(0)); + set_ctrl(cmp, iff->in(0)); + set_ctrl(bol, iff->in(0)); + return true; + } + // See if splitting-up a Store. Any anti-dep loads must go up as // well. An anti-dep load might be in the wrong block, because in // this particular layout/schedule we ignored anti-deps and allow diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 2d01e1ea32c..0f9f5483b66 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1444,7 +1444,7 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { // Move constants to the right of compare's to canonicalize. // Do not muck with Opaque1 nodes, as this indicates a loop // guard that cannot change shape. - if( con->is_Con() && !cmp2->is_Con() && cmp2_op != Op_Opaque1 && + if (con->is_Con() && !cmp2->is_Con() && cmp2_op != Op_OpaqueZeroTripGuard && // Because of NaN's, CmpD and CmpF are not commutative cop != Op_CmpD && cop != Op_CmpF && // Protect against swapping inputs to a compare when it is used by a diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCanonicalLoopEntryOpaqueOrder.java b/test/hotspot/jtreg/compiler/loopopts/TestCanonicalLoopEntryOpaqueOrder.java new file mode 100644 index 00000000000..60dc2ca548e --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCanonicalLoopEntryOpaqueOrder.java @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2022, 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 8269820 + * @summary C2 PhaseIdealLoop::do_unroll get wrong opaque node + * + * @run main/othervm -Xbatch -XX:-TieredCompilation TestCanonicalLoopEntryOpaqueOrder + * + */ + +public class TestCanonicalLoopEntryOpaqueOrder { + static void test() { + int ina8[] = new int[1478]; + int in2 = 136; + long lo3 = 0L; + try { + for (int i = 0; i < 34; i++) { + Math.log1p(1); + } + } catch (Exception e) { + in2 = 1; + } + + for (int i = 0; i < in2; i++) { + if (in2 > 10) { // split if and create wrong opaque order + for (int j = 0; j < in2; j++) { + lo3 -= 1L; + } + } + } + } + public static void main(String[] args) { + for (int i = 0; i < 10000; i++) { + test(); + } + } +} From 6ed36835ec9b3743430a8c1c71635f12c711f48a Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 7 Dec 2022 15:14:32 +0000 Subject: [PATCH 100/494] 8297209: Serial: Refactor GenCollectedHeap::full_process_roots Reviewed-by: tschatzl, iwalulya --- src/hotspot/share/gc/serial/genMarkSweep.cpp | 28 +++++++++---------- .../share/gc/shared/genCollectedHeap.cpp | 14 ---------- .../share/gc/shared/genCollectedHeap.hpp | 15 ++++------ 3 files changed, 18 insertions(+), 39 deletions(-) diff --git a/src/hotspot/share/gc/serial/genMarkSweep.cpp b/src/hotspot/share/gc/serial/genMarkSweep.cpp index 290c64bf92c..ffd6ddfbf61 100644 --- a/src/hotspot/share/gc/serial/genMarkSweep.cpp +++ b/src/hotspot/share/gc/serial/genMarkSweep.cpp @@ -185,12 +185,13 @@ void GenMarkSweep::mark_sweep_phase1(bool clear_all_softrefs) { { StrongRootsScope srs(0); - gch->full_process_roots(false, // not the adjust phase - GenCollectedHeap::SO_None, - ClassUnloading, // only strong roots if ClassUnloading - // is enabled - &follow_root_closure, - &follow_cld_closure); + CLDClosure* weak_cld_closure = ClassUnloading ? NULL : &follow_cld_closure; + MarkingCodeBlobClosure mark_code_closure(&follow_root_closure, !CodeBlobToOopClosure::FixRelocations, true); + gch->process_roots(GenCollectedHeap::SO_None, + &follow_root_closure, + &follow_cld_closure, + weak_cld_closure, + &mark_code_closure); } // Process reference objects found during marking @@ -262,15 +263,12 @@ void GenMarkSweep::mark_sweep_phase3() { ClassLoaderDataGraph::verify_claimed_marks_cleared(ClassLoaderData::_claim_stw_fullgc_adjust); - { - StrongRootsScope srs(0); - - gch->full_process_roots(true, // this is the adjust phase - GenCollectedHeap::SO_AllCodeCache, - false, // all roots - &adjust_pointer_closure, - &adjust_cld_closure); - } + CodeBlobToOopClosure code_closure(&adjust_pointer_closure, CodeBlobToOopClosure::FixRelocations); + gch->process_roots(GenCollectedHeap::SO_AllCodeCache, + &adjust_pointer_closure, + &adjust_cld_closure, + &adjust_cld_closure, + &code_closure); gch->gen_process_weak_roots(&adjust_pointer_closure); diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.cpp b/src/hotspot/share/gc/shared/genCollectedHeap.cpp index 104ddb6fa28..9ae88825819 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.cpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.cpp @@ -793,20 +793,6 @@ void GenCollectedHeap::process_roots(ScanningOption so, DEBUG_ONLY(ScavengableNMethods::asserted_non_scavengable_nmethods_do(&assert_code_is_non_scavengable)); } -void GenCollectedHeap::full_process_roots(bool is_adjust_phase, - ScanningOption so, - bool only_strong_roots, - OopClosure* root_closure, - CLDClosure* cld_closure) { - // Called from either the marking phase or the adjust phase. - const bool is_marking_phase = !is_adjust_phase; - - MarkingCodeBlobClosure mark_code_closure(root_closure, is_adjust_phase, is_marking_phase); - CLDClosure* weak_cld_closure = only_strong_roots ? NULL : cld_closure; - - process_roots(so, root_closure, cld_closure, weak_cld_closure, &mark_code_closure); -} - void GenCollectedHeap::gen_process_weak_roots(OopClosure* root_closure) { WeakProcessor::oops_do(root_closure); } diff --git a/src/hotspot/share/gc/shared/genCollectedHeap.hpp b/src/hotspot/share/gc/shared/genCollectedHeap.hpp index 860e2e0abd5..c688cfa27d7 100644 --- a/src/hotspot/share/gc/shared/genCollectedHeap.hpp +++ b/src/hotspot/share/gc/shared/genCollectedHeap.hpp @@ -326,22 +326,17 @@ class GenCollectedHeap : public CollectedHeap { }; protected: + virtual void gc_prologue(bool full); + virtual void gc_epilogue(bool full); + + public: + // Apply closures on various roots in Young GC or marking/adjust phases of Full GC. void process_roots(ScanningOption so, OopClosure* strong_roots, CLDClosure* strong_cld_closure, CLDClosure* weak_cld_closure, CodeBlobToOopClosure* code_roots); - virtual void gc_prologue(bool full); - virtual void gc_epilogue(bool full); - - public: - void full_process_roots(bool is_adjust_phase, - ScanningOption so, - bool only_strong_roots, - OopClosure* root_closure, - CLDClosure* cld_closure); - // Apply "root_closure" to all the weak roots of the system. // These include JNI weak roots, string table, // and referents of reachable weak refs. From 3de775094dab3c375a32ddabdd24456d177d3009 Mon Sep 17 00:00:00 2001 From: Claes Redestad Date: Wed, 7 Dec 2022 15:37:58 +0000 Subject: [PATCH 101/494] 8298177: Various java.lang.invoke cleanups 8284363: Redundant imports in BoundMethodHandle Reviewed-by: jvernee --- .../java/lang/invoke/BoundMethodHandle.java | 29 +- .../java/lang/invoke/ClassSpecializer.java | 7 +- .../java/lang/invoke/DirectMethodHandle.java | 2 +- .../lang/invoke/InvokerBytecodeGenerator.java | 2 +- .../classes/java/lang/invoke/LambdaForm.java | 30 +- .../classes/java/lang/invoke/MemberName.java | 279 +++--------------- .../java/lang/invoke/MethodHandleImpl.java | 3 +- .../java/lang/invoke/NativeMethodHandle.java | 2 +- .../sun/invoke/util/BytecodeDescriptor.java | 6 +- .../sun/invoke/util/ValueConversions.java | 71 +---- .../sun/invoke/util/ValueConversionsTest.java | 24 -- 11 files changed, 80 insertions(+), 375 deletions(-) diff --git a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java index 143445e0fd5..e174115850b 100644 --- a/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/BoundMethodHandle.java @@ -26,16 +26,12 @@ package java.lang.invoke; import jdk.internal.vm.annotation.Stable; -import sun.invoke.util.ValueConversions; import java.util.ArrayList; import java.util.List; import static java.lang.invoke.LambdaForm.BasicType; import static java.lang.invoke.LambdaForm.BasicType.*; -import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM; -import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM; -import static java.lang.invoke.LambdaForm.BasicType.V_TYPE_NUM; import static java.lang.invoke.MethodHandles.Lookup.IMPL_LOOKUP; import static java.lang.invoke.MethodHandleNatives.Constants.*; import static java.lang.invoke.MethodHandleStatics.newInternalError; @@ -61,22 +57,6 @@ abstract non-sealed class BoundMethodHandle extends MethodHandle { // BMH API and internals // - static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) { - // for some type signatures, there exist pre-defined concrete BMH classes - try { - return switch (xtype) { - case L_TYPE -> bindSingle(type, form, x); // Use known fast path. - case I_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x)); - case J_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x); - case F_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x); - case D_TYPE -> (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x); - default -> throw newInternalError("unexpected xtype: " + xtype); - }; - } catch (Throwable t) { - throw uncaughtException(t); - } - } - /*non-public*/ LambdaFormEditor editor() { return form.editor(); @@ -356,15 +336,16 @@ protected List deriveTransformHelperArguments(MemberName transform, int w private boolean verifyTHAargs(MemberName transform, int whichtm, List args, List fields) { assert(transform == Specializer.BMH_TRANSFORMS.get(whichtm)); - assert(args.size() == transform.getMethodType().parameterCount()); + MethodType tType = transform.getMethodType(); + assert(args.size() == tType.parameterCount()); assert(fields.size() == this.fieldCount()); final int MH_AND_LF = 2; if (whichtm == Specializer.TN_COPY_NO_EXTEND) { - assert(transform.getMethodType().parameterCount() == MH_AND_LF); + assert(tType.parameterCount() == MH_AND_LF); } else if (whichtm < ARG_TYPE_LIMIT) { - assert(transform.getMethodType().parameterCount() == MH_AND_LF+1); + assert(tType.parameterCount() == MH_AND_LF+1); final BasicType type = basicType((byte) whichtm); - assert(transform.getParameterTypes()[MH_AND_LF] == type.basicTypeClass()); + assert(tType.parameterType(MH_AND_LF) == type.basicTypeClass()); } else { return false; } diff --git a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java index 5248204c893..2e3108ce7bb 100644 --- a/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java +++ b/src/java.base/share/classes/java/lang/invoke/ClassSpecializer.java @@ -328,12 +328,13 @@ protected MethodHandle transformHelper(int whichtm) { private final MethodType transformHelperType(int whichtm) { MemberName tm = transformMethods().get(whichtm); + MethodType tmt = tm.getMethodType(); ArrayList> args = new ArrayList<>(); ArrayList> fields = new ArrayList<>(); - Collections.addAll(args, tm.getParameterTypes()); + Collections.addAll(args, tmt.ptypes()); fields.addAll(fieldTypes()); List> helperArgs = deriveTransformHelperArguments(tm, whichtm, args, fields); - return MethodType.methodType(tm.getReturnType(), helperArgs); + return MethodType.methodType(tmt.returnType(), helperArgs); } // Hooks for subclasses: @@ -432,7 +433,7 @@ protected Class deriveSuperClass() { final Class topc = topClass(); if (!topClassIsSuper) { try { - final Constructor con = reflectConstructor(topc, baseConstructorType().parameterArray()); + final Constructor con = reflectConstructor(topc, baseConstructorType().ptypes()); if (!topc.isInterface() && !Modifier.isPrivate(con.getModifiers())) { topClassIsSuper = true; } diff --git a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java index 374c6319efe..00a187205dc 100644 --- a/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/DirectMethodHandle.java @@ -600,7 +600,7 @@ static Object checkCast(Object mh, Object obj) { } Object checkCast(Object obj) { - return member.getReturnType().cast(obj); + return member.getMethodType().returnType().cast(obj); } // Caching machinery for field accessors: diff --git a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java index 7e298de3060..4bb59d18442 100644 --- a/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java +++ b/src/java.base/share/classes/java/lang/invoke/InvokerBytecodeGenerator.java @@ -1043,7 +1043,7 @@ static boolean isStaticallyInvocable(MemberName member) { private static boolean isStaticallyInvocableType(MethodType mtype) { if (!isStaticallyNameable(mtype.returnType())) return false; - for (Class ptype : mtype.parameterArray()) + for (Class ptype : mtype.ptypes()) if (!isStaticallyNameable(ptype)) return false; return true; diff --git a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java index d295b2d23e1..b8592ced555 100644 --- a/src/java.base/share/classes/java/lang/invoke/LambdaForm.java +++ b/src/java.base/share/classes/java/lang/invoke/LambdaForm.java @@ -364,16 +364,6 @@ private Kind(String defaultLambdaName, String methodName) { this(arity, names, LAST_RESULT, forceInline, /*customized=*/null, kind); } - private static Name[] buildNames(Name[] formals, Name[] temps, Name result) { - int arity = formals.length; - int length = arity + temps.length + (result == null ? 0 : 1); - Name[] names = Arrays.copyOf(formals, length); - System.arraycopy(temps, 0, names, arity, temps.length); - if (result != null) - names[length - 1] = result; - return names; - } - private LambdaForm(MethodType mt) { // Make a blank lambda form, which returns a constant zero or null. // It is used as a template for managing the invocation of similar forms that are non-empty. @@ -1338,13 +1328,15 @@ static final class Name { final Object constraint; // additional type information, if not null @Stable final Object[] arguments; + private static final Object[] EMPTY_ARGS = new Object[0]; + private Name(int index, BasicType type, NamedFunction function, Object[] arguments) { this.index = (short)index; this.type = type; this.function = function; this.arguments = arguments; this.constraint = null; - assert(this.index == index); + assert(this.index == index && typesMatch(function, this.arguments)); } private Name(Name that, Object constraint) { this.index = that.index; @@ -1365,9 +1357,17 @@ private Name(Name that, Object constraint) { Name(MemberName function, Object... arguments) { this(new NamedFunction(function), arguments); } + Name(NamedFunction function) { + this(-1, function.returnType(), function, EMPTY_ARGS); + } + Name(NamedFunction function, Object arg) { + this(-1, function.returnType(), function, new Object[] { arg }); + } + Name(NamedFunction function, Object arg0, Object arg1) { + this(-1, function.returnType(), function, new Object[] { arg0, arg1 }); + } Name(NamedFunction function, Object... arguments) { - this(-1, function.returnType(), function, arguments = Arrays.copyOf(arguments, arguments.length, Object[].class)); - assert(typesMatch(function, arguments)); + this(-1, function.returnType(), function, Arrays.copyOf(arguments, arguments.length, Object[].class)); } /** Create a raw parameter of the given type, with an expected index. */ Name(int index, BasicType type) { @@ -1534,6 +1534,10 @@ public String exprString() { } private boolean typesMatch(NamedFunction function, Object ... arguments) { + if (arguments == null) { + assert(function == null); + return true; + } assert(arguments.length == function.arity()) : "arity mismatch: arguments.length=" + arguments.length + " == function.arity()=" + function.arity() + " in " + debugString(); for (int i = 0; i < arguments.length; i++) { assert (typesMatch(function.parameterType(i), arguments[i])) : "types don't match: function.parameterType(" + i + ")=" + function.parameterType(i) + ", arguments[" + i + "]=" + arguments[i] + " in " + debugString(); diff --git a/src/java.base/share/classes/java/lang/invoke/MemberName.java b/src/java.base/share/classes/java/lang/invoke/MemberName.java index 344d45cc43f..941d726a97a 100644 --- a/src/java.base/share/classes/java/lang/invoke/MemberName.java +++ b/src/java.base/share/classes/java/lang/invoke/MemberName.java @@ -25,7 +25,6 @@ package java.lang.invoke; -import sun.invoke.util.BytecodeDescriptor; import sun.invoke.util.VerifyAccess; import java.lang.reflect.Constructor; @@ -33,10 +32,6 @@ import java.lang.reflect.Member; import java.lang.reflect.Method; import java.lang.reflect.Modifier; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; import java.util.Objects; import static java.lang.invoke.MethodHandleNatives.Constants.*; @@ -74,7 +69,7 @@ final class ResolvedMethodName { //@Injected JVM_Method* vmtarget; //@Injected Class vmholder; -}; +} /*non-public*/ final class MemberName implements Member, Cloneable { @@ -198,16 +193,6 @@ public MethodType getInvocationType() { return itype; } - /** Utility method producing the parameter types of the method type. */ - public Class[] getParameterTypes() { - return getMethodType().parameterArray(); - } - - /** Utility method producing the return type of the method type. */ - public Class getReturnType() { - return getMethodType().returnType(); - } - /** Return the declared type of this member, which * must be a field or type. * If it is a type member, that type itself is returned. @@ -249,22 +234,6 @@ public Object getType() { return (isInvocable() ? getMethodType() : getFieldType()); } - /** Utility method to produce the signature of this member, - * used within the class file format to describe its type. - */ - public String getSignature() { - if (type == null) { - expandFromVM(); - if (type == null) { - return null; - } - } - if (isInvocable()) - return BytecodeDescriptor.unparse(getMethodType()); - else - return BytecodeDescriptor.unparse(getFieldType()); - } - /** Return the modifier flags of this member. * @see java.lang.reflect.Modifier */ @@ -356,20 +325,19 @@ private boolean vminfoIsConsistent() { } private MemberName changeReferenceKind(byte refKind, byte oldKind) { - assert(getReferenceKind() == oldKind); - assert(MethodHandleNatives.refKindIsValid(refKind)); + assert(getReferenceKind() == oldKind && MethodHandleNatives.refKindIsValid(refKind)); flags += (((int)refKind - oldKind) << MN_REFERENCE_KIND_SHIFT); return this; } - private boolean testFlags(int mask, int value) { - return (flags & mask) == value; + private boolean matchingFlagsSet(int mask, int flags) { + return (this.flags & mask) == flags; } - private boolean testAllFlags(int mask) { - return testFlags(mask, mask); + private boolean allFlagsSet(int flags) { + return (this.flags & flags) == flags; } - private boolean testAnyFlags(int mask) { - return !testFlags(mask, 0); + private boolean anyFlagSet(int flags) { + return (this.flags & flags) != 0; } /** Utility method to query if this member is a method handle invocation (invoke or invokeExact). @@ -377,26 +345,21 @@ private boolean testAnyFlags(int mask) { public boolean isMethodHandleInvoke() { final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; final int negs = Modifier.STATIC; - if (testFlags(bits | negs, bits) && - clazz == MethodHandle.class) { + if (matchingFlagsSet(bits | negs, bits) && clazz == MethodHandle.class) { return isMethodHandleInvokeName(name); } return false; } public static boolean isMethodHandleInvokeName(String name) { - switch (name) { - case "invoke": - case "invokeExact": - return true; - default: - return false; - } + return switch (name) { + case "invoke", "invokeExact" -> true; + default -> false; + }; } public boolean isVarHandleMethodInvoke() { final int bits = MH_INVOKE_MODS &~ Modifier.PUBLIC; final int negs = Modifier.STATIC; - if (testFlags(bits | negs, bits) && - clazz == VarHandle.class) { + if (matchingFlagsSet(bits | negs, bits) && clazz == VarHandle.class) { return isVarHandleMethodInvokeName(name); } return false; @@ -457,15 +420,15 @@ public boolean isNative() { static final int ENUM = 0x00004000; /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ public boolean isBridge() { - return testAllFlags(IS_METHOD | BRIDGE); + return allFlagsSet(IS_METHOD | BRIDGE); } /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ public boolean isVarargs() { - return testAllFlags(VARARGS) && isInvocable(); + return allFlagsSet(VARARGS) && isInvocable(); } /** Utility method to query the modifier flags of this member; returns false if the member is not a method. */ public boolean isSynthetic() { - return testAllFlags(SYNTHETIC); + return allFlagsSet(SYNTHETIC); } static final String CONSTRUCTOR_NAME = ""; // the ever-popular @@ -485,49 +448,38 @@ public boolean isSynthetic() { static final int ALL_ACCESS = Modifier.PUBLIC | Modifier.PRIVATE | Modifier.PROTECTED; static final int ALL_KINDS = IS_METHOD | IS_CONSTRUCTOR | IS_FIELD | IS_TYPE; static final int IS_INVOCABLE = IS_METHOD | IS_CONSTRUCTOR; - static final int IS_FIELD_OR_METHOD = IS_METHOD | IS_FIELD; - static final int SEARCH_ALL_SUPERS = MN_SEARCH_SUPERCLASSES | MN_SEARCH_INTERFACES; /** Utility method to query whether this member is a method or constructor. */ public boolean isInvocable() { - return testAnyFlags(IS_INVOCABLE); - } - /** Utility method to query whether this member is a method, constructor, or field. */ - public boolean isFieldOrMethod() { - return testAnyFlags(IS_FIELD_OR_METHOD); + return anyFlagSet(IS_INVOCABLE); } /** Query whether this member is a method. */ public boolean isMethod() { - return testAllFlags(IS_METHOD); + return allFlagsSet(IS_METHOD); } /** Query whether this member is a constructor. */ public boolean isConstructor() { - return testAllFlags(IS_CONSTRUCTOR); + return allFlagsSet(IS_CONSTRUCTOR); } /** Query whether this member is a field. */ public boolean isField() { - return testAllFlags(IS_FIELD); + return allFlagsSet(IS_FIELD); } /** Query whether this member is a type. */ public boolean isType() { - return testAllFlags(IS_TYPE); + return allFlagsSet(IS_TYPE); } /** Utility method to query whether this member is neither public, private, nor protected. */ public boolean isPackage() { - return !testAnyFlags(ALL_ACCESS); + return !anyFlagSet(ALL_ACCESS); } /** Query whether this member has a CallerSensitive annotation. */ public boolean isCallerSensitive() { - return testAllFlags(CALLER_SENSITIVE); + return allFlagsSet(CALLER_SENSITIVE); } /** Query whether this member is a trusted final field. */ - public boolean isTrustedFinalField() { return testAllFlags(TRUSTED_FINAL|IS_FIELD); } - - /** Utility method to query whether this member is accessible from a given lookup class. */ - public boolean isAccessibleFrom(Class lookupClass) { - int mode = (ALL_ACCESS|MethodHandles.Lookup.PACKAGE|MethodHandles.Lookup.MODULE); - return VerifyAccess.isMemberAccessible(this.getDeclaringClass(), this.getDeclaringClass(), flags, - lookupClass, null, mode); + public boolean isTrustedFinalField() { + return allFlagsSet(TRUSTED_FINAL | IS_FIELD); } /** @@ -547,8 +499,7 @@ private void init(Class defClass, String name, Object type, int flags) { this.name = name; this.type = type; this.flags = flags; - assert(testAnyFlags(ALL_KINDS)); - assert(this.resolution == null); // nobody should have touched this yet + assert(anyFlagSet(ALL_KINDS) && this.resolution == null); // nobody should have touched this yet //assert(referenceKindIsConsistent()); // do this after resolution } @@ -568,9 +519,9 @@ private void expandFromVM() { // Capturing information from the Core Reflection API: private static int flagsMods(int flags, int mods, byte refKind) { - assert((flags & RECOGNIZED_MODIFIERS) == 0); - assert((mods & ~RECOGNIZED_MODIFIERS) == 0); - assert((refKind & ~MN_REFERENCE_KIND_MASK) == 0); + assert((flags & RECOGNIZED_MODIFIERS) == 0 + && (mods & ~RECOGNIZED_MODIFIERS) == 0 + && (refKind & ~MN_REFERENCE_KIND_MASK) == 0); return flags | mods | (refKind << MN_REFERENCE_KIND_SHIFT); } /** Create a name for the given reflected method. The resulting name will be in a resolved state. */ @@ -607,7 +558,7 @@ public MemberName(Method m, boolean wantSpecial) { } throw new LinkageError(m.toString()); } - assert(isResolved() && this.clazz != null); + assert(isResolved()); this.name = m.getName(); if (this.type == null) this.type = new Object[] { m.getReturnType(), m.getParameterTypes() }; @@ -649,20 +600,16 @@ public MemberName asConstructor() { * undoes that change under the assumption that it occurred.) */ public MemberName asNormalOriginal() { - byte normalVirtual = clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual; byte refKind = getReferenceKind(); - byte newRefKind = refKind; - MemberName result = this; - switch (refKind) { - case REF_invokeInterface: - case REF_invokeVirtual: - case REF_invokeSpecial: - newRefKind = normalVirtual; - break; - } + byte newRefKind = switch (refKind) { + case REF_invokeInterface, + REF_invokeVirtual, + REF_invokeSpecial -> clazz.isInterface() ? REF_invokeInterface : REF_invokeVirtual; + default -> refKind; + }; if (newRefKind == refKind) return this; - result = clone().changeReferenceKind(newRefKind, refKind); + MemberName result = clone().changeReferenceKind(newRefKind, refKind); assert(this.referenceKindIsConsistentWith(result.getReferenceKind())); return result; } @@ -682,6 +629,10 @@ public MemberName(Constructor ctor) { public MemberName(Field fld) { this(fld, false); } + static { + // the following MemberName constructor relies on these ranges matching up + assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); + } @SuppressWarnings("LeakingThisInConstructor") public MemberName(Field fld, boolean makeSetter) { Objects.requireNonNull(fld); @@ -690,7 +641,6 @@ public MemberName(Field fld, boolean makeSetter) { assert(isResolved() && this.clazz != null); this.name = fld.getName(); this.type = fld.getType(); - assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); byte refKind = this.getReferenceKind(); assert(refKind == (isStatic() ? REF_getStatic : REF_getField)); if (makeSetter) { @@ -703,13 +653,7 @@ public boolean isGetter() { public boolean isSetter() { return MethodHandleNatives.refKindIsSetter(getReferenceKind()); } - public MemberName asSetter() { - byte refKind = getReferenceKind(); - assert(MethodHandleNatives.refKindIsGetter(refKind)); - assert((REF_putStatic - REF_getStatic) == (REF_putField - REF_getField)); - byte setterRefKind = (byte)(refKind + (REF_putField - REF_getField)); - return clone().changeReferenceKind(setterRefKind, refKind); - } + /** Create a name for the given class. The resulting name will be in a resolved state. */ public MemberName(Class type) { init(type.getDeclaringClass(), type.getSimpleName(), type, @@ -844,11 +788,6 @@ public MemberName(byte refKind, Class defClass, String name, Object type) { init(defClass, name, type, flagsMods(kindFlags, 0, refKind)); initResolved(false); } - /** Query whether this member name is resolved to a non-static, non-final method. - */ - public boolean hasReceiverTypeDispatch() { - return MethodHandleNatives.refKindDoesDispatch(getReferenceKind()); - } /** Query whether this member name is resolved. * A resolved member name is one for which the JVM has found @@ -930,7 +869,7 @@ private static String getName(Object obj) { } public IllegalAccessException makeAccessException(String message, Object from) { - message = message + ": "+ toString(); + message = message + ": " + this; if (from != null) { if (from == MethodHandles.publicLookup()) { message += ", from public Lookup"; @@ -965,7 +904,7 @@ else if (isMethod()) return "no such field"; } public ReflectiveOperationException makeAccessException() { - String message = message() + ": "+ toString(); + String message = message() + ": " + this; ReflectiveOperationException ex; if (isResolved() || !(resolution instanceof NoSuchMethodError || resolution instanceof NoSuchFieldError)) @@ -992,70 +931,8 @@ static Factory getFactory() { /*non-public*/ static class Factory { private Factory() { } // singleton pattern - static Factory INSTANCE = new Factory(); - - private static int ALLOWED_FLAGS = ALL_KINDS; + static final Factory INSTANCE = new Factory(); - /// Queries - List getMembers(Class defc, - String matchName, Object matchType, - int matchFlags, Class lookupClass) { - matchFlags &= ALLOWED_FLAGS; - String matchSig = null; - if (matchType != null) { - matchSig = BytecodeDescriptor.unparse(matchType); - if (matchSig.startsWith("(")) - matchFlags &= ~(ALL_KINDS & ~IS_INVOCABLE); - else - matchFlags &= ~(ALL_KINDS & ~IS_FIELD); - } - final int BUF_MAX = 0x2000; - int len1 = matchName == null ? 10 : matchType == null ? 4 : 1; - MemberName[] buf = newMemberBuffer(len1); - int totalCount = 0; - ArrayList bufs = null; - int bufCount = 0; - for (;;) { - bufCount = MethodHandleNatives.getMembers(defc, - matchName, matchSig, matchFlags, - lookupClass, - totalCount, buf); - if (bufCount <= buf.length) { - if (bufCount < 0) bufCount = 0; - totalCount += bufCount; - break; - } - // JVM returned to us with an intentional overflow! - totalCount += buf.length; - int excess = bufCount - buf.length; - if (bufs == null) bufs = new ArrayList<>(1); - bufs.add(buf); - int len2 = buf.length; - len2 = Math.max(len2, excess); - len2 = Math.max(len2, totalCount / 4); - buf = newMemberBuffer(Math.min(BUF_MAX, len2)); - } - ArrayList result = new ArrayList<>(totalCount); - if (bufs != null) { - for (MemberName[] buf0 : bufs) { - Collections.addAll(result, buf0); - } - } - for (int i = 0; i < bufCount; i++) { - result.add(buf[i]); - } - // Signature matching is not the same as type matching, since - // one signature might correspond to several types. - // So if matchType is a Class or MethodType, refilter the results. - if (matchType != null && matchType != matchSig) { - for (Iterator it = result.iterator(); it.hasNext();) { - MemberName m = it.next(); - if (!matchType.equals(m.getType())) - it.remove(); - } - } - return result; - } /** Produce a resolved version of the given member. * Super types are searched (for inherited members) if {@code searchSupers} is true. * Access checking is performed on behalf of the given {@code lookupClass}. @@ -1131,69 +1008,5 @@ public MemberName resolveOrNull(byte refKind, MemberName m, Class lookupClass return result; return null; } - /** Return a list of all methods defined by the given class. - * Super types are searched (for inherited members) if {@code searchSupers} is true. - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getMethods(Class defc, boolean searchSupers, - Class lookupClass) { - return getMethods(defc, searchSupers, null, null, lookupClass); - } - /** Return a list of matching methods defined by the given class. - * Super types are searched (for inherited members) if {@code searchSupers} is true. - * Returned methods will match the name (if not null) and the type (if not null). - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getMethods(Class defc, boolean searchSupers, - String name, MethodType type, Class lookupClass) { - int matchFlags = IS_METHOD | (searchSupers ? SEARCH_ALL_SUPERS : 0); - return getMembers(defc, name, type, matchFlags, lookupClass); - } - /** Return a list of all constructors defined by the given class. - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getConstructors(Class defc, Class lookupClass) { - return getMembers(defc, null, null, IS_CONSTRUCTOR, lookupClass); - } - /** Return a list of all fields defined by the given class. - * Super types are searched (for inherited members) if {@code searchSupers} is true. - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getFields(Class defc, boolean searchSupers, - Class lookupClass) { - return getFields(defc, searchSupers, null, null, lookupClass); - } - /** Return a list of all fields defined by the given class. - * Super types are searched (for inherited members) if {@code searchSupers} is true. - * Returned fields will match the name (if not null) and the type (if not null). - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getFields(Class defc, boolean searchSupers, - String name, Class type, Class lookupClass) { - int matchFlags = IS_FIELD | (searchSupers ? SEARCH_ALL_SUPERS : 0); - return getMembers(defc, name, type, matchFlags, lookupClass); - } - /** Return a list of all nested types defined by the given class. - * Super types are searched (for inherited members) if {@code searchSupers} is true. - * Access checking is performed on behalf of the given {@code lookupClass}. - * Inaccessible members are not added to the last. - */ - public List getNestedTypes(Class defc, boolean searchSupers, - Class lookupClass) { - int matchFlags = IS_TYPE | (searchSupers ? SEARCH_ALL_SUPERS : 0); - return getMembers(defc, null, null, matchFlags, lookupClass); - } - private static MemberName[] newMemberBuffer(int length) { - MemberName[] buf = new MemberName[length]; - // fill the buffer with dummy structs for the JVM to fill in - for (int i = 0; i < length; i++) - buf[i] = new MemberName(); - return buf; - } } } diff --git a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java index de37873ae32..ba579e28f15 100644 --- a/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java +++ b/src/java.base/share/classes/java/lang/invoke/MethodHandleImpl.java @@ -1005,7 +1005,8 @@ static MethodHandle fakeMethodHandleInvoke(MemberName method) { } static MethodHandle fakeVarHandleInvoke(MemberName method) { // TODO caching, is it necessary? - MethodType type = MethodType.methodType(method.getReturnType(), UnsupportedOperationException.class, + MethodType type = MethodType.methodType(method.getMethodType().returnType(), + UnsupportedOperationException.class, VarHandle.class, Object[].class); MethodHandle mh = throwException(type); mh = mh.bindTo(new UnsupportedOperationException("cannot reflectively invoke VarHandle")); diff --git a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java index 996b51487c9..4b7cf8d7ef3 100644 --- a/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java +++ b/src/java.base/share/classes/java/lang/invoke/NativeMethodHandle.java @@ -64,7 +64,7 @@ private static boolean hasIllegalType(MethodType type) { if (isIllegalType(type.returnType())) return true; - for (Class pType : type.parameterArray()) { + for (Class pType : type.ptypes()) { if (isIllegalType(pType)) return true; } diff --git a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java index fa7af9239af..6b5b13ecbb8 100644 --- a/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java +++ b/src/java.base/share/classes/sun/invoke/util/BytecodeDescriptor.java @@ -113,15 +113,11 @@ public static String unparse(Class type) { return type.descriptorString(); } - public static String unparse(MethodType type) { - return unparseMethod(type.returnType(), type.parameterArray()); - } - public static String unparse(Object type) { if (type instanceof Class) return unparse((Class) type); if (type instanceof MethodType) - return unparse((MethodType) type); + return ((MethodType) type).toMethodDescriptorString(); return (String) type; } diff --git a/src/java.base/share/classes/sun/invoke/util/ValueConversions.java b/src/java.base/share/classes/sun/invoke/util/ValueConversions.java index cf290c4477c..9bb18e2770a 100644 --- a/src/java.base/share/classes/sun/invoke/util/ValueConversions.java +++ b/src/java.base/share/classes/sun/invoke/util/ValueConversions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2008, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2008, 2022, 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 @@ -342,73 +342,13 @@ static void ignore(Object x) { // no value to return; this is an unbox of null } - static void empty() { - } - - static Object zeroObject() { - return null; - } - - static int zeroInteger() { - return 0; - } - - static long zeroLong() { - return 0; - } - - static float zeroFloat() { - return 0; - } - - static double zeroDouble() { - return 0; - } - - private static final WrapperCache[] CONSTANT_FUNCTIONS = newWrapperCaches(2); - - public static MethodHandle zeroConstantFunction(Wrapper wrap) { - WrapperCache cache = CONSTANT_FUNCTIONS[0]; - MethodHandle mh = cache.get(wrap); - if (mh != null) { - return mh; - } - // slow path - MethodType type = MethodType.methodType(wrap.primitiveType()); - switch (wrap) { - case VOID: - mh = Handles.EMPTY; - break; - case OBJECT: - case INT: case LONG: case FLOAT: case DOUBLE: - try { - mh = IMPL_LOOKUP.findStatic(THIS_CLASS, "zero"+wrap.wrapperSimpleName(), type); - } catch (ReflectiveOperationException ex) { - mh = null; - } - break; - } - if (mh != null) { - return cache.put(wrap, mh); - } - - // use zeroInt and cast the result - if (wrap.isSubwordOrInt() && wrap != Wrapper.INT) { - mh = MethodHandles.explicitCastArguments(zeroConstantFunction(Wrapper.INT), type); - return cache.put(wrap, mh); - } - throw new IllegalArgumentException("cannot find zero constant for " + wrap); - } - private static class Handles { - static final MethodHandle CAST_REFERENCE, IGNORE, EMPTY; + static final MethodHandle IGNORE; static { try { MethodType idType = MethodType.genericMethodType(1); MethodType ignoreType = idType.changeReturnType(void.class); - CAST_REFERENCE = IMPL_LOOKUP.findVirtual(Class.class, "cast", idType); IGNORE = IMPL_LOOKUP.findStatic(THIS_CLASS, "ignore", ignoreType); - EMPTY = IMPL_LOOKUP.findStatic(THIS_CLASS, "empty", ignoreType.dropParameterTypes(0, 1)); } catch (NoSuchMethodException | IllegalAccessException ex) { throw newInternalError("uncaught exception", ex); } @@ -419,10 +359,6 @@ public static MethodHandle ignore() { return Handles.IGNORE; } - /** Return a method that casts its second argument (an Object) to the given type (a Class). */ - public static MethodHandle cast() { - return Handles.CAST_REFERENCE; - } /// Primitive conversions. // These are supported directly by the JVM, usually by a single instruction. @@ -673,7 +609,4 @@ private static String capitalize(String x) { private static InternalError newInternalError(String message, Throwable cause) { return new InternalError(message, cause); } - private static InternalError newInternalError(Throwable cause) { - return new InternalError(cause); - } } diff --git a/test/jdk/sun/invoke/util/ValueConversionsTest.java b/test/jdk/sun/invoke/util/ValueConversionsTest.java index 9a936cc97ff..23e70f31c96 100644 --- a/test/jdk/sun/invoke/util/ValueConversionsTest.java +++ b/test/jdk/sun/invoke/util/ValueConversionsTest.java @@ -134,30 +134,6 @@ public void testBox() throws Throwable { } } - @Test - public void testCast() throws Throwable { - Class[] types = { Object.class, Serializable.class, String.class, Number.class, Integer.class }; - Object[] objects = { new Object(), Boolean.FALSE, "hello", (Long)12L, (Integer)6 }; - for (Class dst : types) { - MethodHandle caster = ValueConversions.cast().bindTo(dst); - assertEquals(caster.type(), MethodHandles.identity(Object.class).type()); - for (Object obj : objects) { - Class src = obj.getClass(); - boolean canCast = dst.isAssignableFrom(src); - try { - Object result = caster.invokeExact(obj); - if (canCast) - assertEquals(obj, result); - else - assertEquals("cast should not have succeeded", dst, obj); - } catch (ClassCastException ex) { - if (canCast) - throw ex; - } - } - } - } - @Test public void testConvert() throws Throwable { for (long tval = 0, ctr = 0;;) { From 29f1c3c6e39170e0f36949dc209edf183c2eb36b Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Wed, 7 Dec 2022 15:45:35 +0000 Subject: [PATCH 102/494] 8298274: Problem list TestSPISigned on Windows Reviewed-by: mullan, dcubed --- test/jdk/ProblemList.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 71001d0e76a..8edd5818c96 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -618,6 +618,8 @@ sun/security/pkcs11/rsa/TestKeyPairGenerator.java 8295343 linux-al sun/security/pkcs11/rsa/TestKeyFactory.java 8295343 linux-all sun/security/pkcs11/KeyStore/Basic.java 8295343 linux-all +java/security/SignedJar/spi-calendar-provider/TestSPISigned.java 8298271 windows-all + ############################################################################ # jdk_sound From dd7385d1e86afe8af79587e80c5046af5c84b5cd Mon Sep 17 00:00:00 2001 From: Tyler Steele Date: Wed, 7 Dec 2022 16:24:51 +0000 Subject: [PATCH 103/494] 8298202: [AIX] Dead code elimination removed jfr constructor used by AIX Reviewed-by: dholmes, stuefe --- src/hotspot/share/runtime/os_perf.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/hotspot/share/runtime/os_perf.hpp b/src/hotspot/share/runtime/os_perf.hpp index 303f463d7b3..0cbc2700acd 100644 --- a/src/hotspot/share/runtime/os_perf.hpp +++ b/src/hotspot/share/runtime/os_perf.hpp @@ -106,6 +106,14 @@ class SystemProcess : public CHeapObj { _next = NULL; } + SystemProcess(int pid, char* name, char* path, char* command_line, SystemProcess* next) { + _pid = pid; + _name = name; + _path = path; + _command_line = command_line; + _next = next; + } + void set_next(SystemProcess* sys_process) { _next = sys_process; } From 389b8f4b788375821a8bb4b017e50f905abdad2d Mon Sep 17 00:00:00 2001 From: Markus KARG Date: Wed, 7 Dec 2022 16:29:43 +0000 Subject: [PATCH 104/494] 8297298: SequenceInputStream should override transferTo Reviewed-by: bpb --- .../classes/java/io/SequenceInputStream.java | 15 ++ .../io/SequenceInputStream/TransferTo.java | 206 ++++++++++++++++++ 2 files changed, 221 insertions(+) create mode 100644 test/jdk/java/io/SequenceInputStream/TransferTo.java diff --git a/src/java.base/share/classes/java/io/SequenceInputStream.java b/src/java.base/share/classes/java/io/SequenceInputStream.java index 6b47aadc855..466091958f8 100644 --- a/src/java.base/share/classes/java/io/SequenceInputStream.java +++ b/src/java.base/share/classes/java/io/SequenceInputStream.java @@ -235,4 +235,19 @@ public void close() throws IOException { throw ioe; } } + + @Override + public long transferTo(OutputStream out) throws IOException { + Objects.requireNonNull(out, "out"); + if (getClass() == SequenceInputStream.class) { + long c = 0; + while (in != null) { + c += in.transferTo(out); + nextStream(); + } + return c; + } else { + return super.transferTo(out); + } + } } diff --git a/test/jdk/java/io/SequenceInputStream/TransferTo.java b/test/jdk/java/io/SequenceInputStream/TransferTo.java new file mode 100644 index 00000000000..a39d2c1e013 --- /dev/null +++ b/test/jdk/java/io/SequenceInputStream/TransferTo.java @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.SequenceInputStream; +import java.util.Arrays; +import java.util.Random; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; +import java.util.function.Supplier; + +import org.testng.annotations.Test; + +import jdk.test.lib.RandomFactory; + +import static java.lang.String.format; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertThrows; +import static org.testng.Assert.assertTrue; + +/* + * @test + * @library /test/lib + * @build jdk.test.lib.RandomFactory + * @run testng/othervm/timeout=180 TransferTo + * @bug 8297298 + * @summary Tests whether java.io.SequenceInputStream.transferTo conforms to the + * InputStream.transferTo specification + * @key randomness + */ +public class TransferTo { + private static final int MIN_SIZE = 10_000; + private static final int MAX_SIZE_INCR = 100_000_000 - MIN_SIZE; + + private static final int ITERATIONS = 10; + + private static final Random RND = RandomFactory.getRandom(); + + /* + * Testing API compliance: input stream must throw NullPointerException + * when parameter "out" is null. + */ + @Test + public void testNullPointerException() throws Exception { + // factory for incoming data provider + InputStreamProvider inputStreamProvider = byteArrayInput(); + + // tests empty input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input().transferTo(null)); + + // tests single-byte input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input((byte) 1).transferTo(null)); + + // tests dual-byte input stream + assertThrows(NullPointerException.class, + () -> inputStreamProvider.input((byte) 1, (byte) 2).transferTo(null)); + } + + /* + * Testing API compliance: complete content of input stream must be + * transferred to output stream. + */ + @Test + public void testStreamContents() throws Exception { + // factory for incoming data provider + InputStreamProvider inputStreamProvider = byteArrayInput(); + + // factory for outgoing data recorder + OutputStreamProvider outputStreamProvider = byteArrayOutput(); + + // tests empty input stream + checkTransferredContents(inputStreamProvider, + outputStreamProvider, new byte[0]); + + // tests input stream with a length between 1k and 4k + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(1024, 4096)); + + // tests input stream with several data chunks, as 16k is more than a + // single chunk can hold + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(16384, 16384)); + + // tests randomly chosen starting positions within source and + // target stream + for (int i = 0; i < ITERATIONS; i++) { + byte[] inBytes = createRandomBytes(MIN_SIZE, MAX_SIZE_INCR); + int posIn = RND.nextInt(inBytes.length); + int posOut = RND.nextInt(MIN_SIZE); + checkTransferredContents(inputStreamProvider, + outputStreamProvider, inBytes, posIn, posOut); + } + + // tests reading beyond source EOF (must not transfer any bytes) + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(4096, 0), 4096, 0); + + // tests writing beyond target EOF (must extend output stream) + checkTransferredContents(inputStreamProvider, + outputStreamProvider, createRandomBytes(4096, 0), 0, 4096); + } + + /* + * Asserts that the transferred content is correct, i.e., compares the bytes + * actually transferred to those expected. The position of the input and + * output streams before the transfer are zero (BOF). + */ + private static void checkTransferredContents(InputStreamProvider inputStreamProvider, + OutputStreamProvider outputStreamProvider, byte[] inBytes) throws Exception { + checkTransferredContents(inputStreamProvider, + outputStreamProvider, inBytes, 0, 0); + } + + /* + * Asserts that the transferred content is correct, i. e. compares the bytes + * actually transferred to those expected. The positions of the input and + * output streams before the transfer are provided by the caller. + */ + private static void checkTransferredContents(InputStreamProvider inputStreamProvider, + OutputStreamProvider outputStreamProvider, byte[] inBytes, int posIn, + int posOut) throws Exception { + AtomicReference> recorder = new AtomicReference<>(); + try (InputStream in = inputStreamProvider.input(inBytes); + OutputStream out = outputStreamProvider.output(recorder::set)) { + // skip bytes until starting position + in.skipNBytes(posIn); + out.write(new byte[posOut]); + + long reported = in.transferTo(out); + int count = inBytes.length - posIn; + + assertEquals(reported, count, + format("reported %d bytes but should report %d", reported, count)); + + byte[] outBytes = recorder.get().get(); + assertTrue(Arrays.equals(inBytes, posIn, posIn + count, + outBytes, posOut, posOut + count), + format("inBytes.length=%d, outBytes.length=%d", count, outBytes.length)); + } + } + + /* + * Creates an array of random size (between min and min + maxRandomAdditive) + * filled with random bytes + */ + private static byte[] createRandomBytes(int min, int maxRandomAdditive) { + byte[] bytes = new byte[min + + (maxRandomAdditive == 0 ? 0 : RND.nextInt(maxRandomAdditive))]; + RND.nextBytes(bytes); + return bytes; + } + + private interface InputStreamProvider { + InputStream input(byte... bytes) throws Exception; + } + + private interface OutputStreamProvider { + OutputStream output(Consumer> spy) throws Exception; + } + + private static InputStreamProvider byteArrayInput() { + return bytes -> { + InputStream is1 = new ByteArrayInputStream(bytes, 0, bytes.length / 2); + InputStream is2 = new ByteArrayInputStream(bytes, bytes.length / 2, bytes.length); + return new SequenceInputStream(is1, is2); + }; + } + + private static OutputStreamProvider byteArrayOutput() { + return new OutputStreamProvider() { + @Override + public OutputStream output(Consumer> spy) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + spy.accept(outputStream::toByteArray); + return outputStream; + } + }; + } + +} From 39344840c7a5fbd37f6c6a972a89c3600396e878 Mon Sep 17 00:00:00 2001 From: Tyler Steele Date: Wed, 7 Dec 2022 16:54:10 +0000 Subject: [PATCH 105/494] 8298205: Prefer Member Initialization Lists for JFR classes in os_perf.hpp Reviewed-by: dholmes, mgronlun --- src/hotspot/share/runtime/os_perf.hpp | 47 +++++++++++++-------------- 1 file changed, 22 insertions(+), 25 deletions(-) diff --git a/src/hotspot/share/runtime/os_perf.hpp b/src/hotspot/share/runtime/os_perf.hpp index 0cbc2700acd..8e39b75deb6 100644 --- a/src/hotspot/share/runtime/os_perf.hpp +++ b/src/hotspot/share/runtime/os_perf.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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,13 +40,12 @@ class CPUInformation : public CHeapObj { const char* _name; public: - CPUInformation() { - _no_of_sockets = 0; - _no_of_cores = 0; - _no_of_hw_threads = 0; - _description = NULL; - _name = NULL; - } + CPUInformation() : + _no_of_sockets(0), + _no_of_cores(0), + _no_of_hw_threads(0), + _description(nullptr), + _name(nullptr) {} int number_of_sockets(void) const { return _no_of_sockets; @@ -98,21 +97,19 @@ class SystemProcess : public CHeapObj { SystemProcess* _next; public: - SystemProcess() { - _pid = 0; - _name = NULL; - _path = NULL; - _command_line = NULL; - _next = NULL; - } - - SystemProcess(int pid, char* name, char* path, char* command_line, SystemProcess* next) { - _pid = pid; - _name = name; - _path = path; - _command_line = command_line; - _next = next; - } + SystemProcess() : + _pid (0), + _name(nullptr), + _path(nullptr), + _command_line(nullptr), + _next(nullptr) {} + + SystemProcess(int pid, char* name, char* path, char* command_line, SystemProcess* next) : + _pid(pid), + _name(name), + _path(path), + _command_line(command_line), + _next(next) {} void set_next(SystemProcess* sys_process) { _next = sys_process; @@ -172,11 +169,11 @@ class NetworkInterface : public ResourceObj { public: NetworkInterface(const char* name, uint64_t bytes_in, uint64_t bytes_out, NetworkInterface* next) : - _name(NULL), + _name(nullptr), _bytes_in(bytes_in), _bytes_out(bytes_out), _next(next) { - assert(name != NULL, "invariant"); + assert(name != nullptr, "invariant"); const size_t length = strlen(name); _name = NEW_RESOURCE_ARRAY(char, length + 1); strncpy(_name, name, length + 1); From 8edb98df3dd393103f2c80e929b011bc6b7993a3 Mon Sep 17 00:00:00 2001 From: Olga Mikhaltsova Date: Wed, 7 Dec 2022 18:02:20 +0000 Subject: [PATCH 106/494] 8165943: LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set. Co-authored-by: Jason Fordham Reviewed-by: prr --- .../classes/sun/font/AttributeValues.java | 17 ++ .../sun/font/ExtendedTextSourceLabel.java | 26 ++- .../classes/sun/font/StandardGlyphVector.java | 11 +- .../LineBreakWithTracking.java | 165 ++++++++++++++++++ .../LineBreakWithTrackingAuto.java | 113 ++++++++++++ 5 files changed, 322 insertions(+), 10 deletions(-) create mode 100644 test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java create mode 100644 test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java diff --git a/src/java.desktop/share/classes/sun/font/AttributeValues.java b/src/java.desktop/share/classes/sun/font/AttributeValues.java index 6b3c0aaf4e2..47acd035e4b 100644 --- a/src/java.desktop/share/classes/sun/font/AttributeValues.java +++ b/src/java.desktop/share/classes/sun/font/AttributeValues.java @@ -846,6 +846,23 @@ public static AffineTransform getCharTransform(Map map) { return null; } + @SuppressWarnings("unchecked") + public static float getTracking(Map map) { + if (map != null) { + AttributeValues av = null; + if (map instanceof AttributeMap && + ((AttributeMap) map).getValues() != null) { + av = ((AttributeMap)map).getValues(); + } else if (map.get(TextAttribute.TRACKING) != null) { + av = AttributeValues.fromMap((Map)map); + } + if (av != null) { + return av.tracking; + } + } + return 0; + } + public void updateDerivedTransforms() { // this also updates the mask for the baseline transform if (transform == null) { diff --git a/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java b/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java index d257855cf84..03022658c54 100644 --- a/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java +++ b/src/java.desktop/share/classes/sun/font/ExtendedTextSourceLabel.java @@ -71,6 +71,8 @@ class ExtendedTextSourceLabel extends ExtendedTextLabel implements Decoration.La StandardGlyphVector gv; float[] charinfo; + float advTracking; + /** * Create from a TextSource. */ @@ -110,6 +112,8 @@ private void finishInit() { source.getStart() + source.getLength(), source.getFRC()); cm = CoreMetrics.get(lm); } + + advTracking = font.getSize() * AttributeValues.getTracking(atts); } @@ -378,10 +382,10 @@ public float getCharAdvance(int index) { validate(index); float[] charinfo = getCharinfo(); int idx = l2v(index) * numvals + advx; - if (charinfo == null || idx >= charinfo.length) { + if (charinfo == null || idx >= charinfo.length || charinfo[idx] == 0) { return 0f; } else { - return charinfo[idx]; + return charinfo[idx] + advTracking; } } @@ -477,16 +481,25 @@ public int visualToLogical(int visualIndex) { } public int getLineBreakIndex(int start, float width) { + final float epsilon = 0.005f; + float[] charinfo = getCharinfo(); int length = source.getLength(); + + if (advTracking > 0) { + width += advTracking; + } + --start; - while (width >= 0 && ++start < length) { + while (width >= -epsilon && ++start < length) { int cidx = l2v(start) * numvals + advx; if (cidx >= charinfo.length) { break; // layout bailed for some reason } float adv = charinfo[cidx]; - width -= adv; + if (adv != 0) { + width -= adv + advTracking; + } } return start; @@ -502,7 +515,10 @@ public float getAdvanceBetween(int start, int limit) { if (cidx >= charinfo.length) { break; // layout bailed for some reason } - a += charinfo[cidx]; + float adv = charinfo[cidx]; + if (adv != 0) { + a += adv + advTracking; + } } return a; diff --git a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java index 35d13a9688b..e333a9de291 100644 --- a/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java +++ b/src/java.desktop/share/classes/sun/font/StandardGlyphVector.java @@ -197,21 +197,22 @@ public StandardGlyphVector(Font font, FontRenderContext frc, int[] glyphs, float // how do we know its a base glyph // for now, it is if the natural advance of the glyph is non-zero - Font2D f2d = FontUtilities.getFont2D(font); - FontStrike strike = f2d.getStrike(font, frc); float[] deltas = { trackPt.x, trackPt.y }; for (int j = 0; j < deltas.length; ++j) { float inc = deltas[j]; + float prevPos = 0; if (inc != 0) { float delta = 0; - for (int i = j, n = 0; n < glyphs.length; i += 2) { - if (strike.getGlyphAdvance(glyphs[n++]) != 0) { // might be an inadequate test + for (int i = j; i < positions.length; i += 2) { + if (i == j || prevPos != positions[i]) { + prevPos = positions[i]; positions[i] += delta; delta += inc; + } else if (prevPos == positions[i]) { + positions[i] = positions[i - 2]; } } - positions[positions.length-2+j] += delta; } } } diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java new file mode 100644 index 00000000000..532a1b8a106 --- /dev/null +++ b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTracking.java @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2022, 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 8165943 + * @summary LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set + * @library ../../regtesthelpers + * @build PassFailJFrame + * @run main/manual LineBreakWithTracking + */ + +import javax.swing.*; +import java.awt.*; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.text.AttributedString; +import java.util.Hashtable; +import java.lang.reflect.InvocationTargetException; + +class LineBreakPanel extends JPanel implements ActionListener { + + private float textTracking = 0.0f; + private static String fontName = "Dialog"; + private static String text = "This is a long line of text that should be broken across multiple lines. " + + "Please set the different tracking values to test via menu! This test should pass if " + + "these lines are broken to fit the width, and fail otherwise. It should " + + "also format the hebrew (\u05d0\u05d1\u05d2 \u05d3\u05d4\u05d5) and arabic " + + "(\u0627\u0628\u062a\u062c \u062e\u0644\u0627\u062e) and CJK " + + "(\u4e00\u4e01\u4e02\uac00\uac01\uc4fa\u67b1\u67b2\u67b3\u67b4\u67b5\u67b6\u67b7" + + "\u67b8\u67b9) text correctly."; + + private LineBreakMeasurer lineMeasurer; + + public void actionPerformed(ActionEvent e) { + textTracking = (float)((JRadioButtonMenuItem)e.getSource()).getClientProperty( "tracking" ); + lineMeasurer = null; + invalidate(); + repaint(); + } + + public void paintComponent(Graphics g) { + super.paintComponent(g); + setBackground(Color.white); + + Graphics2D g2d = (Graphics2D)g; + + if (lineMeasurer == null) { + Float regular = Float.valueOf(16.0f); + Float big = Float.valueOf(24.0f); + + Hashtable map = new Hashtable(); + map.put(TextAttribute.SIZE, (float)18.0); + map.put(TextAttribute.TRACKING, (float)textTracking); + + AttributedString astr = new AttributedString(text, map); + astr.addAttribute(TextAttribute.SIZE, regular, 0, text.length()); + astr.addAttribute(TextAttribute.FAMILY, fontName, 0, text.length()); + + int ix = text.indexOf("broken"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("hebrew"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("arabic"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 6); + ix = text.indexOf("CJK"); + astr.addAttribute(TextAttribute.SIZE, big, ix, ix + 3); + + FontRenderContext frc = g2d.getFontRenderContext(); + lineMeasurer = new LineBreakMeasurer(astr.getIterator(), frc); + } + + lineMeasurer.setPosition(0); + + float w = (float)getSize().width; + float x = 0, y = 0; + TextLayout layout; + while ((layout = lineMeasurer.nextLayout(w)) != null) { + x = layout.isLeftToRight() ? 0 : w - layout.getAdvance(); + y += layout.getAscent(); + layout.draw(g2d, x, y); + y += layout.getDescent() + layout.getLeading(); + } + } +} + +public class LineBreakWithTracking { + + private static final String INSTRUCTIONS = """ + This manual test verifies that LineBreakMeasurer measures the lines' + breaks correctly taking into account the TextAttribute.TRACKING value. + The test string includes Latin, Arabic, CJK and Hebrew. + + You should choose a tracking value from the menu and resize the window. + If the text lines break exactly to the wrapping width: + no room for one more word exists and + the text lines are not too long for given wrapping width, - + then press PASS, otherwise - FAIL. + """; + + public void createGUI(JFrame frame) { + + LineBreakPanel panel = new LineBreakPanel(); + frame.getContentPane().add(panel, BorderLayout.CENTER); + + JMenuBar menuBar = new JMenuBar(); + + JMenu menu = new JMenu("Tracking"); + ButtonGroup btnGroup = new ButtonGroup(); + String btnLabels[] = {"-0.1", "0", "0.1", "0.2", "0.3"}; + float val = -0.1f; + for (String label : btnLabels) { + JRadioButtonMenuItem btn = new JRadioButtonMenuItem(label); + btn.putClientProperty( "tracking", val ); + btn.addActionListener(panel); + btnGroup.add(btn); + menu.add(btn); + val += 0.1f; + } + menuBar.add(menu); + + frame.setJMenuBar(menuBar); + } + + public static void main(String[] args) throws InterruptedException, InvocationTargetException { + + JFrame frame = new JFrame("LineBreakMeasurer with Tracking"); + frame.setSize(new Dimension(640, 480)); + + LineBreakWithTracking controller = new LineBreakWithTracking(); + controller.createGUI(frame); + + PassFailJFrame passFailJFrame = new PassFailJFrame(INSTRUCTIONS); + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + frame.setVisible(true); + passFailJFrame.awaitAndCheck(); + } +} diff --git a/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java new file mode 100644 index 00000000000..32b1f0592d9 --- /dev/null +++ b/test/jdk/java/awt/font/LineBreakMeasurer/LineBreakWithTrackingAuto.java @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022, 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 8165943 + @summary LineBreakMeasurer does not measure correctly if TextAttribute.TRACKING is set + @run main/othervm LineBreakWithTrackingAuto +*/ + +import java.awt.font.FontRenderContext; +import java.awt.font.LineBreakMeasurer; +import java.awt.font.TextAttribute; +import java.awt.font.TextLayout; +import java.text.AttributedString; + +public class LineBreakWithTrackingAuto { + + private static final String WORD = "word"; + private static final String SPACE = " "; + private static final int NUM_WORDS = 12; + private static final float FONT_SIZE = 24.0f; + private static final float TEXT_TRACKING[] = { -0.1f, 0f, 0.1f, 0.2f, 0.3f }; + private static final float EPSILON = 0.005f; + + + public static void main(String[] args) { + new LineBreakWithTrackingAuto().test(); + } + + public void test() { + + final FontRenderContext frc = new FontRenderContext(null, false, false); + + // construct a paragraph as follows: [SPACE + WORD] + ... + StringBuffer text = new StringBuffer(); + for (int i = 0; i < NUM_WORDS; i++) { + text.append(SPACE); + text.append(WORD); + } + AttributedString attrString = new AttributedString(text.toString()); + attrString.addAttribute(TextAttribute.SIZE, Float.valueOf(FONT_SIZE)); + + // test different tracking values: -0.1f, 0f, 0.1f, 0.2f, 0.3f + for (float textTracking : TEXT_TRACKING) { + + final float trackingAdvance = FONT_SIZE * textTracking; + attrString.addAttribute(TextAttribute.TRACKING, textTracking); + + LineBreakMeasurer measurer = new LineBreakMeasurer(attrString.getIterator(), frc); + + final int sequenceLength = WORD.length() + SPACE.length(); + final float sequenceAdvance = getSequenceAdvance(measurer, text.length(), sequenceLength); + final float textAdvance = NUM_WORDS * sequenceAdvance; + + // test different wrapping width starting from the WORD+SPACE to TEXT width + for (float wrappingWidth = sequenceAdvance; wrappingWidth < textAdvance; wrappingWidth += sequenceAdvance / sequenceLength) { + + measurer.setPosition(0); + + // break a paragraph into lines that fit the given wrapping width + do { + TextLayout layout = measurer.nextLayout(wrappingWidth); + float visAdvance = layout.getVisibleAdvance(); + + int currPos = measurer.getPosition(); + if ((trackingAdvance <= 0 && visAdvance - wrappingWidth > EPSILON) + || (trackingAdvance > 0 && visAdvance - wrappingWidth > trackingAdvance + EPSILON)) { + throw new Error("text line is too long for given wrapping width"); + } + + if (currPos < text.length() && visAdvance <= wrappingWidth - sequenceAdvance) { + throw new Error("text line is too short for given wrapping width"); + } + } while (measurer.getPosition() != text.length()); + + } + } + } + + private float getSequenceAdvance(LineBreakMeasurer measurer, int textLength, int sequenceLength) { + + measurer.setPosition(textLength - sequenceLength); + + TextLayout layout = measurer.nextLayout(10000.0f); + if (layout.getCharacterCount() != sequenceLength) { + throw new Error("layout length is incorrect"); + } + + return layout.getVisibleAdvance(); + } + +} From e86f31b5e71af00fea9cd989a86c1e75e3df1821 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Wed, 7 Dec 2022 18:32:28 +0000 Subject: [PATCH 107/494] 8298301: C2: assert(main_cmp->in(2)->Opcode() == Op_Opaque1) failed: main loop has no opaque node? Reviewed-by: thartmann --- src/hotspot/share/opto/loopTransform.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/loopTransform.cpp b/src/hotspot/share/opto/loopTransform.cpp index ddcb8dbd15e..36e85e1f047 100644 --- a/src/hotspot/share/opto/loopTransform.cpp +++ b/src/hotspot/share/opto/loopTransform.cpp @@ -3576,9 +3576,9 @@ void IdealLoopTree::remove_main_post_loops(CountedLoopNode *cl, PhaseIdealLoop * // Remove the Opaque1Node of the pre loop and make it execute all iterations phase->_igvn.replace_input_of(pre_cmp, 2, pre_cmp->in(2)->in(2)); - // Remove the Opaque1Node of the main loop so it can be optimized out + // Remove the OpaqueZeroTripGuardNode of the main loop so it can be optimized out Node* main_cmp = main_iff->in(1)->in(1); - assert(main_cmp->in(2)->Opcode() == Op_Opaque1, "main loop has no opaque node?"); + assert(main_cmp->in(2)->Opcode() == Op_OpaqueZeroTripGuard, "main loop has no opaque node?"); phase->_igvn.replace_input_of(main_cmp, 2, main_cmp->in(2)->in(1)); } From 3b8c7ef8e705764942c4f3df872e3e47021a37f4 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Wed, 7 Dec 2022 18:43:42 +0000 Subject: [PATCH 108/494] 8157023: Integrate NMT with JFR Reviewed-by: stuefe, mgronlun, egahlin --- src/hotspot/share/jfr/metadata/metadata.xml | 13 ++ .../share/jfr/periodic/jfrPeriodic.cpp | 9 + src/hotspot/share/services/mallocTracker.hpp | 7 +- src/hotspot/share/services/memJfrReporter.cpp | 113 ++++++++++++ src/hotspot/share/services/memJfrReporter.hpp | 44 +++++ src/hotspot/share/services/memReporter.cpp | 4 +- src/hotspot/share/services/memReporter.hpp | 10 +- src/hotspot/share/services/nmtUsage.cpp | 129 ++++++++++++++ src/hotspot/share/services/nmtUsage.hpp | 68 +++++++ .../share/services/virtualMemoryTracker.hpp | 5 + src/jdk.jfr/share/conf/jfr/default.jfc | 10 ++ src/jdk.jfr/share/conf/jfr/profile.jfc | 10 ++ .../runtime/TestNativeMemoryUsageEvents.java | 166 ++++++++++++++++++ test/lib/jdk/test/lib/jfr/EventNames.java | 2 + 14 files changed, 582 insertions(+), 8 deletions(-) create mode 100644 src/hotspot/share/services/memJfrReporter.cpp create mode 100644 src/hotspot/share/services/memJfrReporter.hpp create mode 100644 src/hotspot/share/services/nmtUsage.cpp create mode 100644 src/hotspot/share/services/nmtUsage.hpp create mode 100644 test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 9e81561b196..b870ed0b54e 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -720,6 +720,19 @@ + + + + + + + + + + + diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index 84512fe731d..f43ccc254a7 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -63,6 +63,7 @@ #include "runtime/vm_version.hpp" #include "services/classLoadingService.hpp" #include "services/management.hpp" +#include "services/memJfrReporter.hpp" #include "services/threadService.hpp" #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" @@ -624,3 +625,11 @@ TRACE_REQUEST_FUNC(FinalizerStatistics) { log_debug(jfr, system)("Unable to generate requestable event FinalizerStatistics. The required jvm feature 'management' is missing."); #endif } + +TRACE_REQUEST_FUNC(NativeMemoryUsage) { + MemJFRReporter::send_type_events(); +} + +TRACE_REQUEST_FUNC(NativeMemoryUsageTotal) { + MemJFRReporter::send_total_event(); +} diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 556467d4aa3..03681662231 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -153,7 +153,12 @@ class MallocMemorySnapshot : public ResourceObj { public: - inline MallocMemory* by_type(MEMFLAGS flags) { + inline MallocMemory* by_type(MEMFLAGS flags) { + int index = NMTUtil::flag_to_index(flags); + return &_malloc[index]; + } + + inline const MallocMemory* by_type(MEMFLAGS flags) const { int index = NMTUtil::flag_to_index(flags); return &_malloc[index]; } diff --git a/src/hotspot/share/services/memJfrReporter.cpp b/src/hotspot/share/services/memJfrReporter.cpp new file mode 100644 index 00000000000..014fcb09b7f --- /dev/null +++ b/src/hotspot/share/services/memJfrReporter.cpp @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "jfr/jfrEvents.hpp" +#include "services/memJfrReporter.hpp" +#include "services/memTracker.hpp" +#include "services/nmtUsage.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ticks.hpp" + +// Helper class to avoid refreshing the NMTUsage to often and allow +// the two JFR events to use the same data. +class MemJFRCurrentUsage : public AllStatic { +private: + // The age threshold in milliseconds. If older than this refresh the usage. + static const uint64_t AgeThreshold = 50; + + static Ticks _timestamp; + static NMTUsage* _usage; + +public: + static NMTUsage* get_usage(); + static Ticks get_timestamp(); +}; + +Ticks MemJFRCurrentUsage::_timestamp; +NMTUsage* MemJFRCurrentUsage::_usage = nullptr; + +NMTUsage* MemJFRCurrentUsage::get_usage() { + Tickspan since_baselined = Ticks::now() - _timestamp; + + if (_usage == nullptr) { + // First time, create a new NMTUsage. + _usage = new NMTUsage(NMTUsage::OptionsNoTS); + } else if (since_baselined.milliseconds() < AgeThreshold) { + // There is recent enough usage information, return it. + return _usage; + } + + // Refresh the usage information. + _usage->refresh(); + _timestamp.stamp(); + + return _usage; +} + +Ticks MemJFRCurrentUsage::get_timestamp() { + return _timestamp; +} + +void MemJFRReporter::send_total_event() { + if (!MemTracker::enabled()) { + return; + } + + NMTUsage* usage = MemJFRCurrentUsage::get_usage(); + Ticks timestamp = MemJFRCurrentUsage::get_timestamp(); + + EventNativeMemoryUsageTotal event(UNTIMED); + event.set_starttime(timestamp); + event.set_reserved(usage->total_reserved()); + event.set_committed(usage->total_committed()); + event.commit(); +} + +void MemJFRReporter::send_type_event(const Ticks& starttime, const char* type, size_t reserved, size_t committed) { + EventNativeMemoryUsage event(UNTIMED); + event.set_starttime(starttime); + event.set_type(type); + event.set_reserved(reserved); + event.set_committed(committed); + event.commit(); +} + +void MemJFRReporter::send_type_events() { + if (!MemTracker::enabled()) { + return; + } + + NMTUsage* usage = MemJFRCurrentUsage::get_usage(); + Ticks timestamp = MemJFRCurrentUsage::get_timestamp(); + + for (int index = 0; index < mt_number_of_types; index ++) { + MEMFLAGS flag = NMTUtil::index_to_flag(index); + if (flag == mtNone) { + // Skip mtNone since it is not really used. + continue; + } + send_type_event(timestamp, NMTUtil::flag_to_name(flag), usage->reserved(flag), usage->committed(flag)); + } +} diff --git a/src/hotspot/share/services/memJfrReporter.hpp b/src/hotspot/share/services/memJfrReporter.hpp new file mode 100644 index 00000000000..2c1e4450488 --- /dev/null +++ b/src/hotspot/share/services/memJfrReporter.hpp @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 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_SERVICES_MEMJFRREPORTER_HPP +#define SHARE_SERVICES_MEMJFRREPORTER_HPP + +#include "memory/allocation.hpp" +#include "services/nmtUsage.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/ticks.hpp" + +// MemJFRReporter is only used by threads sending periodic JFR +// events. These threads are synchronized at a higher level, +// so no more synchronization is needed. +class MemJFRReporter : public AllStatic { +private: + static void send_type_event(const Ticks& starttime, const char* tag, size_t reserved, size_t committed); + public: + static void send_total_event(); + static void send_type_events(); +}; + +#endif //SHARE_SERVICES_MEMJFRREPORTER_HPP diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp index 4ef40ad196c..7aa7311fdf4 100644 --- a/src/hotspot/share/services/memReporter.cpp +++ b/src/hotspot/share/services/memReporter.cpp @@ -31,11 +31,11 @@ #include "services/virtualMemoryTracker.hpp" #include "utilities/globalDefinitions.hpp" -size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const { +size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) { return malloc->malloc_size() + malloc->arena_size() + vm->reserved(); } -size_t MemReporterBase::committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const { +size_t MemReporterBase::committed_total(const MallocMemory* malloc, const VirtualMemory* vm) { return malloc->malloc_size() + malloc->arena_size() + vm->committed(); } diff --git a/src/hotspot/share/services/memReporter.hpp b/src/hotspot/share/services/memReporter.hpp index 30dee6797e0..1f07e68aec9 100644 --- a/src/hotspot/share/services/memReporter.hpp +++ b/src/hotspot/share/services/memReporter.hpp @@ -49,6 +49,11 @@ class MemReporterBase : public StackObj { _scale(scale), _output(out) {} + // Helper functions + // Calculate total reserved and committed amount + static size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm); + static size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm); + protected: inline outputStream* output() const { return _output; @@ -73,11 +78,6 @@ class MemReporterBase : public StackObj { return amount / scale; } - // Helper functions - // Calculate total reserved and committed amount - size_t reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) const; - size_t committed_total(const MallocMemory* malloc, const VirtualMemory* vm) const; - // Print summary total, malloc and virtual memory void print_total(size_t reserved, size_t committed) const; void print_malloc(const MemoryCounter* c, MEMFLAGS flag = mtNone) const; diff --git a/src/hotspot/share/services/nmtUsage.cpp b/src/hotspot/share/services/nmtUsage.cpp new file mode 100644 index 00000000000..5899abc01cc --- /dev/null +++ b/src/hotspot/share/services/nmtUsage.cpp @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "runtime/threadCritical.hpp" +#include "services/nmtCommon.hpp" +#include "services/nmtUsage.hpp" +#include "services/mallocTracker.hpp" +#include "services/threadStackTracker.hpp" +#include "services/virtualMemoryTracker.hpp" + +// Enabled all options for snapshot. +const NMTUsageOptions NMTUsage::OptionsAll = { true, true, true }; +// Skip expensive thread stacks when refreshing usage. +const NMTUsageOptions NMTUsage::OptionsNoTS = { false, true, true }; + +NMTUsage::NMTUsage(NMTUsageOptions options) : + _malloc_by_type(), + _malloc_total(), + _vm_by_type(), + _vm_total(), + _usage_options(options) { } + +void NMTUsage::walk_thread_stacks() { + // If backed by virtual memory, snapping the thread stacks involves walking + // them to to figure out how much memory is committed if they are backed by + // virtual memory. This needs ot happen before we take the snapshot of the + // virtual memory since it will update this information. + if (ThreadStackTracker::track_as_vm()) { + VirtualMemoryTracker::snapshot_thread_stacks(); + } +} + +void NMTUsage::update_malloc_usage() { + // Thread critical needed keep values in sync, total area size + // is deducted from mtChunk in the end to give correct values. + ThreadCritical tc; + const MallocMemorySnapshot* ms = MallocMemorySummary::as_snapshot(); + + size_t total_arena_size = 0; + for (int i = 0; i < mt_number_of_types; i++) { + MEMFLAGS flag = NMTUtil::index_to_flag(i); + const MallocMemory* mm = ms->by_type(flag); + _malloc_by_type[i] = mm->malloc_size() + mm->arena_size(); + total_arena_size += mm->arena_size(); + } + + // Total malloc size. + _malloc_total = ms->total(); + + // Adjustment due to mtChunk double counting. + _malloc_by_type[NMTUtil::flag_to_index(mtChunk)] -= total_arena_size; + _malloc_total -= total_arena_size; + + // Adjust mtNMT to include malloc overhead. + _malloc_by_type[NMTUtil::flag_to_index(mtNMT)] += ms->malloc_overhead(); +} + +void NMTUsage::update_vm_usage() { + const VirtualMemorySnapshot* vms = VirtualMemorySummary::as_snapshot(); + + // Reset total to allow recalculation. + _vm_total.committed = 0; + _vm_total.reserved = 0; + for (int i = 0; i < mt_number_of_types; i++) { + MEMFLAGS flag = NMTUtil::index_to_flag(i); + const VirtualMemory* vm = vms->by_type(flag); + + _vm_by_type[i].reserved = vm->reserved(); + _vm_by_type[i].committed = vm->committed(); + _vm_total.reserved += vm->reserved(); + _vm_total.committed += vm->committed(); + } +} + +void NMTUsage::refresh() { + if (_usage_options.include_malloc) { + update_malloc_usage(); + } + + if (_usage_options.include_vm) { + // Thread stacks only makes sense if virtual memory + // is also included. It must be executed before the + // over all usage is calculated. + if (_usage_options.update_thread_stacks) { + walk_thread_stacks(); + } + update_vm_usage(); + } +} + +size_t NMTUsage::total_reserved() const { + return _malloc_total + _vm_total.reserved; +} + +size_t NMTUsage::total_committed() const { + return _malloc_total + _vm_total.reserved; +} + +size_t NMTUsage::reserved(MEMFLAGS flag) const { + int index = NMTUtil::flag_to_index(flag); + return _malloc_by_type[index] + _vm_by_type[index].reserved; +} + +size_t NMTUsage::committed(MEMFLAGS flag) const { + int index = NMTUtil::flag_to_index(flag); + return _malloc_by_type[index] + _vm_by_type[index].committed; +} diff --git a/src/hotspot/share/services/nmtUsage.hpp b/src/hotspot/share/services/nmtUsage.hpp new file mode 100644 index 00000000000..38b7b43913f --- /dev/null +++ b/src/hotspot/share/services/nmtUsage.hpp @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022, 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_SERVICES_NMTUSAGE_HPP +#define SHARE_SERVICES_NMTUSAGE_HPP + +#include "memory/allocation.hpp" +#include "utilities/globalDefinitions.hpp" + +struct NMTUsagePair { + size_t reserved; + size_t committed; +}; + +struct NMTUsageOptions { + bool update_thread_stacks; + bool include_malloc; + bool include_vm; +}; + +class NMTUsage : public CHeapObj { +private: + size_t _malloc_by_type[mt_number_of_types]; + size_t _malloc_total; + NMTUsagePair _vm_by_type[mt_number_of_types]; + NMTUsagePair _vm_total; + + NMTUsageOptions _usage_options; + + void walk_thread_stacks(); + void update_malloc_usage(); + void update_vm_usage(); + +public: + static const NMTUsageOptions OptionsAll; + static const NMTUsageOptions OptionsNoTS; + + NMTUsage(NMTUsageOptions options = OptionsAll); + void refresh(); + + size_t total_reserved() const; + size_t total_committed() const; + size_t reserved(MEMFLAGS flag) const; + size_t committed(MEMFLAGS flag) const; +}; + +#endif // SHARE_SERVICES_NMTUSAGE_HPP diff --git a/src/hotspot/share/services/virtualMemoryTracker.hpp b/src/hotspot/share/services/virtualMemoryTracker.hpp index 9ae61a605fb..f79cab7c70d 100644 --- a/src/hotspot/share/services/virtualMemoryTracker.hpp +++ b/src/hotspot/share/services/virtualMemoryTracker.hpp @@ -97,6 +97,11 @@ class VirtualMemorySnapshot : public ResourceObj { return &_virtual_memory[index]; } + inline const VirtualMemory* by_type(MEMFLAGS flag) const { + int index = NMTUtil::flag_to_index(flag); + return &_virtual_memory[index]; + } + inline size_t total_reserved() const { size_t amount = 0; for (int index = 0; index < mt_number_of_types; index ++) { diff --git a/src/jdk.jfr/share/conf/jfr/default.jfc b/src/jdk.jfr/share/conf/jfr/default.jfc index b47b3fd9af0..05936fe8255 100644 --- a/src/jdk.jfr/share/conf/jfr/default.jfc +++ b/src/jdk.jfr/share/conf/jfr/default.jfc @@ -512,6 +512,16 @@ 0 ns + + true + 1000 ms + + + + true + 1000 ms + + true beginChunk diff --git a/src/jdk.jfr/share/conf/jfr/profile.jfc b/src/jdk.jfr/share/conf/jfr/profile.jfc index a14fce5699b..d3b5adf1aef 100644 --- a/src/jdk.jfr/share/conf/jfr/profile.jfc +++ b/src/jdk.jfr/share/conf/jfr/profile.jfc @@ -512,6 +512,16 @@ 0 ns + + true + 1000 ms + + + + true + 1000 ms + + true beginChunk diff --git a/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java new file mode 100644 index 00000000000..7deeb297aad --- /dev/null +++ b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022, 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.event.runtime; + +import static jdk.test.lib.Asserts.assertGreaterThan; +import static jdk.test.lib.Asserts.assertTrue; + +import java.util.ArrayList; +import java.util.List; + +import jdk.jfr.Recording; +import jdk.jfr.consumer.RecordedEvent; +import jdk.test.lib.jfr.EventNames; +import jdk.test.lib.jfr.Events; + +/** + * @test + * @key jfr + * @requires vm.opt.NativeMemoryTracking == null + * @requires vm.hasJFR + * @library /test/lib + * @modules jdk.jfr + * jdk.management + * @run main/othervm -XX:NativeMemoryTracking=summary -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestNativeMemoryUsageEvents true + * @run main/othervm -XX:NativeMemoryTracking=off -Xms16m -Xmx128m -Xlog:gc jdk.jfr.event.runtime.TestNativeMemoryUsageEvents false + */ +public class TestNativeMemoryUsageEvents { + private final static String UsageTotalEvent = EventNames.NativeMemoryUsageTotal; + private final static String UsageEvent = EventNames.NativeMemoryUsage; + + private final static int UsagePeriod = 1000; + private final static int K = 1024; + + private final static String[] UsageEventTypes = { + "Java Heap", + "Class", + "Thread", + "Thread Stack", + "Code", + "GC", + "GCCardSet", + "Compiler", + "JVMCI", + "Internal", + "Other", + "Symbol", + "Native Memory Tracking", + "Shared class space", + "Arena Chunk", + "Test", + "Tracing", + "Logging", + "Statistics", + "Arguments", + "Module", + "Safepoint", + "Synchronization", + "Serviceability", + "Metaspace", + "String Deduplication", + "Object Monitors" + }; + + private static ArrayList data = new ArrayList(); + + private static void generateHeapContents() { + for (int i = 0 ; i < 64; i++) { + for (int j = 0; j < K; j++) { + data.add(new byte[K]); + } + } + } + + private static void generateEvents(Recording recording) throws Exception { + // Enable the two types of events for "everyChunk", it will give + // an event at the beginning of the chunk as well as at the end. + recording.enable(UsageEvent).with("period", "everyChunk"); + recording.enable(UsageTotalEvent).with("period", "everyChunk"); + + recording.start(); + + // Generate data to force heap to grow. + generateHeapContents(); + + recording.stop(); + } + + private static void verifyExpectedEventTypes(List events) throws Exception { + // First verify that the number of total usage events is greater than 0. + long numberOfTotal = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageTotalEvent)) + .count(); + + assertGreaterThan(numberOfTotal, 0L, "Should exist events of type: " + UsageTotalEvent); + + // Now verify that we got the expected events. + List uniqueEventTypes = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageEvent)) + .map(e -> e.getString("type")) + .distinct() + .toList(); + for (String type : UsageEventTypes) { + assertTrue(uniqueEventTypes.contains(type), "Events should include: " + type); + } + } + + private static void verifyHeapGrowth(List events) throws Exception { + List javaHeapCommitted = events.stream() + .filter(e -> e.getEventType().getName().equals(UsageEvent)) + .filter(e -> e.getString("type").equals("Java Heap")) + .map(e -> e.getLong("committed")) + .toList(); + + // Verify that the heap has grown between the first and last sample. + long firstSample = javaHeapCommitted.get(0); + long lastSample = javaHeapCommitted.get(javaHeapCommitted.size() - 1); + assertGreaterThan(lastSample, firstSample, "heap should have grown and NMT should show that"); + } + + private static void verifyNoUsageEvents(List events) throws Exception { + Events.hasNotEvent(events, UsageEvent); + Events.hasNotEvent(events, UsageTotalEvent); + } + + public static void main(String[] args) throws Exception { + // The tests takes a single boolean argument that states wether or not + // it is run with -XX:NativeMemoryTracking=summary. When tracking is + // enabled the tests verifies that the correct events are sent and + // the other way around when turned off. + assertTrue(args.length == 1, "Must have a single argument"); + boolean nmtEnabled = Boolean.parseBoolean(args[0]); + + try (Recording recording = new Recording()) { + generateEvents(recording); + + var events = Events.fromRecording(recording); + if (nmtEnabled) { + verifyExpectedEventTypes(events); + verifyHeapGrowth(events); + } else { + verifyNoUsageEvents(events); + } + } + } +} diff --git a/test/lib/jdk/test/lib/jfr/EventNames.java b/test/lib/jdk/test/lib/jfr/EventNames.java index 5a0a03766fd..87e526f3c73 100644 --- a/test/lib/jdk/test/lib/jfr/EventNames.java +++ b/test/lib/jdk/test/lib/jfr/EventNames.java @@ -86,6 +86,8 @@ public class EventNames { public static final String RetransformClasses = PREFIX + "RetransformClasses"; public static final String ClassRedefinition = PREFIX + "ClassRedefinition"; public static final String FinalizerStatistics = PREFIX + "FinalizerStatistics"; + public static final String NativeMemoryUsage = PREFIX + "NativeMemoryUsage"; + public static final String NativeMemoryUsageTotal = PREFIX + "NativeMemoryUsageTotal"; // This event is hard to test public static final String ReservedStackActivation = PREFIX + "ReservedStackActivation"; From 10356e767a44632c5de142d4666bd85d4618bf71 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Wed, 7 Dec 2022 18:54:18 +0000 Subject: [PATCH 109/494] 8298303: (fs) temporarily remove Path.getExtension Reviewed-by: smarks, alanb --- .../share/classes/java/nio/file/Path.java | 59 +------------ test/jdk/java/nio/file/Path/Extensions.java | 85 ------------------- 2 files changed, 1 insertion(+), 143 deletions(-) delete mode 100644 test/jdk/java/nio/file/Path/Extensions.java diff --git a/src/java.base/share/classes/java/nio/file/Path.java b/src/java.base/share/classes/java/nio/file/Path.java index b88d6710fab..8a2c233bdf2 100644 --- a/src/java.base/share/classes/java/nio/file/Path.java +++ b/src/java.base/share/classes/java/nio/file/Path.java @@ -50,7 +50,7 @@ * file system. {@code Path} defines the {@link #getFileName() getFileName}, * {@link #getParent getParent}, {@link #getRoot getRoot}, and {@link #subpath * subpath} methods to access the path components or a subsequence of its name - * elements, and {@link #getExtension() getExtension} to obtain its extension. + * elements. * *

    In addition to accessing the components of a path, a {@code Path} also * defines the {@link #resolve(Path) resolve} and {@link #resolveSibling(Path) @@ -249,63 +249,6 @@ public static Path of(URI uri) { */ Path getFileName(); - /** - * Returns the file extension of this path's file name as a {@code String}. - * The extension is derived from this {@code Path} by obtaining the - * {@linkplain #getFileName file name element}, deriving its {@linkplain - * #toString string representation}, and then extracting a substring - * determined by the position of a period character ('.', U+002E FULL STOP) - * within the file name string. If the file name element is {@code null}, - * or if the file name string does not contain a period character, or if - * the only period in the file name string is its first character, then - * the extension is {@code null}. Otherwise, the extension is the substring - * after the last period in the file name string. If this last period is - * also the last character in the file name string, then the extension is - * {@linkplain String#isEmpty empty}. - * - * @implSpec - * The default implementation is equivalent for this path to: - *

    {@code
    -     * int lastPeriod = fileName.lastIndexOf('.');
    -     * if (lastPeriod <= 0)
    -     *     return null;
    -     * return (lastPeriod == fileName.length() - 1)
    -     *     ? ""
    -     *     : fileName.substring(lastPeriod + 1);
    -     * }
    - * - * @return the file name extension of this path, which might be the - * empty string, or {@code null} if no extension is found - * - * @since 20 - */ - default String getExtension() { - Path fileName = getFileName(); - if (fileName == null) - return null; - - String fileNameString = fileName.toString(); - int length = fileNameString.length(); - - // An empty or unity length file name string has a null extension - if (length > 1) { - int lastPeriodIndex = fileNameString.lastIndexOf('.'); - - // Indeterminate if there is no period character or - // only the first character is a period character - if (lastPeriodIndex > 0) { - if (lastPeriodIndex == length - 1) { - // empty string - return ""; - } else { - return fileNameString.substring(lastPeriodIndex + 1); - } - } - } - - return null; - } - /** * Returns the parent path, or {@code null} if this path does not * have a parent. diff --git a/test/jdk/java/nio/file/Path/Extensions.java b/test/jdk/java/nio/file/Path/Extensions.java deleted file mode 100644 index d6113210d05..00000000000 --- a/test/jdk/java/nio/file/Path/Extensions.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2022, 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. - */ - -import java.nio.file.Path; - -import org.testng.Assert; -import org.testng.annotations.DataProvider; -import org.testng.annotations.Test; - -/* - * @test - * @bug 8057113 - * @summary Verify getExtension method - * @run testng Extensions - */ -public class Extensions { - /** - * Returns path name string and expected extension pairs. - * - * @return {@code {{"pathname", "extension"},...}} - */ - @DataProvider - static Object[][] getProvider() { - Object[][] pairs = { - {"", null}, - {".", null}, - {"..", ""}, - {"...", ""}, - {"....", ""}, - {".....", ""}, - {"aa", null}, - {"a.", ""}, - {".a", null}, - {"..a", "a"}, - {"...a", "a"}, - {"....a", "a"}, - {".a.b", "b"}, - {"...a.b", "b"}, - {"...a.b.", ""}, - {"..foo", "foo"}, - {"foo.", ""}, - {"test.", ""}, - {"test..", ""}, - {"test...", ""}, - {"test.rb", "rb"}, - {"a/b/d/test.rb" , "rb"}, - {".a/b/d/test.rb", "rb"}, - {"test", null}, - {".profile", null}, - {".profile.sh", "sh"}, - {"foo.tar.gz", "gz"}, - {"foo.bar.", ""}, - {"archive.zip", "zip"}, - {"compress.gzip", "gzip"}, - {"waitwhat.&$!#%", "&$!#%"}, - {"6.283185307", "283185307"} - }; - return pairs; - } - - @Test(dataProvider = "getProvider") - public static void get(String pathname, String extension) { - Assert.assertEquals(Path.of(pathname).getExtension(), extension); - } -} From 5d4c71c8bd361af78c90777f17b79e95d8eb5afe Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Wed, 7 Dec 2022 20:16:45 +0000 Subject: [PATCH 110/494] 8281236: (D)TLS key exchange named groups Reviewed-by: mullan --- .../classes/javax/net/ssl/SSLParameters.java | 131 ++++++++++- .../sun/security/ssl/CertificateVerify.java | 2 + .../sun/security/ssl/DHKeyExchange.java | 14 +- .../sun/security/ssl/DHServerKeyExchange.java | 1 + .../sun/security/ssl/ECDHKeyExchange.java | 7 +- .../security/ssl/ECDHServerKeyExchange.java | 4 +- .../sun/security/ssl/HandshakeContext.java | 32 +-- .../sun/security/ssl/KeyShareExtension.java | 7 +- .../classes/sun/security/ssl/NamedGroup.java | 211 +++++++++++++++++- .../sun/security/ssl/SSLConfiguration.java | 18 ++ .../sun/security/ssl/SSLKeyExchange.java | 14 +- .../sun/security/ssl/SignatureScheme.java | 4 +- .../ssl/SupportedGroupsExtension.java | 206 +++-------------- .../sun/security/ssl/X509Authentication.java | 4 +- .../javax/net/ssl/DTLS/DTLSNamedGroups.java | 143 ++++++++++++ .../net/ssl/SSLParameters/NamedGroups.java | 147 ++++++++++++ .../ssl/SSLParameters/NamedGroupsSpec.java | 97 ++++++++ 17 files changed, 806 insertions(+), 236 deletions(-) create mode 100644 test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java create mode 100644 test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java create mode 100644 test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java diff --git a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java index b4fbdf9a437..0d4872f9051 100644 --- a/src/java.base/share/classes/javax/net/ssl/SSLParameters.java +++ b/src/java.base/share/classes/javax/net/ssl/SSLParameters.java @@ -34,8 +34,8 @@ * the list of protocols to be allowed, the endpoint identification * algorithm during SSL/TLS/DTLS handshaking, the Server Name Indication (SNI), * the maximum network packet size, the algorithm constraints, the signature - * schemes and whether SSL/TLS/DTLS servers should request or require client - * authentication, etc. + * schemes, the key exchange named groups and whether SSL/TLS/DTLS servers + * should request or require client authentication, etc. *

    * {@code SSLParameter} objects can be created via the constructors in this * class, and can be described as pre-populated objects. {@code SSLParameter} @@ -85,6 +85,7 @@ public class SSLParameters { private int maximumPacketSize = 0; private String[] applicationProtocols = new String[0]; private String[] signatureSchemes = null; + private String[] namedGroups = null; /** * Constructs SSLParameters. @@ -810,4 +811,130 @@ public void setSignatureSchemes(String[] signatureSchemes) { this.signatureSchemes = tempSchemes; } + + /** + * Returns a prioritized array of key exchange named groups names that + * can be used over the SSL/TLS/DTLS protocols. + *

    + * Note that the standard list of key exchange named groups are defined + * in the + * Named Groups section of the Java Security Standard Algorithm + * Names Specification. Providers may support named groups not defined + * in this list or may not use the recommended name for a certain named + * group. + *

    + * The set of named groups that will be used over the SSL/TLS/DTLS + * connections is determined by the returned array of this method and the + * underlying provider-specific default named groups. + *

    + * If the returned array is {@code null}, then the underlying + * provider-specific default named groups will be used over the + * SSL/TLS/DTLS connections. + *

    + * If the returned array is empty (zero-length), then the named group + * negotiation mechanism is turned off for SSL/TLS/DTLS protocols, and + * the connections may not be able to be established if the negotiation + * mechanism is required by a certain SSL/TLS/DTLS protocol. This + * parameter will override the underlying provider-specific default + * name groups. + *

    + * If the returned array is not {@code null} or empty (zero-length), + * then the named groups in the returned array will be used over + * the SSL/TLS/DTLS connections. This parameter will override the + * underlying provider-specific default named groups. + *

    + * This method returns the most recent value passed to + * {@link #setNamedGroups} if that method has been called and otherwise + * returns the default named groups for connection populated objects, + * or {@code null} for pre-populated objects. + * + * @apiNote + * Note that a provider may not have been updated to support this method + * and in that case may return {@code null} instead of the default + * named groups for connection populated objects. + * + * @implNote + * The SunJSSE provider supports this method. + * + * @implNote + * Note that applications may use the + * {@systemProperty jdk.tls.namedGroups} system property with the SunJSSE + * provider to override the provider-specific default named groups. + * + * @return an array of key exchange named group names {@code Strings} or + * {@code null} if none have been set. For non-null returns, this + * method will return a new array each time it is invoked. The + * array is ordered based on named group preference, with the first + * entry being the most preferred. Providers should ignore unknown + * named group names while establishing the SSL/TLS/DTLS + * connections. + * @see #setNamedGroups + * + * @since 20 + */ + public String[] getNamedGroups() { + return clone(namedGroups); + } + + /** + * Sets the prioritized array of key exchange named groups names that + * can be used over the SSL/TLS/DTLS protocols. + *

    + * Note that the standard list of key exchange named groups are defined in + * the + * Named Groups section of the Java Security Standard Algorithm + * Names Specification. Providers may support named groups not defined + * in this list or may not use the recommended name for a certain named + * group. + *

    + * The set of named groups that will be used over the SSL/TLS/DTLS + * connections is determined by the input parameter {@code namedGroups} + * array and the underlying provider-specific default named groups. + * See {@link #getNamedGroups} for specific details on how the + * parameters are used in SSL/TLS/DTLS connections. + * + * @apiNote + * Note that a provider may not have been updated to support this method + * and in that case may ignore the named groups that are set. + * + * @implNote + * The SunJSSE provider supports this method. + * + * @param namedGroups an ordered array of key exchange named group names + * with the first entry being the most preferred, or {@code null}. + * This method will make a copy of this array. Providers should + * ignore unknown named group scheme names while establishing the + * SSL/TLS/DTLS connections. + * @throws IllegalArgumentException if any element in the + * {@code namedGroups} array is a duplicate, {@code null} or + * {@linkplain String#isBlank() blank}. + * + * @see #getNamedGroups + * + * @since 20 + */ + public void setNamedGroups(String[] namedGroups) { + String[] tempGroups = null; + + if (namedGroups != null) { + tempGroups = namedGroups.clone(); + Set groupsSet = new HashSet<>(); + for (String namedGroup : tempGroups) { + if (namedGroup == null || namedGroup.isBlank()) { + throw new IllegalArgumentException( + "An element of namedGroups is null or blank"); + } + + if (groupsSet.contains(namedGroup)) { + throw new IllegalArgumentException( + "Duplicate element of namedGroups: " + namedGroup); + } + groupsSet.add(namedGroup); + } + } + + this.namedGroups = tempGroups; + } } diff --git a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java index 97c513535c5..518a525b12f 100644 --- a/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java +++ b/src/java.base/share/classes/sun/security/ssl/CertificateVerify.java @@ -590,6 +590,7 @@ static final class T12CertificateVerifyMessage extends HandshakeMessage { ClientHandshakeContext chc = (ClientHandshakeContext)context; Map.Entry schemeAndSigner = SignatureScheme.getSignerOfPreferableAlgorithm( + chc.sslConfig, chc.algorithmConstraints, chc.peerRequestedSignatureSchemes, x509Possession, @@ -901,6 +902,7 @@ static final class T13CertificateVerifyMessage extends HandshakeMessage { Map.Entry schemeAndSigner = SignatureScheme.getSignerOfPreferableAlgorithm( + context.sslConfig, context.algorithmConstraints, context.peerRequestedSignatureSchemes, x509Possession, diff --git a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java index fc45921cff0..ef39341158a 100644 --- a/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/DHKeyExchange.java @@ -42,7 +42,6 @@ import javax.crypto.spec.DHPublicKeySpec; import sun.security.action.GetPropertyAction; import sun.security.ssl.NamedGroup.NamedGroupSpec; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.util.KeyUtil; @@ -313,12 +312,13 @@ public SSLPossession createPossession(HandshakeContext context) { if (!useLegacyEphemeralDHKeys && (context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { - preferableNamedGroup = - SupportedGroups.getPreferredGroup(context.negotiatedProtocol, - context.algorithmConstraints, - new NamedGroupSpec [] { - NamedGroupSpec.NAMED_GROUP_FFDHE }, - context.clientRequestedNamedGroups); + preferableNamedGroup = NamedGroup.getPreferredGroup( + context.sslConfig, + context.negotiatedProtocol, + context.algorithmConstraints, + new NamedGroupSpec [] { + NamedGroupSpec.NAMED_GROUP_FFDHE }, + context.clientRequestedNamedGroups); if (preferableNamedGroup != null) { return new DHEPossession(preferableNamedGroup, context.sslContext.getSecureRandom()); diff --git a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java index 019d53c75c0..2df62d50fb8 100644 --- a/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/DHServerKeyExchange.java @@ -127,6 +127,7 @@ class DHServerKeyExchangeMessage extends HandshakeMessage { if (useExplicitSigAlgorithm) { Map.Entry schemeAndSigner = SignatureScheme.getSignerOfPreferableAlgorithm( + shc.sslConfig, shc.algorithmConstraints, shc.peerRequestedSignatureSchemes, x509Possession, diff --git a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java index b38b98d4d59..0b415f655be 100644 --- a/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/ECDHKeyExchange.java @@ -44,7 +44,6 @@ import javax.crypto.SecretKey; import javax.net.ssl.SSLHandshakeException; import sun.security.ssl.NamedGroup.NamedGroupSpec; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.ssl.XDHKeyExchange.XDHECredentials; @@ -236,7 +235,8 @@ public SSLPossession createPossession(HandshakeContext context) { // Find most preferred EC or XEC groups if ((context.clientRequestedNamedGroups != null) && (!context.clientRequestedNamedGroups.isEmpty())) { - preferableNamedGroup = SupportedGroups.getPreferredGroup( + preferableNamedGroup = NamedGroup.getPreferredGroup( + context.sslConfig, context.negotiatedProtocol, context.algorithmConstraints, new NamedGroupSpec[] { @@ -244,7 +244,8 @@ public SSLPossession createPossession(HandshakeContext context) { NamedGroupSpec.NAMED_GROUP_XDH }, context.clientRequestedNamedGroups); } else { - preferableNamedGroup = SupportedGroups.getPreferredGroup( + preferableNamedGroup = NamedGroup.getPreferredGroup( + context.sslConfig, context.negotiatedProtocol, context.algorithmConstraints, new NamedGroupSpec[] { diff --git a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java index 07aaa95a462..b31c0ba9cb9 100644 --- a/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/ECDHServerKeyExchange.java @@ -42,7 +42,6 @@ import java.util.Locale; import java.util.Map; import sun.security.ssl.SSLHandshake.HandshakeMessage; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Credentials; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.util.HexDumpEncoder; @@ -139,6 +138,7 @@ class ECDHServerKeyExchangeMessage extends HandshakeMessage { if (useExplicitSigAlgorithm) { Map.Entry schemeAndSigner = SignatureScheme.getSignerOfPreferableAlgorithm( + shc.sslConfig, shc.algorithmConstraints, shc.peerRequestedSignatureSchemes, x509Possession, @@ -204,7 +204,7 @@ class ECDHServerKeyExchangeMessage extends HandshakeMessage { "Unknown named group ID: " + namedGroupId); } - if (!SupportedGroups.isSupported(namedGroup)) { + if (!NamedGroup.isEnabled(chc.sslConfig, namedGroup)) { throw chc.conContext.fatal(Alert.ILLEGAL_PARAMETER, "Unsupported named group: " + namedGroup); } diff --git a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java index e9821c26eb2..4699c5ce309 100644 --- a/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java +++ b/src/java.base/share/classes/sun/security/ssl/HandshakeContext.java @@ -39,7 +39,6 @@ import javax.security.auth.x500.X500Principal; import sun.security.ssl.NamedGroup.NamedGroupSpec; import static sun.security.ssl.NamedGroup.NamedGroupSpec.*; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; abstract class HandshakeContext implements ConnectionContext { // System properties @@ -157,8 +156,8 @@ protected HandshakeContext(SSLContextImpl sslContext, this.algorithmConstraints = SSLAlgorithmConstraints.wrap( sslConfig.userSpecifiedAlgorithmConstraints); - this.activeProtocols = getActiveProtocols(sslConfig.enabledProtocols, - sslConfig.enabledCipherSuites, algorithmConstraints); + this.activeProtocols = + getActiveProtocols(sslConfig, algorithmConstraints); if (activeProtocols.isEmpty()) { throw new SSLHandshakeException( "No appropriate protocol (protocol is disabled or " + @@ -173,8 +172,8 @@ protected HandshakeContext(SSLContextImpl sslContext, } } this.maximumActiveProtocol = maximumVersion; - this.activeCipherSuites = getActiveCipherSuites(this.activeProtocols, - sslConfig.enabledCipherSuites, algorithmConstraints); + this.activeCipherSuites = getActiveCipherSuites(sslConfig, + this.activeProtocols, algorithmConstraints); if (activeCipherSuites.isEmpty()) { throw new SSLHandshakeException("No appropriate cipher suite"); } @@ -256,12 +255,11 @@ private void initialize() { } private static List getActiveProtocols( - List enabledProtocols, - List enabledCipherSuites, + SSLConfiguration sslConfig, AlgorithmConstraints algorithmConstraints) { boolean enabledSSL20Hello = false; ArrayList protocols = new ArrayList<>(4); - for (ProtocolVersion protocol : enabledProtocols) { + for (ProtocolVersion protocol : sslConfig.enabledProtocols) { if (!enabledSSL20Hello && protocol == ProtocolVersion.SSL20Hello) { enabledSSL20Hello = true; continue; @@ -277,9 +275,9 @@ private static List getActiveProtocols( boolean found = false; Map cachedStatus = new EnumMap<>(NamedGroupSpec.class); - for (CipherSuite suite : enabledCipherSuites) { + for (CipherSuite suite : sslConfig.enabledCipherSuites) { if (suite.isAvailable() && suite.supports(protocol)) { - if (isActivatable(suite, + if (isActivatable(sslConfig, suite, algorithmConstraints, cachedStatus)) { protocols.add(protocol); found = true; @@ -309,15 +307,15 @@ private static List getActiveProtocols( } private static List getActiveCipherSuites( + SSLConfiguration sslConfig, List enabledProtocols, - List enabledCipherSuites, AlgorithmConstraints algorithmConstraints) { List suites = new LinkedList<>(); if (enabledProtocols != null && !enabledProtocols.isEmpty()) { Map cachedStatus = new EnumMap<>(NamedGroupSpec.class); - for (CipherSuite suite : enabledCipherSuites) { + for (CipherSuite suite : sslConfig.enabledCipherSuites) { if (!suite.isAvailable()) { continue; } @@ -327,7 +325,7 @@ private static List getActiveCipherSuites( if (!suite.supports(protocol)) { continue; } - if (isActivatable(suite, + if (isActivatable(sslConfig, suite, algorithmConstraints, cachedStatus)) { suites.add(suite); isSupported = true; @@ -525,7 +523,9 @@ boolean isNegotiable(ProtocolVersion protocolVersion) { return activeProtocols.contains(protocolVersion); } - private static boolean isActivatable(CipherSuite suite, + private static boolean isActivatable( + SSLConfiguration sslConfig, + CipherSuite suite, AlgorithmConstraints algorithmConstraints, Map cachedStatus) { @@ -543,8 +543,8 @@ private static boolean isActivatable(CipherSuite suite, if (groupType != NAMED_GROUP_NONE) { Boolean checkedStatus = cachedStatus.get(groupType); if (checkedStatus == null) { - groupAvailable = SupportedGroups.isActivatable( - algorithmConstraints, groupType); + groupAvailable = NamedGroup.isActivatable( + sslConfig, algorithmConstraints, groupType); cachedStatus.put(groupType, groupAvailable); if (!groupAvailable && diff --git a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java index 02a667503c6..2df6d26ff31 100644 --- a/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/KeyShareExtension.java @@ -36,7 +36,6 @@ import sun.security.ssl.SSLExtension.ExtensionConsumer; import sun.security.ssl.SSLExtension.SSLExtensionSpec; import sun.security.ssl.SSLHandshake.HandshakeMessage; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.util.HexDumpEncoder; /** @@ -345,7 +344,7 @@ public void consume(ConnectionContext context, List credentials = new LinkedList<>(); for (KeyShareEntry entry : spec.clientShares) { NamedGroup ng = NamedGroup.valueOf(entry.namedGroupId); - if (ng == null || !SupportedGroups.isActivatable( + if (ng == null || !NamedGroup.isActivatable(shc.sslConfig, shc.algorithmConstraints, ng)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { @@ -647,7 +646,7 @@ public void consume(ConnectionContext context, SHKeyShareSpec spec = new SHKeyShareSpec(chc, buffer); KeyShareEntry keyShare = spec.serverShare; NamedGroup ng = NamedGroup.valueOf(keyShare.namedGroupId); - if (ng == null || !SupportedGroups.isActivatable( + if (ng == null || !NamedGroup.isActivatable(chc.sslConfig, chc.algorithmConstraints, ng)) { throw chc.conContext.fatal(Alert.UNEXPECTED_MESSAGE, "Unsupported named group: " + @@ -800,7 +799,7 @@ public byte[] produce(ConnectionContext context, NamedGroup selectedGroup = null; for (NamedGroup ng : shc.clientRequestedNamedGroups) { - if (SupportedGroups.isActivatable( + if (NamedGroup.isActivatable(shc.sslConfig, shc.algorithmConstraints, ng)) { if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { SSLLogger.fine( diff --git a/src/java.base/share/classes/sun/security/ssl/NamedGroup.java b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java index 143d8689f95..2a6c966a254 100644 --- a/src/java.base/share/classes/sun/security/ssl/NamedGroup.java +++ b/src/java.base/share/classes/sun/security/ssl/NamedGroup.java @@ -33,12 +33,13 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; +import java.util.ArrayList; import java.util.Set; import javax.crypto.KeyAgreement; import javax.crypto.spec.DHParameterSpec; import sun.security.ssl.ECDHKeyExchange.ECDHEPossession; import sun.security.util.CurveDB; - +import sun.security.action.GetPropertyAction; /** * An enum containing all known named groups for use in TLS. @@ -241,9 +242,9 @@ enum NamedGroup { // Constructor used for all NamedGroup types NamedGroup(int id, String name, - NamedGroupSpec namedGroupSpec, - ProtocolVersion[] supportedProtocols, - AlgorithmParameterSpec keAlgParamSpec) { + NamedGroupSpec namedGroupSpec, + ProtocolVersion[] supportedProtocols, + AlgorithmParameterSpec keAlgParamSpec) { this.id = id; this.name = name; this.spec = namedGroupSpec; @@ -369,6 +370,126 @@ static String nameOf(int id) { return "UNDEFINED-NAMED-GROUP(" + id + ")"; } + public static List namesOf(String[] namedGroups) { + if (namedGroups == null) { + return null; + } + + if (namedGroups.length == 0) { + return List.of(); + } + + List ngs = new ArrayList<>(namedGroups.length); + for (String ss : namedGroups) { + NamedGroup ng = NamedGroup.nameOf(ss); + if (ng == null || !ng.isAvailable) { + if (SSLLogger.isOn && + SSLLogger.isOn("ssl,handshake,verbose")) { + SSLLogger.finest( + "Ignore the named group (" + ss + + "), unsupported or unavailable"); + } + + continue; + } + + ngs.add(ng); + } + + return Collections.unmodifiableList(ngs); + } + + // Is there any supported group permitted by the constraints? + static boolean isActivatable(SSLConfiguration sslConfig, + AlgorithmConstraints constraints, NamedGroupSpec type) { + + boolean hasFFDHEGroups = false; + for (String ng : sslConfig.namedGroups) { + NamedGroup namedGroup = NamedGroup.nameOf(ng); + if (namedGroup != null && + namedGroup.isAvailable && namedGroup.spec == type) { + if (namedGroup.isPermitted(constraints)) { + return true; + } + + if (!hasFFDHEGroups && + (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) { + hasFFDHEGroups = true; + } + } + } + + // For compatibility, if no FFDHE groups are defined, the non-FFDHE + // compatible mode (using DHE cipher suite without FFDHE extension) + // is allowed. + // + // Note that the constraints checking on DHE parameters will be + // performed during key exchanging in a handshake. + return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE; + } + + // Is the named group permitted by the constraints? + static boolean isActivatable( + SSLConfiguration sslConfig, + AlgorithmConstraints constraints, NamedGroup namedGroup) { + if (!namedGroup.isAvailable || !isEnabled(sslConfig, namedGroup)) { + return false; + } + + return namedGroup.isPermitted(constraints); + } + + // Is the named group supported? + static boolean isEnabled(SSLConfiguration sslConfig, + NamedGroup namedGroup) { + for (String ng : sslConfig.namedGroups) { + if (namedGroup.name.equalsIgnoreCase(ng)) { + return true; + } + } + + return false; + } + + // Get preferred named group from the configured named groups for the + // negotiated protocol and named group types. + static NamedGroup getPreferredGroup( + SSLConfiguration sslConfig, + ProtocolVersion negotiatedProtocol, + AlgorithmConstraints constraints, NamedGroupSpec[] types) { + for (String name : sslConfig.namedGroups) { + NamedGroup ng = NamedGroup.nameOf(name); + if (ng != null && ng.isAvailable && + (NamedGroupSpec.arrayContains(types, ng.spec)) && + ng.isAvailable(negotiatedProtocol) && + ng.isPermitted(constraints)) { + return ng; + } + } + + return null; + } + + // Get preferred named group from the requested and configured named + // groups for the negotiated protocol and named group types. + static NamedGroup getPreferredGroup( + SSLConfiguration sslConfig, + ProtocolVersion negotiatedProtocol, + AlgorithmConstraints constraints, NamedGroupSpec[] types, + List requestedNamedGroups) { + for (NamedGroup namedGroup : requestedNamedGroups) { + if ((namedGroup.isAvailable && + NamedGroupSpec.arrayContains(types, namedGroup.spec)) && + namedGroup.isAvailable(negotiatedProtocol) && + isEnabled(sslConfig, namedGroup) && + namedGroup.isPermitted(constraints)) { + return namedGroup; + } + } + + return null; + } + // Is the NamedGroup available for the protocols desired? boolean isAvailable(List protocolVersions) { if (this.isAvailable) { @@ -618,4 +739,86 @@ public SSLKeyDerivation createKeyDerivation( return XDHKeyExchange.xdheKAGenerator.createKeyDerivation(hc); } } + + static final class SupportedGroups { + // the supported named groups, non-null immutable list + static final String[] namedGroups; + + static { + // The value of the System Property defines a list of enabled named + // groups in preference order, separated with comma. For example: + // + // jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048" + // + // If the System Property is not defined or the value is empty, the + // default groups and preferences will be used. + String property = GetPropertyAction + .privilegedGetProperty("jdk.tls.namedGroups"); + if (property != null && !property.isEmpty()) { + // remove double quote marks from beginning/end of the property + if (property.length() > 1 && property.charAt(0) == '"' && + property.charAt(property.length() - 1) == '"') { + property = property.substring(1, property.length() - 1); + } + } + + ArrayList groupList; + if (property != null && !property.isEmpty()) { + String[] groups = property.split(","); + groupList = new ArrayList<>(groups.length); + for (String group : groups) { + group = group.trim(); + if (!group.isEmpty()) { + NamedGroup namedGroup = nameOf(group); + if (namedGroup != null) { + if (namedGroup.isAvailable) { + groupList.add(namedGroup.name); + } + } // ignore unknown groups + } + } + + if (groupList.isEmpty()) { + throw new IllegalArgumentException( + "System property jdk.tls.namedGroups(" + + property + ") contains no supported named groups"); + } + } else { // default groups + NamedGroup[] groups = new NamedGroup[] { + + // Primary XDH (RFC 7748) curves + X25519, + + // Primary NIST Suite B curves + SECP256_R1, + SECP384_R1, + SECP521_R1, + + // Secondary XDH curves + X448, + + // FFDHE (RFC 7919) + FFDHE_2048, + FFDHE_3072, + FFDHE_4096, + FFDHE_6144, + FFDHE_8192, + }; + + groupList = new ArrayList<>(groups.length); + for (NamedGroup group : groups) { + if (group.isAvailable) { + groupList.add(group.name); + } + } + + if (groupList.isEmpty() && + SSLLogger.isOn && SSLLogger.isOn("ssl")) { + SSLLogger.warning("No default named groups"); + } + } + + namedGroups = groupList.toArray(new String[0]); + } + } } diff --git a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java index 056f00a5a3c..ea2d2efcb4f 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLConfiguration.java @@ -64,6 +64,9 @@ final class SSLConfiguration implements Cloneable { // "signature_algorithms_cert" extensions String[] signatureSchemes; + // the configured named groups for the "supported_groups" extensions + String[] namedGroups; + // the maximum protocol version of enabled protocols ProtocolVersion maximumProtocolVersion; @@ -109,6 +112,10 @@ final class SSLConfiguration implements Cloneable { static final int maxCertificateChainLength = GetIntegerAction.privilegedGetProperty( "jdk.tls.maxCertificateChainLength", 10); + // To switch off the supported_groups extension for DHE cipher suite. + static final boolean enableFFDHE = + Utilities.getBooleanProperty("jsse.enableFFDHE", true); + // Is the extended_master_secret extension supported? static { boolean supportExtendedMasterSecret = Utilities.getBooleanProperty( @@ -146,6 +153,7 @@ final class SSLConfiguration implements Cloneable { this.signatureSchemes = isClientMode ? CustomizedClientSignatureSchemes.signatureSchemes : CustomizedServerSignatureSchemes.signatureSchemes; + this.namedGroups = NamedGroup.SupportedGroups.namedGroups; this.maximumProtocolVersion = ProtocolVersion.NONE; for (ProtocolVersion pv : enabledProtocols) { if (pv.compareTo(maximumProtocolVersion) > 0) { @@ -201,6 +209,7 @@ SSLParameters getSSLParameters() { params.setEnableRetransmissions(this.enableRetransmissions); params.setMaximumPacketSize(this.maximumPacketSize); params.setSignatureSchemes(this.signatureSchemes); + params.setNamedGroups(this.namedGroups); return params; } @@ -265,6 +274,15 @@ void setSSLParameters(SSLParameters params) { this.signatureSchemes = ss; } // Otherwise, use the default values + String[] ngs = params.getNamedGroups(); + if (ngs != null) { + // Note if 'ngs' is empty, then no named groups should be + // specified over the connections. + this.namedGroups = ngs; + } else { // Otherwise, use the default values. + this.namedGroups = NamedGroup.SupportedGroups.namedGroups; + } + this.preferLocalCipherSuites = params.getUseCipherSuitesOrder(); this.enableRetransmissions = params.getEnableRetransmissions(); this.maximumPacketSize = params.getMaximumPacketSize(); diff --git a/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java b/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java index e0d2733c155..22a44590ce3 100644 --- a/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java +++ b/src/java.base/share/classes/sun/security/ssl/SSLKeyExchange.java @@ -28,8 +28,6 @@ import java.io.IOException; import java.util.*; import java.util.AbstractMap.SimpleImmutableEntry; - -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Possession; final class SSLKeyExchange implements SSLKeyAgreementGenerator, @@ -561,23 +559,13 @@ public Map.Entry[] getHandshakeConsumers( private static final class T13KeyAgreement implements SSLKeyAgreement { private final NamedGroup namedGroup; - static final Map - supportedKeyShares = new HashMap<>(); - - static { - for (NamedGroup namedGroup : - SupportedGroups.supportedNamedGroups) { - supportedKeyShares.put( - namedGroup, new T13KeyAgreement(namedGroup)); - } - } private T13KeyAgreement(NamedGroup namedGroup) { this.namedGroup = namedGroup; } static T13KeyAgreement valueOf(NamedGroup namedGroup) { - return supportedKeyShares.get(namedGroup); + return new T13KeyAgreement(namedGroup); } @Override diff --git a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java index 4897258a93d..4db3f31bae8 100644 --- a/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java +++ b/src/java.base/share/classes/sun/security/ssl/SignatureScheme.java @@ -41,7 +41,6 @@ import java.util.Map; import java.util.Set; import sun.security.ssl.NamedGroup.NamedGroupSpec; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; import sun.security.ssl.X509Authentication.X509Possession; import sun.security.util.KeyUtil; import sun.security.util.SignatureUtil; @@ -466,6 +465,7 @@ static SignatureScheme getPreferableAlgorithm( } static Map.Entry getSignerOfPreferableAlgorithm( + SSLConfiguration sslConfig, AlgorithmConstraints constraints, List schemes, X509Possession x509Possession, @@ -519,7 +519,7 @@ static Map.Entry getSignerOfPreferableAlgorithm( if (params != null) { NamedGroup keyGroup = NamedGroup.valueOf(params); if (keyGroup != null && - SupportedGroups.isSupported(keyGroup)) { + NamedGroup.isEnabled(sslConfig, keyGroup)) { Signature signer = ss.getSigner(signingKey); if (signer != null) { return new SimpleImmutableEntry<>(ss, signer); diff --git a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java index ecf2f0bb35e..d6e1391d09b 100644 --- a/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java +++ b/src/java.base/share/classes/sun/security/ssl/SupportedGroupsExtension.java @@ -27,11 +27,10 @@ import java.io.IOException; import java.nio.ByteBuffer; -import java.security.AlgorithmConstraints; import java.text.MessageFormat; import java.util.*; import javax.net.ssl.SSLProtocolException; -import sun.security.action.GetPropertyAction; + import sun.security.ssl.NamedGroup.NamedGroupSpec; import static sun.security.ssl.SSLExtension.CH_SUPPORTED_GROUPS; import static sun.security.ssl.SSLExtension.EE_SUPPORTED_GROUPS; @@ -64,10 +63,6 @@ final class SupportedGroupsExtension { static final class SupportedGroupsSpec implements SSLExtensionSpec { final int[] namedGroupsIds; - private SupportedGroupsSpec(int[] namedGroupsIds) { - this.namedGroupsIds = namedGroupsIds; - } - private SupportedGroupsSpec(List namedGroups) { this.namedGroupsIds = new int[namedGroups.size()]; int i = 0; @@ -150,174 +145,6 @@ public String toString(HandshakeContext hc, ByteBuffer buffer) { } } - static class SupportedGroups { - // To switch off the supported_groups extension for DHE cipher suite. - static final boolean enableFFDHE = - Utilities.getBooleanProperty("jsse.enableFFDHE", true); - - // the supported named groups - static final NamedGroup[] supportedNamedGroups; - - static { - // The value of the System Property defines a list of enabled named - // groups in preference order, separated with comma. For example: - // - // jdk.tls.namedGroups="secp521r1, secp256r1, ffdhe2048" - // - // If the System Property is not defined or the value is empty, the - // default groups and preferences will be used. - String property = GetPropertyAction - .privilegedGetProperty("jdk.tls.namedGroups"); - if (property != null && !property.isEmpty()) { - // remove double quote marks from beginning/end of the property - if (property.length() > 1 && property.charAt(0) == '"' && - property.charAt(property.length() - 1) == '"') { - property = property.substring(1, property.length() - 1); - } - } - - ArrayList groupList; - if (property != null && !property.isEmpty()) { - String[] groups = property.split(","); - groupList = new ArrayList<>(groups.length); - for (String group : groups) { - group = group.trim(); - if (!group.isEmpty()) { - NamedGroup namedGroup = NamedGroup.nameOf(group); - if (namedGroup != null) { - if (namedGroup.isAvailable) { - groupList.add(namedGroup); - } - } // ignore unknown groups - } - } - - if (groupList.isEmpty()) { - throw new IllegalArgumentException( - "System property jdk.tls.namedGroups(" + - property + ") contains no supported named groups"); - } - } else { // default groups - NamedGroup[] groups = new NamedGroup[] { - - // Primary XDH (RFC 7748) curves - NamedGroup.X25519, - - // Primary NIST Suite B curves - NamedGroup.SECP256_R1, - NamedGroup.SECP384_R1, - NamedGroup.SECP521_R1, - - // Secondary XDH curves - NamedGroup.X448, - - // FFDHE (RFC 7919) - NamedGroup.FFDHE_2048, - NamedGroup.FFDHE_3072, - NamedGroup.FFDHE_4096, - NamedGroup.FFDHE_6144, - NamedGroup.FFDHE_8192, - }; - - groupList = new ArrayList<>(groups.length); - for (NamedGroup group : groups) { - if (group.isAvailable) { - groupList.add(group); - } - } - - if (groupList.isEmpty() && - SSLLogger.isOn && SSLLogger.isOn("ssl")) { - SSLLogger.warning("No default named groups"); - } - } - - supportedNamedGroups = new NamedGroup[groupList.size()]; - int i = 0; - for (NamedGroup namedGroup : groupList) { - supportedNamedGroups[i++] = namedGroup; - } - } - - // Is there any supported group permitted by the constraints? - static boolean isActivatable( - AlgorithmConstraints constraints, NamedGroupSpec type) { - - boolean hasFFDHEGroups = false; - for (NamedGroup namedGroup : supportedNamedGroups) { - if (namedGroup.isAvailable && namedGroup.spec == type) { - if (namedGroup.isPermitted(constraints)) { - return true; - } - - if (!hasFFDHEGroups && - (type == NamedGroupSpec.NAMED_GROUP_FFDHE)) { - hasFFDHEGroups = true; - } - } - } - - // For compatibility, if no FFDHE groups are defined, the non-FFDHE - // compatible mode (using DHE cipher suite without FFDHE extension) - // is allowed. - // - // Note that the constraints checking on DHE parameters will be - // performed during key exchanging in a handshake. - return !hasFFDHEGroups && type == NamedGroupSpec.NAMED_GROUP_FFDHE; - } - - // Is the named group permitted by the constraints? - static boolean isActivatable( - AlgorithmConstraints constraints, NamedGroup namedGroup) { - if (!namedGroup.isAvailable || !isSupported(namedGroup)) { - return false; - } - - return namedGroup.isPermitted(constraints); - } - - // Is the named group supported? - static boolean isSupported(NamedGroup namedGroup) { - for (NamedGroup group : supportedNamedGroups) { - if (namedGroup.id == group.id) { - return true; - } - } - - return false; - } - - static NamedGroup getPreferredGroup( - ProtocolVersion negotiatedProtocol, - AlgorithmConstraints constraints, NamedGroupSpec[] types, - List requestedNamedGroups) { - for (NamedGroup namedGroup : requestedNamedGroups) { - if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) && - namedGroup.isAvailable(negotiatedProtocol) && - isSupported(namedGroup) && - namedGroup.isPermitted(constraints)) { - return namedGroup; - } - } - - return null; - } - - static NamedGroup getPreferredGroup( - ProtocolVersion negotiatedProtocol, - AlgorithmConstraints constraints, NamedGroupSpec[] types) { - for (NamedGroup namedGroup : supportedNamedGroups) { - if ((NamedGroupSpec.arrayContains(types, namedGroup.spec)) && - namedGroup.isAvailable(negotiatedProtocol) && - namedGroup.isPermitted(constraints)) { - return namedGroup; - } - } - - return null; - } - } - /** * Network data producer of a "supported_groups" extension in * the ClientHello handshake message. @@ -346,9 +173,18 @@ public byte[] produce(ConnectionContext context, // Produce the extension. ArrayList namedGroups = - new ArrayList<>(SupportedGroups.supportedNamedGroups.length); - for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { - if ((!SupportedGroups.enableFFDHE) && + new ArrayList<>(chc.sslConfig.namedGroups.length); + for (String name : chc.sslConfig.namedGroups) { + NamedGroup ng = NamedGroup.nameOf(name); + if (ng == null) { + if (SSLLogger.isOn && SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine( + "Ignore unspecified named group: " + name); + } + continue; + } + + if ((!SSLConfiguration.enableFFDHE) && (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) { continue; } @@ -495,9 +331,19 @@ public byte[] produce(ConnectionContext context, // Contains all groups the server supports, regardless of whether // they are currently supported by the client. ArrayList namedGroups = new ArrayList<>( - SupportedGroups.supportedNamedGroups.length); - for (NamedGroup ng : SupportedGroups.supportedNamedGroups) { - if ((!SupportedGroups.enableFFDHE) && + shc.sslConfig.namedGroups.length); + for (String name : shc.sslConfig.namedGroups) { + NamedGroup ng = NamedGroup.nameOf(name); + if (ng == null) { + if (SSLLogger.isOn && + SSLLogger.isOn("ssl,handshake")) { + SSLLogger.fine( + "Ignore unspecified named group: " + name); + } + continue; + } + + if ((!SSLConfiguration.enableFFDHE) && (ng.spec == NamedGroupSpec.NAMED_GROUP_FFDHE)) { continue; } diff --git a/src/java.base/share/classes/sun/security/ssl/X509Authentication.java b/src/java.base/share/classes/sun/security/ssl/X509Authentication.java index 164fb1c6be2..6c29db30c60 100644 --- a/src/java.base/share/classes/sun/security/ssl/X509Authentication.java +++ b/src/java.base/share/classes/sun/security/ssl/X509Authentication.java @@ -39,8 +39,6 @@ import java.util.Map; import javax.net.ssl.X509ExtendedKeyManager; -import sun.security.ssl.SupportedGroupsExtension.SupportedGroups; - enum X509Authentication implements SSLAuthentication { // Require rsaEncryption public key RSA ("RSA", "RSA"), @@ -344,7 +342,7 @@ private static SSLPossession createServerPossession( ((ECPublicKey) serverPublicKey).getParams(); NamedGroup namedGroup = NamedGroup.valueOf(params); if ((namedGroup == null) || - (!SupportedGroups.isSupported(namedGroup)) || + (!NamedGroup.isEnabled(shc.sslConfig, namedGroup)) || ((shc.clientRequestedNamedGroups != null) && !shc.clientRequestedNamedGroups.contains(namedGroup))) { diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java new file mode 100644 index 00000000000..e9165fa391c --- /dev/null +++ b/test/jdk/javax/net/ssl/DTLS/DTLSNamedGroups.java @@ -0,0 +1,143 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8281236 + * @summary Check DTLS connection behaviors for named groups configuration + * @modules java.base/sun.security.util + * @library /test/lib + * @build DTLSOverDatagram + * @run main/othervm DTLSNamedGroups + */ + +import javax.net.ssl.SSLEngine; +import javax.net.ssl.SSLParameters; +import java.security.Security; + +/** + * Test DTLS client authentication. + */ +public class DTLSNamedGroups extends DTLSOverDatagram { + // Make sure default DH(E) key exchange is not used for DTLS v1.2. + private static String[] cipherSuites = new String[] { + "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256" + }; + + private final String[] serverNamedGroups; + private final String[] clientNamedGroups; + + public DTLSNamedGroups(String[] serverNamedGroups, + String[] clientNamedGroups) { + this.serverNamedGroups = serverNamedGroups; + this.clientNamedGroups = clientNamedGroups; + } + + @Override + SSLEngine createSSLEngine(boolean isClient) throws Exception { + SSLEngine engine = super.createSSLEngine(isClient); + + SSLParameters sslParameters = engine.getSSLParameters(); + if (isClient) { + sslParameters.setNamedGroups(clientNamedGroups); + sslParameters.setCipherSuites(cipherSuites); + } else { + sslParameters.setNamedGroups(serverNamedGroups); + } + engine.setSSLParameters(sslParameters); + + return engine; + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + runTest(new String[] { + "x25519", + "secp256r1" + }, + new String[] { + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + new String[] { + "secp256r1" + }, + false); + runTest(null, + new String[] { + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + null, + false); + runTest(new String[0], + new String[] { + "secp256r1" + }, + true); + runTest(new String[] { + "secp256r1" + }, + new String[0], + true); + runTest(new String[] { + "secp256NA" + }, + new String[] { + "secp256r1" + }, + true); + } + + private static void runTest(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) throws Exception { + DTLSNamedGroups testCase = new DTLSNamedGroups( + serverNamedGroups, clientNamedGroups); + try { + testCase.runTest(testCase); + } catch (Exception e) { + if (!exceptionExpected) { + throw e; + } else { // Otherwise, swallow the expected exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + } +} + diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java new file mode 100644 index 00000000000..fc5001e89b8 --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroups.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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. + */ + +// SunJSSE does not support dynamic system properties, no way to re-use +// system properties in samevm/agentvm mode. + +/* + * @test + * @bug 8281236 + * @summary Check TLS connection behaviors for named groups configuration + * @library /javax/net/ssl/templates + * @run main/othervm NamedGroups + */ + +import javax.net.ssl.SSLParameters; +import javax.net.ssl.SSLServerSocket; +import javax.net.ssl.SSLSocket; +import java.security.Security; + +public class NamedGroups extends SSLSocketTemplate { + private final String[] serverNamedGroups; + private final String[] clientNamedGroups; + private final boolean exceptionExpected; + + public NamedGroups(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) { + this.serverNamedGroups = serverNamedGroups; + this.clientNamedGroups = clientNamedGroups; + this.exceptionExpected = exceptionExpected; + } + + @Override + protected void configureServerSocket(SSLServerSocket sslServerSocket) { + SSLParameters sslParameters = sslServerSocket.getSSLParameters(); + sslParameters.setNamedGroups(serverNamedGroups); + sslServerSocket.setSSLParameters(sslParameters); + } + + @Override + protected void configureClientSocket(SSLSocket socket) { + SSLParameters sslParameters = socket.getSSLParameters(); + sslParameters.setNamedGroups(clientNamedGroups); + socket.setSSLParameters(sslParameters); + } + + @Override + protected void runServerApplication(SSLSocket socket) { + try { + super.runServerApplication(socket); + } catch (Exception ex) { + // Just ignore, let the client handle the failure information. + } + } + + @Override + protected void runClientApplication(SSLSocket sslSocket) throws Exception { + try { + super.runClientApplication(sslSocket); + } catch (Exception ex) { + if (!exceptionExpected) { + throw ex; + } else { // Otherwise, swallow the exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + } + + public static void main(String[] args) throws Exception { + Security.setProperty("jdk.tls.disabledAlgorithms", ""); + + runTest(new String[] { + "x25519", + "secp256r1" + }, + new String[] { + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + new String[] { + "secp256r1" + }, + false); + runTest(null, + new String[] { + "secp256r1" + }, + false); + runTest(new String[] { + "secp256r1" + }, + null, + false); + runTest(new String[0], + new String[] { + "secp256r1" + }, + true); + runTest(new String[] { + "secp256r1" + }, + new String[0], + true); + runTest(new String[] { + "secp256NA" + }, + new String[] { + "secp256r1" + }, + true); + } + + private static void runTest(String[] serverNamedGroups, + String[] clientNamedGroups, + boolean exceptionExpected) throws Exception { + new NamedGroups(serverNamedGroups, + clientNamedGroups, exceptionExpected).run(); + } +} diff --git a/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java new file mode 100644 index 00000000000..9146e7b5f7b --- /dev/null +++ b/test/jdk/javax/net/ssl/SSLParameters/NamedGroupsSpec.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2022 THL A29 Limited, a Tencent company. All rights reserved. + * 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 8281236 + * @summary check SSLParameters.setNamedGroups() implementation + */ + +import javax.net.ssl.SSLParameters; +import java.util.Arrays; + +public class NamedGroupsSpec { + public static void main(String[] args) throws Exception { + runTest(null, // null array should be allowed. + false); + runTest(new String[] { // empty array should be allowed + // blank line + }, + false); + runTest(new String[] { // multiple elements should be fine + "x25519", + "secp256r1" + }, + false); + runTest(new String[] { // no duplicate element should be allowed + "x25519", + "x25519" + }, + true); + runTest(new String[] { // no null element should be allowed + null + }, + true); + runTest(new String[] { // no blank element should be allowed + "" + }, + true); + runTest(new String[] { // no blank element should be allowed + "x25519", + "" + }, + true); + runTest(new String[] { // no null element should be allowed. + "x25519", + null + }, + true); + } + + private static void runTest(String[] namedGroups, + boolean exceptionExpected) throws Exception { + SSLParameters sslParams = new SSLParameters(); + try { + sslParams.setNamedGroups(namedGroups); + } catch (Exception ex) { + if (!exceptionExpected || + !(ex instanceof IllegalArgumentException)) { + throw ex; + } else { // Otherwise, swallow the exception and return. + return; + } + } + + if (exceptionExpected) { + throw new RuntimeException("Unexpected success!"); + } + + // Check if the getNamedGroups() method returns the same elements. + String[] configuredNamedGroups = sslParams.getNamedGroups(); + if (!Arrays.equals(namedGroups, configuredNamedGroups)) { + throw new RuntimeException( + "SSLParameters.getNamedGroups() method does not return " + + "the same elements as set with setNamedGroups()"); + } + } +} From 8a9911ef1762ae837e427ec9d91b1399ba33b6e4 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Wed, 7 Dec 2022 20:49:29 +0000 Subject: [PATCH 111/494] 8295803: Console should be usable in jshell and other environments Reviewed-by: jlaskey, alanb --- .../share/classes/java/io/Console.java | 49 +++-- .../share/classes/java/io/PrintWriter.java | 9 + .../classes/java/io/ProxyingConsole.java | 198 ++++++++++++++++++ .../share/classes/java/lang/System.java | 10 +- .../jdk/internal/access/JavaIOAccess.java | 4 +- .../jdk/internal/access/JavaLangAccess.java | 7 + .../classes/jdk/internal/io/JdkConsole.java | 48 +++++ .../jdk/internal/io/JdkConsoleProvider.java | 50 +++++ src/java.base/share/classes/module-info.java | 4 + .../classes/sun/security/util/Password.java | 11 +- .../org/jline/JdkConsoleProviderImpl.java | 131 ++++++++++++ .../share/classes/module-info.java | 5 +- .../java/io/Console/ModuleSelectionTest.java | 68 ++++++ test/jdk/java/io/Console/RedirectTest.java | 61 ++++++ .../java/io/Console/SecurityManagerTest.java | 35 ++++ test/jdk/java/io/Console/input.txt | 3 + test/jdk/java/io/Console/test.policy | 3 + 17 files changed, 673 insertions(+), 23 deletions(-) create mode 100644 src/java.base/share/classes/java/io/ProxyingConsole.java create mode 100644 src/java.base/share/classes/jdk/internal/io/JdkConsole.java create mode 100644 src/java.base/share/classes/jdk/internal/io/JdkConsoleProvider.java create mode 100644 src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java create mode 100644 test/jdk/java/io/Console/ModuleSelectionTest.java create mode 100644 test/jdk/java/io/Console/RedirectTest.java create mode 100644 test/jdk/java/io/Console/SecurityManagerTest.java create mode 100644 test/jdk/java/io/Console/input.txt create mode 100644 test/jdk/java/io/Console/test.policy diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index 287f7d391f5..0f83a72c23d 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -25,10 +25,13 @@ package java.io; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.*; import java.nio.charset.Charset; import jdk.internal.access.JavaIOAccess; import jdk.internal.access.SharedSecrets; +import jdk.internal.io.JdkConsoleProvider; import jdk.internal.util.StaticProperty; import sun.nio.cs.StreamDecoder; import sun.nio.cs.StreamEncoder; @@ -45,7 +48,7 @@ * output streams then its console will exist and will typically be * connected to the keyboard and display from which the virtual machine * was launched. If the virtual machine is started automatically, for - * example by a background job scheduler, then it will typically not + * example by a background job scheduler, then it may not * have a console. *

    * If this virtual machine has a console then it is represented by a @@ -93,7 +96,7 @@ * @since 1.6 */ -public final class Console implements Flushable +public class Console implements Flushable { /** * Retrieves the unique {@link java.io.PrintWriter PrintWriter} object @@ -592,25 +595,43 @@ public int read(char[] cbuf, int offset, int length) CHARSET = cs; + cons = instantiateConsole(istty); + // Set up JavaIOAccess in SharedSecrets SharedSecrets.setJavaIOAccess(new JavaIOAccess() { public Console console() { - if (istty) { - if (cons == null) - cons = new Console(); - return cons; - } - return null; - } - - public Charset charset() { - return CHARSET; + return cons; } }); } - private static Console cons; + + @SuppressWarnings("removal") + private static Console instantiateConsole(boolean istty) { + try { + // Try loading providers + PrivilegedAction pa = () -> { + var consModName = System.getProperty("jdk.console", + JdkConsoleProvider.DEFAULT_PROVIDER_MODULE_NAME); + return ServiceLoader.load(ModuleLayer.boot(), JdkConsoleProvider.class).stream() + .map(ServiceLoader.Provider::get) + .filter(jcp -> consModName.equals(jcp.getClass().getModule().getName())) + .map(jcp -> jcp.console(istty, CHARSET)) + .filter(Objects::nonNull) + .findAny() + .map(jc -> (Console) new ProxyingConsole(jc)) + .orElse(istty ? new Console() : null); + }; + return AccessController.doPrivileged(pa); + } catch (ServiceConfigurationError ignore) { + // default to built-in Console + return istty ? new Console() : null; + } + } + + private static final Console cons; private static native boolean istty(); - private Console() { + + Console() { readLock = new Object(); writeLock = new Object(); out = StreamEncoder.forOutputStreamWriter( diff --git a/src/java.base/share/classes/java/io/PrintWriter.java b/src/java.base/share/classes/java/io/PrintWriter.java index a83521c3ffe..667e6c92337 100644 --- a/src/java.base/share/classes/java/io/PrintWriter.java +++ b/src/java.base/share/classes/java/io/PrintWriter.java @@ -208,6 +208,15 @@ public PrintWriter(String fileName) throws FileNotFoundException { false); } + /* Package private constructor, using the specified lock + * for synchronization. + */ + PrintWriter(Writer out, Object lock) { + super(lock); + this.out = out; + this.autoFlush = false; + } + /* Private constructor */ private PrintWriter(Charset charset, File file) throws FileNotFoundException diff --git a/src/java.base/share/classes/java/io/ProxyingConsole.java b/src/java.base/share/classes/java/io/ProxyingConsole.java new file mode 100644 index 00000000000..4be206a1590 --- /dev/null +++ b/src/java.base/share/classes/java/io/ProxyingConsole.java @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2022, 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. + */ + +package java.io; + +import java.nio.charset.Charset; +import jdk.internal.io.JdkConsole; + +/** + * Console implementation for internal use. Custom Console delegate may be + * provided with jdk.internal.io.JdkConsoleProvider. + */ +final class ProxyingConsole extends Console { + private final JdkConsole delegate; + private final Object readLock; + private final Object writeLock; + private final Reader reader; + private final PrintWriter printWriter; + + ProxyingConsole(JdkConsole delegate) { + this.delegate = delegate; + readLock = new Object(); + writeLock = new Object(); + reader = new WrappingReader(delegate.reader(), readLock); + printWriter = new WrappingWriter(delegate.writer(), writeLock); + } + + /** + * {@inheritDoc} + */ + @Override + public PrintWriter writer() { + return printWriter; + } + + /** + * {@inheritDoc} + */ + @Override + public Reader reader() { + return reader; + } + + /** + * {@inheritDoc} + */ + @Override + public Console format(String fmt, Object ... args) { + synchronized (writeLock) { + delegate.format(fmt, args); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Console printf(String format, Object ... args) { + synchronized (writeLock) { + delegate.printf(format, args); + } + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public String readLine(String fmt, Object ... args) { + synchronized (writeLock) { + synchronized (readLock) { + return delegate.readLine(fmt, args); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public String readLine() { + synchronized (readLock) { + return delegate.readLine(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public char[] readPassword(String fmt, Object ... args) { + synchronized (writeLock) { + synchronized (readLock) { + return delegate.readPassword(fmt, args); + } + } + } + + /** + * {@inheritDoc} + */ + @Override + public char[] readPassword() { + synchronized (readLock) { + return delegate.readPassword(); + } + } + + /** + * {@inheritDoc} + */ + @Override + public void flush() { + delegate.flush(); + } + + /** + * {@inheritDoc} + */ + @Override + public Charset charset() { + return delegate.charset(); + } + + private static class WrappingReader extends Reader { + private final Reader r; + private final Object lock; + + WrappingReader(Reader r, Object lock) { + super(lock); + this.r = r; + this.lock = lock; + } + + @Override + public int read(char[] cbuf, int off, int len) throws IOException { + synchronized (lock) { + return r.read(cbuf, off, len); + } + } + + @Override + public void close() { + // no-op, per Console's spec + } + } + + private static class WrappingWriter extends PrintWriter { + private final PrintWriter pw; + private final Object lock; + + public WrappingWriter(PrintWriter pw, Object lock) { + super(pw, lock); + this.pw = pw; + this.lock = lock; + } + + @Override + public void write(char[] cbuf, int off, int len) { + synchronized (lock) { + pw.write(cbuf, off, len); + } + } + + @Override + public void flush() { + pw.flush(); + } + + @Override + public void close() { + // no-op, per Console's spec + } + } +} diff --git a/src/java.base/share/classes/java/lang/System.java b/src/java.base/share/classes/java/lang/System.java index 455a521d11e..cdb5ec4bcd7 100644 --- a/src/java.base/share/classes/java/lang/System.java +++ b/src/java.base/share/classes/java/lang/System.java @@ -189,6 +189,9 @@ private System() { */ public static final PrintStream err = null; + // Holder for the initial value of `in`, set within `initPhase1()`. + private static InputStream initialIn; + // indicates if a security manager is possible private static final int NEVER = 1; private static final int MAYBE = 2; @@ -2174,7 +2177,8 @@ private static void initPhase1() { FileInputStream fdIn = new FileInputStream(FileDescriptor.in); FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out); FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err); - setIn0(new BufferedInputStream(fdIn)); + initialIn = new BufferedInputStream(fdIn); + setIn0(initialIn); // stdout/err.encoding are set when the VM is associated with the terminal, // thus they are equivalent to Console.charset(), otherwise the encodings // of those properties default to native.encoding @@ -2485,6 +2489,10 @@ public int encodeASCII(char[] src, int srcOff, byte[] dst, int dstOff, int len) return StringCoding.implEncodeAsciiArray(src, srcOff, dst, dstOff, len); } + public InputStream initialSystemIn() { + return initialIn; + } + public void setCause(Throwable t, Throwable cause) { t.setCause(cause); } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java index b054ec00364..532c1f259d4 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaIOAccess.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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 jdk.internal.access; import java.io.Console; -import java.nio.charset.Charset; public interface JavaIOAccess { Console console(); - Charset charset(); } diff --git a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java index 261be6bbe13..6ccc8276a48 100644 --- a/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java +++ b/src/java.base/share/classes/jdk/internal/access/JavaLangAccess.java @@ -25,6 +25,7 @@ package jdk.internal.access; +import java.io.InputStream; import java.lang.annotation.Annotation; import java.lang.invoke.MethodHandle; import java.lang.invoke.MethodType; @@ -363,6 +364,12 @@ public interface JavaLangAccess { */ int decodeASCII(byte[] src, int srcOff, char[] dst, int dstOff, int len); + /** + * Returns the initial `System.in` to determine if it is replaced + * with `System.setIn(newIn)` method + */ + InputStream initialSystemIn(); + /** * Encodes ASCII codepoints as possible from the source array into * the destination byte array, assuming that the encoding is ASCII diff --git a/src/java.base/share/classes/jdk/internal/io/JdkConsole.java b/src/java.base/share/classes/jdk/internal/io/JdkConsole.java new file mode 100644 index 00000000000..a75941fd2a5 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/io/JdkConsole.java @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2022, 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. + */ +package jdk.internal.io; + +import java.io.PrintWriter; +import java.io.Reader; +import java.nio.charset.Charset; + +/** + * Delegate interface for custom Console implementations. + * Methods defined here duplicates the ones in Console class. + * Providers should implement jdk.internal.io.JdkConsoleProvider + * to instantiate an implementation of this interface. + */ +public interface JdkConsole { + PrintWriter writer(); + Reader reader(); + JdkConsole format(String fmt, Object ... args); + JdkConsole printf(String format, Object ... args); + String readLine(String fmt, Object ... args); + String readLine(); + char[] readPassword(String fmt, Object ... args); + char[] readPassword(); + void flush(); + Charset charset(); +} diff --git a/src/java.base/share/classes/jdk/internal/io/JdkConsoleProvider.java b/src/java.base/share/classes/jdk/internal/io/JdkConsoleProvider.java new file mode 100644 index 00000000000..192c1745038 --- /dev/null +++ b/src/java.base/share/classes/jdk/internal/io/JdkConsoleProvider.java @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2022, 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. + */ +package jdk.internal.io; + +import java.nio.charset.Charset; + +/** + * Service provider interface for JdkConsole implementations. + * The provider used for instantiating JdkConsole instance can be + * specified with the system property "jdk.console", whose value + * designates the module name of the implementation, and which defaults + * to "jdk.internal.le" (jline). If no providers is available, + * or instantiation failed, java.base built-in Console implementation + * is used. + */ +public interface JdkConsoleProvider { + /** + * The module name of the JdkConsole default provider. + */ + String DEFAULT_PROVIDER_MODULE_NAME = "jdk.internal.le"; + + /** + * {@return the Console instance, or {@code null} if not available} + * @param isTTY indicates if the jvm is attached to a terminal + * @param charset charset of the platform console + */ + JdkConsole console(boolean isTTY, Charset charset); +} diff --git a/src/java.base/share/classes/module-info.java b/src/java.base/share/classes/module-info.java index a042ecc22dd..d985dec174f 100644 --- a/src/java.base/share/classes/module-info.java +++ b/src/java.base/share/classes/module-info.java @@ -174,6 +174,9 @@ jdk.incubator.vector; exports jdk.internal.event to jdk.jfr; + exports jdk.internal.io to + jdk.internal.le, + jdk.jshell; exports jdk.internal.jimage to jdk.jlink; exports jdk.internal.jimage.decompressor to @@ -409,6 +412,7 @@ // JDK-internal service types + uses jdk.internal.io.JdkConsoleProvider; uses jdk.internal.logger.DefaultLoggerFinder; uses sun.text.spi.JavaTimeDateTimePatternProvider; uses sun.util.spi.CalendarProvider; diff --git a/src/java.base/share/classes/sun/security/util/Password.java b/src/java.base/share/classes/sun/security/util/Password.java index eba907d0c86..7acece65a57 100644 --- a/src/java.base/share/classes/sun/security/util/Password.java +++ b/src/java.base/share/classes/sun/security/util/Password.java @@ -29,6 +29,7 @@ import java.nio.*; import java.nio.charset.*; import java.util.Arrays; +import jdk.internal.access.SharedSecrets; /** * A utility class for reading passwords @@ -51,13 +52,15 @@ public static char[] readPassword(InputStream in, boolean isEchoOn) byte[] consoleBytes = null; try { - // Use the new java.io.Console class + // Only use Console if `in` is the initial System.in Console con; - if (!isEchoOn && in == System.in && ((con = System.console()) != null)) { + if (!isEchoOn && + in == SharedSecrets.getJavaLangAccess().initialSystemIn() && + ((con = System.console()) != null)) { consoleEntered = con.readPassword(); - // readPassword returns "" if you just print ENTER, + // readPassword returns "" if you just press ENTER with the built-in Console, // to be compatible with old Password class, change to null - if (consoleEntered != null && consoleEntered.length == 0) { + if (consoleEntered == null || consoleEntered.length == 0) { return null; } consoleBytes = convertToBytes(consoleEntered); diff --git a/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java new file mode 100644 index 00000000000..2cafa56a30b --- /dev/null +++ b/src/jdk.internal.le/share/classes/jdk/internal/org/jline/JdkConsoleProviderImpl.java @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2022, 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. + */ + +package jdk.internal.org.jline; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.UncheckedIOException; +import java.nio.charset.Charset; + +import jdk.internal.io.JdkConsole; +import jdk.internal.io.JdkConsoleProvider; +import jdk.internal.org.jline.reader.EndOfFileException; +import jdk.internal.org.jline.reader.LineReader; +import jdk.internal.org.jline.reader.LineReaderBuilder; +import jdk.internal.org.jline.terminal.Terminal; +import jdk.internal.org.jline.terminal.TerminalBuilder; + +/** + * JdkConsole/Provider implementations for jline + */ +public class JdkConsoleProviderImpl implements JdkConsoleProvider { + + /** + * {@inheritDoc} + */ + @Override + public JdkConsole console(boolean isTTY, Charset charset) { + return new JdkConsoleImpl(charset); + } + + /** + * An implementation of JdkConsole, which act as a delegate for the + * public Console class. + */ + private static class JdkConsoleImpl implements JdkConsole { + @Override + public PrintWriter writer() { + return terminal.writer(); + } + + @Override + public Reader reader() { + return terminal.reader(); + } + + @Override + public JdkConsole format(String fmt, Object ... args) { + writer().format(fmt, args).flush(); + return this; + } + + @Override + public JdkConsole printf(String format, Object ... args) { + return format(format, args); + } + + @Override + public String readLine(String fmt, Object ... args) { + try { + return jline.readLine(fmt.formatted(args)); + } catch (EndOfFileException eofe) { + return null; + } + } + + @Override + public String readLine() { + return readLine(""); + } + + @Override + public char[] readPassword(String fmt, Object ... args) { + try { + return jline.readLine(fmt.formatted(args), '\0').toCharArray(); + } catch (EndOfFileException eofe) { + return null; + } + } + + @Override + public char[] readPassword() { + return readPassword(""); + } + + @Override + public void flush() { + terminal.flush(); + } + + @Override + public Charset charset() { + return terminal.encoding(); + } + + private final LineReader jline; + private final Terminal terminal; + + public JdkConsoleImpl(Charset charset) { + try { + terminal = TerminalBuilder.builder().encoding(charset).build(); + jline = LineReaderBuilder.builder().terminal(terminal).build(); + } catch (IOException ioe) { + throw new UncheckedIOException(ioe); + } + } + } +} diff --git a/src/jdk.internal.le/share/classes/module-info.java b/src/jdk.internal.le/share/classes/module-info.java index a47e07cd784..127bd7aeb78 100644 --- a/src/jdk.internal.le/share/classes/module-info.java +++ b/src/jdk.internal.le/share/classes/module-info.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -50,5 +50,8 @@ uses jdk.internal.org.jline.terminal.spi.JnaSupport; + // Console + provides jdk.internal.io.JdkConsoleProvider with + jdk.internal.org.jline.JdkConsoleProviderImpl; } diff --git a/test/jdk/java/io/Console/ModuleSelectionTest.java b/test/jdk/java/io/Console/ModuleSelectionTest.java new file mode 100644 index 00000000000..c7e66d0c317 --- /dev/null +++ b/test/jdk/java/io/Console/ModuleSelectionTest.java @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022, 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 8295803 + * @summary Tests System.console() returns correct Console (or null) from the expected + * module. + * @modules java.base/java.io:+open + * @run main/othervm ModuleSelectionTest jdk.internal.le + * @run main/othervm -Djdk.console=jdk.internal.le ModuleSelectionTest jdk.internal.le + * @run main/othervm -Djdk.console=java.base ModuleSelectionTest java.base + * @run main/othervm --limit-modules java.base ModuleSelectionTest java.base + */ + +import java.io.Console; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class ModuleSelectionTest { + public static void main(String... args) throws Throwable { + var con = System.console(); + var pc = Class.forName("java.io.ProxyingConsole"); + var jdkc = Class.forName("jdk.internal.io.JdkConsole"); + var istty = (boolean)MethodHandles.privateLookupIn(Console.class, MethodHandles.lookup()) + .findStatic(Console.class, "istty", MethodType.methodType(boolean.class)) + .invoke(); + var impl = con != null ? MethodHandles.privateLookupIn(pc, MethodHandles.lookup()) + .findGetter(pc, "delegate", jdkc) + .invoke(con) : null; + + var expected = switch (args[0]) { + case "java.base" -> istty ? "java.base" : "null"; + default -> args[0]; + }; + var actual = con == null ? "null" : impl.getClass().getModule().getName(); + + if (!actual.equals(expected)) { + throw new RuntimeException(""" + Console implementation is not the expected one. + Expected: %s + Actual: %s + """.formatted(expected, actual)); + } else { + System.out.printf("%s is the expected implementation. (tty: %s)\n", impl, istty); + } + } +} diff --git a/test/jdk/java/io/Console/RedirectTest.java b/test/jdk/java/io/Console/RedirectTest.java new file mode 100644 index 00000000000..8b55bd488d7 --- /dev/null +++ b/test/jdk/java/io/Console/RedirectTest.java @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.io.File; +import java.nio.file.Files; + +import jdk.test.lib.process.ProcessTools; + +/** + * @test + * @bug 8295803 + * @summary Tests System.console() works with standard input redirection. + * @library /test/lib + */ +public class RedirectTest { + public static void main(String... args) throws Throwable { + if (args.length == 0) { + // no arg will launch the child process that actually perform tests + var pb = ProcessTools.createTestJvm("RedirectTest", "dummy"); + var input = new File(System.getProperty("test.src", "."), "input.txt"); + pb.redirectInput(input); + var oa = ProcessTools.executeProcess(pb); + var output = oa.asLines(); + var expected = Files.readAllLines(input.toPath()); + if (!output.equals(expected)) { + throw new RuntimeException(""" + Standard out had unexpected strings: + Actual output: %s + Expected output: %s + """.formatted(output, expected)); + } + oa.shouldHaveExitValue(0); + } else { + var con = System.console(); + String line; + while ((line = con.readLine()) != null) { + System.out.println(line); + } + } + } +} diff --git a/test/jdk/java/io/Console/SecurityManagerTest.java b/test/jdk/java/io/Console/SecurityManagerTest.java new file mode 100644 index 00000000000..5eed29a7669 --- /dev/null +++ b/test/jdk/java/io/Console/SecurityManagerTest.java @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, 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 8295803 + * @summary Tests System.console() works with the security manager + * @run main/othervm/java.security.policy=test.policy -Djava.security.manager -Djdk.console=jdk.internal.le SecurityManagerTest + */ +public class SecurityManagerTest { + public static void main(String... args) { + System.console(); + // consider it successful if ServiceConfigurationError was not thrown here + } +} diff --git a/test/jdk/java/io/Console/input.txt b/test/jdk/java/io/Console/input.txt new file mode 100644 index 00000000000..9387db2c697 --- /dev/null +++ b/test/jdk/java/io/Console/input.txt @@ -0,0 +1,3 @@ +This is line 1 +This is line 2 +This is the last line diff --git a/test/jdk/java/io/Console/test.policy b/test/jdk/java/io/Console/test.policy new file mode 100644 index 00000000000..61fda0ca63a --- /dev/null +++ b/test/jdk/java/io/Console/test.policy @@ -0,0 +1,3 @@ +grant { + permission java.io.FilePermission "<>","read,write,delete"; +}; From 8b69a2e434ad2fa3369079622b57afb973d5bd9a Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 7 Dec 2022 22:11:11 +0000 Subject: [PATCH 112/494] 8298099: [JVMCI] decouple libgraal from JVMCI module at runtime Reviewed-by: never --- src/hotspot/share/classfile/classLoader.cpp | 33 +++- src/hotspot/share/classfile/classLoader.hpp | 4 + src/hotspot/share/classfile/vmSymbols.hpp | 4 + src/hotspot/share/jvmci/jvmci.cpp | 15 +- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 17 +- src/hotspot/share/jvmci/jvmciEnv.cpp | 181 ++++++++++-------- src/hotspot/share/jvmci/jvmciEnv.hpp | 21 +- src/hotspot/share/jvmci/jvmciJavaClasses.cpp | 2 +- src/hotspot/share/jvmci/jvmciJavaClasses.hpp | 6 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 35 +++- src/hotspot/share/jvmci/vmSymbols_jvmci.hpp | 3 - src/hotspot/share/runtime/arguments.cpp | 6 +- .../jdk/internal/vm}/TranslatedException.java | 94 +++++---- .../classes/jdk/internal/vm/VMSupport.java | 79 +++++++- .../vm/ci/hotspot/HotSpotJVMCIRuntime.java | 62 +----- .../src/jdk/vm/ci/services/Services.java | 112 +---------- .../jdk/vm/ci/hotspot/test/TestServices.java | 93 --------- .../internal/vm}/TestTranslatedException.java | 73 +++---- 18 files changed, 377 insertions(+), 463 deletions(-) rename src/{jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot => java.base/share/classes/jdk/internal/vm}/TranslatedException.java (73%) delete mode 100644 test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java rename test/{hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test => jdk/jdk/internal/vm}/TestTranslatedException.java (56%) diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index 95153d07fe1..534412cb0f7 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -671,6 +671,18 @@ void ClassLoader::setup_bootstrap_search_path_impl(JavaThread* current, const ch } } +// Gets the exploded path for the named module. The memory for the path +// is allocated on the C heap if `c_heap` is true otherwise in the resource area. +static const char* get_exploded_module_path(const char* module_name, bool c_heap) { + const char *home = Arguments::get_java_home(); + const char file_sep = os::file_separator()[0]; + // 10 represents the length of "modules" + 2 file separators + \0 + size_t len = strlen(home) + strlen(module_name) + 10; + char *path = c_heap ? NEW_C_HEAP_ARRAY(char, len, mtModule) : NEW_RESOURCE_ARRAY(char, len); + jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name); + return path; +} + // During an exploded modules build, each module defined to the boot loader // will be added to the ClassLoader::_exploded_entries array. void ClassLoader::add_to_exploded_build_list(JavaThread* current, Symbol* module_sym) { @@ -680,12 +692,7 @@ void ClassLoader::add_to_exploded_build_list(JavaThread* current, Symbol* module // Find the module's symbol ResourceMark rm(current); const char *module_name = module_sym->as_C_string(); - const char *home = Arguments::get_java_home(); - const char file_sep = os::file_separator()[0]; - // 10 represents the length of "modules" + 2 file separators + \0 - size_t len = strlen(home) + strlen(module_name) + 10; - char *path = NEW_RESOURCE_ARRAY(char, len); - jio_snprintf(path, len, "%s%cmodules%c%s", home, file_sep, file_sep, module_name); + const char *path = get_exploded_module_path(module_name, false); struct stat st; if (os::stat(path, &st) == 0) { @@ -1415,6 +1422,20 @@ char* ClassLoader::lookup_vm_options() { return options; } +bool ClassLoader::is_module_observable(const char* module_name) { + assert(JImageOpen != NULL, "jimage library should have been opened"); + if (JImage_file == NULL) { + struct stat st; + const char *path = get_exploded_module_path(module_name, true); + bool res = os::stat(path, &st) == 0; + FREE_C_HEAP_ARRAY(char, path); + return res; + } + jlong size; + const char *jimage_version = get_jimage_version_string(); + return (*JImageFindResource)(JImage_file, module_name, jimage_version, "module-info.class", &size) != 0; +} + #if INCLUDE_CDS void ClassLoader::initialize_shared_path(JavaThread* current) { if (Arguments::is_dumping_archive()) { diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index 20e60b2e210..56aa0977739 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -374,6 +374,10 @@ class ClassLoader: AllStatic { static char* lookup_vm_options(); + // Determines if the named module is present in the + // modules jimage file or in the exploded modules directory. + static bool is_module_observable(const char* module_name); + static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name, const char* file_name, jlong &size); diff --git a/src/hotspot/share/classfile/vmSymbols.hpp b/src/hotspot/share/classfile/vmSymbols.hpp index 6804c49fb2c..891292be7b8 100644 --- a/src/hotspot/share/classfile/vmSymbols.hpp +++ b/src/hotspot/share/classfile/vmSymbols.hpp @@ -745,6 +745,10 @@ do_alias(appendToClassPathForInstrumentation_signature, string_void_signature) \ template(serializePropertiesToByteArray_name, "serializePropertiesToByteArray") \ template(serializeAgentPropertiesToByteArray_name, "serializeAgentPropertiesToByteArray") \ + template(serializeSavedPropertiesToByteArray_name, "serializeSavedPropertiesToByteArray") \ + template(encodeThrowable_name, "encodeThrowable") \ + template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \ + template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(classRedefinedCount_name, "classRedefinedCount") \ template(classLoader_name, "classLoader") \ template(componentType_name, "componentType") \ diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index c14c3553c68..e1b26c18dfb 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -35,6 +35,7 @@ #include "memory/universe.hpp" #include "runtime/arguments.hpp" #include "runtime/atomic.hpp" +#include "runtime/javaThread.inline.hpp" #include "runtime/os.hpp" #include "utilities/events.hpp" @@ -228,9 +229,17 @@ void JVMCI::vlog(int level, const char* format, va_list ap) { void JVMCI::vtrace(int level, const char* format, va_list ap) { if (JVMCITraceLevel >= level) { Thread* thread = Thread::current_or_null_safe(); - if (thread != nullptr) { - ResourceMark rm; - tty->print("JVMCITrace-%d[%s]:%*c", level, thread->name(), level, ' '); + if (thread != nullptr && thread->is_Java_thread()) { + ResourceMark rm(thread); + JavaThreadState state = JavaThread::cast(thread)->thread_state(); + if (state == _thread_in_vm || state == _thread_in_Java || state == _thread_new) { + tty->print("JVMCITrace-%d[%s]:%*c", level, thread->name(), level, ' '); + } else { + // According to check_access_thread_state, it's unsafe to + // resolve the j.l.Thread object unless the thread is in + // one of the states above. + tty->print("JVMCITrace-%d[%s@" PTR_FORMAT "]:%*c", level, thread->type_name(), p2i(thread), level, ' '); + } } else { tty->print("JVMCITrace-%d[?]:%*c", level, level, ' '); } diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index ca37d3e3e1c..181cb97ed87 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -142,8 +142,8 @@ static JavaThread* get_current_thread(bool allow_null=true) { err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return; \ } \ - JVMCITraceMark jtm("CompilerToVM::" #name); \ - C2V_BLOCK(result_type, name, signature) + C2V_BLOCK(result_type, name, signature) \ + JVMCITraceMark jtm("CompilerToVM::" #name); #define C2V_VMENTRY_(result_type, name, signature, result) \ JNIEXPORT result_type JNICALL c2v_ ## name signature { \ @@ -153,8 +153,8 @@ static JavaThread* get_current_thread(bool allow_null=true) { err_msg("Cannot call into HotSpot from JVMCI shared library without attaching current thread")); \ return result; \ } \ - JVMCITraceMark jtm("CompilerToVM::" #name); \ - C2V_BLOCK(result_type, name, signature) + C2V_BLOCK(result_type, name, signature) \ + JVMCITraceMark jtm("CompilerToVM::" #name); #define C2V_VMENTRY_NULL(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, NULL) #define C2V_VMENTRY_0(result_type, name, signature) C2V_VMENTRY_(result_type, name, signature, 0) @@ -503,7 +503,7 @@ C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGU } else { // Use the System class loader class_loader = Handle(THREAD, SystemDictionary::java_system_loader()); - JVMCIENV->runtime()->initialize(JVMCIENV); + JVMCIENV->runtime()->initialize(JVMCI_CHECK_NULL); } if (resolve) { @@ -2312,9 +2312,9 @@ C2V_VMENTRY_PREFIX(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject c2vm // Called from unattached JVMCI shared library thread return false; } - JVMCITraceMark jtm("isCurrentThreadAttached"); if (thread->jni_environment() == env) { C2V_BLOCK(jboolean, isCurrentThreadAttached, (JNIEnv* env, jobject)) + JVMCITraceMark jtm("isCurrentThreadAttached"); requireJVMCINativeLibrary(JVMCI_CHECK_0); JVMCIRuntime* runtime = thread->libjvmci_runtime(); if (runtime == nullptr || !runtime->has_shared_library_javavm()) { @@ -2331,7 +2331,6 @@ C2V_VMENTRY_PREFIX(jlong, getCurrentJavaThread, (JNIEnv* env, jobject c2vm)) // Called from unattached JVMCI shared library thread return 0L; } - JVMCITraceMark jtm("getCurrentJavaThread"); return (jlong) p2i(thread); C2V_END @@ -2377,10 +2376,10 @@ C2V_VMENTRY_PREFIX(jboolean, attachCurrentThread, (JNIEnv* env, jobject c2vm, jb attachSharedLibraryThread(env, name, as_daemon); return true; } - JVMCITraceMark jtm("attachCurrentThread"); if (thread->jni_environment() == env) { // Called from HotSpot C2V_BLOCK(jboolean, attachCurrentThread, (JNIEnv* env, jobject, jboolean)) + JVMCITraceMark jtm("attachCurrentThread"); requireJVMCINativeLibrary(JVMCI_CHECK_0); JVMCIRuntime* runtime = JVMCI::compiler_runtime(thread); @@ -2435,10 +2434,10 @@ C2V_VMENTRY_PREFIX(jboolean, detachCurrentThread, (JNIEnv* env, jobject c2vm, jb // Called from unattached JVMCI shared library thread JNI_THROW_("detachCurrentThread", IllegalStateException, "Cannot detach non-attached thread", false); } - JVMCITraceMark jtm("detachCurrentThread"); if (thread->jni_environment() == env) { // Called from HotSpot C2V_BLOCK(void, detachCurrentThread, (JNIEnv* env, jobject)) + JVMCITraceMark jtm("detachCurrentThread"); requireJVMCINativeLibrary(JVMCI_CHECK_0); requireInHotSpot("detachCurrentThread", JVMCI_CHECK_0); JVMCIRuntime* runtime = thread->libjvmci_runtime(); diff --git a/src/hotspot/share/jvmci/jvmciEnv.cpp b/src/hotspot/share/jvmci/jvmciEnv.cpp index 346dd046a7c..41ea554a505 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.cpp +++ b/src/hotspot/share/jvmci/jvmciEnv.cpp @@ -39,11 +39,15 @@ #include "runtime/deoptimization.hpp" #include "runtime/jniHandles.inline.hpp" #include "runtime/javaCalls.hpp" +#include "runtime/thread.inline.hpp" #include "runtime/os.hpp" #include "jvmci/jniAccessMark.inline.hpp" #include "jvmci/jvmciCompiler.hpp" #include "jvmci/jvmciRuntime.hpp" +jbyte* JVMCIEnv::_serialized_saved_properties = nullptr; +int JVMCIEnv::_serialized_saved_properties_len = 0; + JVMCICompileState::JVMCICompileState(CompileTask* task, JVMCICompiler* compiler): _task(task), _compiler(compiler), @@ -98,61 +102,73 @@ bool JVMCICompileState::jvmti_state_changed() const { return false; } -void JVMCIEnv::copy_saved_properties() { - assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image"); - - JavaThread* THREAD = JavaThread::current(); // For exception macros. +jbyte* JVMCIEnv::get_serialized_saved_properties(int& props_len, TRAPS) { + jbyte* props = _serialized_saved_properties; + if (props == nullptr) { + // load VMSupport + Symbol* klass = vmSymbols::jdk_internal_vm_VMSupport(); + Klass* k = SystemDictionary::resolve_or_fail(klass, true, CHECK_NULL); - Klass* k = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_services_Services(), Handle(), Handle(), true, THREAD); - if (HAS_PENDING_EXCEPTION) { - JVMCIRuntime::fatal_exception(NULL, "Error initializing jdk.vm.ci.services.Services"); - } - InstanceKlass* ik = InstanceKlass::cast(k); - if (ik->should_be_initialized()) { - ik->initialize(THREAD); - if (HAS_PENDING_EXCEPTION) { - JVMCIRuntime::fatal_exception(NULL, "Error initializing jdk.vm.ci.services.Services"); + InstanceKlass* ik = InstanceKlass::cast(k); + if (ik->should_be_initialized()) { + ik->initialize(CHECK_NULL); } - } - // Get the serialized saved properties from HotSpot - TempNewSymbol serializeSavedProperties = SymbolTable::new_symbol("serializeSavedProperties"); - JavaValue result(T_OBJECT); - JavaCallArguments args; - JavaCalls::call_static(&result, ik, serializeSavedProperties, vmSymbols::void_byte_array_signature(), &args, THREAD); - if (HAS_PENDING_EXCEPTION) { - JVMCIRuntime::fatal_exception(NULL, "Error calling jdk.vm.ci.services.Services.serializeSavedProperties"); + // invoke the serializeSavedPropertiesToByteArray method + JavaValue result(T_OBJECT); + JavaCallArguments args; + + Symbol* signature = vmSymbols::void_byte_array_signature(); + JavaCalls::call_static(&result, + ik, + vmSymbols::serializeSavedPropertiesToByteArray_name(), + signature, + &args, + CHECK_NULL); + + oop res = result.get_oop(); + assert(res->is_typeArray(), "must be"); + assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be"); + typeArrayOop ba = typeArrayOop(res); + props_len = ba->length(); + + // Copy serialized saved properties from HotSpot object into C heap + props = NEW_C_HEAP_ARRAY(jbyte, props_len, mtJVMCI); + memcpy(props, ba->byte_at_addr(0), props_len); + + _serialized_saved_properties_len = props_len; + _serialized_saved_properties = props; + } else { + props_len = _serialized_saved_properties_len; } - oop res = result.get_oop(); - assert(res->is_typeArray(), "must be"); - assert(TypeArrayKlass::cast(res->klass())->element_type() == T_BYTE, "must be"); - typeArrayOop ba = typeArrayOop(res); - int serialized_properties_len = ba->length(); + return props; +} - // Copy serialized saved properties from HotSpot object into native buffer - jbyte* serialized_properties = NEW_RESOURCE_ARRAY(jbyte, serialized_properties_len); - memcpy(serialized_properties, ba->byte_at_addr(0), serialized_properties_len); +void JVMCIEnv::copy_saved_properties(jbyte* properties, int properties_len, JVMCI_TRAPS) { + assert(!is_hotspot(), "can only copy saved properties from HotSpot to native image"); + JavaThread* thread = JavaThread::current(); // For exception macros. // Copy native buffer into shared library object - JVMCIPrimitiveArray buf = new_byteArray(serialized_properties_len, this); + JVMCIPrimitiveArray buf = new_byteArray(properties_len, this); if (has_pending_exception()) { - describe_pending_exception(true); - fatal("Error in copy_saved_properties"); + _runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties"); } - copy_bytes_from(serialized_properties, buf, 0, serialized_properties_len); + copy_bytes_from(properties, buf, 0, properties_len); if (has_pending_exception()) { - describe_pending_exception(true); - fatal("Error in copy_saved_properties"); + _runtime->fatal_exception(JVMCIENV, "Error in copy_saved_properties"); } // Initialize saved properties in shared library jclass servicesClass = JNIJVMCI::Services::clazz(); jmethodID initializeSavedProperties = JNIJVMCI::Services::initializeSavedProperties_method(); - JNIAccessMark jni(this, THREAD); - jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject()); - if (jni()->ExceptionCheck()) { - jni()->ExceptionDescribe(); - fatal("Error calling jdk.vm.ci.services.Services.initializeSavedProperties"); + bool exception = false; + { + JNIAccessMark jni(this, thread); + jni()->CallStaticVoidMethod(servicesClass, initializeSavedProperties, buf.as_jobject()); + exception = jni()->ExceptionCheck(); + } + if (exception) { + _runtime->fatal_exception(JVMCIENV, "Error calling jdk.vm.ci.services.Services.initializeSavedProperties"); } } @@ -302,39 +318,40 @@ class ExceptionTranslation: public StackObj { // Encodes the exception in `_from_env` into `buffer`. // Where N is the number of bytes needed for the encoding, returns N if N <= `buffer_size` // and the encoding was written to `buffer` otherwise returns -N. - virtual int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) = 0; + virtual int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) = 0; // Decodes the exception in `buffer` in `_to_env` and throws it. - virtual void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) = 0; + virtual void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) = 0; public: void doit(JavaThread* THREAD) { - // Resolve HotSpotJVMCIRuntime class explicitly as HotSpotJVMCI::compute_offsets + // Resolve VMSupport class explicitly as HotSpotJVMCI::compute_offsets // may not have been called. - Klass* runtimeKlass = SystemDictionary::resolve_or_fail(vmSymbols::jdk_vm_ci_hotspot_HotSpotJVMCIRuntime(), true, CHECK); + Klass* vmSupport = SystemDictionary::resolve_or_fail(vmSymbols::jdk_internal_vm_VMSupport(), true, THREAD); + guarantee(!HAS_PENDING_EXCEPTION, ""); int buffer_size = 2048; while (true) { ResourceMark rm; jlong buffer = (jlong) NEW_RESOURCE_ARRAY_IN_THREAD_RETURN_NULL(THREAD, jbyte, buffer_size); if (buffer == 0L) { - decode(THREAD, runtimeKlass, 0L); + decode(THREAD, vmSupport, 0L); return; } - int res = encode(THREAD, runtimeKlass, buffer, buffer_size); + int res = encode(THREAD, vmSupport, buffer, buffer_size); if (_from_env != nullptr && !_from_env->is_hotspot() && _from_env->has_pending_exception()) { // Cannot get name of exception thrown by `encode` as that involves // calling into libjvmci which in turn can raise another exception. _from_env->clear_pending_exception(); - decode(THREAD, runtimeKlass, -2L); + decode(THREAD, vmSupport, -2L); return; } else if (HAS_PENDING_EXCEPTION) { Symbol *ex_name = PENDING_EXCEPTION->klass()->name(); CLEAR_PENDING_EXCEPTION; if (ex_name == vmSymbols::java_lang_OutOfMemoryError()) { - decode(THREAD, runtimeKlass, -1L); + decode(THREAD, vmSupport, -1L); } else { - decode(THREAD, runtimeKlass, -2L); + decode(THREAD, vmSupport, -2L); } return; } else if (res < 0) { @@ -343,9 +360,9 @@ class ExceptionTranslation: public StackObj { buffer_size = required_buffer_size; } } else { - decode(THREAD, runtimeKlass, buffer); + decode(THREAD, vmSupport, buffer); if (!_to_env->has_pending_exception()) { - _to_env->throw_InternalError("HotSpotJVMCIRuntime.decodeAndThrowThrowable should have thrown an exception"); + _to_env->throw_InternalError("decodeAndThrowThrowable should have thrown an exception"); } return; } @@ -358,23 +375,23 @@ class HotSpotToSharedLibraryExceptionTranslation : public ExceptionTranslation { private: const Handle& _throwable; - int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) { + int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) { JavaCallArguments jargs; jargs.push_oop(_throwable); jargs.push_long(buffer); jargs.push_int(buffer_size); JavaValue result(T_INT); JavaCalls::call_static(&result, - runtimeKlass, + vmSupport, vmSymbols::encodeThrowable_name(), vmSymbols::encodeThrowable_signature(), &jargs, THREAD); return result.get_jint(); } - void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) { + void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) { JNIAccessMark jni(_to_env, THREAD); - jni()->CallStaticVoidMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), - JNIJVMCI::HotSpotJVMCIRuntime::decodeAndThrowThrowable_method(), + jni()->CallStaticVoidMethod(JNIJVMCI::VMSupport::clazz(), + JNIJVMCI::VMSupport::decodeAndThrowThrowable_method(), buffer); } public: @@ -387,19 +404,19 @@ class SharedLibraryToHotSpotExceptionTranslation : public ExceptionTranslation { private: jthrowable _throwable; - int encode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer, int buffer_size) { + int encode(JavaThread* THREAD, Klass* vmSupport, jlong buffer, int buffer_size) { JNIAccessMark jni(_from_env, THREAD); - return jni()->CallStaticIntMethod(JNIJVMCI::HotSpotJVMCIRuntime::clazz(), - JNIJVMCI::HotSpotJVMCIRuntime::encodeThrowable_method(), + return jni()->CallStaticIntMethod(JNIJVMCI::VMSupport::clazz(), + JNIJVMCI::VMSupport::encodeThrowable_method(), _throwable, buffer, buffer_size); } - void decode(JavaThread* THREAD, Klass* runtimeKlass, jlong buffer) { + void decode(JavaThread* THREAD, Klass* vmSupport, jlong buffer) { JavaCallArguments jargs; jargs.push_long(buffer); JavaValue result(T_VOID); JavaCalls::call_static(&result, - runtimeKlass, + vmSupport, vmSymbols::decodeAndThrowThrowable_name(), vmSymbols::long_void_signature(), &jargs, THREAD); } @@ -416,32 +433,35 @@ void JVMCIEnv::translate_from_jni_exception(JavaThread* THREAD, jthrowable throw SharedLibraryToHotSpotExceptionTranslation(hotspot_env, jni_env, throwable).doit(THREAD); } +jboolean JVMCIEnv::transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env) { + if (HAS_PENDING_EXCEPTION) { + Handle throwable = Handle(THREAD, PENDING_EXCEPTION); + CLEAR_PENDING_EXCEPTION; + translate_to_jni_exception(THREAD, throwable, hotspot_env, jni_env); + return true; + } + return false; +} + jboolean JVMCIEnv::transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env) { if (is_hotspot()) { - if (HAS_PENDING_EXCEPTION) { - Handle throwable = Handle(THREAD, PENDING_EXCEPTION); - CLEAR_PENDING_EXCEPTION; - translate_to_jni_exception(THREAD, throwable, this, peer_env); - return true; - } - } else { - jthrowable ex = nullptr; - { - JNIAccessMark jni(this, THREAD); - ex = jni()->ExceptionOccurred(); - if (ex != nullptr) { - jni()->ExceptionClear(); - } - } + return transfer_pending_exception_to_jni(THREAD, this, peer_env); + } + jthrowable ex = nullptr; + { + JNIAccessMark jni(this, THREAD); + ex = jni()->ExceptionOccurred(); if (ex != nullptr) { - translate_from_jni_exception(THREAD, ex, peer_env, this); - return true; + jni()->ExceptionClear(); } } + if (ex != nullptr) { + translate_from_jni_exception(THREAD, ex, peer_env, this); + return true; + } return false; } - JVMCIEnv::~JVMCIEnv() { if (_attach_threw_OOME) { return; @@ -469,7 +489,8 @@ JVMCIEnv::~JVMCIEnv() { if (has_pending_exception()) { char message[256]; - jio_snprintf(message, 256, "Uncaught exception exiting JVMCIEnv scope entered at %s:%d", _file, _line); + jio_snprintf(message, 256, "Uncaught exception exiting %s JVMCIEnv scope entered at %s:%d", + is_hotspot() ? "HotSpot" : "libjvmci", _file, _line); JVMCIRuntime::fatal_exception(this, message); } diff --git a/src/hotspot/share/jvmci/jvmciEnv.hpp b/src/hotspot/share/jvmci/jvmciEnv.hpp index fa76dfae3a2..45646daea6e 100644 --- a/src/hotspot/share/jvmci/jvmciEnv.hpp +++ b/src/hotspot/share/jvmci/jvmciEnv.hpp @@ -180,6 +180,12 @@ class JVMCIEnv : public ResourceObj { // The translated exception is pending in hotspot_env upon returning. static void translate_from_jni_exception(JavaThread* THREAD, jthrowable throwable, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env); + // Used by copy_saved_properties() to avoid OutOfMemoryErrors when + // initializing a libjvmci runtime in low HotSpot heap conditions. + // Must hold JVMCI_lock when initializing. + static jbyte* _serialized_saved_properties; + static int _serialized_saved_properties_len; + public: // Opens a JVMCIEnv scope for a Java to VM call (e.g., via CompilerToVM). // An exception occurring within the scope is left pending when the @@ -221,9 +227,13 @@ class JVMCIEnv : public ResourceObj { return _runtime; } - // Initializes Services.savedProperties in the shared library by copying - // the values from the same field in the HotSpot heap. - void copy_saved_properties(); + // Gets the serialized saved properties from the HotSpot heap. + // The length of the returned array is saved in `len`. + jbyte* get_serialized_saved_properties(int& len, TRAPS); + + // Initializes Services.savedProperties in the shared library from the given + // properties in the format produced by `get_serialized_saved_properties`. + void copy_saved_properties(jbyte* properties, int properties_len, JVMCI_TRAPS); jboolean has_pending_exception(); void clear_pending_exception(); @@ -233,6 +243,11 @@ class JVMCIEnv : public ResourceObj { // if a pending exception was transferred, false otherwise. jboolean transfer_pending_exception(JavaThread* THREAD, JVMCIEnv* peer_env); + // If there is a pending HotSpot exception, clears it and translates it to the shared library heap. + // The translated exception is pending in the shared library upon returning. + // Returns true if a pending exception was transferred, false otherwise. + static jboolean transfer_pending_exception_to_jni(JavaThread* THREAD, JVMCIEnv* hotspot_env, JVMCIEnv* jni_env); + // Prints an exception and stack trace of a pending exception. void describe_pending_exception(bool clear); diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp index f0841786c4b..2d2da32de28 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.cpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.cpp @@ -346,7 +346,7 @@ void JNIJVMCI::initialize_field_id(JNIEnv* env, jfieldID &fieldid, jclass clazz, JVMCI_event_2(" jclass for %s = " PTR_FORMAT, current_class_name, p2i(k)); \ /* SVM guarantees that jclass handles to classes in a native image are also */ \ /* in the image. Further calling NewGlobalRef on such a handle returns a stable */ \ - /* values across all JavaVMs executing on the same native image. */ \ + /* value across all JavaVMs executing on the same native image. */ \ if (current != nullptr) { \ fatal("jclass for %s re-initialized: " PTR_FORMAT " -> " PTR_FORMAT, \ current_class_name, p2i(current), p2i(k)); \ diff --git a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp index 8e73a738853..0fd0ef8c92a 100644 --- a/src/hotspot/share/jvmci/jvmciJavaClasses.hpp +++ b/src/hotspot/share/jvmci/jvmciJavaClasses.hpp @@ -191,8 +191,6 @@ objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;") \ jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \ jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature, (JVMCIObject runtime, int gcIdentifier)) \ - jvmci_method(CallStaticBooleanMethod, GetStaticMethodID, call_static, bool, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable, jlong buffer, int buffer_size)) \ - jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, HotSpotJVMCIRuntime, decodeAndThrowThrowable, long_void_signature, (jlong buffer)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \ jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, shutdown, void_method_signature, (JVMCIObject runtime)) \ jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, runtime, runtime_signature, (JVMCI_TRAPS)) \ @@ -216,6 +214,10 @@ start_class(Class, java_lang_Class) \ jvmci_method(CallObjectMethod, GetMethodID, call_virtual, JVMCIObject, Class, getName, void_string_signature, (JVMCI_TRAPS)) \ end_class \ + start_class(VMSupport, jdk_internal_vm_VMSupport) \ + jvmci_method(CallStaticIntMethod, GetStaticMethodID, call_static, int, VMSupport, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable, jlong buffer, int buffer_size)) \ + jvmci_method(CallStaticVoidMethod, GetStaticMethodID, call_static, void, VMSupport, decodeAndThrowThrowable, long_void_signature, (jlong buffer)) \ + end_class \ start_class(ArrayIndexOutOfBoundsException, java_lang_ArrayIndexOutOfBoundsException) \ jvmci_constructor(ArrayIndexOutOfBoundsException, "(Ljava/lang/String;)V") \ end_class \ diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index c7e220d2e01..96d95e65baa 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -749,7 +749,7 @@ JVM_END void JVMCIRuntime::call_getCompiler(TRAPS) { THREAD_JVMCIENV(JavaThread::current()); JVMCIObject jvmciRuntime = JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_CHECK); - initialize(JVMCIENV); + initialize(JVMCI_CHECK); JVMCIENV->call_HotSpotJVMCIRuntime_getCompiler(jvmciRuntime, JVMCI_CHECK); } @@ -1315,7 +1315,7 @@ void JVMCIRuntime::initialize_HotSpotJVMCIRuntime(JVMCI_TRAPS) { } } - initialize(JVMCIENV); + initialize(JVMCI_CHECK); // This should only be called in the context of the JVMCI class being initialized JVMCIObject result = JVMCIENV->call_HotSpotJVMCIRuntime_runtime(JVMCI_CHECK); @@ -1370,12 +1370,17 @@ class JavaVMRefsInitialization: public StackObj { } }; -void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { +void JVMCIRuntime::initialize(JVMCI_TRAPS) { // Check first without _lock if (_init_state == fully_initialized) { return; } + JavaThread* THREAD = JavaThread::current(); + + int properties_len = 0; + jbyte* properties = NULL; + MutexLocker locker(_lock); // Check again under _lock if (_init_state == fully_initialized) { @@ -1397,7 +1402,6 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { { MutexUnlocker unlock(_lock); - JavaThread* THREAD = JavaThread::current(); HandleMark hm(THREAD); ResourceMark rm(THREAD); { @@ -1441,7 +1445,12 @@ void JVMCIRuntime::initialize(JVMCIEnv* JVMCIENV) { DEBUG_ONLY(CodeInstaller::verify_bci_constants(JVMCIENV);) if (!JVMCIENV->is_hotspot()) { - JVMCIENV->copy_saved_properties(); + Handle properties_exception; + properties = JVMCIENV->get_serialized_saved_properties(properties_len, THREAD); + if (JVMCIEnv::transfer_pending_exception_to_jni(THREAD, nullptr, JVMCIENV)) { + return; + } + JVMCIENV->copy_saved_properties(properties, properties_len, JVMCI_CHECK); } } @@ -1484,7 +1493,7 @@ void JVMCIRuntime::initialize_JVMCI(JVMCI_TRAPS) { } JVMCIObject JVMCIRuntime::get_HotSpotJVMCIRuntime(JVMCI_TRAPS) { - initialize(JVMCIENV); + initialize(JVMCI_CHECK_(JVMCIObject())); initialize_JVMCI(JVMCI_CHECK_(JVMCIObject())); return _HotSpotJVMCIRuntime_instance; } @@ -1992,11 +2001,21 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c HandleMark hm(thread); JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV); if (JVMCIENV->has_pending_exception()) { - fatal_exception(JVMCIENV, "Exception during HotSpotJVMCIRuntime initialization"); + if (PrintWarnings) { + ResourceMark rm(thread); + warning("HotSpotJVMCIRuntime initialization failed when compiling %s", method->name_and_sig_as_C_string()); + JVMCIENV->describe_pending_exception(true); + } + compile_state->set_failure(false, "exception during HotSpotJVMCIRuntime initialization"); + return; } JVMCIObject jvmci_method = JVMCIENV->get_jvmci_method(method, JVMCIENV); if (JVMCIENV->has_pending_exception()) { - JVMCIENV->describe_pending_exception(true); + if (PrintWarnings) { + ResourceMark rm(thread); + warning("Error creating JVMCI wrapper for %s", method->name_and_sig_as_C_string()); + JVMCIENV->describe_pending_exception(true); + } compile_state->set_failure(false, "exception getting JVMCI wrapper method"); return; } diff --git a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp index e22cedb2f05..6624936d4d8 100644 --- a/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp +++ b/src/hotspot/share/jvmci/vmSymbols_jvmci.hpp @@ -79,9 +79,6 @@ template(compileMethod_name, "compileMethod") \ template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \ template(isGCSupported_name, "isGCSupported") \ - template(encodeThrowable_name, "encodeThrowable") \ - template(encodeThrowable_signature, "(Ljava/lang/Throwable;JI)I") \ - template(decodeAndThrowThrowable_name, "decodeAndThrowThrowable") \ template(fromMetaspace_name, "fromMetaspace") \ template(method_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \ template(constantPool_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;") \ diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 405fb123e8d..a9ca3e424af 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -1954,8 +1954,10 @@ bool Arguments::check_vm_args_consistency() { if (status && EnableJVMCI) { PropertyList_unique_add(&_system_properties, "jdk.internal.vm.ci.enabled", "true", AddProperty, UnwriteableProperty, InternalProperty); - if (!create_numbered_module_property("jdk.module.addmods", "jdk.internal.vm.ci", addmods_count++)) { - return false; + if (ClassLoader::is_module_observable("jdk.internal.vm.ci")) { + if (!create_numbered_module_property("jdk.module.addmods", "jdk.internal.vm.ci", addmods_count++)) { + return false; + } } } #endif diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java b/src/java.base/share/classes/jdk/internal/vm/TranslatedException.java similarity index 73% rename from src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java rename to src/java.base/share/classes/jdk/internal/vm/TranslatedException.java index 127a28a45f9..6907f4fec9d 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/TranslatedException.java +++ b/src/java.base/share/classes/jdk/internal/vm/TranslatedException.java @@ -4,7 +4,9 @@ * * 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. + * 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 @@ -20,13 +22,14 @@ * or visit www.oracle.com if you need additional information or have any * questions. */ -package jdk.vm.ci.hotspot; +package jdk.internal.vm; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.DataInputStream; import java.io.DataOutputStream; import java.io.IOException; +import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Arrays; @@ -35,31 +38,32 @@ import java.util.zip.GZIPInputStream; import java.util.zip.GZIPOutputStream; -import jdk.vm.ci.common.JVMCIError; - /** - * Support for translating exceptions between different runtime heaps. + * Support for translating exceptions between the HotSpot heap and libjvmci heap. */ @SuppressWarnings("serial") final class TranslatedException extends Exception { /** - * The value returned by {@link #encodeThrowable(Throwable)} when encoding fails due to an - * {@link OutOfMemoryError}. + * The value returned by {@link #encodeThrowable(Throwable)} when encoding + * fails due to an {@link OutOfMemoryError}. */ private static final byte[] FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES; /** - * The value returned by {@link #encodeThrowable(Throwable)} when encoding fails for any reason - * other than {@link OutOfMemoryError}. + * The value returned by {@link #encodeThrowable(Throwable)} when encoding + * fails for any reason other than {@link OutOfMemoryError}. */ private static final byte[] FALLBACK_ENCODED_THROWABLE_BYTES; static { try { - FALLBACK_ENCODED_THROWABLE_BYTES = encodeThrowable(new TranslatedException("error during encoding", ""), false); - FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES = encodeThrowable(new OutOfMemoryError(), false); + FALLBACK_ENCODED_THROWABLE_BYTES = + encodeThrowable(new TranslatedException("error during encoding", + ""), false); + FALLBACK_ENCODED_OUTOFMEMORYERROR_BYTES = + encodeThrowable(new OutOfMemoryError(), false); } catch (IOException e) { - throw new JVMCIError(e); + throw new InternalError(e); } } @@ -74,7 +78,8 @@ private TranslatedException(String message, String originalExceptionClassName) { } /** - * No need to record an initial stack trace since it will be manually overwritten. + * No need to record an initial stack trace since + * it will be manually overwritten. */ @SuppressWarnings("sync-override") @Override @@ -95,12 +100,14 @@ public String toString() { } /** - * Prints a stack trace for {@code throwable} and returns {@code true}. Used to print stack - * traces only when assertions are enabled. + * Prints a stack trace for {@code throwable} if the system property + * {@code "jdk.internal.vm.TranslatedException.debug"} is true. */ - private static boolean printStackTrace(Throwable throwable) { - throwable.printStackTrace(); - return true; + private static void debugPrintStackTrace(Throwable throwable) { + if (Boolean.getBoolean("jdk.internal.vm.TranslatedException.debug")) { + System.err.print("DEBUG: "); + throwable.printStackTrace(); + } } private static Throwable initCause(Throwable throwable, Throwable cause) { @@ -109,7 +116,7 @@ private static Throwable initCause(Throwable throwable, Throwable cause) { throwable.initCause(cause); } catch (IllegalStateException e) { // Cause could not be set or overwritten. - assert printStackTrace(e); + debugPrintStackTrace(e); } } return throwable; @@ -120,7 +127,8 @@ private static Throwable create(String className, String message, Throwable caus try { Class cls = Class.forName(className); if (cause != null) { - // Handle known exception types whose cause must be set in the constructor + // Handle known exception types whose cause must + // be set in the constructor if (cls == InvocationTargetException.class) { return new InvocationTargetException(cause, message); } @@ -129,10 +137,13 @@ private static Throwable create(String className, String message, Throwable caus } } if (message == null) { - return initCause((Throwable) cls.getConstructor().newInstance(), cause); + Constructor cons = cls.getConstructor(); + return initCause((Throwable) cons.newInstance(), cause); } - return initCause((Throwable) cls.getDeclaredConstructor(String.class).newInstance(message), cause); + Constructor cons = cls.getDeclaredConstructor(String.class); + return initCause((Throwable) cons.newInstance(message), cause); } catch (Throwable translationFailure) { + debugPrintStackTrace(translationFailure); return initCause(new TranslatedException(message, className), cause); } } @@ -149,7 +160,7 @@ private static String emptyAsNull(String value) { * Encodes {@code throwable} including its stack and causes as a {@linkplain GZIPOutputStream * compressed} byte array that can be decoded by {@link #decodeThrowable}. */ - static byte[] encodeThrowable(Throwable throwable) throws Throwable { + static byte[] encodeThrowable(Throwable throwable) { try { return encodeThrowable(throwable, true); } catch (OutOfMemoryError e) { @@ -159,7 +170,8 @@ static byte[] encodeThrowable(Throwable throwable) throws Throwable { } } - private static byte[] encodeThrowable(Throwable throwable, boolean withCauseAndStack) throws IOException { + private static byte[] encodeThrowable(Throwable throwable, + boolean withCauseAndStack) throws IOException { ByteArrayOutputStream baos = new ByteArrayOutputStream(); try (DataOutputStream dos = new DataOutputStream(new GZIPOutputStream(baos))) { List throwables = new ArrayList<>(); @@ -199,20 +211,20 @@ private static byte[] encodeThrowable(Throwable throwable, boolean withCauseAndS } /** - * Gets the stack of the current thread without the frames between this call and the one just - * below the frame of the first method in {@link CompilerToVM}. The chopped frames are for the - * VM call to {@link HotSpotJVMCIRuntime#decodeAndThrowThrowable}. + * Gets the stack of the current thread as of the first native method. The chopped + * frames are for the VM call to {@link VMSupport#decodeAndThrowThrowable}. */ private static StackTraceElement[] getMyStackTrace() { - StackTraceElement[] stack = new Exception().getStackTrace(); + Exception ex = new Exception(); + StackTraceElement[] stack = ex.getStackTrace(); for (int i = 0; i < stack.length; i++) { StackTraceElement e = stack[i]; - if (e.getClassName().equals(CompilerToVM.class.getName())) { + if (e.isNativeMethod()) { return Arrays.copyOfRange(stack, i, stack.length); } } - // This should never happen but since we're in exception handling - // code, just return a safe value instead raising a nested exception. + // This should never happen but since this is exception handling + // code, be defensive instead raising a nested exception. return new StackTraceElement[0]; } @@ -223,7 +235,8 @@ private static StackTraceElement[] getMyStackTrace() { * {@link #encodeThrowable} */ static Throwable decodeThrowable(byte[] encodedThrowable) { - try (DataInputStream dis = new DataInputStream(new GZIPInputStream(new ByteArrayInputStream(encodedThrowable)))) { + ByteArrayInputStream bais = new ByteArrayInputStream(encodedThrowable); + try (DataInputStream dis = new DataInputStream(new GZIPInputStream(bais))) { Throwable cause = null; Throwable throwable = null; StackTraceElement[] myStack = getMyStackTrace(); @@ -243,7 +256,13 @@ static Throwable decodeThrowable(byte[] encodedThrowable) { String methodName = emptyAsNull(dis.readUTF()); String fileName = emptyAsNull(dis.readUTF()); int lineNumber = dis.readInt(); - StackTraceElement ste = new StackTraceElement(classLoaderName, moduleName, moduleVersion, className, methodName, fileName, lineNumber); + StackTraceElement ste = new StackTraceElement(classLoaderName, + moduleName, + moduleVersion, + className, + methodName, + fileName, + lineNumber); if (ste.isNativeMethod()) { // Best effort attempt to weave stack traces from two heaps into @@ -263,13 +282,18 @@ static Throwable decodeThrowable(byte[] encodedThrowable) { while (myStackIndex < myStack.length) { stackTrace[stackTraceIndex++] = myStack[myStackIndex++]; } + if (stackTraceIndex != stackTrace.length) { + // Remove null entries at end of stackTrace + stackTrace = Arrays.copyOf(stackTrace, stackTraceIndex); + } throwable.setStackTrace(stackTrace); cause = throwable; } return throwable; } catch (Throwable translationFailure) { - assert printStackTrace(translationFailure); - return new TranslatedException("Error decoding exception: " + encodedThrowable, translationFailure.getClass().getName()); + debugPrintStackTrace(translationFailure); + return new TranslatedException("Error decoding exception: " + encodedThrowable, + translationFailure.getClass().getName()); } } } diff --git a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java index b1344683265..6e66c481952 100644 --- a/src/java.base/share/classes/jdk/internal/vm/VMSupport.java +++ b/src/java.base/share/classes/jdk/internal/vm/VMSupport.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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,12 +32,17 @@ import java.util.jar.Manifest; import java.util.jar.Attributes; +import jdk.internal.misc.VM; +import jdk.internal.misc.Unsafe; + /* - * Support class used by JVMTI and VM attach mechanism. + * Support class used by JVMCI, JVMTI and VM attach mechanism. */ public class VMSupport { + private static final Unsafe U = Unsafe.getUnsafe(); private static Properties agentProps = null; + /** * Returns the agent properties. */ @@ -51,13 +56,20 @@ public static synchronized Properties getAgentProperties() { private static native Properties initAgentProperties(Properties props); /** - * Write the given properties list to a byte array and return it. Properties with - * a key or value that is not a String is filtered out. The stream written to the byte - * array is ISO 8859-1 encoded. + * Writes the given properties list to a byte array and return it. The stream written + * to the byte array is ISO 8859-1 encoded. */ private static byte[] serializePropertiesToByteArray(Properties p) throws IOException { ByteArrayOutputStream out = new ByteArrayOutputStream(4096); + p.store(out, null); + return out.toByteArray(); + } + /** + * @returns a Properties object containing only the entries in {@code p} + * whose key and value are both Strings + */ + private static Properties onlyStrings(Properties p) { Properties props = new Properties(); // stringPropertyNames() returns a snapshot of the property keys @@ -66,17 +78,28 @@ private static byte[] serializePropertiesToByteArray(Properties p) throws IOExce String value = p.getProperty(key); props.put(key, value); } - - props.store(out, null); - return out.toByteArray(); + return props; } public static byte[] serializePropertiesToByteArray() throws IOException { - return serializePropertiesToByteArray(System.getProperties()); + return serializePropertiesToByteArray(onlyStrings(System.getProperties())); } public static byte[] serializeAgentPropertiesToByteArray() throws IOException { - return serializePropertiesToByteArray(getAgentProperties()); + return serializePropertiesToByteArray(onlyStrings(getAgentProperties())); + } + + /** + * Serializes {@link VM#getSavedProperties()} to a byte array. + * + * Used by JVMCI to copy properties into libjvmci. + */ + public static byte[] serializeSavedPropertiesToByteArray() throws IOException { + Properties props = new Properties(); + for (var e : VM.getSavedProperties().entrySet()) { + props.put(e.getKey(), e.getValue()); + } + return serializePropertiesToByteArray(props); } /* @@ -88,4 +111,40 @@ public static byte[] serializeAgentPropertiesToByteArray() throws IOException { * variables such as java.io.tmpdir. */ public static native String getVMTemporaryDirectory(); + + /** + * Decodes the exception encoded in {@code buffer} and throws it. + * + * @param buffer a native byte buffer containing an exception encoded by + * {@link #encodeThrowable} + */ + public static void decodeAndThrowThrowable(long buffer) throws Throwable { + int encodingLength = U.getInt(buffer); + byte[] encoding = new byte[encodingLength]; + U.copyMemory(null, buffer + 4, encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, encodingLength); + throw TranslatedException.decodeThrowable(encoding); + } + + /** + * If {@code bufferSize} is large enough, encodes {@code throwable} into a byte array and writes + * it to {@code buffer}. The encoding in {@code buffer} can be decoded by + * {@link #decodeAndThrowThrowable}. + * + * @param throwable the exception to encode + * @param buffer a native byte buffer + * @param bufferSize the size of {@code buffer} in bytes + * @return the number of bytes written into {@code buffer} if {@code bufferSize} is large + * enough, otherwise {@code -N} where {@code N} is the value {@code bufferSize} needs to + * be to fit the encoding + */ + public static int encodeThrowable(Throwable throwable, long buffer, int bufferSize) { + byte[] encoding = TranslatedException.encodeThrowable(throwable); + int requiredSize = 4 + encoding.length; + if (bufferSize < requiredSize) { + return -requiredSize; + } + U.putInt(buffer, encoding.length); + U.copyMemory(encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buffer + 4, encoding.length); + return requiredSize; + } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java index 849ca7c1c8c..1ec015a1415 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.hotspot/src/jdk/vm/ci/hotspot/HotSpotJVMCIRuntime.java @@ -206,64 +206,6 @@ public static HotSpotJVMCIRuntime runtime() { return result; } - /** - * Decodes the exception encoded in {@code buffer} and throws it. - * - * @param errorOrBuffer an error code or a native byte buffer containing an exception encoded by - * {@link #encodeThrowable}. Error code values and their meanings are: - * - *

    -     *             0: native memory for the buffer could not be allocated
    -     *            -1: an OutOfMemoryError was thrown while encoding the exception
    -     *            -2: some other throwable was thrown while encoding the exception
    -     *            
    - */ - @VMEntryPoint - static void decodeAndThrowThrowable(long errorOrBuffer) throws Throwable { - if (errorOrBuffer >= -2L && errorOrBuffer <= 0) { - String context = String.format("while encoding an exception to translate it from %s to %s", - IS_IN_NATIVE_IMAGE ? "HotSpot" : "libjvmci", - IS_IN_NATIVE_IMAGE ? "libjvmci" : "HotSpot"); - if (errorOrBuffer == 0) { - throw new InternalError("native buffer could not be allocated " + context); - } - if (errorOrBuffer == -1L) { - throw new OutOfMemoryError("OutOfMemoryError occurred " + context); - } - throw new InternalError("unexpected problem occurred " + context); - } - Unsafe unsafe = UnsafeAccess.UNSAFE; - int encodingLength = unsafe.getInt(errorOrBuffer); - byte[] encoding = new byte[encodingLength]; - unsafe.copyMemory(null, errorOrBuffer + 4, encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, encodingLength); - throw TranslatedException.decodeThrowable(encoding); - } - - /** - * If {@code bufferSize} is large enough, encodes {@code throwable} into a byte array and writes - * it to {@code buffer}. The encoding in {@code buffer} can be decoded by - * {@link #decodeAndThrowThrowable}. - * - * @param throwable the exception to encode - * @param buffer a native byte buffer - * @param bufferSize the size of {@code buffer} in bytes - * @return the number of bytes written into {@code buffer} if {@code bufferSize} is large - * enough, otherwise {@code -N} where {@code N} is the value {@code bufferSize} needs to - * be to fit the encoding - */ - @VMEntryPoint - static int encodeThrowable(Throwable throwable, long buffer, int bufferSize) throws Throwable { - byte[] encoding = TranslatedException.encodeThrowable(throwable); - int requiredSize = 4 + encoding.length; - if (bufferSize < requiredSize) { - return -requiredSize; - } - Unsafe unsafe = UnsafeAccess.UNSAFE; - unsafe.putInt(buffer, encoding.length); - unsafe.copyMemory(encoding, Unsafe.ARRAY_BYTE_BASE_OFFSET, null, buffer + 4, encoding.length); - return requiredSize; - } - @VMEntryPoint static String callToString(Object o) { return o.toString(); @@ -1330,7 +1272,7 @@ static void postTranslation(Object translatedObject) { for (String filter : filters) { Matcher m = FORCE_TRANSLATE_FAILURE_FILTER_RE.matcher(filter); if (!m.matches()) { - throw new JVMCIError(Option.ForceTranslateFailure + " filter does not match " + FORCE_TRANSLATE_FAILURE_FILTER_RE + ": " + filter); + throw new IllegalArgumentException(Option.ForceTranslateFailure + " filter does not match " + FORCE_TRANSLATE_FAILURE_FILTER_RE + ": " + filter); } String typeSelector = m.group(1); String substring = m.group(2); @@ -1350,7 +1292,7 @@ static void postTranslation(Object translatedObject) { continue; } if (toMatch.contains(substring)) { - throw new JVMCIError("translation of " + translatedObject + " failed due to matching " + Option.ForceTranslateFailure + " filter \"" + filter + "\""); + throw new RuntimeException("translation of " + translatedObject + " failed due to matching " + Option.ForceTranslateFailure + " filter \"" + filter + "\""); } } } diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java index 51a443af92b..3881662fd08 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.services/src/jdk/vm/ci/services/Services.java @@ -23,9 +23,6 @@ package jdk.vm.ci.services; import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.DataInputStream; -import java.io.DataOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; @@ -34,6 +31,7 @@ import java.util.List; import java.util.Map; import java.util.Objects; +import java.util.Properties; import java.util.ServiceLoader; import java.util.Set; import java.util.function.Consumer; @@ -42,8 +40,6 @@ import jdk.internal.misc.TerminatingThreadLocal; import jdk.internal.misc.VM; -import static java.nio.charset.StandardCharsets.UTF_8; - /** * Provides utilities needed by JVMCI clients. */ @@ -266,109 +262,21 @@ protected void threadTerminated(T value) { } /** - * A Java {@code char} has a maximal UTF8 length of 3. - */ - private static final int MAX_UNICODE_IN_UTF8_LENGTH = 3; - - /** - * {@link DataOutputStream#writeUTF(String)} only supports values whose UTF8 encoding length is - * less than 65535. - */ - private static final int MAX_UTF8_PROPERTY_STRING_LENGTH = 65535 / MAX_UNICODE_IN_UTF8_LENGTH; - - /** - * Serializes the {@linkplain #getSavedProperties() saved system properties} to a byte array for - * the purpose of {@linkplain #initializeSavedProperties(byte[]) initializing} the initial - * properties in the JVMCI shared library. - */ - @VMEntryPoint - private static byte[] serializeSavedProperties() throws IOException { - if (IS_IN_NATIVE_IMAGE) { - throw new InternalError("Can only serialize saved properties in HotSpot runtime"); - } - return serializeProperties(Services.getSavedProperties()); - } - - private static byte[] serializeProperties(Map props) throws IOException { - // Compute size of output on the assumption that - // all system properties have ASCII names and values - int estimate = 4 + 4; - int nonUtf8Props = 0; - for (Map.Entry e : props.entrySet()) { - String name = e.getKey(); - String value = e.getValue(); - estimate += (2 + (name.length())) + (2 + (value.length())); - if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { - nonUtf8Props++; - } - } - - ByteArrayOutputStream baos = new ByteArrayOutputStream(estimate); - DataOutputStream out = new DataOutputStream(baos); - out.writeInt(props.size() - nonUtf8Props); - out.writeInt(nonUtf8Props); - for (Map.Entry e : props.entrySet()) { - String name = e.getKey(); - String value = e.getValue(); - if (name.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH && value.length() <= MAX_UTF8_PROPERTY_STRING_LENGTH) { - out.writeUTF(name); - out.writeUTF(value); - } - } - if (nonUtf8Props != 0) { - for (Map.Entry e : props.entrySet()) { - String name = e.getKey(); - String value = e.getValue(); - if (name.length() > MAX_UTF8_PROPERTY_STRING_LENGTH || value.length() > MAX_UTF8_PROPERTY_STRING_LENGTH) { - byte[] utf8Name = name.getBytes(UTF_8); - byte[] utf8Value = value.getBytes(UTF_8); - out.writeInt(utf8Name.length); - out.write(utf8Name); - out.writeInt(utf8Value.length); - out.write(utf8Value); - } - } - } - return baos.toByteArray(); - } - - /** - * Initialized the {@linkplain #getSavedProperties() saved system properties} in the JVMCI - * shared library from the {@linkplain #serializeSavedProperties() serialized saved properties} - * in the HotSpot runtime. + * Initializes {@link #savedProperties} from the byte array returned by + * {@code jdk.internal.vm.VMSupport.serializeSavedPropertiesToByteArray()}. */ @VMEntryPoint private static void initializeSavedProperties(byte[] serializedProperties) throws IOException { if (!IS_IN_NATIVE_IMAGE) { throw new InternalError("Can only initialize saved properties in JVMCI shared library runtime"); } - savedProperties = Collections.unmodifiableMap(deserializeProperties(serializedProperties)); - } - - private static Map deserializeProperties(byte[] serializedProperties) throws IOException { - DataInputStream in = new DataInputStream(new ByteArrayInputStream(serializedProperties)); - int utf8Props = in.readInt(); - int nonUtf8Props = in.readInt(); - Map props = new HashMap<>(utf8Props + nonUtf8Props); - int index = 0; - while (in.available() != 0) { - if (index < utf8Props) { - String name = in.readUTF(); - String value = in.readUTF(); - props.put(name, value); - } else { - int nameLen = in.readInt(); - byte[] nameBytes = new byte[nameLen]; - in.read(nameBytes); - int valueLen = in.readInt(); - byte[] valueBytes = new byte[valueLen]; - in.read(valueBytes); - String name = new String(nameBytes, UTF_8); - String value = new String(valueBytes, UTF_8); - props.put(name, value); - } - index++; + Properties props = new Properties(); + props.load(new ByteArrayInputStream(serializedProperties)); + Map map = new HashMap<>(props.size()); + for (var e : props.entrySet()) { + map.put((String) e.getKey(), (String) e.getValue()); } - return props; + + savedProperties = Collections.unmodifiableMap(map); } } diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java b/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java deleted file mode 100644 index 8c4c32c1cf0..00000000000 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestServices.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2019, 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 - * @requires vm.jvmci - * @modules jdk.internal.vm.ci/jdk.vm.ci.services:+open - * @library /compiler/jvmci/jdk.vm.ci.hotspot.test/src - * @run testng/othervm - * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler - * jdk.vm.ci.hotspot.test.TestServices - */ - -package jdk.vm.ci.hotspot.test; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.Map; - -import org.testng.Assert; -import org.testng.annotations.Test; - -import jdk.vm.ci.services.Services; - -public class TestServices { - - @SuppressWarnings("unchecked") - @Test - public void serializeSavedPropertiesTest() throws Exception { - - Field f = Services.class.getDeclaredField("MAX_UTF8_PROPERTY_STRING_LENGTH"); - f.setAccessible(true); - int maxUtf8PropertyStringLength = (int) f.get(null); - - Method serializeProperties = Services.class.getDeclaredMethod("serializeProperties", Map.class); - Method deserializeProperties = Services.class.getDeclaredMethod("deserializeProperties", byte[].class); - serializeProperties.setAccessible(true); - deserializeProperties.setAccessible(true); - - Map props = new HashMap<>(Services.getSavedProperties()); - String[] names = { - new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', 'x'), - new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', 'x'), - new String(new char[maxUtf8PropertyStringLength]).replace('\0', 'y'), - new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', 'z'), - new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', 'z') - }; - String[] values = { - new String(new char[maxUtf8PropertyStringLength - 100]).replace('\0', '1'), - new String(new char[maxUtf8PropertyStringLength - 1]).replace('\0', '1'), - new String(new char[maxUtf8PropertyStringLength]).replace('\0', '2'), - new String(new char[maxUtf8PropertyStringLength + 1]).replace('\0', '1'), - new String(new char[maxUtf8PropertyStringLength + 100]).replace('\0', '3') - }; - for (String name : names) { - for (String value : values) { - props.put(name, value); - } - } - - byte[] data = (byte[]) serializeProperties.invoke(null, props); - - Map newProps = (Map) deserializeProperties.invoke(null, data); - - Assert.assertEquals(props.size(), newProps.size()); - for (String name : props.keySet()) { - String expect = props.get(name); - String actual = newProps.get(name); - Assert.assertEquals(expect, actual); - } - } -} diff --git a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java b/test/jdk/jdk/internal/vm/TestTranslatedException.java similarity index 56% rename from test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java rename to test/jdk/jdk/internal/vm/TestTranslatedException.java index 57a505901a5..e17631595f9 100644 --- a/test/hotspot/jtreg/compiler/jvmci/jdk.vm.ci.hotspot.test/src/jdk/vm/ci/hotspot/test/TestTranslatedException.java +++ b/test/jdk/jdk/internal/vm/TestTranslatedException.java @@ -23,16 +23,12 @@ /* * @test - * @requires vm.jvmci - * @modules jdk.internal.vm.ci/jdk.vm.ci.hotspot:+open + * @modules java.base/jdk.internal.vm * java.base/jdk.internal.misc - * @library /compiler/jvmci/jdk.vm.ci.hotspot.test/src * @run testng/othervm - * -XX:+UnlockExperimentalVMOptions -XX:+EnableJVMCI -XX:-UseJVMCICompiler - * jdk.vm.ci.hotspot.test.TestTranslatedException + * jdk.internal.vm.test.TestTranslatedException */ - -package jdk.vm.ci.hotspot.test; +package jdk.internal.vm.test; import java.io.ByteArrayOutputStream; import java.io.PrintStream; @@ -43,7 +39,7 @@ import org.testng.annotations.Test; import jdk.internal.misc.Unsafe; -import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime; +import jdk.internal.vm.VMSupport; public class TestTranslatedException { @SuppressWarnings("serial") @@ -56,52 +52,37 @@ public Untranslatable(String message, Throwable cause) { @SuppressWarnings("unchecked") @Test public void encodeDecodeTest() throws Exception { - - Class translatedExceptionClass = Class.forName("jdk.vm.ci.hotspot.TranslatedException"); - - Method encode = translatedExceptionClass.getDeclaredMethod("encodeThrowable", Throwable.class); - Method decode = translatedExceptionClass.getDeclaredMethod("decodeThrowable", byte[].class); - encode.setAccessible(true); - decode.setAccessible(true); - Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); for (int i = 0; i < 10; i++) { throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); } - byte[] encoding = (byte[]) encode.invoke(null, throwable); - Throwable decoded = (Throwable) decode.invoke(null, encoding); - assertThrowableEquals(throwable, decoded); + encodeDecode(throwable); } - @SuppressWarnings("unchecked") @Test public void encodeDecodeTest2() throws Exception { + Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); + for (int i = 0; i < 10; i++) { + throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); + } + encodeDecode(throwable); + } + + private void encodeDecode(Throwable throwable) throws Exception { Unsafe unsafe = Unsafe.getUnsafe(); int bufferSize = 512; long buffer = 0L; while (true) { buffer = unsafe.allocateMemory(bufferSize); try { - Throwable throwable = new ExceptionInInitializerError(new InvocationTargetException(new Untranslatable("test exception", new NullPointerException()), "invoke")); - for (int i = 0; i < 10; i++) { - throwable = new ExceptionInInitializerError(new InvocationTargetException(new RuntimeException(String.valueOf(i), throwable), "invoke")); - } - - Method encode = HotSpotJVMCIRuntime.class.getDeclaredMethod("encodeThrowable", Throwable.class, long.class, int.class); - Method decode = HotSpotJVMCIRuntime.class.getDeclaredMethod("decodeAndThrowThrowable", long.class); - encode.setAccessible(true); - decode.setAccessible(true); - - int res = (Integer) encode.invoke(null, throwable, buffer, bufferSize); - + int res = VMSupport.encodeThrowable(throwable, buffer, bufferSize); if (res < 0) { bufferSize = -res; } else { try { - decode.invoke(null, buffer); + VMSupport.decodeAndThrowThrowable(buffer); throw new AssertionError("expected decodeAndThrowThrowable to throw an exception"); - } catch (InvocationTargetException e) { - Throwable decoded = e.getCause(); + } catch (Throwable decoded) { assertThrowableEquals(throwable, decoded); } return; @@ -117,12 +98,12 @@ private static void assertThrowableEquals(Throwable original, Throwable decoded) Assert.assertEquals(original == null, decoded == null); while (original != null) { if (Untranslatable.class.equals(original.getClass())) { - Assert.assertEquals("jdk.vm.ci.hotspot.TranslatedException", decoded.getClass().getName()); - Assert.assertEquals("jdk.vm.ci.hotspot.TranslatedException[jdk.vm.ci.hotspot.test.TestTranslatedException$Untranslatable]: test exception", decoded.toString()); - Assert.assertEquals("test exception", original.getMessage()); + Assert.assertEquals(decoded.getClass().getName(), "jdk.internal.vm.TranslatedException"); + Assert.assertEquals(decoded.toString(), "jdk.internal.vm.TranslatedException[jdk.internal.vm.test.TestTranslatedException$Untranslatable]: test exception"); + Assert.assertEquals(original.getMessage(), "test exception"); } else { - Assert.assertEquals(original.getClass().getName(), decoded.getClass().getName()); - Assert.assertEquals(original.getMessage(), decoded.getMessage()); + Assert.assertEquals(decoded.getClass().getName(), original.getClass().getName()); + Assert.assertEquals(decoded.getMessage(), original.getMessage()); } StackTraceElement[] originalStack = original.getStackTrace(); StackTraceElement[] decodedStack = decoded.getStackTrace(); @@ -130,12 +111,12 @@ private static void assertThrowableEquals(Throwable original, Throwable decoded) for (int i = 0, n = originalStack.length; i < n; ++i) { StackTraceElement originalStackElement = originalStack[i]; StackTraceElement decodedStackElement = decodedStack[i]; - Assert.assertEquals(originalStackElement.getClassLoaderName(), decodedStackElement.getClassLoaderName()); - Assert.assertEquals(originalStackElement.getModuleName(), decodedStackElement.getModuleName()); - Assert.assertEquals(originalStackElement.getClassName(), decodedStackElement.getClassName()); - Assert.assertEquals(originalStackElement.getMethodName(), decodedStackElement.getMethodName()); - Assert.assertEquals(originalStackElement.getFileName(), decodedStackElement.getFileName()); - Assert.assertEquals(originalStackElement.getLineNumber(), decodedStackElement.getLineNumber()); + Assert.assertEquals(decodedStackElement.getClassLoaderName(), originalStackElement.getClassLoaderName()); + Assert.assertEquals(decodedStackElement.getModuleName(), originalStackElement.getModuleName()); + Assert.assertEquals(decodedStackElement.getClassName(), originalStackElement.getClassName()); + Assert.assertEquals(decodedStackElement.getMethodName(), originalStackElement.getMethodName()); + Assert.assertEquals(decodedStackElement.getFileName(), originalStackElement.getFileName()); + Assert.assertEquals(decodedStackElement.getLineNumber(), originalStackElement.getLineNumber()); } original = original.getCause(); decoded = decoded.getCause(); From af8fb7eef7188ef762399cfb3faf5c8afd49efa7 Mon Sep 17 00:00:00 2001 From: Alexander Zuev Date: Thu, 8 Dec 2022 00:32:13 +0000 Subject: [PATCH 113/494] 8282578: AIOOBE in javax.sound.sampled.Clip Reviewed-by: prr, aivanov, azvegint --- .../com/sun/media/sound/SoftMainMixer.java | 567 ++++++++++-------- .../com/sun/media/sound/SoftTuning.java | 43 +- .../SysexMessage/EmptySysExMessageTest.java | 82 +++ .../sound/midi/SysexMessage/zerosysex.mid | Bin 0 -> 74 bytes 4 files changed, 441 insertions(+), 251 deletions(-) create mode 100644 test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java create mode 100644 test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftMainMixer.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftMainMixer.java index bdcf00d067e..300e01b5ab8 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftMainMixer.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftMainMixer.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -123,102 +123,126 @@ public double[] get(int instance, String name) { private void processSystemExclusiveMessage(byte[] data) { synchronized (synth.control_mutex) { activity(); - + if (data.length < 3 || (data[1] & 0xFF) != 0x7E && (data[1] & 0xFF) != 0x7F ) { + // Not enough data to determine SysEx type or SysEx type is not supported + return; + } // Universal Non-Real-Time SysEx if ((data[1] & 0xFF) == 0x7E) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + if (data.length < 4) { + return; + } int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { - case 0x08: // MIDI Tuning Standard - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // BULK TUNING DUMP - { - // http://www.midi.org/about-midi/tuning.shtml - SoftTuning tuning = synth.getTuning(new Patch(0, - data[5] & 0xFF)); - tuning.load(data); - break; - } - case 0x04: // KEY-BASED TUNING DUMP - case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format - case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format - case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) + case 0x08: // MIDI Tuning Standard + if (data.length < 5) { + break; + } + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // BULK TUNING DUMP + { + if (data.length < 6) { + break; + } + // http://www.midi.org/about-midi/tuning.shtml + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + break; + } + case 0x04: // KEY-BASED TUNING DUMP + case 0x05: // SCALE/OCTAVE TUNING DUMP, 1 byte format + case 0x06: // SCALE/OCTAVE TUNING DUMP, 2 byte format + case 0x07: // SINGLE NOTE TUNING CHANGE (NON REAL-TIME) // (BANK) - { - // http://www.midi.org/about-midi/tuning_extens.shtml - SoftTuning tuning = synth.getTuning(new Patch( - data[5] & 0xFF, data[6] & 0xFF)); - tuning.load(data); - break; - } - case 0x08: // scale/octave tuning 1-byte form (Non + { + if (data.length < 7) { + break; + } + // http://www.midi.org/about-midi/tuning_extens.shtml + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); // Check inside! + break; + } + case 0x08: // scale/octave tuning 1-byte form (Non // Real-Time) - case 0x09: // scale/octave tuning 2-byte form (Non + case 0x09: // scale/octave tuning 2-byte form (Non // Real-Time) - { - // http://www.midi.org/about-midi/tuning-scale.shtml - SoftTuning tuning = new SoftTuning(data); - int channelmask = (data[5] & 0xFF) * 16384 - + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); - SoftChannel[] channels = synth.channels; - for (int i = 0; i < channels.length; i++) - if ((channelmask & (1 << i)) != 0) - channels[i].tuning = tuning; - break; - } - default: - break; - } - break; - case 0x09: // General Midi Message - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // General Midi 1 On - synth.setGeneralMidiMode(1); - reset(); - break; - case 0x02: // General Midi Off - synth.setGeneralMidiMode(0); - reset(); - break; - case 0x03: // General MidI Level 2 On - synth.setGeneralMidiMode(2); - reset(); - break; - default: - break; - } - break; - case 0x0A: // DLS Message - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // DLS On - if (synth.getGeneralMidiMode() == 0) - synth.setGeneralMidiMode(1); - synth.voice_allocation_mode = 1; - reset(); - break; - case 0x02: // DLS Off - synth.setGeneralMidiMode(0); - synth.voice_allocation_mode = 0; - reset(); + { + if (data.length < 8) { + break; + } + // http://www.midi.org/about-midi/tuning-scale.shtml + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + break; + } + default: + break; + } break; - case 0x03: // DLS Static Voice Allocation Off - synth.voice_allocation_mode = 0; + case 0x09: // General Midi Message + if (data.length < 5) { + break; + } + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // General Midi 1 On + synth.setGeneralMidiMode(1); + reset(); + break; + case 0x02: // General Midi Off + synth.setGeneralMidiMode(0); + reset(); + break; + case 0x03: // General MidI Level 2 On + synth.setGeneralMidiMode(2); + reset(); + break; + default: + break; + } break; - case 0x04: // DLS Static Voice Allocation On - synth.voice_allocation_mode = 1; + case 0x0A: // DLS Message + if (data.length < 5) { + break; + } + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // DLS On + if (synth.getGeneralMidiMode() == 0) + synth.setGeneralMidiMode(1); + synth.voice_allocation_mode = 1; + reset(); + break; + case 0x02: // DLS Off + synth.setGeneralMidiMode(0); + synth.voice_allocation_mode = 0; + reset(); + break; + case 0x03: // DLS Static Voice Allocation Off + synth.voice_allocation_mode = 0; + break; + case 0x04: // DLS Static Voice Allocation On + synth.voice_allocation_mode = 1; + break; + default: + break; + } break; + default: break; - } - break; - - default: - break; } } } @@ -227,197 +251,240 @@ private void processSystemExclusiveMessage(byte[] data) { if ((data[1] & 0xFF) == 0x7F) { int deviceID = data[2] & 0xFF; if (deviceID == 0x7F || deviceID == synth.getDeviceID()) { + if (data.length < 4) { + return; + } int subid1 = data[3] & 0xFF; int subid2; switch (subid1) { - case 0x04: // Device Control - - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // Master Volume - case 0x02: // Master Balane - case 0x03: // Master fine tuning - case 0x04: // Master coarse tuning - int val = (data[5] & 0x7F) - + ((data[6] & 0x7F) * 128); - if (subid2 == 0x01) - setVolume(val); - else if (subid2 == 0x02) - setBalance(val); - else if (subid2 == 0x03) - setFineTuning(val); - else if (subid2 == 0x04) - setCoarseTuning(val); - break; - case 0x05: // Global Parameter Control - int ix = 5; - int slotPathLen = (data[ix++] & 0xFF); - int paramWidth = (data[ix++] & 0xFF); - int valueWidth = (data[ix++] & 0xFF); - int[] slotPath = new int[slotPathLen]; - for (int i = 0; i < slotPathLen; i++) { - int msb = (data[ix++] & 0xFF); - int lsb = (data[ix++] & 0xFF); - slotPath[i] = msb * 128 + lsb; + case 0x04: // Device Control + if (data.length < 5) { + break; } - int paramCount = (data.length - 1 - ix) - / (paramWidth + valueWidth); - long[] params = new long[paramCount]; - long[] values = new long[paramCount]; - for (int i = 0; i < paramCount; i++) { - values[i] = 0; - for (int j = 0; j < paramWidth; j++) - params[i] = params[i] * 128 - + (data[ix++] & 0xFF); - for (int j = 0; j < valueWidth; j++) - values[i] = values[i] * 128 - + (data[ix++] & 0xFF); - + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Master Volume + case 0x02: // Master Balane + case 0x03: // Master fine tuning + case 0x04: // Master coarse tuning + if (data.length < 7) { + break; + } + int val = (data[5] & 0x7F) + + ((data[6] & 0x7F) * 128); + if (subid2 == 0x01) + setVolume(val); + else if (subid2 == 0x02) + setBalance(val); + else if (subid2 == 0x03) + setFineTuning(val); + else if (subid2 == 0x04) + setCoarseTuning(val); + break; + case 0x05: // Global Parameter Control + if (data.length < 6) { + break; + } + int ix = 5; + int slotPathLen = (data[ix++] & 0xFF); + if (data.length < slotPathLen * 2 + 8) { + break; + } + int paramWidth = (data[ix++] & 0xFF); + int valueWidth = (data[ix++] & 0xFF); + int[] slotPath = new int[slotPathLen]; + for (int i = 0; i < slotPathLen; i++) { + int msb = (data[ix++] & 0xFF); + int lsb = (data[ix++] & 0xFF); + slotPath[i] = msb * 128 + lsb; + } + int paramCount = (data.length - 1 - ix) + / (paramWidth + valueWidth); + if (paramCount < 1) { + break; + } + long[] params = new long[paramCount]; + long[] values = new long[paramCount]; + for (int i = 0; i < paramCount; i++) { + values[i] = 0; + for (int j = 0; j < paramWidth; j++) + params[i] = params[i] * 128 + + (data[ix++] & 0xFF); + for (int j = 0; j < valueWidth; j++) + values[i] = values[i] * 128 + + (data[ix++] & 0xFF); + + } + globalParameterControlChange(slotPath, params, values); + break; + default: + break; } - globalParameterControlChange(slotPath, params, values); - break; - default: break; - } - break; - case 0x08: // MIDI Tuning Standard - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) - { - // http://www.midi.org/about-midi/tuning.shtml - SoftTuning tuning = synth.getTuning(new Patch(0, - data[5] & 0xFF)); - tuning.load(data); - SoftVoice[] voices = synth.getVoices(); - for (int i = 0; i < voices.length; i++) - if (voices[i].active) - if (voices[i].tuning == tuning) - voices[i].updateTuning(tuning); - break; - } - case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + case 0x08: // MIDI Tuning Standard + if (data.length < 5) { + break; + } + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) + { + // http://www.midi.org/about-midi/tuning.shtml + if (data.length < 6) { + break; + } + SoftTuning tuning = synth.getTuning(new Patch(0, + data[5] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + break; + } + case 0x07: // SINGLE NOTE TUNING CHANGE (REAL-TIME) // (BANK) - { - // http://www.midi.org/about-midi/tuning_extens.shtml - SoftTuning tuning = synth.getTuning(new Patch( - data[5] & 0xFF, data[6] & 0xFF)); - tuning.load(data); - SoftVoice[] voices = synth.getVoices(); - for (int i = 0; i < voices.length; i++) - if (voices[i].active) - if (voices[i].tuning == tuning) - voices[i].updateTuning(tuning); - break; - } - case 0x08: // scale/octave tuning 1-byte form + { + // http://www.midi.org/about-midi/tuning_extens.shtml + if (data.length < 7) { + break; + } + SoftTuning tuning = synth.getTuning(new Patch( + data[5] & 0xFF, data[6] & 0xFF)); + tuning.load(data); + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if (voices[i].tuning == tuning) + voices[i].updateTuning(tuning); + break; + } + case 0x08: // scale/octave tuning 1-byte form //(Real-Time) - case 0x09: // scale/octave tuning 2-byte form + case 0x09: // scale/octave tuning 2-byte form // (Real-Time) - { - // http://www.midi.org/about-midi/tuning-scale.shtml - SoftTuning tuning = new SoftTuning(data); - int channelmask = (data[5] & 0xFF) * 16384 - + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); - SoftChannel[] channels = synth.channels; - for (int i = 0; i < channels.length; i++) - if ((channelmask & (1 << i)) != 0) - channels[i].tuning = tuning; - SoftVoice[] voices = synth.getVoices(); - for (int i = 0; i < voices.length; i++) - if (voices[i].active) - if ((channelmask & (1 << (voices[i].channel))) != 0) - voices[i].updateTuning(tuning); - break; - } - default: - break; - } - break; - case 0x09: // Control Destination Settings - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // Channel Pressure - { - int[] destinations = new int[(data.length - 7) / 2]; - int[] ranges = new int[(data.length - 7) / 2]; - int ix = 0; - for (int j = 6; j < data.length - 1; j += 2) { - destinations[ix] = data[j] & 0xFF; - ranges[ix] = data[j + 1] & 0xFF; - ix++; + { + // http://www.midi.org/about-midi/tuning-scale.shtml + if (data.length < 8) { + break; + } + SoftTuning tuning = new SoftTuning(data); + int channelmask = (data[5] & 0xFF) * 16384 + + (data[6] & 0xFF) * 128 + (data[7] & 0xFF); + SoftChannel[] channels = synth.channels; + for (int i = 0; i < channels.length; i++) + if ((channelmask & (1 << i)) != 0) + channels[i].tuning = tuning; + SoftVoice[] voices = synth.getVoices(); + for (int i = 0; i < voices.length; i++) + if (voices[i].active) + if ((channelmask & (1 << (voices[i].channel))) != 0) + voices[i].updateTuning(tuning); + break; + } + default: + break; } - int channel = data[5] & 0xFF; - SoftChannel softchannel = synth.channels[channel]; - softchannel.mapChannelPressureToDestination( - destinations, ranges); break; - } - case 0x02: // Poly Pressure - { - int[] destinations = new int[(data.length - 7) / 2]; - int[] ranges = new int[(data.length - 7) / 2]; - int ix = 0; - for (int j = 6; j < data.length - 1; j += 2) { - destinations[ix] = data[j] & 0xFF; - ranges[ix] = data[j + 1] & 0xFF; - ix++; + case 0x09: // Control Destination Settings + if (data.length < 5) { + break; } - int channel = data[5] & 0xFF; - SoftChannel softchannel = synth.channels[channel]; - softchannel.mapPolyPressureToDestination( - destinations, ranges); - break; - } - case 0x03: // Control Change - { - int[] destinations = new int[(data.length - 7) / 2]; - int[] ranges = new int[(data.length - 7) / 2]; - int ix = 0; - for (int j = 7; j < data.length - 1; j += 2) { - destinations[ix] = data[j] & 0xFF; - ranges[ix] = data[j + 1] & 0xFF; - ix++; + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Channel Pressure + { + if (data.length < 8) { + break; + } + int[] destinations = new int[(data.length - 6) / 2]; + int[] ranges = new int[(data.length - 6) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapChannelPressureToDestination( + destinations, ranges); + break; + } + case 0x02: // Poly Pressure + { + if (data.length < 8) { + break; + } + int[] destinations = new int[(data.length - 6) / 2]; + int[] ranges = new int[(data.length - 6) / 2]; + int ix = 0; + for (int j = 6; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + softchannel.mapPolyPressureToDestination( + destinations, ranges); + break; + } + case 0x03: // Control Change + { + if (data.length < 8) { + break; + } + int[] destinations = new int[(data.length - 7) / 2]; + int[] ranges = new int[(data.length - 7) / 2]; + int ix = 0; + for (int j = 7; j < data.length - 1; j += 2) { + destinations[ix] = data[j] & 0xFF; + ranges[ix] = data[j + 1] & 0xFF; + ix++; + } + int channel = data[5] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + int control = data[6] & 0xFF; + softchannel.mapControlToDestination(control, + destinations, ranges); + break; + } + default: + break; } - int channel = data[5] & 0xFF; - SoftChannel softchannel = synth.channels[channel]; - int control = data[6] & 0xFF; - softchannel.mapControlToDestination(control, - destinations, ranges); - break; - } - default: break; - } - break; - case 0x0A: // Key Based Instrument Control - { - subid2 = data[4] & 0xFF; - switch (subid2) { - case 0x01: // Basic Message - int channel = data[5] & 0xFF; - int keynumber = data[6] & 0xFF; - SoftChannel softchannel = synth.channels[channel]; - for (int j = 7; j < data.length - 1; j += 2) { - int controlnumber = data[j] & 0xFF; - int controlvalue = data[j + 1] & 0xFF; - softchannel.controlChangePerNote(keynumber, - controlnumber, controlvalue); + case 0x0A: // Key Based Instrument Control + { + if (data.length < 8 || (data[4] & 0xFF) != 0x01) { + break; + } + subid2 = data[4] & 0xFF; + switch (subid2) { + case 0x01: // Basic Message + int channel = data[5] & 0xFF; + int keynumber = data[6] & 0xFF; + SoftChannel softchannel = synth.channels[channel]; + for (int j = 7; j < data.length - 1; j += 2) { + int controlnumber = data[j] & 0xFF; + int controlvalue = data[j + 1] & 0xFF; + softchannel.controlChangePerNote(keynumber, + controlnumber, controlvalue); + } + break; + default: + break; } break; + } default: break; - } - break; - } - default: - break; } } } - } } diff --git a/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java b/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java index 73b2226c6f1..b951ffacc23 100644 --- a/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java +++ b/src/java.desktop/share/classes/com/sun/media/sound/SoftTuning.java @@ -89,10 +89,21 @@ private boolean checksumOK2(byte[] data) { */ public void load(byte[] data) { // Universal Non-Real-Time / Real-Time SysEx + if (data.length < 2) { + return; + } + if ((data[1] & 0xFF) == 0x7E || (data[1] & 0xFF) == 0x7F) { + if (data.length < 4) { + return; + } + int subid1 = data[3] & 0xFF; switch (subid1) { case 0x08: // MIDI Tuning Standard + if (data.length < 5) { + break; + } int subid2 = data[4] & 0xFF; switch (subid2) { case 0x01: // BULK TUNING DUMP (NON-REAL-TIME) @@ -100,8 +111,11 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning.shtml //if (!checksumOK2(data)) // break; - name = new String(data, 6, 16, US_ASCII); int r = 22; + if (data.length < 128 * 3 + r) { + break; + } + name = new String(data, 6, 16, US_ASCII); for (int i = 0; i < 128; i++) { int xx = data[r++] & 0xFF; int yy = data[r++] & 0xFF; @@ -115,8 +129,14 @@ public void load(byte[] data) { case 0x02: // SINGLE NOTE TUNING CHANGE (REAL-TIME) { // http://www.midi.org/about-midi/tuning.shtml + if (data.length < 7) { + break; + } int ll = data[6] & 0xFF; int r = 7; + if (data.length < ll * 4 + r) { + break; + } for (int i = 0; i < ll; i++) { int kk = data[r++] & 0xFF; int xx = data[r++] & 0xFF; @@ -132,6 +152,9 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; + if (data.length < 407) { + break; + } name = new String(data, 7, 16, US_ASCII); int r = 23; for (int i = 0; i < 128; i++) { @@ -149,6 +172,9 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; + if (data.length < 35) { + break; + } name = new String(data, 7, 16, US_ASCII); int[] octave_tuning = new int[12]; for (int i = 0; i < 12; i++) @@ -163,6 +189,9 @@ public void load(byte[] data) { // http://www.midi.org/about-midi/tuning_extens.shtml if (!checksumOK(data)) break; + if (data.length < 47) { + break; + } name = new String(data, 7, 16, US_ASCII); double[] octave_tuning = new double[12]; for (int i = 0; i < 12; i++) { @@ -177,7 +206,13 @@ public void load(byte[] data) { case 0x07: // SINGLE NOTE TUNING CHANGE (NON // REAL-TIME/REAL-TIME) (BANK) // http://www.midi.org/about-midi/tuning_extens.shtml + if (data.length < 8) { + break; + } int ll = data[7] & 0xFF; + if (data.length < ll * 4 + 8) { + break; + } int r = 8; for (int i = 0; i < ll; i++) { int kk = data[r++] & 0xFF; @@ -193,6 +228,9 @@ public void load(byte[] data) { // Real-Time/REAL-TIME) { // http://www.midi.org/about-midi/tuning-scale.shtml + if (data.length < 20) { + break; + } int[] octave_tuning = new int[12]; for (int i = 0; i < 12; i++) octave_tuning[i] = (data[i + 8] & 0xFF) - 64; @@ -204,6 +242,9 @@ public void load(byte[] data) { // Real-Time/REAL-TIME) { // http://www.midi.org/about-midi/tuning-scale.shtml + if (data.length < 32) { + break; + } double[] octave_tuning = new double[12]; for (int i = 0; i < 12; i++) { int v = (data[i * 2 + 8] & 0xFF) * 128 diff --git a/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java b/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java new file mode 100644 index 00000000000..03c940c2289 --- /dev/null +++ b/test/jdk/javax/sound/midi/SysexMessage/EmptySysExMessageTest.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2022, 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. + */ + +import javax.sound.sampled.AudioInputStream; +import javax.sound.sampled.AudioSystem; +import javax.sound.sampled.Clip; +import javax.sound.sampled.LineUnavailableException; +import javax.sound.sampled.UnsupportedAudioFileException; +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; + +/* + * @test + * @key sound + * @bug 8282578 + * @summary AIOOBE in javax.sound.sampled.Clip + * @run main EmptySysExMessageTest + */ + +public class EmptySysExMessageTest { + public static void main(String[] args) { + String sep = System.getProperty("file.separator"); + String dir = System.getProperty("test.src", "."); + String name = "zerosysex.mid"; + try { + readAudioFile(dir + sep + name); + } catch (Throwable t) { + throw new RuntimeException("Invalid file " + name + + " caused unexpected exception during read: " + + t + System.lineSeparator()); + } + } + + static void readAudioFile(String name) throws IOException { + File soundFile = new File(name); + Path path = Paths.get(soundFile.getAbsolutePath()); + byte[] samples = Files.readAllBytes(path); + + try { + AudioInputStream audioInputStream = + AudioSystem.getAudioInputStream(new ByteArrayInputStream(samples)); + try (Clip clip = AudioSystem.getClip()) { + clip.open(audioInputStream); + clip.start(); + Thread.sleep(1000); + clip.stop(); + } + } catch (UnsupportedAudioFileException + | LineUnavailableException + | IOException + | InterruptedException + | IllegalArgumentException + | IllegalStateException + | SecurityException expected) { + // Do nothing, these types of exception are expected on invalid file + } + } +} diff --git a/test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid b/test/jdk/javax/sound/midi/SysexMessage/zerosysex.mid new file mode 100644 index 0000000000000000000000000000000000000000..cf92458b9522fb91beee50851813f8d231ef6180 GIT binary patch literal 74 zcmeYb$w*;fU|<7cM#cxeAw}6hmI=fE2o@G52@Zz;fz0d+6&NPiI4~>#;t3KC%?S+> W4h#(-P6&|mfq|hR#DU?zJ_7)3eiEbr literal 0 HcmV?d00001 From 3aa4070d4ca21b9e90388995efbcde318892e25f Mon Sep 17 00:00:00 2001 From: Darragh Clarke Date: Thu, 8 Dec 2022 01:39:07 +0000 Subject: [PATCH 114/494] 8294047: HttpResponseInputStream swallows interrupts Reviewed-by: dfuchs, vtewari, jpai --- .../classes/java/net/http/HttpResponse.java | 9 +- .../net/http/ResponseSubscribers.java | 7 +- .../HttpResponseInputStreamInterruptTest.java | 176 ++++++++++++++++++ 3 files changed, 190 insertions(+), 2 deletions(-) create mode 100644 test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java diff --git a/src/java.net.http/share/classes/java/net/http/HttpResponse.java b/src/java.net.http/share/classes/java/net/http/HttpResponse.java index a8af2070013..f518d86eae1 100644 --- a/src/java.net.http/share/classes/java/net/http/HttpResponse.java +++ b/src/java.net.http/share/classes/java/net/http/HttpResponse.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -1178,6 +1178,13 @@ public static BodySubscriber ofFile(Path file) { * the underlying HTTP connection to be closed and prevent it * from being reused for subsequent operations. * + * @implNote The {@code read} method of the {@code InputStream} + * returned by the default implementation of this method will + * throw an {@code IOException} with the {@linkplain Thread#isInterrupted() + * thread interrupt status set} if the thread is interrupted + * while blocking on read. In that case, the request will also be + * cancelled and the {@code InputStream} will be closed. + * * @return a body subscriber that streams the response body as an * {@link InputStream}. */ diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java index 6b68293bb7d..22572f08985 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/ResponseSubscribers.java @@ -481,7 +481,12 @@ private ByteBuffer current() throws IOException { if (debug.on()) debug.log("Next Buffer"); currentBuffer = currentListItr.next(); } catch (InterruptedException ex) { - // continue + try { + close(); + } catch (IOException ignored) { + } + Thread.currentThread().interrupt(); + throw new IOException(ex); } } assert currentBuffer == LAST_BUFFER || currentBuffer.hasRemaining(); diff --git a/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java new file mode 100644 index 00000000000..6468175ab59 --- /dev/null +++ b/test/jdk/java/net/httpclient/HttpResponseInputStreamInterruptTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2022, 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 8294047 + * @library /test/lib + * @run junit HttpResponseInputStreamInterruptTest + */ + +import com.sun.net.httpserver.HttpExchange; +import com.sun.net.httpserver.HttpHandler; +import com.sun.net.httpserver.HttpServer; +import jdk.test.lib.net.URIBuilder; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.util.concurrent.CountDownLatch; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class HttpResponseInputStreamInterruptTest { + + HttpServer server; + int port; + private final CountDownLatch interruptReadyLatch = new CountDownLatch(2); + private final CountDownLatch interruptDoneLatch = new CountDownLatch(1); + static final String FIRST_MESSAGE = "Should be received"; + static final String SECOND_MESSAGE = "Shouldn't be received"; + + @BeforeAll + void before() throws Exception { + InetAddress loopback = InetAddress.getLoopbackAddress(); + InetSocketAddress addr = new InetSocketAddress(loopback, 0); + server = HttpServer.create(addr, 0); + port = server.getAddress().getPort(); + Handler handler = new Handler(interruptReadyLatch, interruptDoneLatch); + server.createContext("/HttpResponseInputStreamInterruptTest/", handler); + server.start(); + } + + @AfterAll + void after() throws Exception { + server.stop(0); + } + + @Test + public void test() throws Exception { + // create client and interrupter threads + Thread clientThread = createClientThread(interruptReadyLatch, port); + Thread interrupterThread = new Thread(() -> { + try { + // wait until the clientThread is just about to read the second message sent by the server + // then interrupt the thread to cause an error to be thrown + interruptReadyLatch.await(); + clientThread.interrupt(); + interruptDoneLatch.countDown(); + } catch (InterruptedException e) { + System.out.println("interrupterThread failed"); + throw new RuntimeException(e); + } + }); + + // Start the threads then wait until clientThread completes + clientThread.start(); + interrupterThread.start(); + clientThread.join(); + } + + static class Handler implements HttpHandler { + + CountDownLatch interruptReadyLatch; + CountDownLatch interruptDoneLatch; + + public Handler(CountDownLatch interruptReadyLatch, CountDownLatch interruptDoneLatch) { + this.interruptReadyLatch = interruptReadyLatch; + this.interruptDoneLatch = interruptDoneLatch; + } + + @Override + public void handle(HttpExchange exchange) throws IOException { + try (OutputStream os = exchange.getResponseBody()) { + byte[] workingResponse = FIRST_MESSAGE.getBytes(); + byte[] errorResponse = SECOND_MESSAGE.getBytes(); + exchange.sendResponseHeaders(200, workingResponse.length + errorResponse.length); + + // write and flush the first message which is expected to be received successfully + os.write(workingResponse); + os.flush(); + + // await the interrupt threads completion, then write the second message + interruptReadyLatch.countDown(); + interruptDoneLatch.await(); + os.write(errorResponse); + } catch (InterruptedException e) { + System.out.println("interruptDoneLatch await failed"); + throw new RuntimeException(e); + } + } + } + + static Thread createClientThread(CountDownLatch interruptReadyLatch, int port) { + return new Thread(() -> { + try { + HttpClient client = HttpClient + .newBuilder() + .proxy(HttpClient.Builder.NO_PROXY) + .build(); + + URI uri = URIBuilder.newBuilder() + .scheme("http") + .loopback() + .port(port) + .path("/HttpResponseInputStreamInterruptTest/") + .build(); + + HttpRequest request = HttpRequest + .newBuilder(uri) + .GET() + .build(); + + // Send a httpRequest and assert the first response is received as expected + HttpResponse response = client.send(request, HttpResponse.BodyHandlers.ofInputStream()); + String firstOutput = new String(response.body().readNBytes(FIRST_MESSAGE.getBytes().length)); + assertEquals(firstOutput, FIRST_MESSAGE); + + // countdown on latch, and assert that an IOException is throw due to the interrupt + // and assert that the cause is a InterruptedException + interruptReadyLatch.countDown(); + var thrown = assertThrows(IOException.class, () -> response.body().readAllBytes(), "expected IOException"); + var cause = thrown.getCause(); + assertTrue(cause instanceof InterruptedException, cause + " is not an InterruptedException"); + var thread = Thread.currentThread(); + assertTrue(thread.isInterrupted(), "Thread " + thread + " is not interrupted"); + } catch (Throwable t) { + t.printStackTrace(); + fail(); + } + }); + } +} From 74f346b33f7fa053ad5c99ef85baa32b7fb12fa6 Mon Sep 17 00:00:00 2001 From: Xiaolin Zheng Date: Thu, 8 Dec 2022 02:19:35 +0000 Subject: [PATCH 115/494] 8298075: RISC-V: Implement post-call NOPs Reviewed-by: fyang, luhenry --- src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp | 4 +++- .../riscv/c2_safepointPollStubTable_riscv.cpp | 4 +++- src/hotspot/cpu/riscv/macroAssembler_riscv.cpp | 5 +++-- src/hotspot/cpu/riscv/macroAssembler_riscv.hpp | 3 +++ src/hotspot/cpu/riscv/nativeInst_riscv.cpp | 10 +++++++++- src/hotspot/cpu/riscv/nativeInst_riscv.hpp | 18 ++++++++++++++++-- 6 files changed, 37 insertions(+), 7 deletions(-) diff --git a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp index b241a753050..197216d6eca 100644 --- a/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp +++ b/src/hotspot/cpu/riscv/c1_CodeStubs_riscv.cpp @@ -43,7 +43,9 @@ void C1SafepointPollStub::emit_code(LIR_Assembler* ce) { __ bind(_entry); InternalAddress safepoint_pc(__ pc() - __ offset() + safepoint_offset()); __ relocate(safepoint_pc.rspec(), [&] { - __ la(t0, safepoint_pc.target()); + int32_t offset; + __ la_patchable(t0, safepoint_pc.target(), offset); + __ addi(t0, t0, offset); }); __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp index d22a6a75843..e68b8d0486e 100644 --- a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp @@ -40,7 +40,9 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP __ bind(entry->_stub_label); InternalAddress safepoint_pc(__ pc() - __ offset() + entry->_safepoint_offset); __ relocate(safepoint_pc.rspec(), [&] { - __ la(t0, safepoint_pc.target()); + int32_t offset; + __ la_patchable(t0, safepoint_pc.target(), offset); + __ addi(t0, t0, offset); }); __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); __ far_jump(callback_addr); diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp index 90032696513..ec45262c8f3 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.cpp @@ -210,6 +210,7 @@ void MacroAssembler::post_call_nop() { } relocate(post_call_nop_Relocation::spec(), [&] { nop(); + li32(zr, 0); }); } @@ -1383,7 +1384,7 @@ static int patch_imm_in_li64(address branch, address target) { return LI64_INSTRUCTIONS_NUM * NativeInstruction::instruction_size; } -static int patch_imm_in_li32(address branch, int32_t target) { +int MacroAssembler::patch_imm_in_li32(address branch, int32_t target) { const int LI32_INSTRUCTIONS_NUM = 2; // lui + addiw int64_t upper = (intptr_t)target; int32_t lower = (((int32_t)target) << 20) >> 20; @@ -1447,7 +1448,7 @@ static address get_target_of_li64(address insn_addr) { return (address)target_address; } -static address get_target_of_li32(address insn_addr) { +address MacroAssembler::get_target_of_li32(address insn_addr) { assert_cond(insn_addr != NULL); intptr_t target_address = (((int64_t)Assembler::sextract(((unsigned*)insn_addr)[0], 31, 12)) & 0xfffff) << 12; // Lui. target_address += ((int64_t)Assembler::sextract(((unsigned*)insn_addr)[1], 31, 20)); // Addiw. diff --git a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp index 811eef7f8ab..4ddad837fd4 100644 --- a/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/macroAssembler_riscv.hpp @@ -387,6 +387,9 @@ class MacroAssembler: public Assembler { static int patch_oop(address insn_addr, address o); + static address get_target_of_li32(address insn_addr); + static int patch_imm_in_li32(address branch, int32_t target); + // Return whether code is emitted to a scratch blob. virtual bool in_scratch_emit_size() { return false; diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp index e7be863660d..d7385f59737 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.cpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.cpp @@ -444,8 +444,16 @@ void NativePostCallNop::make_deopt() { NativeDeoptInstruction::insert(addr_at(0)); } +int NativePostCallNop::displacement() const { + // Discard the high 32 bits + return (int)(intptr_t)MacroAssembler::get_target_of_li32(addr_at(4)); +} + void NativePostCallNop::patch(jint diff) { - // unsupported for now + assert(diff != 0, "must be"); + assert(is_lui_to_zr_at(addr_at(4)) && is_addiw_to_zr_at(addr_at(8)), "must be"); + + MacroAssembler::patch_imm_in_li32(addr_at(4), diff); } void NativeDeoptInstruction::verify() { diff --git a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp index a6ed27870c4..72a7b62c124 100644 --- a/src/hotspot/cpu/riscv/nativeInst_riscv.hpp +++ b/src/hotspot/cpu/riscv/nativeInst_riscv.hpp @@ -78,7 +78,9 @@ class NativeInstruction { static bool is_jump_at(address instr) { assert_cond(instr != NULL); return is_branch_at(instr) || is_jal_at(instr) || is_jalr_at(instr); } static bool is_addi_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0010011 && extract_funct3(instr) == 0b000; } static bool is_addiw_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0011011 && extract_funct3(instr) == 0b000; } + static bool is_addiw_to_zr_at(address instr) { assert_cond(instr != NULL); return is_addiw_at(instr) && extract_rd(instr) == zr; } static bool is_lui_at(address instr) { assert_cond(instr != NULL); return extract_opcode(instr) == 0b0110111; } + static bool is_lui_to_zr_at(address instr) { assert_cond(instr != NULL); return is_lui_at(instr) && extract_rd(instr) == zr; } static bool is_slli_shift_at(address instr, uint32_t shift) { assert_cond(instr != NULL); return (extract_opcode(instr) == 0b0010011 && // opcode field @@ -554,10 +556,22 @@ inline NativeMembar *NativeMembar_at(address addr) { return (NativeMembar*)addr; } +// A NativePostCallNop takes the form of three instructions: +// nop; lui zr, hi20; addiw zr, lo12 +// +// The nop is patchable for a deoptimization trap. The lui and addiw +// instructions execute as nops but have a 20/12-bit payload in which we +// can store an offset from the initial nop to the nmethod. class NativePostCallNop: public NativeInstruction { public: - bool check() const { return is_nop(); } - int displacement() const { return 0; } + bool check() const { + // Check for two instructions: nop; lui zr, hi20 + // These instructions only ever appear together in a post-call + // NOP, so it's unnecessary to check that the third instruction is + // an addiw as well. + return is_nop() && is_lui_to_zr_at(addr_at(4)); + } + int displacement() const; void patch(jint diff); void make_deopt(); }; From d5cf18e7fb591185eecb042bfa015609ea7d15e0 Mon Sep 17 00:00:00 2001 From: Tejesh R Date: Thu, 8 Dec 2022 04:34:48 +0000 Subject: [PATCH 116/494] 8296198: JFileChooser throws InternalError java.lang.InternalError with Windows shortcuts Reviewed-by: serb, abhiscxk --- .../swing/plaf/basic/BasicFileChooserUI.java | 29 +-- .../FileSystemView/CustomFSVLinkTest.java | 218 ++++++++++++++++++ 2 files changed, 234 insertions(+), 13 deletions(-) create mode 100644 test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java diff --git a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java index 3ae763a4afd..c307a138114 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/basic/BasicFileChooserUI.java @@ -1408,22 +1408,25 @@ public void actionPerformed(ActionEvent e) { private void changeDirectory(File dir) { JFileChooser fc = getFileChooser(); // Traverse shortcuts on Windows - if (dir != null && FilePane.usesShellFolder(fc)) { + if (dir != null) { try { - ShellFolder shellFolder = ShellFolder.getShellFolder(dir); - - if (shellFolder.isLink()) { - File linkedTo = shellFolder.getLinkLocation(); - - // If linkedTo is null we try to use dir - if (linkedTo != null) { - if (fc.isTraversable(linkedTo)) { - dir = linkedTo; - } else { - return; + File linkedTo = null; + if (FilePane.usesShellFolder(fc)) { + ShellFolder shellFolder = ShellFolder.getShellFolder(dir); + if (shellFolder.isLink()) { + linkedTo = shellFolder.getLinkLocation(); + if (linkedTo == null) { + dir = shellFolder; } + } + } else if ( fc.getFileSystemView().isLink(dir)){ + linkedTo = fc.getFileSystemView().getLinkLocation(dir); + } + if (linkedTo != null) { + if (fc.isTraversable(linkedTo)) { + dir = linkedTo; } else { - dir = shellFolder; + return; } } } catch (FileNotFoundException ex) { diff --git a/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java b/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java new file mode 100644 index 00000000000..2c5f1a2c446 --- /dev/null +++ b/test/jdk/javax/swing/JFileChooser/FileSystemView/CustomFSVLinkTest.java @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2022, 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. + */ + +import java.awt.BorderLayout; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; + +import javax.swing.JFrame; +import javax.swing.JFileChooser; +import javax.swing.SwingUtilities; +import javax.swing.Icon; +import javax.swing.WindowConstants; +import javax.swing.filechooser.FileSystemView; + +/* + * @test + * @bug 8296198 + * @key headful + * @requires (os.family == "windows") + * @library /java/awt/regtesthelpers + * @build PassFailJFrame + * @summary Test to check if the Link to a folder is traversable with custom + * FileSystemView is valid on ValueChanged property listener. + * @run main/manual CustomFSVLinkTest + */ +public class CustomFSVLinkTest { + static JFrame frame; + static JFileChooser jfc; + + static PassFailJFrame passFailJFrame; + + public static void main(String[] args) throws Exception { + SwingUtilities.invokeAndWait(new Runnable() { + public void run() { + try { + initialize(); + } catch (InterruptedException | InvocationTargetException e) { + throw new RuntimeException(e); + } + } + }); + passFailJFrame.awaitAndCheck(); + } + + static void initialize() throws InterruptedException, InvocationTargetException { + //Initialize the components + final String INSTRUCTIONS = """ + Instructions to Test: + 1. Create a link to a any valid folder. + 2. Navigate to the linked folder through the link created + (From FileChooser). + 3. If "link" can't be traversed or if its absolute path is null + click FAIL. If "link" can be traversed then click PASS. + """; + frame = new JFrame("JFileChooser Link test"); + jfc = new JFileChooser(new MyFileSystemView()); + passFailJFrame = new PassFailJFrame("Test Instructions", INSTRUCTIONS, 5L, 8, 40); + + PassFailJFrame.addTestWindow(frame); + PassFailJFrame.positionTestWindow(frame, PassFailJFrame.Position.HORIZONTAL); + frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); + jfc.setDialogType(JFileChooser.CUSTOM_DIALOG); + + frame.add(jfc, BorderLayout.CENTER); + frame.pack(); + frame.setVisible(true); + } + + private static class MyFileSystemView extends FileSystemView { + FileSystemView delegate; + + MyFileSystemView() { + delegate = FileSystemView.getFileSystemView(); + } + + @Override + public File createNewFolder(File containingDir) throws IOException { + return delegate.createNewFolder(containingDir); + } + + @Override + public boolean isRoot(File f) { + return delegate.isRoot(f); + } + + @Override + public Boolean isTraversable(File f) { + return delegate.isTraversable(f); + } + + @Override + public String getSystemDisplayName(File f) { + return delegate.getSystemDisplayName(f); + } + + @Override + public String getSystemTypeDescription(File f) { + return delegate.getSystemTypeDescription(f); + } + + @Override + public Icon getSystemIcon(File f) { + return delegate.getSystemIcon(f); + } + + @Override + public boolean isParent(File folder, File file) { + return delegate.isParent(folder, file); + } + + @Override + public File getChild(File parent, String fileName) { + return delegate.getChild(parent, fileName); + } + + @Override + public boolean isFileSystem(File f) { + return delegate.isFileSystem(f); + } + + @Override + public boolean isHiddenFile(File f) { + return delegate.isHiddenFile(f); + } + + @Override + public boolean isFileSystemRoot(File dir) { + return delegate.isFileSystemRoot(dir); + } + + @Override + public boolean isDrive(File dir) { + return delegate.isDrive(dir); + } + + @Override + public boolean isFloppyDrive(File dir) { + return delegate.isFloppyDrive(dir); + } + + @Override + public boolean isComputerNode(File dir) { + return delegate.isComputerNode(dir); + } + + @Override + public File[] getRoots() { + return delegate.getRoots(); + } + + @Override + public File getHomeDirectory() { + return delegate.getHomeDirectory(); + } + + @Override + public File getDefaultDirectory() { + return delegate.getDefaultDirectory(); + } + + @Override + public File createFileObject(File dir, String filename) { + return delegate.createFileObject(dir, filename); + } + + @Override + public File createFileObject(String path) { + return delegate.createFileObject(path); + } + + @Override + public File[] getFiles(File dir, boolean useFileHiding) { + return delegate.getFiles(dir, useFileHiding); + } + + @Override + public File getParentDirectory(File dir) { + return delegate.getParentDirectory(dir); + } + + @Override + public File[] getChooserComboBoxFiles() { + return delegate.getChooserComboBoxFiles(); + } + + @Override + public boolean isLink(File file) { + return delegate.isLink(file); + } + + @Override + public File getLinkLocation(File file) throws FileNotFoundException { + return delegate.getLinkLocation(file); + } + } +} From 51759650e5593f48ce616a1a8abf51f5f8fd5302 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Thu, 8 Dec 2022 07:15:02 +0000 Subject: [PATCH 117/494] 8298323: trivial typo in JOptionPane.OK_OPTION Reviewed-by: iris --- src/java.desktop/share/classes/javax/swing/JOptionPane.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/java.desktop/share/classes/javax/swing/JOptionPane.java b/src/java.desktop/share/classes/javax/swing/JOptionPane.java index 28a547dc2cb..930acc90b35 100644 --- a/src/java.desktop/share/classes/javax/swing/JOptionPane.java +++ b/src/java.desktop/share/classes/javax/swing/JOptionPane.java @@ -353,7 +353,7 @@ public class JOptionPane extends JComponent implements Accessible public static final int NO_OPTION = 1; /** Return value from class method if CANCEL is chosen. */ public static final int CANCEL_OPTION = 2; - /** Return value form class method if OK is chosen. */ + /** Return value from class method if OK is chosen. */ public static final int OK_OPTION = 0; /** Return value from class method if user closes window without selecting * anything, more than likely this should be treated as either a From 1166c8e2c0047869cd50b7ddc5355290ac2a695a Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 8 Dec 2022 07:37:32 +0000 Subject: [PATCH 118/494] 8296896: Change virtual Thread.yield to use external submit Reviewed-by: jpai, rpressler --- .../classes/java/lang/VirtualThread.java | 75 +++++++---- .../lang/Thread/virtual/YieldQueuing.java | 126 ++++++++++++++++++ .../lang/Thread/virtual/stress/YieldALot.java | 2 +- 3 files changed, 176 insertions(+), 27 deletions(-) create mode 100644 test/jdk/java/lang/Thread/virtual/YieldQueuing.java diff --git a/src/java.base/share/classes/java/lang/VirtualThread.java b/src/java.base/share/classes/java/lang/VirtualThread.java index 3dd722739e3..1ee253d4d6c 100644 --- a/src/java.base/share/classes/java/lang/VirtualThread.java +++ b/src/java.base/share/classes/java/lang/VirtualThread.java @@ -224,45 +224,59 @@ private void runContinuation() { } /** - * Submits the runContinuation task to the scheduler. - * @param {@code lazySubmit} to lazy submit + * Submits the runContinuation task to the scheduler. For the default scheduler, + * and calling it on a worker thread, the task will be pushed to the local queue, + * otherwise it will be pushed to a submission queue. + * * @throws RejectedExecutionException - * @see ForkJoinPool#lazySubmit(ForkJoinTask) */ - private void submitRunContinuation(boolean lazySubmit) { + private void submitRunContinuation() { try { - if (lazySubmit && scheduler instanceof ForkJoinPool pool) { - pool.lazySubmit(ForkJoinTask.adapt(runContinuation)); - } else { - scheduler.execute(runContinuation); - } + scheduler.execute(runContinuation); } catch (RejectedExecutionException ree) { - // record event - var event = new VirtualThreadSubmitFailedEvent(); - if (event.isEnabled()) { - event.javaThreadId = threadId(); - event.exceptionMessage = ree.getMessage(); - event.commit(); - } + submitFailed(ree); throw ree; } } /** - * Submits the runContinuation task to the scheduler. + * Submits the runContinuation task to the scheduler with a lazy submit. * @throws RejectedExecutionException + * @see ForkJoinPool#lazySubmit(ForkJoinTask) */ - private void submitRunContinuation() { - submitRunContinuation(false); + private void lazySubmitRunContinuation(ForkJoinPool pool) { + try { + pool.lazySubmit(ForkJoinTask.adapt(runContinuation)); + } catch (RejectedExecutionException ree) { + submitFailed(ree); + throw ree; + } } /** - * Submits the runContinuation task to the scheduler and without signalling - * any threads if possible. + * Submits the runContinuation task to the scheduler as an external submit. * @throws RejectedExecutionException + * @see ForkJoinPool#externalSubmit(ForkJoinTask) */ - private void lazySubmitRunContinuation() { - submitRunContinuation(true); + private void externalSubmitRunContinuation(ForkJoinPool pool) { + try { + pool.externalSubmit(ForkJoinTask.adapt(runContinuation)); + } catch (RejectedExecutionException ree) { + submitFailed(ree); + throw ree; + } + } + + /** + * If enabled, emits a JFR VirtualThreadSubmitFailedEvent. + */ + private void submitFailed(RejectedExecutionException ree) { + var event = new VirtualThreadSubmitFailedEvent(); + if (event.isEnabled()) { + event.javaThreadId = threadId(); + event.exceptionMessage = ree.getMessage(); + event.commit(); + } } /** @@ -437,7 +451,12 @@ private void afterYield() { // may have been unparked while parking if (parkPermit && compareAndSetState(PARKED, RUNNABLE)) { // lazy submit to continue on the current thread as carrier if possible - lazySubmitRunContinuation(); + if (currentThread() instanceof CarrierThread ct) { + lazySubmitRunContinuation(ct.getPool()); + } else { + submitRunContinuation(); + } + } } else if (s == YIELDING) { // Thread.yield setState(RUNNABLE); @@ -445,8 +464,12 @@ private void afterYield() { // notify JVMTI that unmount has completed, thread is runnable if (notifyJvmtiEvents) notifyJvmtiUnmountEnd(false); - // lazy submit to continue on the current thread as carrier if possible - lazySubmitRunContinuation(); + // external submit if there are no tasks in the local task queue + if (currentThread() instanceof CarrierThread ct && ct.getQueuedTaskCount() == 0) { + externalSubmitRunContinuation(ct.getPool()); + } else { + submitRunContinuation(); + } } } diff --git a/test/jdk/java/lang/Thread/virtual/YieldQueuing.java b/test/jdk/java/lang/Thread/virtual/YieldQueuing.java new file mode 100644 index 00000000000..33961848667 --- /dev/null +++ b/test/jdk/java/lang/Thread/virtual/YieldQueuing.java @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2022, 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 Test Thread.yield submits the virtual thread task to the expected queue + * @requires vm.continuations + * @enablePreview + * @run junit/othervm -Djdk.virtualThreadScheduler.maxPoolSize=1 YieldQueuing + */ + +import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.locks.LockSupport; + +import org.junit.jupiter.api.Test; +import static org.junit.jupiter.api.Assertions.*; + +class YieldQueuing { + + /** + * Test Thread.yield submits the task for the current virtual thread to a scheduler + * submission queue when there are no tasks in the local queue. + */ + @Test + void testYieldWithEmptyLocalQueue() throws Exception { + var list = new CopyOnWriteArrayList(); + + var threadsStarted = new AtomicBoolean(); + + var threadA = Thread.ofVirtual().unstarted(() -> { + // pin thread until task for B is in submission queue + while (!threadsStarted.get()) { + Thread.onSpinWait(); + } + + list.add("A"); + Thread.yield(); // push task for A to submission queue, B should run + list.add("A"); + }); + + var threadB = Thread.ofVirtual().unstarted(() -> { + list.add("B"); + }); + + // push tasks for A and B to submission queue + threadA.start(); + threadB.start(); + + // release A + threadsStarted.set(true); + + // wait for result + threadA.join(); + threadB.join(); + assertEquals(list, List.of("A", "B", "A")); + } + + /** + * Test Thread.yield submits the task for the current virtual thread to the local + * queue when there are tasks in the local queue. + */ + @Test + void testYieldWithNonEmptyLocalQueue() throws Exception { + var list = new CopyOnWriteArrayList(); + + var threadsStarted = new AtomicBoolean(); + + var threadA = Thread.ofVirtual().unstarted(() -> { + // pin thread until tasks for B and C are in submission queue + while (!threadsStarted.get()) { + Thread.onSpinWait(); + } + + list.add("A"); + LockSupport.park(); // B should run + list.add("A"); + }); + + var threadB = Thread.ofVirtual().unstarted(() -> { + list.add("B"); + LockSupport.unpark(threadA); // push task for A to local queue + Thread.yield(); // push task for B to local queue, A should run + list.add("B"); + }); + + var threadC = Thread.ofVirtual().unstarted(() -> { + list.add("C"); + }); + + // push tasks for A, B and C to submission queue + threadA.start(); + threadB.start(); + threadC.start(); + + // release A + threadsStarted.set(true); + + // wait for result + threadA.join(); + threadB.join(); + threadC.join(); + assertEquals(list, List.of("A", "B", "A", "B", "C")); + } +} diff --git a/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java b/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java index 327ca0e4fd4..51381f12b02 100644 --- a/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java +++ b/test/jdk/java/lang/Thread/virtual/stress/YieldALot.java @@ -26,7 +26,7 @@ * @summary Stress test Thread.yield * @requires vm.debug != true * @enablePreview - * @run main YieldALot 500000 + * @run main YieldALot 350000 */ /* From 46cd457b0f78996a3f26e44452de8f8a66041f58 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Thu, 8 Dec 2022 09:33:06 +0000 Subject: [PATCH 119/494] 8298341: Ensure heap growth in TestNativeMemoryUsageEvents.java Reviewed-by: egahlin, stuefe --- .../jfr/event/runtime/TestNativeMemoryUsageEvents.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java index 7deeb297aad..6495addbaec 100644 --- a/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java +++ b/test/jdk/jdk/jfr/event/runtime/TestNativeMemoryUsageEvents.java @@ -103,6 +103,15 @@ private static void generateEvents(Recording recording) throws Exception { // Generate data to force heap to grow. generateHeapContents(); + // To allow the two usage events to share a single NMTUsage snapshot + // there is an AgeThreshold set to 50ms and if the two events occur + // within this interval they will use the same snapshot. On fast + // machines it is possible that the whole heap contents generation + // take less than 50ms and therefor both beginChunk end endChunk + // events will use the same NMTUsage snapshot. To avoid this, do + // a short sleep. + Thread.sleep(100); + recording.stop(); } From 073897c88bbc430e8751a18baf7487f6474fd0c3 Mon Sep 17 00:00:00 2001 From: Smita Kamath Date: Thu, 8 Dec 2022 09:46:59 +0000 Subject: [PATCH 120/494] 8294588: Auto vectorize half precision floating point conversion APIs Reviewed-by: sviswanathan, kvn, jbhateja, fgao, xgong --- src/hotspot/cpu/x86/assembler_x86.cpp | 27 +++++- src/hotspot/cpu/x86/assembler_x86.hpp | 2 + src/hotspot/cpu/x86/vm_version_x86.cpp | 1 + src/hotspot/cpu/x86/x86.ad | 55 +++++++++++ src/hotspot/share/adlc/formssel.cpp | 2 +- src/hotspot/share/opto/classes.hpp | 2 + src/hotspot/share/opto/superword.cpp | 2 +- src/hotspot/share/opto/vectorIntrinsics.cpp | 4 +- src/hotspot/share/opto/vectornode.cpp | 23 ++++- src/hotspot/share/opto/vectornode.hpp | 18 +++- .../compiler/lib/ir_framework/IRNode.java | 10 ++ .../TestFloatConversionsVector.java | 95 +++++++++++++++++++ 12 files changed, 231 insertions(+), 10 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index ad7543cfb78..e1a68906d8d 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -1931,14 +1931,14 @@ void Assembler::vcvtdq2pd(XMMRegister dst, XMMRegister src, int vector_len) { } void Assembler::vcvtps2ph(XMMRegister dst, XMMRegister src, int imm8, int vector_len) { - assert(VM_Version::supports_avx512vl() || VM_Version::supports_f16c(), ""); + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /*uses_vl */ true); int encode = vex_prefix_and_encode(src->encoding(), 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); emit_int24(0x1D, (0xC0 | encode), imm8); } void Assembler::evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm8, int vector_len) { - assert(VM_Version::supports_avx512vl(), ""); + assert(VM_Version::supports_evex(), ""); InstructionMark im(this); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /*uses_vl */ true); attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_64bit); @@ -1951,13 +1951,34 @@ void Assembler::evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm emit_int8(imm8); } +void Assembler::vcvtps2ph(Address dst, XMMRegister src, int imm8, int vector_len) { + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /*uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(dst, 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_3A, &attributes); + emit_int8(0x1D); + emit_operand(src, dst, 1); + emit_int8(imm8); +} + void Assembler::vcvtph2ps(XMMRegister dst, XMMRegister src, int vector_len) { - assert(VM_Version::supports_avx512vl() || VM_Version::supports_f16c(), ""); + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */false, /* no_mask_reg */ true, /* uses_vl */ true); int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); emit_int16(0x13, (0xC0 | encode)); } +void Assembler::vcvtph2ps(XMMRegister dst, Address src, int vector_len) { + assert(VM_Version::supports_evex() || VM_Version::supports_f16c(), ""); + InstructionMark im(this); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ false, /*uses_vl */ true); + attributes.set_address_attributes(/* tuple_type */ EVEX_HVM, /* input_size_in_bits */ EVEX_NObit); + vex_prefix(src, 0, dst->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int8(0x13); + emit_operand(dst, src, 0); +} + void Assembler::cvtdq2ps(XMMRegister dst, XMMRegister src) { NOT_LP64(assert(VM_Version::supports_sse2(), "")); InstructionAttr attributes(AVX_128bit, /* rex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index 7b4288e775e..a5d8f2dabfc 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1160,6 +1160,8 @@ class Assembler : public AbstractAssembler { void vcvtps2ph(XMMRegister dst, XMMRegister src, int imm8, int vector_len); void vcvtph2ps(XMMRegister dst, XMMRegister src, int vector_len); void evcvtps2ph(Address dst, KRegister mask, XMMRegister src, int imm8, int vector_len); + void vcvtps2ph(Address dst, XMMRegister src, int imm8, int vector_len); + void vcvtph2ps(XMMRegister dst, Address src, int vector_len); // Convert Packed Signed Doubleword Integers to Packed Single-Precision Floating-Point Value void cvtdq2ps(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/vm_version_x86.cpp b/src/hotspot/cpu/x86/vm_version_x86.cpp index 5a0a085401b..83979a60245 100644 --- a/src/hotspot/cpu/x86/vm_version_x86.cpp +++ b/src/hotspot/cpu/x86/vm_version_x86.cpp @@ -956,6 +956,7 @@ void VM_Version::get_processor_features() { if (UseAVX < 1) { _features &= ~CPU_AVX; _features &= ~CPU_VZEROUPPER; + _features &= ~CPU_F16C; } if (logical_processors_per_package() == 1) { diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index 629ae77567d..d70389245ad 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1687,6 +1687,12 @@ const bool Matcher::match_rule_supported(int opcode) { return false; } break; + case Op_VectorCastF2HF: + case Op_VectorCastHF2F: + if (!VM_Version::supports_f16c() && !VM_Version::supports_evex()) { + return false; + } + break; } return true; // Match rules are supported by default. } @@ -1901,6 +1907,14 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; } break; + case Op_VectorCastF2HF: + case Op_VectorCastHF2F: + if (!VM_Version::supports_f16c() && + ((!VM_Version::supports_evex() || + ((size_in_bits != 512) && !VM_Version::supports_avx512vl())))) { + return false; + } + break; case Op_RoundVD: if (!VM_Version::supports_avx512dq()) { return false; @@ -3673,6 +3687,26 @@ instruct convF2HF_mem_reg(memory mem, regF src, kReg ktmp, rRegI rtmp) %{ ins_pipe( pipe_slow ); %} +instruct vconvF2HF(vec dst, vec src) %{ + match(Set dst (VectorCastF2HF src)); + format %{ "vector_conv_F2HF $dst $src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this, $src); + __ vcvtps2ph($dst$$XMMRegister, $src$$XMMRegister, 0x04, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vconvF2HF_mem_reg(memory mem, vec src) %{ + match(Set mem (StoreVector mem (VectorCastF2HF src))); + format %{ "vcvtps2ph $mem,$src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this, $src); + __ vcvtps2ph($mem$$Address, $src$$XMMRegister, 0x04, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + instruct convHF2F_reg_reg(regF dst, rRegI src) %{ match(Set dst (ConvHF2F src)); format %{ "vcvtph2ps $dst,$src" %} @@ -3683,6 +3717,27 @@ instruct convHF2F_reg_reg(regF dst, rRegI src) %{ ins_pipe( pipe_slow ); %} +instruct vconvHF2F_reg_mem(vec dst, memory mem) %{ + match(Set dst (VectorCastHF2F (LoadVector mem))); + format %{ "vcvtph2ps $dst,$mem" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vcvtph2ps($dst$$XMMRegister, $mem$$Address, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + +instruct vconvHF2F(vec dst, vec src) %{ + match(Set dst (VectorCastHF2F src)); + ins_cost(125); + format %{ "vector_conv_HF2F $dst,$src" %} + ins_encode %{ + int vlen_enc = vector_length_encoding(this); + __ vcvtph2ps($dst$$XMMRegister, $src$$XMMRegister, vlen_enc); + %} + ins_pipe( pipe_slow ); +%} + // ---------------------------------------- VectorReinterpret ------------------------------------ instruct reinterpret_mask(kReg dst) %{ predicate(n->bottom_type()->isa_vectmask() && diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index d09c6a5ca92..21a01306333 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -4223,7 +4223,7 @@ bool MatchRule::is_vector() const { "VectorTest", "VectorLoadMask", "VectorStoreMask", "VectorBlend", "VectorInsert", "VectorRearrange","VectorLoadShuffle", "VectorLoadConst", "VectorCastB2X", "VectorCastS2X", "VectorCastI2X", - "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", + "VectorCastL2X", "VectorCastF2X", "VectorCastD2X", "VectorCastF2HF", "VectorCastHF2F", "VectorUCastB2X", "VectorUCastS2X", "VectorUCastI2X", "VectorMaskWrapper","VectorMaskCmp","VectorReinterpret","LoadVectorMasked","StoreVectorMasked", "FmaVD","FmaVF","PopCountVI","PopCountVL","PopulateIndex","VectorLongToMask", diff --git a/src/hotspot/share/opto/classes.hpp b/src/hotspot/share/opto/classes.hpp index 45b7f8f2f85..112bf860c57 100644 --- a/src/hotspot/share/opto/classes.hpp +++ b/src/hotspot/share/opto/classes.hpp @@ -506,6 +506,8 @@ macro(VectorCastI2X) macro(VectorCastL2X) macro(VectorCastF2X) macro(VectorCastD2X) +macro(VectorCastF2HF) +macro(VectorCastHF2F) macro(VectorUCastB2X) macro(VectorUCastS2X) macro(VectorUCastI2X) diff --git a/src/hotspot/share/opto/superword.cpp b/src/hotspot/share/opto/superword.cpp index 35dce686ec5..4df7b4219e8 100644 --- a/src/hotspot/share/opto/superword.cpp +++ b/src/hotspot/share/opto/superword.cpp @@ -2712,7 +2712,7 @@ bool SuperWord::output() { assert(n->req() == 2, "only one input expected"); BasicType bt = velt_basic_type(n); Node* in = vector_opd(p, 1); - int vopc = VectorCastNode::opcode(in->bottom_type()->is_vect()->element_basic_type()); + int vopc = VectorCastNode::opcode(opc, in->bottom_type()->is_vect()->element_basic_type()); vn = VectorCastNode::make(vopc, in, bt, vlen); vlen_in_bytes = vn->as_Vector()->length_in_bytes(); } else if (is_cmov_pack(p)) { diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index 4d131760e45..ec4ed774ada 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -775,7 +775,7 @@ bool LibraryCallKit::inline_vector_shuffle_to_vector() { return false; } - int cast_vopc = VectorCastNode::opcode(T_BYTE); // from shuffle of type T_BYTE + int cast_vopc = VectorCastNode::opcode(-1, T_BYTE); // from shuffle of type T_BYTE // Make sure that cast is implemented to particular type/size combination. if (!arch_supports_vector(cast_vopc, num_elem, elem_bt, VecMaskNotUsed)) { if (C->print_intrinsics()) { @@ -2489,7 +2489,7 @@ bool LibraryCallKit::inline_vector_convert() { Node* op = opd1; if (is_cast) { assert(!is_mask || num_elem_from == num_elem_to, "vector mask cast needs the same elem num"); - int cast_vopc = VectorCastNode::opcode(elem_bt_from, !is_ucast); + int cast_vopc = VectorCastNode::opcode(-1, elem_bt_from, !is_ucast); // Make sure that vector cast is implemented to particular type/size combination if it is // not a mask casting. diff --git a/src/hotspot/share/opto/vectornode.cpp b/src/hotspot/share/opto/vectornode.cpp index 92ec6d80cfe..dfc81402ede 100644 --- a/src/hotspot/share/opto/vectornode.cpp +++ b/src/hotspot/share/opto/vectornode.cpp @@ -467,6 +467,8 @@ bool VectorNode::is_convert_opcode(int opc) { case Op_ConvD2F: case Op_ConvF2D: case Op_ConvD2I: + case Op_ConvF2HF: + case Op_ConvHF2F: return true; default: return false; @@ -1328,14 +1330,31 @@ VectorCastNode* VectorCastNode::make(int vopc, Node* n1, BasicType bt, uint vlen case Op_VectorUCastB2X: return new VectorUCastB2XNode(n1, vt); case Op_VectorUCastS2X: return new VectorUCastS2XNode(n1, vt); case Op_VectorUCastI2X: return new VectorUCastI2XNode(n1, vt); + case Op_VectorCastHF2F: return new VectorCastHF2FNode(n1, vt); + case Op_VectorCastF2HF: return new VectorCastF2HFNode(n1, vt); default: assert(false, "unknown node: %s", NodeClassNames[vopc]); return NULL; } } -int VectorCastNode::opcode(BasicType bt, bool is_signed) { +int VectorCastNode::opcode(int sopc, BasicType bt, bool is_signed) { assert((is_integral_type(bt) && bt != T_LONG) || is_signed, ""); + + // Handle special case for to/from Half Float conversions + switch (sopc) { + case Op_ConvHF2F: + assert(bt == T_SHORT, ""); + return Op_VectorCastHF2F; + case Op_ConvF2HF: + assert(bt == T_FLOAT, ""); + return Op_VectorCastF2HF; + default: + // Handled normally below + break; + } + + // Handle normal conversions switch (bt) { case T_BYTE: return is_signed ? Op_VectorCastB2X : Op_VectorUCastB2X; case T_SHORT: return is_signed ? Op_VectorCastS2X : Op_VectorUCastS2X; @@ -1354,7 +1373,7 @@ bool VectorCastNode::implemented(int opc, uint vlen, BasicType src_type, BasicTy is_java_primitive(src_type) && (vlen > 1) && is_power_of_2(vlen) && VectorNode::vector_size_supported(dst_type, vlen)) { - int vopc = VectorCastNode::opcode(src_type); + int vopc = VectorCastNode::opcode(opc, src_type); return vopc > 0 && Matcher::match_rule_supported_superword(vopc, vlen, dst_type); } return false; diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index aa672ca983e..21a8a8737a6 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1542,7 +1542,7 @@ class VectorCastNode : public VectorNode { virtual int Opcode() const; static VectorCastNode* make(int vopc, Node* n1, BasicType bt, uint vlen); - static int opcode(BasicType bt, bool is_signed = true); + static int opcode(int opc, BasicType bt, bool is_signed = true); static bool implemented(int opc, uint vlen, BasicType src_type, BasicType dst_type); virtual Node* Identity(PhaseGVN* phase); @@ -1628,6 +1628,22 @@ class VectorUCastS2XNode : public VectorCastNode { virtual int Opcode() const; }; +class VectorCastHF2FNode : public VectorCastNode { + public: + VectorCastHF2FNode(Node* in, const TypeVect* vt) : VectorCastNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == T_SHORT, "must be short"); + } + virtual int Opcode() const; +}; + +class VectorCastF2HFNode : public VectorCastNode { + public: + VectorCastF2HFNode(Node* in, const TypeVect* vt) : VectorCastNode(in, vt) { + assert(in->bottom_type()->is_vect()->element_basic_type() == T_FLOAT, "must be float"); + } + virtual int Opcode() const; +}; + class VectorUCastI2XNode : public VectorCastNode { public: VectorUCastI2XNode(Node* in, const TypeVect* vt) : VectorCastNode(in, vt) { diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 6f30d9f83be..7e08baab74c 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1079,6 +1079,16 @@ public class IRNode { beforeMatchingNameRegex(VECTOR_CAST_S2X, "VectorCastS2X"); } + public static final String VECTOR_CAST_F2HF = PREFIX + "VECTOR_CAST_F2HF" + POSTFIX; + static { + beforeMatchingNameRegex(VECTOR_CAST_F2HF, "VectorCastF2HF"); + } + + public static final String VECTOR_CAST_HF2F = PREFIX + "VECTOR_CAST_HF2F" + POSTFIX; + static { + beforeMatchingNameRegex(VECTOR_CAST_HF2F, "VectorCastHF2F"); + } + public static final String VECTOR_MASK_CAST = PREFIX + "VECTOR_MASK_CAST" + POSTFIX; static { beforeMatchingNameRegex(VECTOR_MASK_CAST, "VectorMaskCast"); diff --git a/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java new file mode 100644 index 00000000000..e84b734144e --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorization/TestFloatConversionsVector.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2022, 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 8294588 + * @summary Auto-vectorize Float.floatToFloat16, Float.float16ToFloat APIs + * @requires vm.compiler2.enabled + * @requires os.simpleArch == "x64" + * @library /test/lib / + * @run driver compiler.vectorization.TestFloatConversionsVector + */ + +package compiler.vectorization; + +import compiler.lib.ir_framework.*; + +public class TestFloatConversionsVector { + private static final int ARRLEN = 1024; + private static final int ITERS = 11000; + private static float [] finp; + private static short [] sout; + private static short [] sinp; + private static float [] fout; + + public static void main(String args[]) { + TestFramework.runWithFlags("-XX:-TieredCompilation", + "-XX:CompileThresholdScaling=0.3"); + System.out.println("PASSED"); + } + + @Test + @IR(counts = {IRNode.VECTOR_CAST_F2HF, "> 0"}, applyIfCPUFeatureOr = {"avx512f", "true", "f16c", "true"}) + public void test_float_float16(short[] sout, float[] finp) { + for (int i = 0; i < finp.length; i++) { + sout[i] = Float.floatToFloat16(finp[i]); + } + } + + @Run(test = {"test_float_float16"}, mode = RunMode.STANDALONE) + public void kernel_test_float_float16() { + finp = new float[ARRLEN]; + sout = new short[ARRLEN]; + + for (int i = 0; i < ARRLEN; i++) { + finp[i] = (float) i * 1.4f; + } + + for (int i = 0; i < ITERS; i++) { + test_float_float16(sout, finp); + } + } + + @Test + @IR(counts = {IRNode.VECTOR_CAST_HF2F, "> 0"}, applyIfCPUFeatureOr = {"avx512f", "true", "f16c", "true"}) + public void test_float16_float(float[] fout, short[] sinp) { + for (int i = 0; i < sinp.length; i++) { + fout[i] = Float.float16ToFloat(sinp[i]); + } + } + + @Run(test = {"test_float16_float"}, mode = RunMode.STANDALONE) + public void kernel_test_float16_float() { + sinp = new short[ARRLEN]; + fout = new float[ARRLEN]; + + for (int i = 0; i < ARRLEN; i++) { + sinp[i] = (short)i; + } + + for (int i = 0; i < ITERS; i++) { + test_float16_float(fout , sinp); + } + } +} From 297bf6a5965c4f01ca2091976b5e6ca675ab5395 Mon Sep 17 00:00:00 2001 From: Anthony Vanelverdinghe Date: Thu, 8 Dec 2022 10:19:39 +0000 Subject: [PATCH 121/494] 8287397: Print top-level exception when snippet fails to read file Reviewed-by: jjg --- .../internal/doclets/toolkit/taglets/SnippetTaglet.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java index 2e2003a5123..9ebe5f281d4 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclets/toolkit/taglets/SnippetTaglet.java @@ -229,7 +229,7 @@ private Content generateContent(Element holder, DocTree tag, TagletWriter writer } } catch (IOException | IllegalArgumentException e) { // TODO: test this when JDK-8276892 is integrated // JavaFileManager.getFileForInput can throw IllegalArgumentException in certain cases - throw new BadSnippetException(a, "doclet.exception.read.file", v, e.getCause()); + throw new BadSnippetException(a, "doclet.exception.read.file", v, e); } if (fileObject == null) { @@ -241,7 +241,7 @@ private Content generateContent(Element holder, DocTree tag, TagletWriter writer externalContent = fileObject.getCharContent(true).toString(); } catch (IOException e) { // TODO: test this when JDK-8276892 is integrated throw new BadSnippetException(a, "doclet.exception.read.file", - fileObject.getName(), e.getCause()); + fileObject.getName(), e); } } From b9346e149e6cfcaf18bfafbd262f6fed209dc644 Mon Sep 17 00:00:00 2001 From: Sergey Tsypanov Date: Thu, 8 Dec 2022 10:21:56 +0000 Subject: [PATCH 122/494] 8298033: Character.codePoint{At|Before}(char[], int, int) doesn't do JavaDoc-specified check Reviewed-by: rriggs --- src/java.base/share/classes/java/lang/Character.java | 5 ++--- test/jdk/java/lang/Character/Supplementary.java | 8 ++++---- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Character.java b/src/java.base/share/classes/java/lang/Character.java index afe1fb8f7c0..ab487c8fcf9 100644 --- a/src/java.base/share/classes/java/lang/Character.java +++ b/src/java.base/share/classes/java/lang/Character.java @@ -39,7 +39,6 @@ import static java.lang.constant.ConstantDescs.BSM_EXPLICIT_CAST; import static java.lang.constant.ConstantDescs.CD_char; -import static java.lang.constant.ConstantDescs.CD_int; import static java.lang.constant.ConstantDescs.DEFAULT_NAME; /** @@ -9375,7 +9374,7 @@ public static int codePointAt(char[] a, int index) { * @since 1.5 */ public static int codePointAt(char[] a, int index, int limit) { - if (index >= limit || limit < 0 || limit > a.length) { + if (index >= limit || index < 0 || limit > a.length) { throw new IndexOutOfBoundsException(); } return codePointAtImpl(a, index, limit); @@ -9478,7 +9477,7 @@ public static int codePointBefore(char[] a, int index) { * @since 1.5 */ public static int codePointBefore(char[] a, int index, int start) { - if (index <= start || start < 0 || start >= a.length) { + if (index <= start || start < 0 || index > a.length) { throw new IndexOutOfBoundsException(); } return codePointBeforeImpl(a, index, start); diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index 3056eba8b83..e246e257c2c 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022 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,7 +23,7 @@ /* * @test - * @bug 4533872 4985214 4985217 4993841 5017268 5017280 + * @bug 4533872 4985214 4985217 4993841 5017268 5017280 8298033 * @summary Unit tests for supplementary character support (JSR-204) * @compile Supplementary.java * @run main/timeout=600 Supplementary @@ -797,12 +797,12 @@ private static void callCodePoint(boolean isAt, char[] a, int index, } private static void callCodePoint(boolean isAt, char[] a, int index, int limit, - Class expectedException) { + Class expectedException) { try { int c = isAt ? Character.codePointAt(a, index, limit) : Character.codePointBefore(a, index, limit); } catch (Exception e) { - if (expectedException.isInstance(e)) { + if (expectedException == e.getClass()) { return; } throw new RuntimeException("Unspecified exception", e); From 2f426cd68b28c8bf50b7102f961b15fd47b63b6a Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Thu, 8 Dec 2022 11:02:21 +0000 Subject: [PATCH 123/494] 8298375: Bad copyright header in test/jdk/java/lang/Character/Supplementary.java Reviewed-by: alanb --- test/jdk/java/lang/Character/Supplementary.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/java/lang/Character/Supplementary.java b/test/jdk/java/lang/Character/Supplementary.java index e246e257c2c..acb162ad947 100644 --- a/test/jdk/java/lang/Character/Supplementary.java +++ b/test/jdk/java/lang/Character/Supplementary.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2022 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 From 49b86224aacc7fd8b4d3354a85d72ef636a18a12 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Thu, 8 Dec 2022 11:23:42 +0000 Subject: [PATCH 124/494] 8290850: C2: create_new_if_for_predicate() does not clone pinned phi input nodes resulting in a broken graph Reviewed-by: thartmann, kvn --- src/hotspot/share/opto/loopPredicate.cpp | 181 ++++---- src/hotspot/share/opto/loopnode.hpp | 28 +- .../TestCreateNewIfForPredicateCloning.java | 408 ++++++++++++++++++ 3 files changed, 520 insertions(+), 97 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestCreateNewIfForPredicateCloning.java diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index 07300c81c0c..a7c6f858f41 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -109,9 +109,9 @@ void PhaseIdealLoop::register_control(Node* n, IdealLoopTree *loop, Node* pred, // Otherwise, the continuation projection is set up to be the false // projection. This code is also used to clone predicates to cloned loops. ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, - Deoptimization::DeoptReason reason, int opcode, - bool if_cont_is_true_proj, Node_List* old_new, - UnswitchingAction unswitching_action) { + Deoptimization::DeoptReason reason, + const int opcode, const bool rewire_uncommon_proj_phi_inputs, + const bool if_cont_is_true_proj) { assert(cont_proj->is_uncommon_trap_if_pattern(reason), "must be a uct if pattern!"); IfNode* iff = cont_proj->in(0)->as_If(); @@ -196,39 +196,25 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* assert(use->in(0) == rgn, ""); _igvn.rehash_node_delayed(use); Node* phi_input = use->in(proj_index); - if (unswitching_action == UnswitchingAction::FastLoopCloning - && !phi_input->is_CFG() && !phi_input->is_Phi() && get_ctrl(phi_input) == uncommon_proj) { - // There are some control dependent nodes on the uncommon projection and we are currently copying predicates - // to the fast loop in loop unswitching (first step, slow loop is processed afterwards). For the fast loop, - // we need to clone all the data nodes in the chain from the phi ('use') up until the node whose control input - // is the uncommon_proj. The slow loop can reuse the old data nodes and thus only needs to update the control - // input to the uncommon_proj (done on the next invocation of this method when 'unswitch_is_slow_loop' is true. - assert(LoopUnswitching, "sanity check"); - phi_input = clone_data_nodes_for_fast_loop(phi_input, uncommon_proj, if_uct, old_new); - } else if (unswitching_action == UnswitchingAction::SlowLoopRewiring) { - // Replace phi input for the old predicate path with TOP as the predicate is dying anyways. This avoids the need - // to clone the data nodes again for the slow loop. - assert(LoopUnswitching, "sanity check"); - _igvn.replace_input_of(use, proj_index, C->top()); + + if (uncommon_proj->outcnt() > 1 && !phi_input->is_CFG() && !phi_input->is_Phi() && get_ctrl(phi_input) == uncommon_proj) { + // There are some control dependent nodes on the uncommon projection. We cannot simply reuse these data nodes. + // We either need to rewire them from the old uncommon projection to the newly created uncommon proj (if the old + // If is dying) or clone them and update their control (if the old If is not dying). + if (rewire_uncommon_proj_phi_inputs) { + // Replace phi input for the old uncommon projection with TOP as the If is dying anyways. Reuse the old data + // nodes by simply updating control inputs and ctrl. + _igvn.replace_input_of(use, proj_index, C->top()); + set_ctrl_of_nodes_with_same_ctrl(phi_input, uncommon_proj, if_uct); + } else { + phi_input = clone_nodes_with_same_ctrl(phi_input, uncommon_proj, if_uct); + } } use->add_req(phi_input); has_phi = true; } } assert(!has_phi || rgn->req() > 3, "no phis when region is created"); - if (unswitching_action == UnswitchingAction::SlowLoopRewiring) { - // Rewire the control dependent data nodes for the slow loop from the old to the new uncommon projection. - assert(uncommon_proj->outcnt() > 1 && old_new == NULL, "sanity"); - for (DUIterator_Fast jmax, j = uncommon_proj->fast_outs(jmax); j < jmax; j++) { - Node* data = uncommon_proj->fast_out(j); - if (!data->is_CFG()) { - _igvn.replace_input_of(data, 0, if_uct); - set_ctrl(data, if_uct); - --j; - --jmax; - } - } - } if (new_entry == NULL) { // Attach if_cont to iff @@ -240,70 +226,98 @@ ProjNode* PhaseIdealLoop::create_new_if_for_predicate(ProjNode* cont_proj, Node* return if_cont->as_Proj(); } -// Clone data nodes for the fast loop while creating a new If with create_new_if_for_predicate. Returns the node which is -// used for the uncommon trap phi input. -Node* PhaseIdealLoop::clone_data_nodes_for_fast_loop(Node* phi_input, ProjNode* uncommon_proj, Node* if_uct, Node_List* old_new) { - // Step 1: Clone all nodes on the data chain but do not rewire anything, yet. Keep track of the cloned nodes - // by using the old_new mapping. This mapping is then used in step 2 to rewire the cloned nodes accordingly. - DEBUG_ONLY(uint last_idx = C->unique();) - Unique_Node_List list; - list.push(phi_input); - for (uint j = 0; j < list.size(); j++) { - Node* next = list.at(j); - Node* clone = next->clone(); - _igvn.register_new_node_with_optimizer(clone); - old_new->map(next->_idx, clone); +// Update ctrl and control inputs of all data nodes starting from 'node' to 'new_ctrl' which have 'old_ctrl' as +// current ctrl. +void PhaseIdealLoop::set_ctrl_of_nodes_with_same_ctrl(Node* node, ProjNode* old_ctrl, Node* new_ctrl) { + Unique_Node_List nodes_with_same_ctrl = find_nodes_with_same_ctrl(node, old_ctrl); + for (uint j = 0; j < nodes_with_same_ctrl.size(); j++) { + Node* next = nodes_with_same_ctrl[j]; + if (next->in(0) == old_ctrl) { + _igvn.replace_input_of(next, 0, new_ctrl); + } + set_ctrl(next, new_ctrl); + } +} + +// Recursively find all input nodes with the same ctrl. +Unique_Node_List PhaseIdealLoop::find_nodes_with_same_ctrl(Node* node, const ProjNode* ctrl) { + Unique_Node_List nodes_with_same_ctrl; + nodes_with_same_ctrl.push(node); + for (uint j = 0; j < nodes_with_same_ctrl.size(); j++) { + Node* next = nodes_with_same_ctrl[j]; for (uint k = 1; k < next->req(); k++) { Node* in = next->in(k); - if (!in->is_Phi() && get_ctrl(in) == uncommon_proj) { - list.push(in); + if (!in->is_Phi() && get_ctrl(in) == ctrl) { + nodes_with_same_ctrl.push(in); } } } + return nodes_with_same_ctrl; +} + +// Clone all nodes with the same ctrl as 'old_ctrl' starting from 'node' by following its inputs. Rewire the cloned nodes +// to 'new_ctrl'. Returns the clone of 'node'. +Node* PhaseIdealLoop::clone_nodes_with_same_ctrl(Node* node, ProjNode* old_ctrl, Node* new_ctrl) { + DEBUG_ONLY(uint last_idx = C->unique();) + Unique_Node_List nodes_with_same_ctrl = find_nodes_with_same_ctrl(node, old_ctrl); + Dict old_new_mapping = clone_nodes(nodes_with_same_ctrl); // Cloned but not rewired, yet + rewire_cloned_nodes_to_ctrl(old_ctrl, new_ctrl, nodes_with_same_ctrl, old_new_mapping); + Node* clone_phi_input = static_cast(old_new_mapping[node]); + assert(clone_phi_input != NULL && clone_phi_input->_idx >= last_idx, "must exist and be a proper clone"); + return clone_phi_input; +} + +// Clone all the nodes on 'list_to_clone' and return an old->new mapping. +Dict PhaseIdealLoop::clone_nodes(const Node_List& list_to_clone) { + Dict old_new_mapping(cmpkey, hashkey); + for (uint i = 0; i < list_to_clone.size(); i++) { + Node* next = list_to_clone[i]; + Node* clone = next->clone(); + _igvn.register_new_node_with_optimizer(clone); + old_new_mapping.Insert(next, clone); + } + return old_new_mapping; +} - // Step 2: All nodes are cloned. Rewire them by using the old_new mapping. - for (uint j = 0; j < list.size(); j++) { - Node* next = list.at(j); - Node* clone = old_new->at(next->_idx); - assert(clone != NULL && clone->_idx >= last_idx, "must exist and be a proper clone"); - if (next->in(0) == uncommon_proj) { +// Rewire inputs of the unprocessed cloned nodes (inputs are not updated, yet, and still point to the old nodes) by +// using the old_new_mapping. +void PhaseIdealLoop::rewire_cloned_nodes_to_ctrl(const ProjNode* old_ctrl, Node* new_ctrl, + const Node_List& nodes_with_same_ctrl, const Dict& old_new_mapping) { + for (uint i = 0; i < nodes_with_same_ctrl.size(); i++) { + Node* next = nodes_with_same_ctrl[i]; + Node* clone = static_cast(old_new_mapping[next]); + if (next->in(0) == old_ctrl) { // All data nodes with a control input to the uncommon projection in the chain need to be rewired to the new uncommon // projection (could not only be the last data node in the chain but also, for example, a DivNode within the chain). - _igvn.replace_input_of(clone, 0, if_uct); - set_ctrl(clone, if_uct); + _igvn.replace_input_of(clone, 0, new_ctrl); + set_ctrl(clone, new_ctrl); } + rewire_inputs_of_clones_to_clones(new_ctrl, clone, old_new_mapping, next); + } +} - // Rewire the inputs of the cloned nodes to the old nodes to the new clones. - for (uint k = 1; k < next->req(); k++) { - Node* in = next->in(k); - if (!in->is_Phi()) { - assert(!in->is_CFG(), "must be data node"); - Node* in_clone = old_new->at(in->_idx); - if (in_clone != NULL) { - assert(in_clone->_idx >= last_idx, "must be a valid clone"); - _igvn.replace_input_of(clone, k, in_clone); - set_ctrl(clone, if_uct); - } +// Rewire the inputs of the cloned nodes to the old nodes to the new clones. +void PhaseIdealLoop::rewire_inputs_of_clones_to_clones(Node* new_ctrl, Node* clone, const Dict& old_new_mapping, + const Node* next) { + for (uint i = 1; i < next->req(); i++) { + Node* in = next->in(i); + if (!in->is_Phi()) { + assert(!in->is_CFG(), "must be data node"); + Node* in_clone = static_cast(old_new_mapping[in]); + if (in_clone != NULL) { + _igvn.replace_input_of(clone, i, in_clone); + set_ctrl(clone, new_ctrl); } } } - Node* clone_phi_input = old_new->at(phi_input->_idx); - assert(clone_phi_input != NULL && clone_phi_input->_idx >= last_idx, "must exist and be a proper clone"); - return clone_phi_input; } + //--------------------------clone_predicate----------------------- ProjNode* PhaseIdealLoop::clone_predicate_to_unswitched_loop(ProjNode* predicate_proj, Node* new_entry, - Deoptimization::DeoptReason reason, Node_List* old_new) { - UnswitchingAction unswitching_action; - if (predicate_proj->other_if_proj()->outcnt() > 1) { - // There are some data dependencies that need to be taken care of when cloning a predicate. - unswitching_action = old_new == NULL ? UnswitchingAction::SlowLoopRewiring : UnswitchingAction::FastLoopCloning; - } else { - unswitching_action = UnswitchingAction::None; - } + Deoptimization::DeoptReason reason, const bool slow_loop) { ProjNode* new_predicate_proj = create_new_if_for_predicate(predicate_proj, new_entry, reason, Op_If, - true, old_new, unswitching_action); + slow_loop); IfNode* iff = new_predicate_proj->in(0)->as_If(); Node* ctrl = iff->in(0); @@ -402,7 +416,8 @@ ProjNode* PhaseIdealLoop::clone_skeleton_predicate_for_unswitched_loops(Node* if Deoptimization::DeoptReason reason, ProjNode* output_proj) { Node* bol = clone_skeleton_predicate_bool(iff, NULL, NULL, output_proj); - ProjNode* proj = create_new_if_for_predicate(output_proj, NULL, reason, iff->Opcode(), predicate->is_IfTrue()); + ProjNode* proj = create_new_if_for_predicate(output_proj, NULL, reason, iff->Opcode(), + false, predicate->is_IfTrue()); _igvn.replace_input_of(proj->in(0), 1, bol); _igvn.replace_input_of(output_proj->in(0), 0, proj); set_idom(output_proj->in(0), proj, dom_depth(proj)); @@ -435,8 +450,8 @@ void PhaseIdealLoop::clone_predicates_to_unswitched_loop(IdealLoopTree* loop, No } if (predicate_proj != NULL) { // right pattern that can be used by loop predication // clone predicate - iffast_pred = clone_predicate_to_unswitched_loop(predicate_proj, iffast_pred, Deoptimization::Reason_predicate, &old_new); - ifslow_pred = clone_predicate_to_unswitched_loop(predicate_proj, ifslow_pred, Deoptimization::Reason_predicate); + iffast_pred = clone_predicate_to_unswitched_loop(predicate_proj, iffast_pred, Deoptimization::Reason_predicate,false); + ifslow_pred = clone_predicate_to_unswitched_loop(predicate_proj, ifslow_pred, Deoptimization::Reason_predicate,true); clone_skeleton_predicates_to_unswitched_loop(loop, old_new, Deoptimization::Reason_predicate, predicate_proj, iffast_pred, ifslow_pred); check_created_predicate_for_unswitching(iffast_pred); @@ -444,8 +459,8 @@ void PhaseIdealLoop::clone_predicates_to_unswitched_loop(IdealLoopTree* loop, No } if (profile_predicate_proj != NULL) { // right pattern that can be used by loop predication // clone predicate - iffast_pred = clone_predicate_to_unswitched_loop(profile_predicate_proj, iffast_pred, Deoptimization::Reason_profile_predicate, &old_new); - ifslow_pred = clone_predicate_to_unswitched_loop(profile_predicate_proj, ifslow_pred, Deoptimization::Reason_profile_predicate); + iffast_pred = clone_predicate_to_unswitched_loop(profile_predicate_proj, iffast_pred,Deoptimization::Reason_profile_predicate, false); + ifslow_pred = clone_predicate_to_unswitched_loop(profile_predicate_proj, ifslow_pred,Deoptimization::Reason_profile_predicate, true); clone_skeleton_predicates_to_unswitched_loop(loop, old_new, Deoptimization::Reason_profile_predicate, profile_predicate_proj, iffast_pred, ifslow_pred); check_created_predicate_for_unswitching(iffast_pred); @@ -455,8 +470,8 @@ void PhaseIdealLoop::clone_predicates_to_unswitched_loop(IdealLoopTree* loop, No // Clone loop limit check last to insert it before loop. // Don't clone a limit check which was already finalized // for this counted loop (only one limit check is needed). - iffast_pred = clone_predicate_to_unswitched_loop(limit_check_proj, iffast_pred, Deoptimization::Reason_loop_limit_check, &old_new); - ifslow_pred = clone_predicate_to_unswitched_loop(limit_check_proj, ifslow_pred, Deoptimization::Reason_loop_limit_check); + iffast_pred = clone_predicate_to_unswitched_loop(limit_check_proj, iffast_pred,Deoptimization::Reason_loop_limit_check, false); + ifslow_pred = clone_predicate_to_unswitched_loop(limit_check_proj, ifslow_pred,Deoptimization::Reason_loop_limit_check, true); check_created_predicate_for_unswitching(iffast_pred); check_created_predicate_for_unswitching(ifslow_pred); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index b5b01a9fcd7..defb1ad6cbb 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -1308,22 +1308,22 @@ class PhaseIdealLoop : public PhaseTransform { jlong* p_scale, Node** p_offset, bool* p_short_scale, int depth); - - // Enum to determine the action to be performed in create_new_if_for_predicate() when processing phis of UCT regions. - enum class UnswitchingAction { - None, // No special action. - FastLoopCloning, // Need to clone nodes for the fast loop. - SlowLoopRewiring // Need to rewire nodes for the slow loop. - }; - // Create a new if above the uncommon_trap_if_pattern for the predicate to be promoted ProjNode* create_new_if_for_predicate(ProjNode* cont_proj, Node* new_entry, Deoptimization::DeoptReason reason, - int opcode, bool if_cont_is_true_proj = true, Node_List* old_new = NULL, - UnswitchingAction unswitching_action = UnswitchingAction::None); + int opcode, bool rewire_uncommon_proj_phi_inputs = false, + bool if_cont_is_true_proj = true); - // Clone data nodes for the fast loop while creating a new If with create_new_if_for_predicate. - Node* clone_data_nodes_for_fast_loop(Node* phi_input, ProjNode* uncommon_proj, Node* if_uct, Node_List* old_new); + private: + // Helper functions for create_new_if_for_predicate() + void set_ctrl_of_nodes_with_same_ctrl(Node* node, ProjNode* old_ctrl, Node* new_ctrl); + Unique_Node_List find_nodes_with_same_ctrl(Node* node, const ProjNode* ctrl); + Node* clone_nodes_with_same_ctrl(Node* node, ProjNode* old_ctrl, Node* new_ctrl); + Dict clone_nodes(const Node_List& list_to_clone); + void rewire_cloned_nodes_to_ctrl(const ProjNode* old_ctrl, Node* new_ctrl, const Node_List& nodes_with_same_ctrl, + const Dict& old_new_mapping); + void rewire_inputs_of_clones_to_clones(Node* new_ctrl, Node* clone, const Dict& old_new_mapping, const Node* next); + public: void register_control(Node* n, IdealLoopTree *loop, Node* pred, bool update_body = true); static Node* skip_all_loop_predicates(Node* entry); @@ -1640,8 +1640,8 @@ class PhaseIdealLoop : public PhaseTransform { // Clone loop predicates to slow and fast loop when unswitching a loop void clone_predicates_to_unswitched_loop(IdealLoopTree* loop, Node_List& old_new, ProjNode*& iffast_pred, ProjNode*& ifslow_pred); - ProjNode* clone_predicate_to_unswitched_loop(ProjNode* predicate_proj, Node* new_entry, Deoptimization::DeoptReason reason, - Node_List* old_new = NULL); + ProjNode* clone_predicate_to_unswitched_loop(ProjNode* predicate_proj, Node* new_entry, + Deoptimization::DeoptReason reason, bool slow_loop); void clone_skeleton_predicates_to_unswitched_loop(IdealLoopTree* loop, const Node_List& old_new, Deoptimization::DeoptReason reason, ProjNode* old_predicate_proj, ProjNode* iffast_pred, ProjNode* ifslow_pred); ProjNode* clone_skeleton_predicate_for_unswitched_loops(Node* iff, ProjNode* predicate, diff --git a/test/hotspot/jtreg/compiler/loopopts/TestCreateNewIfForPredicateCloning.java b/test/hotspot/jtreg/compiler/loopopts/TestCreateNewIfForPredicateCloning.java new file mode 100644 index 00000000000..33f0d20da9c --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestCreateNewIfForPredicateCloning.java @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2022, 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 8290850 + * @summary Test cloning of pinned phi input nodes in create_new_if_for_predicate(). + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestCreateNewIfForPredicateCloning::* + * compiler.loopopts.TestCreateNewIfForPredicateCloning + */ + +package compiler.loopopts; + +public class TestCreateNewIfForPredicateCloning { + static int iFld, iFld2, iFld3, nonZero = 2, nonZero2 = 3; + static boolean bFld = true, bFld2 = false; + static int[] iArrFld = new int[100]; + + public static void main(String[] args) { + try { + testUnswitching(); + testLoopPredicatation(); + testLoopPredicatationComplex(); + testUnswitchingWithPredicates(); + testUnswitchingWithPredicatesDiv(); + testFuzzer1(); + testFuzzer2(); + testFuzzer3(); + } catch (Exception e) { + // Expected + } + } + + // Test case for the already fixed problem in 8271954: Calling create_new_if_for_predicate in + // clone_predicate_to_unswitched_loop(). This does not crash anymore. But still use it as sanity test here with the + // new fix. + static void testUnswitching() { + int x = 3; + + // Block to delay precise type information to after CCP. + int limit = 2; + int constantAfterCCP = 2; + for (; limit < 4; limit *= 2); + for (int i = 2; i < limit; i++) { + constantAfterCCP = 6; // Only known to be constant 6 after CCP. + } + + for (int i = 51; i > 9; i -= 3) { + if (bFld) { + x *= 6; + } + // (1) after unswitching: + // if (bFld) {...} + // Since we have a back to back if now with the same condition, we can merge them together by using the + // split if optimization. That will create phi nodes for the UCT regions. Whenever we then call + // create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap + // projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But + // in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon + // trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph: + // the LCA of the old and new uncommon projection would be above the early control (control input of the + // CastII nodes). + // + // 8271954 fixes this when calling create_new_if_for_predicate() in + // clone_predicate_to_unswitched_loop(). + x -= 5; + + for (int j = 1; j < 10; j++) { + if (bFld) { // Unswitching on bFld such that this condition is moved to (1) + continue; + } + x = 34; // Redefine x such that x is only used in UCT before this loop after split if. + int y = 34; + if (constantAfterCCP == 2) { + // Known to be never taken after CCP, so y will always be 34. + y = 35; + } + if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching + continue; + } + iFld3 = 34; // Just another statement sucht that the second round of unswitching is done + + } + } + + // This loop is only needed to delay the second round of unswitching for the inner loop above. + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 3; + } + } + + // Similar to testUnswitching() but we are calling create_new_if_for_predicate in Loop Predication for: + // - Creating hoised range check predicate and skeleton predicate + // - Creating invariant check predicate + // which leads to a crash. + static void testLoopPredicatation() { + int x = 3; + + // Block to delay precise type information to after CCP. + int limit = 2; + int constantAfterCCP = 2; + for (; limit < 4; limit *= 2); + for (int i = 2; i < limit; i++) { + constantAfterCCP = 6; // Only known to be constant 6 after CCP. + } + + for (int i = 51; i > 9; i -= 3) { + if (bFld) { + x *= 6; + } + // (1) after unswitching: + // if (bFld) {...} + // Since we have a back to back if now with the same condition, we can merge them together by using the + // split if optimization. That will create phi nodes for the UCT regions. Whenever we then call + // create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap + // projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But + // in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon + // trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph: + // the LCA of the old and new uncommon projection would be above the early control (control input of the + // CastII nodes). + x -= 5; + + for (int j = 1; j < 10; j++) { + if (bFld) { // Unswitching on bFld such that this condition is moved to (1) + continue; + } + x = 34; // Redefine x such that x is only used in UCT before this loop after split if. + int y = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if. + } + } + + // This loop is only needed to delay the second round of unswitching for the inner loop above. + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 3; + } + } + + // Similar to testLoopPredicatation() but we are adding some computations for x such that we sink more nodes which + // need to be cloned when calling create_new_if_for_predicate(). + static void testLoopPredicatationComplex() { + int x = 3; + + // Block to delay precise type information to after CCP. + int limit = 2; + int constantAfterCCP = 2; + for (; limit < 4; limit *= 2); + for (int i = 2; i < limit; i++) { + constantAfterCCP = 6; // Only known to be constant 6 after CCP. + } + + for (int i = 51; i > 9; i -= 3) { + if (bFld) { + x *= 6; + } + // (1) after unswitching: + // if (bFld) {...} + // Since we have a back to back if now with the same condition, we can merge them together by using the + // split if optimization. That will create phi nodes for the UCT regions. Whenever we then call + // create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap + // projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But + // in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon + // trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph: + // the LCA of the old and new uncommon projection would be above the early control (control input of the + // CastII nodes). + x -= 5; + + // Add some more computations such that more nodes are sunk and therefore more nodes need to be cloned in + // create_new_if_for_predicate(). + double d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + d1 = 5 + (double) x; + x = (int)((d1 + iFld2) - (d1 + iFld)); + + for (int j = 1; j < 10; j++) { + if (bFld) { // Unswitching on bFld such that this condition is moved to (1) + continue; + } + x = 34; // Redefine x such that x is only used in UCT before this loop after split if. + int y = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if. + } + } + + // This loop is only needed to delay the second round of unswitching for the inner loop above. + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 3; + } + } + + // Combination of testUnswitching() and testLoopPredicatation(): After creating predicates in loop predication, + // we perform another round of loop unswitching where we additionally call create_new_if_for_predicate in + // clone_skeleton_predicate_for_unswitched_loops() which currently leads to a crash. + static void testUnswitchingWithPredicates() { + int x = 3; + if (iArrFld == null) { + // Makes sure to get rid of null check for iArrFld to only create range check predicate + return; + } + // Block to delay precise type information to after CCP. + int limit = 2; + int constantAfterCCP = 2; + for (; limit < 4; limit *= 2); + for (int i = 2; i < limit; i++) { + constantAfterCCP = 6; // Only known to be constant 6 after CCP. + } + + for (int i = 51; i > 9; i -= 3) { + if (bFld) { + x *= 6; + } + // (1) after unswitching: + // if (bFld) {...} + // Since we have a back to back if now with the same condition, we can merge them together by using the + // split if optimization. That will create phi nodes for the UCT regions. Whenever we then call + // create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap + // projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But + // in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon + // trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph: + // the LCA of the old and new uncommon projection would be above the early control (control input of the + // CastII nodes). + x -= 5; + + for (int j = 1; j < 10; j++) { + if (bFld) { // Unswitching on bFld such that this condition is moved to (1) + continue; + } + x = 34; // Redefine x such that x is only used in UCT before this loop after split if. + int z = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if. + int y = 34; + if (constantAfterCCP == 2) { + // Known to be never taken after CCP, so y will always be 34. + y = 35; + } + if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching + continue; + } + iFld3 = 34; // Just another statement sucht that the second round of unswitching is done + } + } + + // This loop is only needed to delay the second round of unswitching for the inner loop above. + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 3; + } + } + + // Same as testUnswitchingWithPredicates() but with a DivI node which has a control input which needs + // to be rewired as well. + static void testUnswitchingWithPredicatesDiv() { + int x = 3; + if (iArrFld == null) { + // Makes sure to get rid of null check for iArrFld to only create range check predicate + return; + } + // Block to delay precise type information to after CCP. + int limit = 2; + int constantAfterCCP = 2; + for (; limit < 4; limit *= 2); + for (int i = 2; i < limit; i++) { + constantAfterCCP = 6; // Only known to be constant 6 after CCP. + } + + for (int i = 51; i > 9; i -= 3) { + if (bFld) { + x *= 6; + } + // (1) after unswitching: + // if (bFld) {...} + // Since we have a back to back if now with the same condition, we can merge them together by using the + // split if optimization. That will create phi nodes for the UCT regions. Whenever we then call + // create_new_if_for_predicate(), we would just reuse the old phi input for the newly create uncommon trap + // projection. This is done when unswitching again to clone the predicates to the fast and slow loop. But + // in the meantime, we have sunk x out of the loop with CastII nodes which are pinned on the old uncommon + // trap projections. Just reusing these data nodes on the new uncommon trap proj leads to a broken graph: + // the LCA of the old and new uncommon projection would be above the early control (control input of the + // CastII nodes). + x -= 5; + + double d = 5.5f + (double) x; + int a = (int)d; + x = (a / nonZero) - (a / nonZero2); + + + for (int j = 1; j < 10; j++) { + if (bFld) { // Unswitching on bFld such that this condition is moved to (1) + continue; + } + x = 34; // Redefine x such that x is only used in UCT before this loop after split if. + int z = iArrFld[j]; // Range check and null check will be hoisted after Unswitching and split if. + int y = 34; + if (constantAfterCCP == 2) { + // Known to be never taken after CCP, so y will always be 34. + y = 35; + } + if (y == iFld) { // Folds to 34 == iFld after CCP and trigger another unswitching + continue; + } + iFld3 = 34; // Just another statement sucht that the second round of unswitching is done + } + } + + // This loop is only needed to delay the second round of unswitching for the inner loop above. + for (int i = 0; i < iArrFld.length; i++) { + iArrFld[i] = 3; + } + } + + static void testFuzzer1() { + int x = 0; + int[] iArr = new int[400]; + boolean b = true; + long[] lArr = new long[400]; + for (long l1 : lArr) { + for (int i = 63; i > 1; i -= 3) { + for (int j = 1; j < 4; j++) { + if (!b) { + x -= 5; + } + } + for (int j = 1; j < 4; j++) { + if (!b) { + x = iArr[j]; + } + if (i == 0) { + l1 += 5; + } + } + } + } + } + + static void testFuzzer2() { + int i, i1, i17 = 6, i18; + short s1; + boolean b2 = true; + float f3; + long lArr[][] = new long[400][]; + byte byArrFld[] = new byte[4]; + i = 1; + do { + for (i1 = 14; 6 < i1; i1--) + ; + i17 -= i18 = 1; + while (i18 < 4) { + i18 <<= i17 = 2; + switch (i1) { + case 114: + s1 = byArrFld[1]; + break; + case 116: + lArr[1][i18] = iFld; + if (b2) + continue; + case 118: + f3 = iFld; + } + } + i++; + } while (i < 10000); + } + + static void testFuzzer3() { + int x = 8; + int y = 4; + for (int i : iArrFld) { + x += 2; + if (bFld) { + x = 3; + } else { + y = 2; + } + for (int j = 0; j < 10; j++) { + x = 0; + y += 5; + if (!bFld) { + iArrFld[1] = 5; + } + } + } + } +} + From 94575d14f47e2dfb11b671bce26b69270b6bb3c8 Mon Sep 17 00:00:00 2001 From: Christian Hagedorn Date: Thu, 8 Dec 2022 12:00:01 +0000 Subject: [PATCH 125/494] 8295116: C2: assert(dead->outcnt() == 0 && !dead->is_top()) failed: node must be dead Reviewed-by: thartmann, rcastanedalo --- src/hotspot/share/opto/ifnode.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/hotspot/share/opto/ifnode.cpp b/src/hotspot/share/opto/ifnode.cpp index 7c2864c732a..4f258293cf2 100644 --- a/src/hotspot/share/opto/ifnode.cpp +++ b/src/hotspot/share/opto/ifnode.cpp @@ -733,6 +733,7 @@ bool IfNode::is_ctrl_folds(Node* ctrl, PhaseIterGVN* igvn) { ctrl->in(0)->as_If()->cmpi_folds(igvn, true) && // Must compare same value ctrl->in(0)->in(1)->in(1)->in(1) != NULL && + ctrl->in(0)->in(1)->in(1)->in(1) != igvn->C->top() && ctrl->in(0)->in(1)->in(1)->in(1) == in(1)->in(1)->in(1); } From 9353899bc5564827826ed94c0530497ff828e01b Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 8 Dec 2022 12:02:13 +0000 Subject: [PATCH 126/494] 8298175: JFR: Common timestamp for periodic events Reviewed-by: dholmes, mgronlun --- .../build/tools/jfr/GenerateJfrFiles.java | 10 ++++- src/hotspot/share/jfr/jni/jfrJniMethod.cpp | 4 +- .../share/jfr/periodic/jfrPeriodic.cpp | 12 ++++++ src/hotspot/share/utilities/ticks.hpp | 1 + .../share/classes/jdk/jfr/internal/JVM.java | 4 +- .../jdk/jfr/internal/RequestEngine.java | 37 ++++++++++--------- 6 files changed, 45 insertions(+), 23 deletions(-) diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index 712487ce32b..ed82128727d 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -573,9 +573,13 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro out.write("#include \"jfrfiles/jfrEventIds.hpp\""); out.write("#include \"memory/allocation.hpp\""); out.write(""); + out.write("enum PeriodicType {BEGIN_CHUNK, INTERVAL, END_CHUNK};"); + out.write(""); out.write("class JfrPeriodicEventSet : public AllStatic {"); out.write(" public:"); - out.write(" static void requestEvent(JfrEventId id) {"); + out.write(" static void requestEvent(JfrEventId id, jlong timestamp, PeriodicType periodicType) {"); + out.write(" _timestamp = Ticks(timestamp);"); + out.write(" _type = periodicType;"); out.write(" switch(id) {"); out.write(" "); for (TypeElement e : metadata.getPeriodicEvents()) { @@ -595,6 +599,10 @@ private static void printJfrPeriodicHpp(Metadata metadata, File outputFile) thro out.write(" static void request" + e.name + "(void);"); out.write(""); } + out.write(" static Ticks timestamp(void);"); + out.write(" static Ticks _timestamp;"); + out.write(" static PeriodicType type(void);"); + out.write(" static PeriodicType _type;"); out.write("};"); out.write(""); out.write("#endif // INCLUDE_JFR"); diff --git a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp index 8ae2eb0c276..cf4aae2add5 100644 --- a/src/hotspot/share/jfr/jni/jfrJniMethod.cpp +++ b/src/hotspot/share/jfr/jni/jfrJniMethod.cpp @@ -238,8 +238,8 @@ JVM_ENTRY_NO_ENV(void, jfr_mark_chunk_final(JNIEnv * env, jobject jvm)) JfrRepository::mark_chunk_final(); JVM_END -JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong eventTypeId, jlong timeStamp, jlong when)) - JfrPeriodicEventSet::requestEvent((JfrEventId)eventTypeId); +JVM_ENTRY_NO_ENV(jboolean, jfr_emit_event(JNIEnv* env, jobject jvm, jlong event_type_id, jlong timestamp, jlong periodic_type)) + JfrPeriodicEventSet::requestEvent((JfrEventId)event_type_id, timestamp, static_cast(periodic_type)); return thread->has_pending_exception() ? JNI_FALSE : JNI_TRUE; JVM_END diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index f43ccc254a7..79f42b6f425 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -81,6 +81,18 @@ */ #define TRACE_REQUEST_FUNC(id) void JfrPeriodicEventSet::request##id(void) +// Timestamp to correlate events in the same batch/generation +Ticks JfrPeriodicEventSet::_timestamp; +PeriodicType JfrPeriodicEventSet::_type; + +Ticks JfrPeriodicEventSet::timestamp(void) { + return _timestamp; +} + +PeriodicType JfrPeriodicEventSet::type(void) { + return _type; +} + TRACE_REQUEST_FUNC(JVMInformation) { ResourceMark rm; EventJVMInformation event; diff --git a/src/hotspot/share/utilities/ticks.hpp b/src/hotspot/share/utilities/ticks.hpp index 969f6792fbe..8d2bbc7ce1f 100644 --- a/src/hotspot/share/utilities/ticks.hpp +++ b/src/hotspot/share/utilities/ticks.hpp @@ -231,6 +231,7 @@ class TimeInstant : public Rep { friend class GranularTimer; friend class ObjectSample; friend class EventEmitter; + friend class JfrPeriodicEventSet; // GC unit tests friend class TimePartitionsTest; friend class GCTimerTest; diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java index 2ebe586d083..605900a8638 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/JVM.java @@ -118,11 +118,11 @@ private JVM() { * @param eventTypeId type id * * @param timestamp commit time for event - * @param when when it is being done {@link Periodic.When} + * @param periodicType when it is being done {@link PeriodicType.When} * * @return true if the event was committed */ - public native boolean emitEvent(long eventTypeId, long timestamp, long when); + public native boolean emitEvent(long eventTypeId, long timestamp, long periodicType); /** * Return a list of all classes deriving from {@link jdk.internal.event.Event} diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java index 2958e585893..1b144cdcd9a 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/RequestEngine.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 2022, 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,9 @@ import jdk.jfr.EventType; public final class RequestEngine { + enum PeriodicType { + BEGIN_CHUNK, INTERVAL, END_CHUNK + } private static final JVM jvm = JVM.getJVM(); private static final ReentrantLock lock = new ReentrantLock(); @@ -62,13 +65,13 @@ private RequestHook(@SuppressWarnings("removal") AccessControlContext acc, Platf this(null, eventType, null); } - private void execute() { + private void execute(long timestamp, PeriodicType periodicType) { try { if (accessControllerContext == null) { // native if (type.isJDK()) { hook.run(); } else { - emitJVMEvent(type); + emitJVMEvent(type, timestamp, periodicType); } if (Logger.shouldLog(LogTag.JFR_SYSTEM, LogLevel.DEBUG)) { Logger.log(LogTag.JFR_SYSTEM, LogLevel.DEBUG, "Executed periodic hook for " + type.getLogName()); @@ -82,13 +85,13 @@ private void execute() { } } - private void emitJVMEvent(PlatformEventType type) { + private void emitJVMEvent(PlatformEventType type, long timestamp, PeriodicType periodicType) { try { // There should only be one thread in native at a time. // ReentrantLock is used to avoid JavaMonitorBlocked event // from synchronized block. lock.lock(); - jvm.emitEvent(type.getId(), JVM.counterTime(), 0); + jvm.emitEvent(type.getId(), timestamp, periodicType.ordinal()); } finally { lock.unlock(); } @@ -183,35 +186,33 @@ static void addHooks(List newEntries) { } static void doChunkEnd() { - doChunk(x -> x.isEndChunk()); + doChunk(x -> x.isEndChunk(), PeriodicType.END_CHUNK); } static void doChunkBegin() { - doChunk(x -> x.isBeginChunk()); + doChunk(x -> x.isBeginChunk(), PeriodicType.BEGIN_CHUNK); } - private static void doChunk(Predicate predicate) { + private static void doChunk(Predicate predicate, PeriodicType type) { + long timestamp = JVM.counterTime(); for (RequestHook requestHook : entries) { PlatformEventType s = requestHook.type; if (s.isEnabled() && predicate.test(s)) { - requestHook.execute(); + requestHook.execute(timestamp, type); } } } static long doPeriodic() { - return run_requests(entries); + return run_requests(entries, JVM.counterTime()); } // code copied from native impl. - private static long run_requests(Collection entries) { + private static long run_requests(Collection entries, long eventTimestamp) { long last = lastTimeMillis; - // Bug 9000556 - current time millis has rather lame resolution - // The use of os::elapsed_counter() is deliberate here, we don't - // want it exchanged for os::ft_elapsed_counter(). - // Keeping direct call os::elapsed_counter() here for reliable - // real time values in order to decide when registered requestable - // events are due. + // The interval for periodic events is typically at least 1 s, so + // System.currentTimeMillis() is sufficient. JVM.counterTime() lacks + // unit and has in the past been more unreliable. long now = System.currentTimeMillis(); long min = 0; long delta = 0; @@ -249,7 +250,7 @@ private static long run_requests(Collection entries) { // Bug 9000556 - don't try to compensate // for wait > period r_delta = 0; - he.execute(); + he.execute(eventTimestamp, PeriodicType.INTERVAL); } // calculate time left From d8ef60b406a9e8fe6cc6b7be0b74e45de38604c5 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Thu, 8 Dec 2022 12:06:24 +0000 Subject: [PATCH 127/494] 8298272: Clean up ProblemList Reviewed-by: chagedorn, kvn --- test/hotspot/jtreg/ProblemList.txt | 2 -- 1 file changed, 2 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 4e188102701..fec8dfa1a7c 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -45,8 +45,6 @@ compiler/ciReplay/TestSAServer.java 8029528 generic-all compiler/compilercontrol/jcmd/ClearDirectivesFileStackTest.java 8225370 generic-all -compiler/jvmci/compilerToVM/GetFlagValueTest.java 8204459 generic-all -compiler/tiered/LevelTransitionTest.java 8067651 generic-all compiler/cpuflags/TestAESIntrinsicsOnSupportedConfig.java 8190680 generic-all From fbe7b007383b034589e93d398706bebeb24461ee Mon Sep 17 00:00:00 2001 From: Kevin Walls Date: Thu, 8 Dec 2022 12:10:26 +0000 Subject: [PATCH 128/494] 8298173: GarbageCollectionNotificationContentTest test failed: no decrease in Eden usage Reviewed-by: dcubed, cjplummer, sspitsyn --- ...bageCollectionNotificationContentTest.java | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java index be8329ac48f..9fdb1b06423 100644 --- a/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java +++ b/test/jdk/com/sun/management/GarbageCollectorMXBean/GarbageCollectionNotificationContentTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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,8 +52,8 @@ public class GarbageCollectionNotificationContentTest { private static HashMap listenerInvoked = new HashMap(); - static volatile long count = 0; - static volatile long number = 0; + static volatile long notificationReceivedCount = 0; + static volatile long numberOfGCMBeans = 0; static Object synchronizer = new Object(); static class GcListener implements NotificationListener { @@ -64,12 +64,12 @@ public void handleNotification(Notification notif, Object handback) { GarbageCollectionNotificationInfo.from((CompositeData) notif.getUserData()); String source = ((ObjectName)notif.getSource()).getCanonicalName(); synchronized(synchronizer) { - if(listenerInvoked.get(source) == null) { - listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(),gcNotif); - count++; - if(count >= number) { - synchronizer.notify(); - } + if (listenerInvoked.get(source) == null) { + listenerInvoked.put(((ObjectName)notif.getSource()).getCanonicalName(), gcNotif); + notificationReceivedCount++; + if (notificationReceivedCount >= numberOfGCMBeans) { + synchronizer.notify(); + } } } } @@ -85,16 +85,14 @@ public static void main(String[] args) throws Exception { System.out.println("GC Notification not supported by the JVM, test skipped"); return; } - final ObjectName gcMXBeanPattern = - new ObjectName("java.lang:type=GarbageCollector,*"); - Set names = - mbs.queryNames(gcMXBeanPattern, null); + final ObjectName gcMXBeanPattern = new ObjectName("java.lang:type=GarbageCollector,*"); + Set names = mbs.queryNames(gcMXBeanPattern, null); if (names.isEmpty()) throw new Exception("Test incorrect: no GC MXBeans"); - number = names.size(); + numberOfGCMBeans = names.size(); for (ObjectName n : names) { - if(mbs.isInstanceOf(n,"javax.management.NotificationEmitter")) { - listenerInvoked.put(n.getCanonicalName(),null); + if (mbs.isInstanceOf(n, "javax.management.NotificationEmitter")) { + listenerInvoked.put(n.getCanonicalName(), null); GcListener listener = new GcListener(); mbs.addNotificationListener(n, listener, null, null); } @@ -112,7 +110,7 @@ public static void main(String[] args) throws Exception { } int wakeup = 0; synchronized(synchronizer) { - while(count != number) { + while(notificationReceivedCount != numberOfGCMBeans) { synchronizer.wait(10000); wakeup++; if(wakeup > 10) @@ -126,9 +124,9 @@ public static void main(String[] args) throws Exception { } private static void checkGarbageCollectionNotificationInfoContent(GarbageCollectionNotificationInfo notif) throws Exception { - System.out.println("GC notification for "+notif.getGcName()); - System.out.print("Action: "+notif.getGcAction()); - System.out.println(" Cause: "+notif.getGcCause()); + System.out.println("GC notification for " + notif.getGcName()); + System.out.print("Action: " + notif.getGcAction()); + System.out.println(" Cause: " + notif.getGcCause()); GcInfo info = notif.getGcInfo(); System.out.print("GC Info #" + info.getId()); System.out.print(" start:" + info.getStartTime()); @@ -136,6 +134,12 @@ private static void checkGarbageCollectionNotificationInfoContent(GarbageCollect System.out.println(" (" + info.getDuration() + "ms)"); Map usage = info.getMemoryUsageBeforeGc(); + // Check MemoryUsage is present. For all but No GC events, check Eden usage decreases: + boolean doCheckMemoryUsage = true; + if (notif.getGcCause().equals("No GC")) { + System.out.println("(skip memory usage check for event with 'No GC' cause)"); + doCheckMemoryUsage = false; + } List pnames = new ArrayList(); for (Map.Entry entry : usage.entrySet() ) { String poolname = (String) entry.getKey(); @@ -143,22 +147,22 @@ private static void checkGarbageCollectionNotificationInfoContent(GarbageCollect MemoryUsage busage = (MemoryUsage) entry.getValue(); MemoryUsage ausage = (MemoryUsage) info.getMemoryUsageAfterGc().get(poolname); if (ausage == null) { - throw new RuntimeException("After Gc Memory does not exist" + - " for " + poolname); + throw new RuntimeException("After Gc Memory does not exist for " + poolname); } System.out.println("Usage for pool " + poolname); System.out.println(" Before GC: " + busage); System.out.println(" After GC: " + ausage); - checkMemoryUsage(poolname, busage, ausage); + if (doCheckMemoryUsage) { + checkMemoryUsage(poolname, busage, ausage); + } } // check if memory usage for all memory pools are returned List pools = ManagementFactory.getMemoryPoolMXBeans(); for (MemoryPoolMXBean p : pools ) { if (!pnames.contains(p.getName())) { - throw new RuntimeException("GcInfo does not contain " + - "memory usage for pool " + p.getName()); + throw new RuntimeException("GcInfo does not contain memory usage for pool " + p.getName()); } } } From 165dcdd27de16824478ac9ebdfbd7b00fffe51e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Sj=C3=B6len?= Date: Thu, 8 Dec 2022 12:32:59 +0000 Subject: [PATCH 129/494] 8297718: Make NMT free:ing protocol more granular Reviewed-by: stuefe, gziemski --- src/hotspot/share/runtime/os.cpp | 34 ++++++++++--------- src/hotspot/share/services/mallocHeader.hpp | 13 ++++++- .../share/services/mallocHeader.inline.hpp | 10 ++++++ src/hotspot/share/services/mallocTracker.cpp | 14 +++++--- src/hotspot/share/services/mallocTracker.hpp | 7 ++-- src/hotspot/share/services/memTracker.hpp | 6 +++- .../gtest/nmt/test_nmt_cornercases.cpp | 13 +++++++ 7 files changed, 72 insertions(+), 25 deletions(-) diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 0bced39d616..26cd072e0f7 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -62,6 +62,7 @@ #include "runtime/vm_version.hpp" #include "services/attachListener.hpp" #include "services/mallocTracker.hpp" +#include "services/mallocHeader.inline.hpp" #include "services/memTracker.hpp" #include "services/nmtPreInit.hpp" #include "services/nmtCommon.hpp" @@ -714,30 +715,31 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCa return NULL; } - const size_t old_size = MallocTracker::malloc_header(memblock)->size(); - - // De-account the old block from NMT *before* calling the real realloc(3) since it - // may invalidate old block including its header. This will also perform integrity checks - // on the old block (e.g. overwriters) and mark the old header as dead. - void* const old_outer_ptr = MemTracker::record_free(memblock); + // Perform integrity checks on and mark the old block as dead *before* calling the real realloc(3) since it + // may invalidate the old block, including its header. + MallocHeader* header = MallocTracker::malloc_header(memblock); + header->assert_block_integrity(); // Assert block hasn't been tampered with. + const MallocHeader::FreeInfo free_info = header->free_info(); + header->mark_block_as_dead(); // the real realloc - ALLOW_C_FUNCTION(::realloc, void* const new_outer_ptr = ::realloc(old_outer_ptr, new_outer_size);) + ALLOW_C_FUNCTION(::realloc, void* const new_outer_ptr = ::realloc(header, new_outer_size);) if (new_outer_ptr == NULL) { - // If realloc(3) failed, the old block still exists. We must re-instantiate the old - // NMT header then, since we marked it dead already. Otherwise subsequent os::realloc() - // or os::free() calls would trigger block integrity asserts. - void* p = MemTracker::record_malloc(old_outer_ptr, old_size, memflags, stack); - assert(p == memblock, "sanity"); - return NULL; + // realloc(3) failed and the block still exists. + // We have however marked it as dead, revert this change. + header->revive(); + return nullptr; } + // realloc(3) succeeded, variable header now points to invalid memory and we need to deaccount the old block. + MemTracker::deaccount(free_info); - // After a successful realloc(3), we re-account the resized block with its new size - // to NMT. This re-instantiates the NMT header. + // After a successful realloc(3), we account the resized block with its new size + // to NMT. void* const new_inner_ptr = MemTracker::record_malloc(new_outer_ptr, size, memflags, stack); #ifdef ASSERT + size_t old_size = free_info.size; if (old_size < size) { // We also zap the newly extended region. ::memset((char*)new_inner_ptr + old_size, uninitBlockPad, size - old_size); @@ -774,7 +776,7 @@ void os::free(void *memblock) { DEBUG_ONLY(break_if_ptr_caught(memblock);) - // If NMT is enabled, this checks for heap overwrites, then de-accounts the old block. + // When NMT is enabled this checks for heap overwrites, then deaccounts the old block. void* const old_outer_ptr = MemTracker::record_free(memblock); ALLOW_C_FUNCTION(::free, ::free(old_outer_ptr);) diff --git a/src/hotspot/share/services/mallocHeader.hpp b/src/hotspot/share/services/mallocHeader.hpp index 8758703c5a6..214d058a46c 100644 --- a/src/hotspot/share/services/mallocHeader.hpp +++ b/src/hotspot/share/services/mallocHeader.hpp @@ -88,7 +88,7 @@ class outputStream; */ class MallocHeader { - + NONCOPYABLE(MallocHeader); NOT_LP64(uint32_t _alt_canary); const size_t _size; const uint32_t _mst_marker; @@ -115,6 +115,12 @@ class MallocHeader { void set_footer(uint16_t v) { footer_address()[0] = v >> 8; footer_address()[1] = (uint8_t)v; } public: + // Contains all of the necessary data to to deaccount block with NMT. + struct FreeInfo { + const size_t size; + const MEMFLAGS flags; + const uint32_t mst_marker; + }; inline MallocHeader(size_t size, MEMFLAGS flags, uint32_t mst_marker); @@ -123,7 +129,12 @@ class MallocHeader { inline uint32_t mst_marker() const { return _mst_marker; } bool get_stack(NativeCallStack& stack) const; + // Return the necessary data to deaccount the block with NMT. + FreeInfo free_info() { + return FreeInfo{this->size(), this->flags(), this->mst_marker()}; + } inline void mark_block_as_dead(); + inline void revive(); // If block is broken, fill in a short descriptive text in out, // an option pointer to the corruption in p_corruption, and return false. diff --git a/src/hotspot/share/services/mallocHeader.inline.hpp b/src/hotspot/share/services/mallocHeader.inline.hpp index 5ec37be680b..6d781880f78 100644 --- a/src/hotspot/share/services/mallocHeader.inline.hpp +++ b/src/hotspot/share/services/mallocHeader.inline.hpp @@ -45,6 +45,16 @@ inline MallocHeader::MallocHeader(size_t size, MEMFLAGS flags, uint32_t mst_mark set_footer(_footer_canary_life_mark); // set after initializing _size } +inline void MallocHeader::revive() { + assert(_canary == _header_canary_dead_mark, "must be dead"); + assert(get_footer() == _footer_canary_dead_mark, "must be dead"); + NOT_LP64(assert(_alt_canary == _header_alt_canary_dead_mark, "must be dead")); + _canary = _header_canary_life_mark; + NOT_LP64(_alt_canary = _header_alt_canary_life_mark); + set_footer(_footer_canary_life_mark); +} + +// The effects of this method must be reversible with MallocHeader::revive() inline void MallocHeader::mark_block_as_dead() { _canary = _header_canary_dead_mark; NOT_LP64(_alt_canary = _header_alt_canary_dead_mark); diff --git a/src/hotspot/share/services/mallocTracker.cpp b/src/hotspot/share/services/mallocTracker.cpp index 4d2eca4f587..f80e4d2d534 100644 --- a/src/hotspot/share/services/mallocTracker.cpp +++ b/src/hotspot/share/services/mallocTracker.cpp @@ -180,23 +180,27 @@ void* MallocTracker::record_malloc(void* malloc_base, size_t size, MEMFLAGS flag return memblock; } -void* MallocTracker::record_free(void* memblock) { +void* MallocTracker::record_free_block(void* memblock) { assert(MemTracker::enabled(), "Sanity"); assert(memblock != NULL, "precondition"); MallocHeader* const header = malloc_header(memblock); header->assert_block_integrity(); - MallocMemorySummary::record_free(header->size(), header->flags()); - if (MemTracker::tracking_level() == NMT_detail) { - MallocSiteTable::deallocation_at(header->size(), header->mst_marker()); - } + deaccount(header->free_info()); header->mark_block_as_dead(); return (void*)header; } +void MallocTracker::deaccount(MallocHeader::FreeInfo free_info) { + MallocMemorySummary::record_free(free_info.size, free_info.flags); + if (MemTracker::tracking_level() == NMT_detail) { + MallocSiteTable::deallocation_at(free_info.size, free_info.mst_marker); + } +} + // Given a pointer, if it seems to point to the start of a valid malloced block, // print the block. Note that since there is very low risk of memory looking // accidentally like a valid malloc block header (canaries and all) this is not diff --git a/src/hotspot/share/services/mallocTracker.hpp b/src/hotspot/share/services/mallocTracker.hpp index 03681662231..b99b59ac3a2 100644 --- a/src/hotspot/share/services/mallocTracker.hpp +++ b/src/hotspot/share/services/mallocTracker.hpp @@ -303,8 +303,11 @@ class MallocTracker : AllStatic { static void* record_malloc(void* malloc_base, size_t size, MEMFLAGS flags, const NativeCallStack& stack); - // Record free on specified memory block - static void* record_free(void* memblock); + // Given a block returned by os::malloc() or os::realloc(): + // deaccount block from NMT, mark its header as dead and return pointer to header. + static void* record_free_block(void* memblock); + // Given the free info from a block, de-account block from NMT. + static void deaccount(MallocHeader::FreeInfo free_info); static inline void record_new_arena(MEMFLAGS flags) { MallocMemorySummary::record_new_arena(flags); diff --git a/src/hotspot/share/services/memTracker.hpp b/src/hotspot/share/services/memTracker.hpp index c373d47589f..22f6ff95478 100644 --- a/src/hotspot/share/services/memTracker.hpp +++ b/src/hotspot/share/services/memTracker.hpp @@ -109,7 +109,11 @@ class MemTracker : AllStatic { if (!enabled()) { return memblock; } - return MallocTracker::record_free(memblock); + return MallocTracker::record_free_block(memblock); + } + static inline void deaccount(MallocHeader::FreeInfo free_info) { + assert(enabled(), "NMT must be enabled"); + MallocTracker::deaccount(free_info); } // Record creation of an arena diff --git a/test/hotspot/gtest/nmt/test_nmt_cornercases.cpp b/test/hotspot/gtest/nmt/test_nmt_cornercases.cpp index 43f5e6bd3b0..7c3dc0f6cfe 100644 --- a/test/hotspot/gtest/nmt/test_nmt_cornercases.cpp +++ b/test/hotspot/gtest/nmt/test_nmt_cornercases.cpp @@ -141,3 +141,16 @@ TEST_VM(NMT, random_reallocs) { os::free(p); } + +TEST_VM(NMT, HeaderKeepsIntegrityAfterRevival) { + if (!MemTracker::enabled()) { + return; + } + size_t some_size = 16; + void* p = os::malloc(some_size, mtTest); + ASSERT_NOT_NULL(p) << "Failed to malloc()"; + MallocHeader* hdr = MallocTracker::malloc_header(p); + hdr->mark_block_as_dead(); + hdr->revive(); + check_expected_malloc_header(p, mtTest, some_size); +} From ea108f504ccb63fc9651e804e3bbba1c108dcead Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Dec 2022 12:51:46 +0000 Subject: [PATCH 130/494] 8298129: Let checkpoint event sizes grow beyond u4 limit Reviewed-by: egahlin --- .../checkpoint/jfrCheckpointManager.cpp | 109 ++++++++++-------- src/hotspot/share/jfr/writers/jfrEncoders.hpp | 49 +++++++- src/hotspot/share/jfr/writers/jfrEncoding.hpp | 5 + .../share/jfr/writers/jfrWriterHost.hpp | 2 + .../jfr/writers/jfrWriterHost.inline.hpp | 6 + .../jfr/internal/consumer/ChunkParser.java | 6 +- 6 files changed, 122 insertions(+), 55 deletions(-) diff --git a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp index edbbb5c76cf..b9923a9c8ad 100644 --- a/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp +++ b/src/hotspot/share/jfr/recorder/checkpoint/jfrCheckpointManager.cpp @@ -300,75 +300,72 @@ BufferPtr JfrCheckpointManager::flush(BufferPtr old, size_t used, size_t request } // offsets into the JfrCheckpointEntry -static const juint starttime_offset = sizeof(jlong); -static const juint duration_offset = starttime_offset + sizeof(jlong); -static const juint checkpoint_type_offset = duration_offset + sizeof(jlong); -static const juint types_offset = checkpoint_type_offset + sizeof(juint); -static const juint payload_offset = types_offset + sizeof(juint); +static const size_t starttime_offset = sizeof(int64_t); +static const size_t duration_offset = starttime_offset + sizeof(int64_t); +static const size_t checkpoint_type_offset = duration_offset + sizeof(int64_t); +static const size_t types_offset = checkpoint_type_offset + sizeof(uint32_t); +static const size_t payload_offset = types_offset + sizeof(uint32_t); template static Return read_data(const u1* data) { return JfrBigEndian::read(data); } -static jlong total_size(const u1* data) { - return read_data(data); +static size_t total_size(const u1* data) { + const int64_t size = read_data(data); + assert(size > 0, "invariant"); + return static_cast(size); } -static jlong starttime(const u1* data) { - return read_data(data + starttime_offset); +static int64_t starttime(const u1* data) { + return read_data(data + starttime_offset); } -static jlong duration(const u1* data) { - return read_data(data + duration_offset); +static int64_t duration(const u1* data) { + return read_data(data + duration_offset); } -static juint checkpoint_type(const u1* data) { - return read_data(data + checkpoint_type_offset); +static int32_t checkpoint_type(const u1* data) { + return read_data(data + checkpoint_type_offset); } -static juint number_of_types(const u1* data) { - return read_data(data + types_offset); +static uint32_t number_of_types(const u1* data) { + return read_data(data + types_offset); } -static void write_checkpoint_header(JfrChunkWriter& cw, int64_t delta_to_last_checkpoint, const u1* data) { - cw.reserve(sizeof(u4)); - cw.write(EVENT_CHECKPOINT); - cw.write(starttime(data)); - cw.write(duration(data)); - cw.write(delta_to_last_checkpoint); - cw.write(checkpoint_type(data)); - cw.write(number_of_types(data)); +static size_t payload_size(const u1* data) { + return total_size(data) - sizeof(JfrCheckpointEntry); } -static void write_checkpoint_content(JfrChunkWriter& cw, const u1* data, size_t size) { - assert(data != NULL, "invariant"); - cw.write_unbuffered(data + payload_offset, size - sizeof(JfrCheckpointEntry)); -} - -static size_t write_thread_checkpoint_content(JfrChunkWriter& cw, const u1* data) { - assert(data != NULL, "invariant"); - const size_t size = total_size(data); - assert(size > sizeof(JfrCheckpointEntry), "invariant"); - assert(checkpoint_type(data) == THREADS, "invariant"); - assert(number_of_types(data) == 1, "invariant"); - // Thread checkpoints are small so write them buffered to cache as much as possible before flush. - cw.write_buffered(data + payload_offset, size - sizeof(JfrCheckpointEntry)); - return size; +static uint64_t calculate_event_size_bytes(JfrChunkWriter& cw, const u1* data, int64_t event_begin, int64_t delta_to_last_checkpoint) { + assert(data != nullptr, "invariant"); + size_t bytes = cw.size_in_bytes(EVENT_CHECKPOINT); + bytes += cw.size_in_bytes(starttime(data)); + bytes += cw.size_in_bytes(duration(data)); + bytes += cw.size_in_bytes(delta_to_last_checkpoint); + bytes += cw.size_in_bytes(checkpoint_type(data)); + bytes += cw.size_in_bytes(number_of_types(data)); + bytes += payload_size(data); // in bytes already. + return bytes + cw.size_in_bytes(bytes + cw.size_in_bytes(bytes)); } static size_t write_checkpoint_event(JfrChunkWriter& cw, const u1* data) { assert(data != NULL, "invariant"); const int64_t event_begin = cw.current_offset(); const int64_t last_checkpoint_event = cw.last_checkpoint_offset(); - const int64_t delta_to_last_checkpoint = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin; - const int64_t checkpoint_size = total_size(data); - write_checkpoint_header(cw, delta_to_last_checkpoint, data); - write_checkpoint_content(cw, data, checkpoint_size); - const int64_t event_size = cw.current_offset() - event_begin; - cw.write_padded_at_offset(event_size, event_begin); cw.set_last_checkpoint_offset(event_begin); - return (size_t)checkpoint_size; + const int64_t delta_to_last_checkpoint = last_checkpoint_event == 0 ? 0 : last_checkpoint_event - event_begin; + const uint64_t event_size = calculate_event_size_bytes(cw, data, event_begin, delta_to_last_checkpoint); + cw.write(event_size); + cw.write(EVENT_CHECKPOINT); + cw.write(starttime(data)); + cw.write(duration(data)); + cw.write(delta_to_last_checkpoint); + cw.write(checkpoint_type(data)); + cw.write(number_of_types(data)); + cw.write_unbuffered(data + payload_offset, payload_size(data)); + assert(static_cast(cw.current_offset() - event_begin) == event_size, "invariant"); + return total_size(data); } static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) { @@ -387,6 +384,17 @@ static size_t write_checkpoints(JfrChunkWriter& cw, const u1* data, size_t size) return processed; } +static size_t write_thread_checkpoint_content(JfrChunkWriter& cw, const u1* data) { + assert(data != NULL, "invariant"); + const size_t size = total_size(data); + assert(size > 0, "invariant"); + assert(checkpoint_type(data) == THREADS, "invariant"); + assert(number_of_types(data) == 1, "invariant"); + // Thread checkpoints are small so write them buffered to cache as much as possible before flush. + cw.write_buffered(data + payload_offset, payload_size(data)); + return size; +} + static size_t write_thread_checkpoint_payloads(JfrChunkWriter& cw, const u1* data, size_t size, u4& elements) { assert(cw.is_valid(), "invariant"); assert(data != NULL, "invariant"); @@ -419,7 +427,6 @@ class CheckpointWriteOp { size_t processed() const { return _processed; } }; - // This op will collapse all individual vthread checkpoints into a single checkpoint. template class VirtualThreadLocalCheckpointWriteOp { @@ -428,14 +435,14 @@ class VirtualThreadLocalCheckpointWriteOp { int64_t _begin_offset; int64_t _elements_offset; size_t _processed; - u4 _elements; + uint32_t _elements; public: typedef T Type; VirtualThreadLocalCheckpointWriteOp(JfrChunkWriter& cw) : _cw(cw), _begin_offset(cw.current_offset()), _elements_offset(0), _processed(0), _elements(0) { const int64_t last_checkpoint = cw.last_checkpoint_offset(); const int64_t delta = last_checkpoint == 0 ? 0 : last_checkpoint - _begin_offset; - cw.reserve(sizeof(u4)); - cw.write(EVENT_CHECKPOINT); + cw.reserve(sizeof(uint64_t)); + cw.write(EVENT_CHECKPOINT); cw.write(JfrTicks::now().value()); cw.write(0); cw.write(delta); @@ -443,7 +450,7 @@ class VirtualThreadLocalCheckpointWriteOp { cw.write(1); // Number of types in this checkpoint, only one, TYPE_THREAD. cw.write(TYPE_THREAD); // Constant pool type. _elements_offset = cw.current_offset(); // Offset for the number of entries in the TYPE_THREAD constant pool. - cw.reserve(sizeof(u4)); + cw.reserve(sizeof(uint32_t)); } ~VirtualThreadLocalCheckpointWriteOp() { @@ -453,8 +460,8 @@ class VirtualThreadLocalCheckpointWriteOp { return; } const int64_t event_size = _cw.current_offset() - _begin_offset; - _cw.write_padded_at_offset(_elements, _elements_offset); - _cw.write_padded_at_offset(event_size, _begin_offset); + _cw.write_padded_at_offset(_elements, _elements_offset); + _cw.write_padded_at_offset(event_size, _begin_offset); _cw.set_last_checkpoint_offset(_begin_offset); } diff --git a/src/hotspot/share/jfr/writers/jfrEncoders.hpp b/src/hotspot/share/jfr/writers/jfrEncoders.hpp index 262a61da81a..6850eba83c1 100644 --- a/src/hotspot/share/jfr/writers/jfrEncoders.hpp +++ b/src/hotspot/share/jfr/writers/jfrEncoders.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ -63,6 +63,9 @@ class BigEndianEncoderImpl { template static size_t encode_padded(const T* src, size_t len, u1* dest); + template + static size_t size_in_bytes(T value); + }; template @@ -129,6 +132,17 @@ inline size_t BigEndianEncoderImpl::encode_padded(const T* src, size_t len, u1* return size; } +template +inline size_t BigEndianEncoderImpl::size_in_bytes(T value) { + switch (sizeof(T)) { + case 1: return 1; + case 2: return 2; + case 4: return 4; + case 8:return 8; + } + ShouldNotReachHere(); + return 0; +} // The Varint128 encoder implements encoding according to // msb(it) 128bit encoding (1 encode bit | 7 value bits), @@ -160,6 +174,9 @@ class Varint128EncoderImpl { template static size_t encode_padded(const T* src, size_t len, u1* dest); + template + static size_t size_in_bytes(T value); + }; template @@ -295,4 +312,34 @@ inline size_t Varint128EncoderImpl::encode_padded(const T* src, size_t len, u1* return size; } +template +inline size_t Varint128EncoderImpl::size_in_bytes(T value) { + const u8 v = to_u8(value); + if (LESS_THAN_128(v)) { + return 1; + } + if (LESS_THAN_128(v >> 7)) { + return 2; + } + if (LESS_THAN_128(v >> 14)) { + return 3; + } + if (LESS_THAN_128(v >> 21)) { + return 4; + } + if (LESS_THAN_128(v >> 28)) { + return 5; + } + if (LESS_THAN_128(v >> 35)) { + return 6; + } + if (LESS_THAN_128(v >> 42)) { + return 7; + } + if (LESS_THAN_128(v >> 49)) { + return 8; + } + return 9; +} + #endif // SHARE_JFR_WRITERS_JFRENCODERS_HPP diff --git a/src/hotspot/share/jfr/writers/jfrEncoding.hpp b/src/hotspot/share/jfr/writers/jfrEncoding.hpp index 3d4c7c55e0e..90ca5b13873 100644 --- a/src/hotspot/share/jfr/writers/jfrEncoding.hpp +++ b/src/hotspot/share/jfr/writers/jfrEncoding.hpp @@ -69,6 +69,11 @@ class EncoderHost : public AllStatic { return pos + IntegerEncoder::encode_padded(value, len, pos); } + template + static size_t size_in_bytes(T value) { + return IntegerEncoder::size_in_bytes(value); + } + template static u1* write(T value, u1* pos) { return write(&value, 1, pos); diff --git a/src/hotspot/share/jfr/writers/jfrWriterHost.hpp b/src/hotspot/share/jfr/writers/jfrWriterHost.hpp index 753d32b40a3..2d28e84fd29 100644 --- a/src/hotspot/share/jfr/writers/jfrWriterHost.hpp +++ b/src/hotspot/share/jfr/writers/jfrWriterHost.hpp @@ -98,6 +98,8 @@ class WriterHost : public WriterPolicyImpl { template void write_be_at_offset(T value, int64_t offset); int64_t reserve(size_t size); + template + size_t size_in_bytes(T value); }; #endif // SHARE_JFR_WRITERS_JFRWRITERHOST_HPP diff --git a/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp b/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp index 6c677b1a808..629f994bb76 100644 --- a/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp +++ b/src/hotspot/share/jfr/writers/jfrWriterHost.inline.hpp @@ -363,4 +363,10 @@ inline void WriterHost::write_be_at_offset(T value, in } } +template +template +inline size_t WriterHost::size_in_bytes(T value) { + return IE::size_in_bytes(value); +} + #endif // SHARE_JFR_WRITERS_JFRWRITERHOST_INLINE_HPP diff --git a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java index 6ddc15bc454..e0a55bf26eb 100644 --- a/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java +++ b/src/jdk.jfr/share/classes/jdk/jfr/internal/consumer/ChunkParser.java @@ -228,7 +228,7 @@ public RecordedEvent readEvent() throws IOException { long absoluteChunkEnd = chunkHeader.getEnd(); while (input.position() < absoluteChunkEnd) { long pos = input.position(); - int size = input.readInt(); + long size = input.readLong(); if (size == 0) { throw new IOException("Event can't have zero size"); } @@ -243,7 +243,7 @@ public RecordedEvent readEvent() throws IOException { if (chunkWriter.accept(event)) { chunkWriter.writeEvent(pos, input.position()); input.position(pos); - input.readInt(); // size + input.readLong(); // size input.readLong(); // type chunkWriter.touch(ep.parseReferences(input)); } @@ -310,7 +310,7 @@ private void fillConstantPools(long abortCP) throws IOException { } input.position(thisCP); lastCP = thisCP; - int size = input.readInt(); // size + long size = input.readLong(); // size long typeId = input.readLong(); if (typeId != CONSTANT_POOL_TYPE_ID) { throw new IOException("Expected check point event (id = 1) at position " + lastCP + ", but found type id = " + typeId); From c084431fae8c9f9b5a157cdaca484f63cbd6691a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Thu, 8 Dec 2022 14:37:18 +0000 Subject: [PATCH 131/494] 8298379: JFR: Some UNTIMED events only sets endTime Reviewed-by: ehelin, egahlin --- src/hotspot/share/gc/shared/gcTraceSend.cpp | 1 + src/hotspot/share/gc/shared/objectCountEventSender.cpp | 5 +++-- .../share/jfr/periodic/jfrFinalizerStatisticsEvent.cpp | 3 ++- src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp | 4 +++- src/hotspot/share/jfr/periodic/jfrOSInterface.cpp | 3 ++- src/hotspot/share/jfr/periodic/jfrPeriodic.cpp | 3 +++ src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp | 1 + 7 files changed, 15 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/shared/gcTraceSend.cpp b/src/hotspot/share/gc/shared/gcTraceSend.cpp index 5ee37592f28..1cbf1f6fdb0 100644 --- a/src/hotspot/share/gc/shared/gcTraceSend.cpp +++ b/src/hotspot/share/gc/shared/gcTraceSend.cpp @@ -389,6 +389,7 @@ void GCLockerTracer::report_gc_locker() { EventGCLocker event(UNTIMED); if (event.should_commit()) { event.set_starttime(_needs_gc_start_timestamp); + event.set_endtime(_needs_gc_start_timestamp); event.set_lockCount(_jni_lock_count); event.set_stallCount(_stall_count); event.commit(); diff --git a/src/hotspot/share/gc/shared/objectCountEventSender.cpp b/src/hotspot/share/gc/shared/objectCountEventSender.cpp index bf24a98cf67..ce78b847708 100644 --- a/src/hotspot/share/gc/shared/objectCountEventSender.cpp +++ b/src/hotspot/share/gc/shared/objectCountEventSender.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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,11 +54,12 @@ template void ObjectCountEventSender::send_event_if_enabled(Klass* klass, jlong count, julong size, const Ticks& timestamp) { T event(UNTIMED); if (event.should_commit()) { + event.set_starttime(timestamp); + event.set_endtime(timestamp); event.set_gcId(GCId::current()); event.set_objectClass(klass); event.set_count(count); event.set_totalSize(size); - event.set_endtime(timestamp); event.commit(); } } diff --git a/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.cpp b/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.cpp index d292173ba10..ad1c3043690 100644 --- a/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.cpp +++ b/src/hotspot/share/jfr/periodic/jfrFinalizerStatisticsEvent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -42,6 +42,7 @@ static void send_event(const FinalizerEntry* fe, const InstanceKlass* ik, const const char* const url = fe != nullptr ? fe->codesource() : nullptr; const traceid url_symbol_id = url != NULL ? JfrSymbolTable::add(url) : 0; EventFinalizerStatistics event(UNTIMED); + event.set_starttime(timestamp); event.set_endtime(timestamp); event.set_finalizableClass(ik); event.set_codeSource(url_symbol_id); diff --git a/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp b/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp index e73e21d3479..ef9ede8bc1d 100644 --- a/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp +++ b/src/hotspot/share/jfr/periodic/jfrModuleEvent.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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,7 @@ class ModuleExportClosure : public ModuleEventCallbackClosure { static void write_module_dependency_event(const void* from_module, const ModuleEntry* to_module) { EventModuleRequire event(UNTIMED); + event.set_starttime(invocation_time); event.set_endtime(invocation_time); event.set_source((const ModuleEntry* const)from_module); event.set_requiredModule(to_module); @@ -68,6 +69,7 @@ static void write_module_dependency_event(const void* from_module, const ModuleE static void write_module_export_event(const void* package, const ModuleEntry* qualified_export) { EventModuleExport event(UNTIMED); + event.set_starttime(invocation_time); event.set_endtime(invocation_time); event.set_exportedPackage((const PackageEntry*)package); event.set_targetModule(qualified_export); diff --git a/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp b/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp index 85f6614ff5e..9a14bf4837a 100644 --- a/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp +++ b/src/hotspot/share/jfr/periodic/jfrOSInterface.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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 @@ -292,6 +292,7 @@ int JfrOSInterface::generate_initial_environment_variable_events() { strncpy(key, variable, key_length); key[key_length] = '\0'; EventInitialEnvironmentVariable event(UNTIMED); + event.set_starttime(time_stamp); event.set_endtime(time_stamp); event.set_key(key); event.set_value(value); diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index 79f42b6f425..3704bec1555 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -151,6 +151,7 @@ static int _native_library_callback(const char* name, address base, address top, event.set_name(name); event.set_baseAddress((u8)base); event.set_topAddress((u8)top); + event.set_starttime(*(JfrTicks*)param); event.set_endtime(*(JfrTicks*) param); event.commit(); return 0; @@ -425,6 +426,7 @@ TRACE_REQUEST_FUNC(InitialSystemProperty) { EventInitialSystemProperty event(UNTIMED); event.set_key(p->key()); event.set_value(p->value()); + event.set_starttime(time_stamp); event.set_endtime(time_stamp); event.commit(); } @@ -451,6 +453,7 @@ TRACE_REQUEST_FUNC(ThreadAllocationStatistics) { EventThreadAllocationStatistics event(UNTIMED); event.set_allocated(allocated.at(i)); event.set_thread(thread_ids.at(i)); + event.set_starttime(time_stamp); event.set_endtime(time_stamp); event.commit(); } diff --git a/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp b/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp index f9e9c537fd8..41dadd0d394 100644 --- a/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp +++ b/src/hotspot/share/jfr/periodic/jfrThreadCPULoadEvent.cpp @@ -120,6 +120,7 @@ void JfrThreadCPULoadEvent::send_events() { EventThreadCPULoad event(UNTIMED); if (JfrThreadCPULoadEvent::update_event(event, jt, cur_wallclock_time, processor_count)) { event.set_starttime(event_time); + event.set_endtime(event_time); if (jt != periodic_thread) { // Commit reads the thread id from this thread's trace data, so put it there temporarily JfrThreadLocal::impersonate(periodic_thread, JFR_JVM_THREAD_ID(jt)); From e555d5470536b8379179879ec7343e004be95e36 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Thu, 8 Dec 2022 14:42:04 +0000 Subject: [PATCH 132/494] 8298383: JFR: GenerateJfrFiles.java lacks copyright header Reviewed-by: mgronlun, erikj --- .../build/tools/jfr/GenerateJfrFiles.java | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java index ed82128727d..6b89d02ad2f 100644 --- a/make/src/classes/build/tools/jfr/GenerateJfrFiles.java +++ b/make/src/classes/build/tools/jfr/GenerateJfrFiles.java @@ -1,3 +1,28 @@ +/* + * Copyright (c) 2018, 2022, 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. + */ + package build.tools.jfr; import java.io.BufferedOutputStream; From fc52f21f9a30c5c34caa06f8524c8d5bd74f16f7 Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 8 Dec 2022 15:05:45 +0000 Subject: [PATCH 133/494] 8298255: JFR provide information about dynamization of number of compiler threads Reviewed-by: stuefe, mgronlun, egahlin --- src/hotspot/share/jfr/metadata/metadata.xml | 1 + src/hotspot/share/jfr/periodic/jfrPeriodic.cpp | 1 + test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java | 3 ++- test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java | 8 ++++---- 4 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index b870ed0b54e..017c33a0857 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -937,6 +937,7 @@ + diff --git a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp index 3704bec1555..5f15d0a018a 100644 --- a/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp +++ b/src/hotspot/share/jfr/periodic/jfrPeriodic.cpp @@ -588,6 +588,7 @@ TRACE_REQUEST_FUNC(CompilerConfiguration) { EventCompilerConfiguration event; event.set_threadCount(CICompilerCount); event.set_tieredCompilation(TieredCompilation); + event.set_dynamicCompilerThreadCount(UseDynamicNumberOfCompilerThreads); event.commit(); } diff --git a/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java b/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java index ffd3ef99174..0e4834ccfa1 100644 --- a/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java +++ b/test/jdk/jdk/jfr/event/compiler/TestCompilerConfig.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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,7 @@ public static void main(String[] args) throws Exception { System.out.println("Event:" + event); Events.assertField(event, "threadCount").atLeast(0); Events.assertField(event, "tieredCompilation"); + Events.assertField(event, "dynamicCompilerThreadCount"); } } } diff --git a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java index 9f45bd8630f..afdb84952f4 100644 --- a/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java +++ b/test/jdk/jdk/jfr/event/metadata/TestEventMetadata.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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 @@ -98,7 +98,7 @@ public static void main(String[] args) throws Exception { Set eventNames= new HashSet<>(); for (EventType eventType : eventTypes) { verifyEventType(eventType); - verifyValueDesscriptors(eventType.getFields(), types); + verifyValueDescriptors(eventType.getFields(), types); System.out.println(); String eventName = eventType.getName(); if (eventNames.contains(eventName)) { @@ -116,11 +116,11 @@ public static void main(String[] args) throws Exception { } } - private static void verifyValueDesscriptors(List fields, Set visitedTypes) { + private static void verifyValueDescriptors(List fields, Set visitedTypes) { for (ValueDescriptor v : fields) { if (!visitedTypes.contains(v.getTypeName())) { visitedTypes.add(v.getTypeName()); - verifyValueDesscriptors(v.getFields(), visitedTypes); + verifyValueDescriptors(v.getFields(), visitedTypes); } verifyValueDescriptor(v); } From d562d3fcbe22a0443037c5b447e1a41401275814 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Thu, 8 Dec 2022 15:29:26 +0000 Subject: [PATCH 134/494] 8297642: PhaseIdealLoop::only_has_infinite_loops must detect all loops that never lead to termination Reviewed-by: thartmann, roland --- src/hotspot/share/opto/loopnode.cpp | 57 +++++------ .../loopopts/TestOnlyInfiniteLoops.jasm | 96 +++++++++++++++++++ .../loopopts/TestOnlyInfiniteLoopsMain.java | 53 ++++++++++ 3 files changed, 175 insertions(+), 31 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoops.jasm create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoopsMain.java diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 2c244496727..f8250bf59b4 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4190,45 +4190,40 @@ bool PhaseIdealLoop::process_expensive_nodes() { } #ifdef ASSERT -// Goes over all children of the root of the loop tree, collects all controls for the loop and its inner loops then -// checks whether any control is a branch out of the loop and if it is, whether it's not a NeverBranch. +// Goes over all children of the root of the loop tree. Check if any of them have a path +// down to Root, that does not go via a NeverBranch exit. bool PhaseIdealLoop::only_has_infinite_loops() { + ResourceMark rm; + Unique_Node_List worklist; + // start traversal at all loop heads of first-level loops for (IdealLoopTree* l = _ltree_root->_child; l != NULL; l = l->_next) { - Unique_Node_List wq; Node* head = l->_head; assert(head->is_Region(), ""); - for (uint i = 1; i < head->req(); ++i) { - Node* in = head->in(i); - if (get_loop(in) != _ltree_root) { - wq.push(in); - } - } - for (uint i = 0; i < wq.size(); ++i) { - Node* c = wq.at(i); - if (c == head) { - continue; - } else if (c->is_Region()) { - for (uint j = 1; j < c->req(); ++j) { - wq.push(c->in(j)); - } - } else { - wq.push(c->in(0)); - } - } - assert(wq.member(head), ""); - for (uint i = 0; i < wq.size(); ++i) { - Node* c = wq.at(i); - if (c->is_MultiBranch()) { - for (DUIterator_Fast jmax, j = c->fast_outs(jmax); j < jmax; j++) { - Node* u = c->fast_out(j); - assert(u->is_CFG(), ""); - if (!wq.member(u) && c->Opcode() != Op_NeverBranch) { - return false; - } + worklist.push(head); + } + // BFS traversal down the CFG, except through NeverBranch exits + for (uint i = 0; i < worklist.size(); ++i) { + Node* n = worklist.at(i); + assert(n->is_CFG(), "only traverse CFG"); + if (n->is_Root()) { + // Found root -> there was an exit! + return false; + } else if (n->Opcode() == Op_NeverBranch) { + // Only follow the loop-internal projection, not the NeverBranch exit + ProjNode* proj = n->as_Multi()->proj_out_or_null(0); + assert(proj != nullptr, "must find loop-internal projection of NeverBranch"); + worklist.push(proj); + } else { + // Traverse all CFG outputs + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* use = n->fast_out(i); + if (use->is_CFG()) { + worklist.push(use); } } } } + // No exit found for any loop -> all are infinite return true; } #endif diff --git a/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoops.jasm b/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoops.jasm new file mode 100644 index 00000000000..c9cb0e50d8e --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoops.jasm @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2022, 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. + */ + + +super public class TestOnlyInfiniteLoops +{ + public Method "":"()V" + stack 2 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + + static Method test_simple:"(III)I" + stack 200 locals 10 + { + // Nested infinite loop, where inner loop eventually + // looses exit to outer loop. Then, the inner loop + // floats outside the inner loop. The entry from + // outer to inner loop now becomes an exit for the + // outer loop, where it now enters the next loop, that + // used to be the inner loop. + iconst_0; + istore 9; + + iload 0; + ifeq LEND; // skip + + LOOP1: + iload 1; + ifeq LOOP1; // dominates + LOOP2: + // SKIP: prevent loop-exit from becoming zero-trip guard + iload 2; + ifeq SKIP; + iinc 9, 1; + SKIP: + iload 1; + ifeq LOOP1; // is dominated + goto LOOP2; + + LEND: + iload 9; + ireturn; + } + static Method test_irreducible:"(IIII)V" + stack 200 locals 200 + { + iload_0; + ifeq LEND; // skip + + L1: + iload 1; + ifgt MERGE; + L2: + iload 2; + ifge MERGE; + goto L1; + + MERGE: + nop; + LOOP: + iload 3; + ifle L2; + iconst_0; // always true + ifeq LOOP; + iconst_0; // always true + ifeq LOOP; + INFTY: + goto INFTY; // infinite loop + + LEND: + return; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoopsMain.java b/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoopsMain.java new file mode 100644 index 00000000000..e85e9a572fb --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestOnlyInfiniteLoopsMain.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2022, 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 8297642 + * @compile TestOnlyInfiniteLoops.jasm + * @summary Nested irreducible loops, where the inner loop floats out of the outer + * @run main/othervm + * -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test* + * -XX:-TieredCompilation -Xcomp + * TestOnlyInfiniteLoopsMain + * + * @test + * @bug 8297642 + * @compile TestOnlyInfiniteLoops.jasm + * @summary Nested irreducible loops, where the inner loop floats out of the outer + * @run main/othervm + * -XX:CompileCommand=compileonly,TestOnlyInfiniteLoops::test* + * -XX:-TieredCompilation -Xcomp + * -XX:PerMethodTrapLimit=0 + * TestOnlyInfiniteLoopsMain +*/ + +public class TestOnlyInfiniteLoopsMain { + public static void main(String[] args) { + TestOnlyInfiniteLoops t = new TestOnlyInfiniteLoops(); + System.out.println("test_simple"); + t.test_simple(0, 0, 0); + System.out.println("test_irreducible"); + t.test_irreducible(0, 0, 0, 0); + } +} From 175e3d3ff332be25cca9822c58c46f1e012953c2 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Thu, 8 Dec 2022 16:04:00 +0000 Subject: [PATCH 135/494] 8296149: Start of release updates for JDK 21 8296150: Add SourceVersion.RELEASE_21 8296151: Add source 21 and target 21 to javac Reviewed-by: dholmes, iris, erikj, vromero, jlahoda --- .jcheck/conf | 2 +- make/conf/version-numbers.conf | 10 +- .../share/classfile/classFileParser.cpp | 2 + .../lang/reflect/ClassFileFormatVersion.java | 14 +- .../org/objectweb/asm/ClassReader.java | 2 +- .../internal/org/objectweb/asm/Opcodes.java | 1 + .../javax/lang/model/SourceVersion.java | 19 +- .../AbstractAnnotationValueVisitor14.java | 2 +- .../model/util/AbstractElementVisitor14.java | 2 +- .../model/util/AbstractTypeVisitor14.java | 2 +- .../lang/model/util/ElementKindVisitor14.java | 2 +- .../lang/model/util/ElementScanner14.java | 2 +- .../util/SimpleAnnotationValueVisitor14.java | 2 +- .../model/util/SimpleElementVisitor14.java | 2 +- .../lang/model/util/SimpleTypeVisitor14.java | 2 +- .../lang/model/util/TypeKindVisitor14.java | 2 +- .../com/sun/tools/javac/code/Source.java | 9 +- .../com/sun/tools/javac/jvm/ClassFile.java | 3 +- .../com/sun/tools/javac/jvm/Target.java | 5 +- .../javac/processing/PrintingProcessor.java | 2 +- .../share/data/symbols/java.base-K.sym.txt | 1016 +++++++++++++++++ .../data/symbols/java.compiler-K.sym.txt | 116 ++ .../data/symbols/java.datatransfer-K.sym.txt | 36 + .../share/data/symbols/java.desktop-K.sym.txt | 871 ++++++++++++++ .../data/symbols/java.instrument-K.sym.txt | 31 + .../share/data/symbols/java.logging-K.sym.txt | 55 + .../data/symbols/java.management-K.sym.txt | 268 +++++ .../symbols/java.management.rmi-K.sym.txt | 39 + .../share/data/symbols/java.naming-K.sym.txt | 85 ++ .../share/data/symbols/java.rmi-K.sym.txt | 52 + .../data/symbols/java.scripting-K.sym.txt | 32 + .../data/symbols/java.security.jgss-K.sym.txt | 69 ++ .../data/symbols/java.security.sasl-K.sym.txt | 32 + .../data/symbols/java.smartcardio-K.sym.txt | 62 + .../share/data/symbols/java.sql-K.sym.txt | 60 + .../data/symbols/java.sql.rowset-K.sym.txt | 73 ++ .../share/data/symbols/java.xml-K.sym.txt | 150 +++ .../data/symbols/java.xml.crypto-K.sym.txt | 46 + .../data/symbols/jdk.accessibility-K.sym.txt | 44 + .../share/data/symbols/jdk.attach-K.sym.txt | 55 + .../share/data/symbols/jdk.compiler-K.sym.txt | 381 +++++++ .../share/data/symbols/jdk.dynalink-K.sym.txt | 136 +++ .../data/symbols/jdk.httpserver-K.sym.txt | 47 + .../jdk.incubator.concurrent-K.sym.txt | 57 + .../symbols/jdk.incubator.vector-K.sym.txt | 31 + .../share/data/symbols/jdk.jartool-K.sym.txt | 34 + .../share/data/symbols/jdk.javadoc-K.sym.txt | 36 + .../share/data/symbols/jdk.jconsole-K.sym.txt | 31 + .../share/data/symbols/jdk.jdi-K.sym.txt | 395 +++++++ .../share/data/symbols/jdk.jfr-K.sym.txt | 31 + .../share/data/symbols/jdk.jlink-K.sym.txt | 31 + .../share/data/symbols/jdk.jpackage-K.sym.txt | 31 + .../share/data/symbols/jdk.jshell-K.sym.txt | 135 +++ .../share/data/symbols/jdk.jsobject-K.sym.txt | 31 + .../data/symbols/jdk.management-K.sym.txt | 46 + .../share/data/symbols/jdk.net-K.sym.txt | 31 + .../share/data/symbols/jdk.sctp-K.sym.txt | 73 ++ .../data/symbols/jdk.security.auth-K.sym.txt | 106 ++ .../data/symbols/jdk.security.jgss-K.sym.txt | 47 + .../data/symbols/jdk.unsupported-K.sym.txt | 48 + .../share/data/symbols/jdk.xml.dom-K.sym.txt | 295 +++++ src/jdk.compiler/share/data/symbols/symbols | 3 +- .../ClassFile/ClassFileVersionTest.java | 4 +- .../CommandLine/VMDeprecatedOptions.java | 1 - .../javac/api/TestGetSourceVersions.java | 2 +- .../javac/classfiles/ClassVersionChecker.java | 3 +- .../lib/JavacTestingAbstractProcessor.java | 18 +- .../classReaderTest/Client.nopreview.out | 2 +- .../classReaderTest/Client.preview.out | 2 +- .../tools/javac/versions/Versions.java | 25 +- 70 files changed, 5338 insertions(+), 54 deletions(-) create mode 100644 src/jdk.compiler/share/data/symbols/java.base-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.compiler-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.datatransfer-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.desktop-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.instrument-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.logging-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.management-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.management.rmi-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.naming-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.rmi-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.scripting-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.security.jgss-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.security.sasl-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.smartcardio-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.sql-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.sql.rowset-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.xml-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/java.xml.crypto-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.accessibility-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.attach-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.dynalink-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.httpserver-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jartool-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.javadoc-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jconsole-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jdi-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jlink-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jpackage-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jshell-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.jsobject-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.management-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.net-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.sctp-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.security.auth-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.security.jgss-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.unsupported-K.sym.txt create mode 100644 src/jdk.compiler/share/data/symbols/jdk.xml.dom-K.sym.txt diff --git a/.jcheck/conf b/.jcheck/conf index 6f2de4d3805..8993c274fe0 100644 --- a/.jcheck/conf +++ b/.jcheck/conf @@ -1,7 +1,7 @@ [general] project=jdk jbs=JDK -version=20 +version=21 [checks] error=author,committer,reviewers,merge,issues,executable,symlink,message,hg-tag,whitespace,problemlists diff --git a/make/conf/version-numbers.conf b/make/conf/version-numbers.conf index 5be559266fe..4a3e5133567 100644 --- a/make/conf/version-numbers.conf +++ b/make/conf/version-numbers.conf @@ -26,17 +26,17 @@ # Default version, product, and vendor information to use, # unless overridden by configure -DEFAULT_VERSION_FEATURE=20 +DEFAULT_VERSION_FEATURE=21 DEFAULT_VERSION_INTERIM=0 DEFAULT_VERSION_UPDATE=0 DEFAULT_VERSION_PATCH=0 DEFAULT_VERSION_EXTRA1=0 DEFAULT_VERSION_EXTRA2=0 DEFAULT_VERSION_EXTRA3=0 -DEFAULT_VERSION_DATE=2023-03-21 -DEFAULT_VERSION_CLASSFILE_MAJOR=64 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" +DEFAULT_VERSION_DATE=2023-09-19 +DEFAULT_VERSION_CLASSFILE_MAJOR=65 # "`$EXPR $DEFAULT_VERSION_FEATURE + 44`" DEFAULT_VERSION_CLASSFILE_MINOR=0 DEFAULT_VERSION_DOCS_API_SINCE=11 -DEFAULT_ACCEPTABLE_BOOT_VERSIONS="19 20" -DEFAULT_JDK_SOURCE_TARGET_VERSION=20 +DEFAULT_ACCEPTABLE_BOOT_VERSIONS="19 20 21" +DEFAULT_JDK_SOURCE_TARGET_VERSION=21 DEFAULT_PROMOTED_VERSION_PRE=ea diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index b8b6eab1d03..e1837f3ca86 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -142,6 +142,8 @@ #define JAVA_20_VERSION 64 +#define JAVA_21_VERSION 65 + void ClassFileParser::set_class_bad_constant_seen(short bad_constant) { assert((bad_constant == JVM_CONSTANT_Module || bad_constant == JVM_CONSTANT_Package) && _major_version >= JAVA_9_VERSION, diff --git a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java index b1258f0236d..65d8aa991ce 100644 --- a/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java +++ b/src/java.base/share/classes/java/lang/reflect/ClassFileFormatVersion.java @@ -262,7 +262,17 @@ public enum ClassFileFormatVersion { * href="https://docs.oracle.com/javase/specs/jvms/se20/html/index.html"> * The Java Virtual Machine Specification, Java SE 20 Edition */ - RELEASE_20(64); + RELEASE_20(64), + + /** + * The version recognized by the Java Platform, Standard Edition + * 21. + * + * @see + * The Java Virtual Machine Specification, Java SE 21 Edition + */ + RELEASE_21(65); // Note to maintainers: when adding constants for newer releases, // the implementation of latest() must be updated too. @@ -277,7 +287,7 @@ private ClassFileFormatVersion(int major) { * {@return the latest class file format version} */ public static ClassFileFormatVersion latest() { - return RELEASE_20; + return RELEASE_21; } /** diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java index 37d194583fb..ec1ee7fdef6 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/ClassReader.java @@ -226,7 +226,7 @@ public ClassReader( this.b = classFileBuffer; // Check the class' major_version. This field is after the magic and minor_version fields, which // use 4 and 2 bytes respectively. - if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V20) { + if (checkClassVersion && readShort(classFileOffset + 6) > Opcodes.V21) { throw new IllegalArgumentException( "Unsupported class file major version " + readShort(classFileOffset + 6)); } diff --git a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java index a28714e858b..7a90e3d1bdb 100644 --- a/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java +++ b/src/java.base/share/classes/jdk/internal/org/objectweb/asm/Opcodes.java @@ -310,6 +310,7 @@ public interface Opcodes { int V18 = 0 << 16 | 62; int V19 = 0 << 16 | 63; int V20 = 0 << 16 | 64; + int V21 = 0 << 16 | 65; /** * Version flag indicating that the class is using 'preview' features. diff --git a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java index be3fb580de7..00cdbe320c5 100644 --- a/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java +++ b/src/java.compiler/share/classes/javax/lang/model/SourceVersion.java @@ -71,6 +71,7 @@ public enum SourceVersion { * record patterns in preview) * 20: no changes (pattern matching for switch in fourth preview, * record patterns in second preview) + * 21: tbd */ /** @@ -372,7 +373,19 @@ public enum SourceVersion { * href="https://docs.oracle.com/javase/specs/jls/se20/html/index.html"> * The Java Language Specification, Java SE 20 Edition */ - RELEASE_20; + RELEASE_20, + + /** + * The version recognized by the Java Platform, Standard Edition + * 21. + * + * @since 21 + * + * @see + * The Java Language Specification, Java SE 21 Edition + */ + RELEASE_21; // Note that when adding constants for newer releases, the // behavior of latest() and latestSupported() must be updated too. @@ -381,7 +394,7 @@ public enum SourceVersion { * {@return the latest source version that can be modeled} */ public static SourceVersion latest() { - return RELEASE_20; + return RELEASE_21; } private static final SourceVersion latestSupported = getLatestSupported(); @@ -396,7 +409,7 @@ public static SourceVersion latest() { private static SourceVersion getLatestSupported() { int intVersion = Runtime.version().feature(); return (intVersion >= 11) ? - valueOf("RELEASE_" + Math.min(20, intVersion)): + valueOf("RELEASE_" + Math.min(21, intVersion)): RELEASE_10; } diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java index 5696a03ffdf..5206b49ab6c 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractAnnotationValueVisitor14.java @@ -44,7 +44,7 @@ * @see AbstractAnnotationValueVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public abstract class AbstractAnnotationValueVisitor14 extends AbstractAnnotationValueVisitor9 { /** diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java index 3a373297c8b..d7b51093bce 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractElementVisitor14.java @@ -49,7 +49,7 @@ * @see AbstractElementVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public abstract class AbstractElementVisitor14 extends AbstractElementVisitor9 { /** * Constructor for concrete subclasses to call. diff --git a/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java index e300b107639..aa7d70cbd70 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/AbstractTypeVisitor14.java @@ -47,7 +47,7 @@ * @see AbstractTypeVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public abstract class AbstractTypeVisitor14 extends AbstractTypeVisitor9 { /** * Constructor for concrete subclasses to call. diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java index db8af23f387..5ce90e144ec 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementKindVisitor14.java @@ -61,7 +61,7 @@ * @see ElementKindVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class ElementKindVisitor14 extends ElementKindVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java index 0dddf71c245..55cd3e9cd7c 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/ElementScanner14.java @@ -77,7 +77,7 @@ * @see ElementScanner9 * @since 16 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class ElementScanner14 extends ElementScanner9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java index 87776d91abb..95b51f1cd37 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleAnnotationValueVisitor14.java @@ -52,7 +52,7 @@ * @see SimpleAnnotationValueVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class SimpleAnnotationValueVisitor14 extends SimpleAnnotationValueVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java index 6cf1c4de150..bf6c2e0863f 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleElementVisitor14.java @@ -57,7 +57,7 @@ * @see SimpleElementVisitor9 * @since 16 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class SimpleElementVisitor14 extends SimpleElementVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java index 352bd6bb0d1..850668bb8aa 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/SimpleTypeVisitor14.java @@ -56,7 +56,7 @@ * @see SimpleTypeVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class SimpleTypeVisitor14 extends SimpleTypeVisitor9 { /** * Constructor for concrete subclasses; uses {@code null} for the diff --git a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java index a7fbc37ac20..5352e23fa8e 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/TypeKindVisitor14.java @@ -61,7 +61,7 @@ * @see TypeKindVisitor9 * @since 14 */ -@SupportedSourceVersion(RELEASE_20) +@SupportedSourceVersion(RELEASE_21) public class TypeKindVisitor14 extends TypeKindVisitor9 { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java index 854e87cf182..d5a452b6612 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/code/Source.java @@ -127,7 +127,12 @@ public enum Source { /** * 20, no major changes */ - JDK20("20"); + JDK20("20"), + + /** + * 21, tbd + */ + JDK21("21"); private static final Context.Key sourceKey = new Context.Key<>(); @@ -179,6 +184,7 @@ public boolean isSupported() { public Target requiredTarget() { return switch(this) { + case JDK21 -> Target.JDK1_21; case JDK20 -> Target.JDK1_20; case JDK19 -> Target.JDK1_19; case JDK18 -> Target.JDK1_18; @@ -312,6 +318,7 @@ public static SourceVersion toSourceVersion(Source source) { case JDK18 -> RELEASE_18; case JDK19 -> RELEASE_19; case JDK20 -> RELEASE_20; + case JDK21 -> RELEASE_21; default -> null; }; } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java index e5a1ae3bcee..9805e564976 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/ClassFile.java @@ -121,7 +121,8 @@ public enum Version { V61(61, 0), // JDK 17 V62(62, 0), // JDK 18 V63(63, 0), // JDK 19 - V64(64, 0); // JDK 20 + V64(64, 0), // JDK 20 + V65(65, 0); // JDK 21 Version(int major, int minor) { this.major = major; this.minor = minor; diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java index 3be79a32284..2164e067cf5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/jvm/Target.java @@ -94,7 +94,10 @@ public enum Target { JDK1_19("19", 63, 0), /** JDK 20. */ - JDK1_20("20", 64, 0); + JDK1_20("20", 64, 0), + + /** JDK 21. */ + JDK1_21("21", 65, 0); private static final Context.Key targetKey = new Context.Key<>(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java index 03c5a5f7005..974318f7c44 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/processing/PrintingProcessor.java @@ -55,7 +55,7 @@ * deletion without notice. */ @SupportedAnnotationTypes("*") -@SupportedSourceVersion(SourceVersion.RELEASE_20) +@SupportedSourceVersion(SourceVersion.RELEASE_21) public class PrintingProcessor extends AbstractProcessor { PrintWriter writer; diff --git a/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt new file mode 100644 index 00000000000..e0716a1b796 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt @@ -0,0 +1,1016 @@ +# +# Copyright (c) 2022, 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/io/BufferedInputStream +method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 + +class name java/io/PrintStream +header extends java/io/FilterOutputStream implements java/lang/Appendable,java/io/Closeable flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/io/PushbackInputStream +method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 + +class name java/lang/AbstractStringBuilder +header extends java/lang/Object implements java/lang/Appendable,java/lang/CharSequence sealed true flags 420 +innerclass innerClass java/util/Spliterator$OfInt outerClass java/util/Spliterator innerClassName OfInt flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/Character$UnicodeBlock +field name ARABIC_EXTENDED_C descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name DEVANAGARI_EXTENDED_A descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name KAWI descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name KAKTOVIK_NUMERALS descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name CYRILLIC_EXTENDED_D descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name NAG_MUNDARI descriptor Ljava/lang/Character$UnicodeBlock; flags 19 +field name CJK_UNIFIED_IDEOGRAPHS_EXTENSION_H descriptor Ljava/lang/Character$UnicodeBlock; flags 19 + +class name java/lang/Character$UnicodeScript +field name KAWI descriptor Ljava/lang/Character$UnicodeScript; flags 4019 +field name NAG_MUNDARI descriptor Ljava/lang/Character$UnicodeScript; flags 4019 + +class name java/lang/Class +header extends java/lang/Object implements java/io/Serializable,java/lang/reflect/GenericDeclaration,java/lang/reflect/Type,java/lang/reflect/AnnotatedElement,java/lang/invoke/TypeDescriptor$OfField,java/lang/constant/Constable flags 31 signature Ljava/lang/Object;Ljava/io/Serializable;Ljava/lang/reflect/GenericDeclaration;Ljava/lang/reflect/Type;Ljava/lang/reflect/AnnotatedElement;Ljava/lang/invoke/TypeDescriptor$OfField;>;Ljava/lang/constant/Constable; +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/Compiler +header extends java/lang/Object flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="9") + +class name java/lang/Deprecated +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;)@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;CONSTRUCTOR;eLjava/lang/annotation/ElementType;FIELD;eLjava/lang/annotation/ElementType;LOCAL_VARIABLE;eLjava/lang/annotation/ElementType;METHOD;eLjava/lang/annotation/ElementType;PACKAGE;eLjava/lang/annotation/ElementType;MODULE;eLjava/lang/annotation/ElementType;PARAMETER;eLjava/lang/annotation/ElementType;TYPE;}) + +class name java/lang/Double +-method name isFinite descriptor (D)Z +method name isFinite descriptor (D)Z flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + +class name java/lang/Float +-method name isFinite descriptor (F)Z +method name isFinite descriptor (F)Z flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name float16ToFloat descriptor (S)F flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name floatToFloat16 descriptor (F)S flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + +class name java/lang/IllegalCallerException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/Integer +-method name compareUnsigned descriptor (II)I +-method name reverse descriptor (I)I +method name compareUnsigned descriptor (II)I flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name reverse descriptor (I)I flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + +class name java/lang/LayerInstantiationException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/Long +-method name compareUnsigned descriptor (JJ)I +-method name reverse descriptor (J)J +method name compareUnsigned descriptor (JJ)I flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +method name reverse descriptor (J)J flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + +class name java/lang/NamedPackage +header extends java/lang/Object flags 20 + +class name java/lang/Thread$Builder +header extends java/lang/Object nestHost java/lang/Thread sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;VIRTUAL_THREADS;) +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfVirtual outerClass java/lang/Thread$Builder innerClassName OfVirtual flags 609 +innerclass innerClass java/lang/Thread$Builder$OfPlatform outerClass java/lang/Thread$Builder innerClassName OfPlatform flags 609 +innerclass innerClass java/lang/Thread$UncaughtExceptionHandler outerClass java/lang/Thread innerClassName UncaughtExceptionHandler flags 609 + +class name java/lang/Thread$Builder$OfPlatform +header extends java/lang/Object implements java/lang/Thread$Builder nestHost java/lang/Thread sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;VIRTUAL_THREADS;) +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfPlatform outerClass java/lang/Thread$Builder innerClassName OfPlatform flags 609 +innerclass innerClass java/lang/Thread$UncaughtExceptionHandler outerClass java/lang/Thread innerClassName UncaughtExceptionHandler flags 609 + +class name java/lang/Thread$Builder$OfVirtual +header extends java/lang/Object implements java/lang/Thread$Builder nestHost java/lang/Thread sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;VIRTUAL_THREADS;) +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfVirtual outerClass java/lang/Thread$Builder innerClassName OfVirtual flags 609 +innerclass innerClass java/lang/Thread$UncaughtExceptionHandler outerClass java/lang/Thread innerClassName UncaughtExceptionHandler flags 609 + +class name java/lang/ThreadDeath +header extends java/lang/Error flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="20") + +class name java/lang/constant/ClassDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc,java/lang/invoke/TypeDescriptor$OfField sealed true flags 601 signature Ljava/lang/Object;Ljava/lang/constant/ConstantDesc;Ljava/lang/invoke/TypeDescriptor$OfField; +innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 +method name ofInternalName descriptor (Ljava/lang/String;)Ljava/lang/constant/ClassDesc; flags 9 + +class name java/lang/constant/ConstantDesc +header extends java/lang/Object sealed true flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/constant/DirectMethodHandleDesc +header extends java/lang/Object implements java/lang/constant/MethodHandleDesc nestMembers java/lang/constant/DirectMethodHandleDesc$Kind sealed true flags 601 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 + +class name java/lang/constant/MethodHandleDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc sealed true flags 601 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 + +class name java/lang/constant/MethodTypeDesc +header extends java/lang/Object implements java/lang/constant/ConstantDesc,java/lang/invoke/TypeDescriptor$OfMethod sealed true flags 601 signature Ljava/lang/Object;Ljava/lang/constant/ConstantDesc;Ljava/lang/invoke/TypeDescriptor$OfMethod; +innerclass innerClass java/lang/invoke/TypeDescriptor$OfMethod outerClass java/lang/invoke/TypeDescriptor innerClassName OfMethod flags 609 +innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/foreign/Addressable +header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) + +class name java/lang/foreign/FunctionDescriptor +header extends java/lang/Object sealed true flags 21 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/foreign/Linker +header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) + +class name java/lang/foreign/MemoryAddress +header extends java/lang/Object implements java/lang/foreign/Addressable sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 + +class name java/lang/foreign/MemoryLayout +header extends java/lang/Object nestMembers java/lang/foreign/MemoryLayout$PathElement sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/foreign/MemoryLayout$PathElement +header extends java/lang/Object nestHost java/lang/foreign/MemoryLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/foreign/MemorySegment +header extends java/lang/Object implements java/lang/foreign/Addressable sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 + +class name java/lang/foreign/MemorySession +header extends java/lang/Object implements java/lang/AutoCloseable,java/lang/foreign/SegmentAllocator sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) + +class name java/lang/foreign/VaList +header extends java/lang/Object implements java/lang/foreign/Addressable nestMembers java/lang/foreign/VaList$Builder sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/VaList$Builder outerClass java/lang/foreign/VaList innerClassName Builder flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 + +class name java/lang/foreign/VaList$Builder +header extends java/lang/Object nestHost java/lang/foreign/VaList sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/VaList$Builder outerClass java/lang/foreign/VaList innerClassName Builder flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 + +class name java/lang/foreign/ValueLayout +header extends java/lang/foreign/AbstractLayout implements java/lang/foreign/MemoryLayout nestMembers java/lang/foreign/ValueLayout$OfAddress,java/lang/foreign/ValueLayout$OfDouble,java/lang/foreign/ValueLayout$OfLong,java/lang/foreign/ValueLayout$OfFloat,java/lang/foreign/ValueLayout$OfInt,java/lang/foreign/ValueLayout$OfShort,java/lang/foreign/ValueLayout$OfChar,java/lang/foreign/ValueLayout$OfByte,java/lang/foreign/ValueLayout$OfBoolean sealed true flags 21 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 + +class name java/lang/invoke/CallSite +header extends java/lang/Object sealed true flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/invoke/LambdaMetafactory +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/invoke/MethodHandle +header extends java/lang/Object implements java/lang/constant/Constable sealed true flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +innerclass innerClass java/lang/constant/DirectMethodHandleDesc$Kind outerClass java/lang/constant/DirectMethodHandleDesc innerClassName Kind flags 4019 + +class name java/lang/invoke/MethodHandleProxies +header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/lang/invoke/StringConcatException +header extends java/lang/Exception flags 21 + +class name java/lang/invoke/VarHandle +header extends java/lang/Object implements java/lang/constant/Constable nestMembers java/lang/invoke/VarHandle$VarHandleDesc,java/lang/invoke/VarHandle$AccessMode sealed true flags 421 +innerclass innerClass java/lang/invoke/VarHandle$AccessMode outerClass java/lang/invoke/VarHandle innerClassName AccessMode flags 4019 +innerclass innerClass java/lang/invoke/VarHandle$VarHandleDesc outerClass java/lang/invoke/VarHandle innerClassName VarHandleDesc flags 19 + +class name java/lang/module/Configuration +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/module/FindException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/InvalidModuleDescriptorException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/ModuleDescriptor +header extends java/lang/Object implements java/lang/Comparable nestMembers java/lang/module/ModuleDescriptor$Builder,java/lang/module/ModuleDescriptor$Version,java/lang/module/ModuleDescriptor$Provides,java/lang/module/ModuleDescriptor$Opens,java/lang/module/ModuleDescriptor$Opens$Modifier,java/lang/module/ModuleDescriptor$Exports,java/lang/module/ModuleDescriptor$Exports$Modifier,java/lang/module/ModuleDescriptor$Requires,java/lang/module/ModuleDescriptor$Requires$Modifier,java/lang/module/ModuleDescriptor$Modifier flags 21 signature Ljava/lang/Object;Ljava/lang/Comparable; +innerclass innerClass java/lang/module/ModuleDescriptor$Version outerClass java/lang/module/ModuleDescriptor innerClassName Version flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Modifier outerClass java/lang/module/ModuleDescriptor innerClassName Modifier flags 4019 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +innerclass innerClass java/lang/module/ModuleDescriptor$Builder outerClass java/lang/module/ModuleDescriptor innerClassName Builder flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Provides outerClass java/lang/module/ModuleDescriptor innerClassName Provides flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Opens outerClass java/lang/module/ModuleDescriptor innerClassName Opens flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Exports outerClass java/lang/module/ModuleDescriptor innerClassName Exports flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Requires outerClass java/lang/module/ModuleDescriptor innerClassName Requires flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Opens$Modifier outerClass java/lang/module/ModuleDescriptor$Opens innerClassName Modifier flags 4019 +innerclass innerClass java/lang/module/ModuleDescriptor$Exports$Modifier outerClass java/lang/module/ModuleDescriptor$Exports innerClassName Modifier flags 4019 +innerclass innerClass java/lang/module/ModuleDescriptor$Requires$Modifier outerClass java/lang/module/ModuleDescriptor$Requires innerClassName Modifier flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/module/ModuleDescriptor$Exports +header extends java/lang/Object implements java/lang/Comparable nestHost java/lang/module/ModuleDescriptor flags 31 signature Ljava/lang/Object;Ljava/lang/Comparable; +innerclass innerClass java/lang/module/ModuleDescriptor$Exports outerClass java/lang/module/ModuleDescriptor innerClassName Exports flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Exports$Modifier outerClass java/lang/module/ModuleDescriptor$Exports innerClassName Modifier flags 4019 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/module/ModuleDescriptor$Opens +header extends java/lang/Object implements java/lang/Comparable nestHost java/lang/module/ModuleDescriptor flags 31 signature Ljava/lang/Object;Ljava/lang/Comparable; +innerclass innerClass java/lang/module/ModuleDescriptor$Opens outerClass java/lang/module/ModuleDescriptor innerClassName Opens flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Opens$Modifier outerClass java/lang/module/ModuleDescriptor$Opens innerClassName Modifier flags 4019 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/module/ModuleDescriptor$Requires +header extends java/lang/Object implements java/lang/Comparable nestHost java/lang/module/ModuleDescriptor flags 31 signature Ljava/lang/Object;Ljava/lang/Comparable; +innerclass innerClass java/lang/module/ModuleDescriptor$Requires outerClass java/lang/module/ModuleDescriptor innerClassName Requires flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Version outerClass java/lang/module/ModuleDescriptor innerClassName Version flags 19 +innerclass innerClass java/lang/module/ModuleDescriptor$Requires$Modifier outerClass java/lang/module/ModuleDescriptor$Requires innerClassName Modifier flags 4019 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/module/ModuleReader +header extends java/lang/Object implements java/io/Closeable flags 601 + +class name java/lang/module/ModuleReference +header extends java/lang/Object flags 421 + +class name java/lang/module/ResolutionException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/module/ResolvedModule +header extends java/lang/Object flags 31 + +class name java/lang/ref/Reference +header extends java/lang/Object sealed true flags 421 signature Ljava/lang/Object; + +class name java/lang/reflect/AccessFlag +header extends java/lang/Enum nestMembers java/lang/reflect/AccessFlag$Location flags 4031 signature Ljava/lang/Enum; +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +field name PUBLIC descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name PRIVATE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name PROTECTED descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name STATIC descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name FINAL descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name SUPER descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name OPEN descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name TRANSITIVE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name SYNCHRONIZED descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name STATIC_PHASE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name VOLATILE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name BRIDGE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name TRANSIENT descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name VARARGS descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name NATIVE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name INTERFACE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name ABSTRACT descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name STRICT descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name SYNTHETIC descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name ANNOTATION descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name ENUM descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name MANDATED descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +field name MODULE descriptor Ljava/lang/reflect/AccessFlag; flags 4019 +method name values descriptor ()[Ljava/lang/reflect/AccessFlag; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Ljava/lang/reflect/AccessFlag; flags 9 +method name mask descriptor ()I flags 1 +method name sourceModifier descriptor ()Z flags 1 +method name locations descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; +method name locations descriptor (Ljava/lang/reflect/ClassFileFormatVersion;)Ljava/util/Set; flags 1 signature (Ljava/lang/reflect/ClassFileFormatVersion;)Ljava/util/Set; +method name maskToAccessFlags descriptor (ILjava/lang/reflect/AccessFlag$Location;)Ljava/util/Set; flags 9 signature (ILjava/lang/reflect/AccessFlag$Location;)Ljava/util/Set; + +class name java/lang/reflect/AccessFlag$Location +header extends java/lang/Enum nestHost java/lang/reflect/AccessFlag flags 4031 signature Ljava/lang/Enum; +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +field name CLASS descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name FIELD descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name METHOD descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name INNER_CLASS descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name METHOD_PARAMETER descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name MODULE descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name MODULE_REQUIRES descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name MODULE_EXPORTS descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +field name MODULE_OPENS descriptor Ljava/lang/reflect/AccessFlag$Location; flags 4019 +method name values descriptor ()[Ljava/lang/reflect/AccessFlag$Location; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Ljava/lang/reflect/AccessFlag$Location; flags 9 + +class name java/lang/reflect/AccessibleObject +header extends java/lang/Object implements java/lang/reflect/AnnotatedElement flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/lang/reflect/AnnotatedElement +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/reflect/ClassFileFormatVersion +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; +innerclass innerClass java/lang/Runtime$Version outerClass java/lang/Runtime innerClassName Version flags 19 +field name RELEASE_0 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_1 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_2 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_3 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_4 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_5 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_6 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_7 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_8 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_9 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_10 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_11 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_12 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_13 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_14 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_15 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_16 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_17 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_18 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_19 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +field name RELEASE_20 descriptor Ljava/lang/reflect/ClassFileFormatVersion; flags 4019 +method name values descriptor ()[Ljava/lang/reflect/ClassFileFormatVersion; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Ljava/lang/reflect/ClassFileFormatVersion; flags 9 +method name latest descriptor ()Ljava/lang/reflect/ClassFileFormatVersion; flags 9 +method name major descriptor ()I flags 1 +method name valueOf descriptor (Ljava/lang/Runtime$Version;)Ljava/lang/reflect/ClassFileFormatVersion; flags 9 +method name runtimeVersion descriptor ()Ljava/lang/Runtime$Version; flags 1 +method name fromMajor descriptor (I)Ljava/lang/reflect/ClassFileFormatVersion; flags 9 + +class name java/lang/reflect/Executable +header extends java/lang/reflect/AccessibleObject implements java/lang/reflect/Member,java/lang/reflect/GenericDeclaration sealed true flags 421 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name getParameterCount descriptor ()I +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; +method name getParameterCount descriptor ()I flags 401 + +class name java/lang/reflect/Field +header extends java/lang/reflect/AccessibleObject implements java/lang/reflect/Member flags 31 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/reflect/InaccessibleObjectException +header extends java/lang/RuntimeException flags 21 + +class name java/lang/reflect/Member +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/lang/reflect/Parameter +header extends java/lang/Object implements java/lang/reflect/AnnotatedElement flags 31 +innerclass innerClass java/lang/reflect/AccessFlag$Location outerClass java/lang/reflect/AccessFlag innerClassName Location flags 4019 +method name accessFlags descriptor ()Ljava/util/Set; flags 1 signature ()Ljava/util/Set; + +class name java/math/BigDecimal +header extends java/lang/Number implements java/lang/Comparable flags 21 signature Ljava/lang/Number;Ljava/lang/Comparable; +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/net/DatagramPacket +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/net/DatagramSocket +header extends java/lang/Object implements java/io/Closeable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/net/InetAddress +header extends java/lang/Object implements java/io/Serializable sealed true flags 21 +innerclass innerClass java/net/spi/InetAddressResolver$LookupPolicy outerClass java/net/spi/InetAddressResolver innerClassName LookupPolicy flags 19 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/net/spi/InetAddressResolverProvider$Configuration outerClass java/net/spi/InetAddressResolverProvider innerClassName Configuration flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/net/SocketImpl +header extends java/lang/Object implements java/net/SocketOptions flags 421 + +class name java/net/URL +-method name descriptor (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V +-method name descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V +-method name descriptor (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/net/URLStreamHandler;)V +-method name descriptor (Ljava/lang/String;)V +-method name descriptor (Ljava/net/URL;Ljava/lang/String;)V +-method name descriptor (Ljava/net/URL;Ljava/lang/String;Ljava/net/URLStreamHandler;)V +method name descriptor (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name descriptor (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name descriptor (Ljava/lang/String;Ljava/lang/String;ILjava/lang/String;Ljava/net/URLStreamHandler;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name descriptor (Ljava/lang/String;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name descriptor (Ljava/net/URL;Ljava/lang/String;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name descriptor (Ljava/net/URL;Ljava/lang/String;Ljava/net/URLStreamHandler;)V thrownTypes java/net/MalformedURLException flags 1 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="20") +method name of descriptor (Ljava/net/URI;Ljava/net/URLStreamHandler;)Ljava/net/URL; thrownTypes java/net/MalformedURLException flags 9 + +class name java/net/spi/InetAddressResolverProvider$Configuration +header extends java/lang/Object nestHost java/net/spi/InetAddressResolverProvider sealed true flags 601 +innerclass innerClass java/net/spi/InetAddressResolverProvider$Configuration outerClass java/net/spi/InetAddressResolverProvider innerClassName Configuration flags 609 + +class name java/net/spi/URLStreamHandlerProvider +header extends java/lang/Object implements java/net/URLStreamHandlerFactory flags 421 + +class name java/nio/Buffer +header extends java/lang/Object sealed true flags 421 + +class name java/nio/ByteBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/CharBuffer +header extends java/nio/Buffer implements java/lang/Comparable,java/lang/Appendable,java/lang/CharSequence,java/lang/Readable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable;Ljava/lang/Appendable;Ljava/lang/CharSequence;Ljava/lang/Readable; +innerclass innerClass java/util/Spliterator$OfInt outerClass java/util/Spliterator innerClassName OfInt flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/nio/DoubleBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/FloatBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/IntBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/LongBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/MappedByteBuffer +header extends java/nio/ByteBuffer sealed true flags 421 + +class name java/nio/ShortBuffer +header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; + +class name java/nio/file/Path +method name getExtension descriptor ()Ljava/lang/String; flags 1 + +class name java/nio/file/spi/FileSystemProvider +method name exists descriptor (Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z flags 81 +method name readAttributesIfExists descriptor (Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)Ljava/nio/file/attribute/BasicFileAttributes; thrownTypes java/io/IOException flags 81 signature (Ljava/nio/file/Path;Ljava/lang/Class;[Ljava/nio/file/LinkOption;)TA; + +class name java/security/Certificate +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/Identity +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 421 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="1.2") + +class name java/security/InvalidParameterException +method name descriptor (Ljava/lang/String;Ljava/lang/Throwable;)V flags 1 +method name descriptor (Ljava/lang/Throwable;)V flags 1 + +class name java/security/KeyStore +header extends java/lang/Object nestMembers java/security/KeyStore$Builder,java/security/KeyStore$TrustedCertificateEntry,java/security/KeyStore$SecretKeyEntry,java/security/KeyStore$PrivateKeyEntry,java/security/KeyStore$Entry,java/security/KeyStore$Entry$Attribute,java/security/KeyStore$CallbackHandlerProtection,java/security/KeyStore$PasswordProtection,java/security/KeyStore$ProtectionParameter,java/security/KeyStore$LoadStoreParameter flags 21 +innerclass innerClass java/security/KeyStore$LoadStoreParameter outerClass java/security/KeyStore innerClassName LoadStoreParameter flags 609 +innerclass innerClass java/security/KeyStore$ProtectionParameter outerClass java/security/KeyStore innerClassName ProtectionParameter flags 609 +innerclass innerClass java/security/KeyStore$Entry outerClass java/security/KeyStore innerClassName Entry flags 609 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/security/KeyStore$Builder outerClass java/security/KeyStore innerClassName Builder flags 409 +innerclass innerClass java/security/KeyStore$TrustedCertificateEntry outerClass java/security/KeyStore innerClassName TrustedCertificateEntry flags 19 +innerclass innerClass java/security/KeyStore$SecretKeyEntry outerClass java/security/KeyStore innerClassName SecretKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$PrivateKeyEntry outerClass java/security/KeyStore innerClassName PrivateKeyEntry flags 19 +innerclass innerClass java/security/KeyStore$CallbackHandlerProtection outerClass java/security/KeyStore innerClassName CallbackHandlerProtection flags 9 +innerclass innerClass java/security/KeyStore$PasswordProtection outerClass java/security/KeyStore innerClassName PasswordProtection flags 9 +innerclass innerClass java/security/KeyStore$Entry$Attribute outerClass java/security/KeyStore$Entry innerClassName Attribute flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/ProtectionDomain +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/Provider +header extends java/util/Properties nestMembers java/security/Provider$Service flags 421 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/SecureRandom +header extends java/util/Random flags 21 runtimeAnnotations @Ljdk/internal/util/random/RandomSupport$RandomGeneratorProperties;(name="SecureRandom",isStochastic=Ztrue) +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/SecureRandomParameters +header extends java/lang/Object flags 601 + +class name java/security/Security +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/SignedObject +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/security/cert/CertPathBuilder +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/cert/CertPathValidator +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/cert/CertStore +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name getDefaultType descriptor ()Ljava/lang/String; +method name getDefaultType descriptor ()Ljava/lang/String; flags 9 + +class name java/security/cert/CertificateRevokedException +header extends java/security/cert/CertificateException flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/security/cert/URICertStoreParameters +header extends java/lang/Object implements java/security/cert/CertStoreParameters flags 31 + +class name java/security/interfaces/DSAKeyPairGenerator +-method name initialize descriptor (Ljava/security/interfaces/DSAParams;Ljava/security/SecureRandom;)V +-method name initialize descriptor (IZLjava/security/SecureRandom;)V +method name initialize descriptor (Ljava/security/interfaces/DSAParams;Ljava/security/SecureRandom;)V flags 401 +method name initialize descriptor (IZLjava/security/SecureRandom;)V flags 401 + +class name java/security/interfaces/RSAKey +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/EncodedKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/security/spec/MGF1ParameterSpec +-field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; +-field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; +field name SHA512_224 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 +field name SHA512_256 descriptor Ljava/security/spec/MGF1ParameterSpec; flags 19 + +class name java/security/spec/PSSParameterSpec +-field name TRAILER_FIELD_BC descriptor I +-method name toString descriptor ()Ljava/lang/String; +field name TRAILER_FIELD_BC descriptor I constantValue 1 flags 19 +method name toString descriptor ()Ljava/lang/String; flags 1 + +class name java/security/spec/RSAKeyGenParameterSpec +-method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (ILjava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getKeyParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/RSAMultiPrimePrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;[Ljava/security/spec/RSAOtherPrimeInfo;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 + +class name java/security/spec/RSAPrivateCrtKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 + +class name java/security/spec/RSAPrivateKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/security/spec/RSAPublicKeySpec +-method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V +-method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; +method name descriptor (Ljava/math/BigInteger;Ljava/math/BigInteger;Ljava/security/spec/AlgorithmParameterSpec;)V flags 1 +method name getParams descriptor ()Ljava/security/spec/AlgorithmParameterSpec; flags 1 + +class name java/text/DateFormatSymbols +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/text/RuleBasedCollator +header extends java/text/Collator flags 21 +innerclass innerClass java/text/Normalizer$Form outerClass java/text/Normalizer innerClassName Form flags 4019 + +class name java/time/ZoneId +header extends java/lang/Object implements java/io/Serializable sealed true flags 421 runtimeAnnotations @Ljdk/internal/ValueBased; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/time/ZoneOffset +header extends java/time/ZoneId implements java/time/temporal/TemporalAccessor,java/time/temporal/TemporalAdjuster,java/lang/Comparable,java/io/Serializable flags 31 signature Ljava/time/ZoneId;Ljava/time/temporal/TemporalAccessor;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable;Ljava/io/Serializable; runtimeAnnotations @Ljdk/internal/ValueBased; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/ChronoLocalDate +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/chrono/ChronoLocalDateTime +header extends java/lang/Object implements java/time/temporal/Temporal,java/time/temporal/TemporalAdjuster,java/lang/Comparable flags 601 signature Ljava/lang/Object;Ljava/time/temporal/Temporal;Ljava/time/temporal/TemporalAdjuster;Ljava/lang/Comparable;>; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/format/DecimalStyle +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/time/temporal/TemporalAdjusters +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/Comparator +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/DoubleSummaryStatistics +header extends java/lang/Object implements java/util/function/DoubleConsumer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/EnumSet +header extends java/util/AbstractSet implements java/lang/Cloneable,java/io/Serializable sealed true flags 421 signature ;>Ljava/util/AbstractSet;Ljava/lang/Cloneable;Ljava/io/Serializable; + +class name java/util/GregorianCalendar +header extends java/util/Calendar flags 21 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/util/IdentityHashMap +method name remove descriptor (Ljava/lang/Object;Ljava/lang/Object;)Z flags 1 +method name replace descriptor (Ljava/lang/Object;Ljava/lang/Object;Ljava/lang/Object;)Z flags 1 signature (TK;TV;TV;)Z + +class name java/util/IllegalFormatException +header extends java/lang/IllegalArgumentException sealed true flags 21 + +class name java/util/Locale$IsoCountryCode +header extends java/lang/Enum nestHost java/util/Locale sealed true flags 4421 signature Ljava/lang/Enum; +innerclass innerClass java/util/Locale$IsoCountryCode outerClass java/util/Locale innerClassName IsoCountryCode flags 4409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/Observable +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/Observer +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/TimeZone +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 + +class name java/util/TreeSet +header extends java/util/AbstractSet implements java/util/NavigableSet,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/NavigableSet;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/util/concurrent/ConcurrentHashMap$CollectionView +header extends java/lang/Object implements java/util/Collection,java/io/Serializable nestHost java/util/concurrent/ConcurrentHashMap sealed true flags 420 signature Ljava/lang/Object;Ljava/util/Collection;Ljava/io/Serializable; +innerclass innerClass java/util/concurrent/ConcurrentHashMap$CollectionView outerClass java/util/concurrent/ConcurrentHashMap innerClassName CollectionView flags 408 +innerclass innerClass java/util/concurrent/ConcurrentHashMap$KeySetView outerClass java/util/concurrent/ConcurrentHashMap innerClassName KeySetView flags 19 + +class name java/util/concurrent/ConcurrentMap +header extends java/lang/Object implements java/util/Map flags 601 signature Ljava/lang/Object;Ljava/util/Map; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/ConcurrentSkipListSet +header extends java/util/AbstractSet implements java/util/NavigableSet,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/util/AbstractSet;Ljava/util/NavigableSet;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/CountedCompleter +header extends java/util/concurrent/ForkJoinTask flags 421 signature Ljava/util/concurrent/ForkJoinTask; classAnnotations @Ljdk/Profile+Annotation;(value=I1) + +class name java/util/concurrent/atomic/AtomicBoolean +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/atomic/AtomicReference +header extends java/lang/Object implements java/io/Serializable flags 21 signature Ljava/lang/Object;Ljava/io/Serializable; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/atomic/AtomicReferenceArray +header extends java/lang/Object implements java/io/Serializable flags 21 signature Ljava/lang/Object;Ljava/io/Serializable; +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/concurrent/locks/StampedLock +header extends java/lang/Object implements java/io/Serializable flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I1) +-method name tryWriteLock descriptor ()J +-method name writeLockInterruptibly descriptor ()J +-method name tryReadLock descriptor ()J +-method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J +-method name readLockInterruptibly descriptor ()J +-method name unlock descriptor (J)V +method name tryWriteLock descriptor ()J flags 1 +method name writeLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name tryReadLock descriptor ()J flags 1 +method name tryReadLock descriptor (JLjava/util/concurrent/TimeUnit;)J thrownTypes java/lang/InterruptedException flags 1 +method name readLockInterruptibly descriptor ()J thrownTypes java/lang/InterruptedException flags 1 +method name unlock descriptor (J)V flags 1 + +class name java/util/function/BiConsumer +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BiFunction +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BiPredicate +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/BinaryOperator +header extends java/lang/Object implements java/util/function/BiFunction flags 601 signature Ljava/lang/Object;Ljava/util/function/BiFunction; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Consumer +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoubleConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoublePredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/DoubleUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Function +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntPredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/IntUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongConsumer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongPredicate +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/LongUnaryOperator +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/Predicate +header extends java/lang/Object flags 601 signature Ljava/lang/Object; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/function/UnaryOperator +header extends java/lang/Object implements java/util/function/Function flags 601 signature Ljava/lang/Object;Ljava/util/function/Function; runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/regex/MatchResult +method name start descriptor (Ljava/lang/String;)I flags 1 +method name end descriptor (Ljava/lang/String;)I flags 1 +method name group descriptor (Ljava/lang/String;)Ljava/lang/String; flags 1 +method name namedGroups descriptor ()Ljava/util/Map; flags 1 signature ()Ljava/util/Map; +method name hasMatch descriptor ()Z flags 1 + +class name java/util/regex/Matcher +method name namedGroups descriptor ()Ljava/util/Map; flags 1 signature ()Ljava/util/Map; +method name hasMatch descriptor ()Z flags 1 + +class name java/util/regex/Pattern +method name namedGroups descriptor ()Ljava/util/Map; flags 1 signature ()Ljava/util/Map; + +class name java/util/spi/AbstractResourceBundleProvider +header extends java/lang/Object implements java/util/spi/ResourceBundleProvider flags 421 +innerclass innerClass java/util/ResourceBundle$Control outerClass java/util/ResourceBundle innerClassName Control flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/spi/CurrencyNameProvider +header extends java/util/spi/LocaleServiceProvider flags 421 +innerclass innerClass java/util/ResourceBundle$Control outerClass java/util/ResourceBundle innerClassName Control flags 9 + +class name java/util/spi/ResourceBundleProvider +header extends java/lang/Object flags 601 + +class name java/util/spi/ToolProvider +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/zip/CRC32C +header extends java/lang/Object implements java/util/zip/Checksum flags 31 + +class name java/util/zip/ZipInputStream +method name read descriptor ()I thrownTypes java/io/IOException flags 1 +method name readAllBytes descriptor ()[B thrownTypes java/io/IOException flags 1 +method name readNBytes descriptor (I)[B thrownTypes java/io/IOException flags 1 +method name readNBytes descriptor ([BII)I thrownTypes java/io/IOException flags 1 +method name skipNBytes descriptor (J)V thrownTypes java/io/IOException flags 1 +method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 + +class name javax/crypto/AEADBadTagException +header extends javax/crypto/BadPaddingException flags 21 + +class name javax/crypto/BadPaddingException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/CipherInputStream +header extends java/io/FilterInputStream flags 21 + +class name javax/crypto/CipherOutputStream +header extends java/io/FilterOutputStream flags 21 + +class name javax/crypto/CipherSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/EncryptedPrivateKeyInfo +header extends java/lang/Object flags 21 + +class name javax/crypto/ExemptionMechanism +header extends java/lang/Object flags 21 + +class name javax/crypto/ExemptionMechanismException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/ExemptionMechanismSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/IllegalBlockSizeException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/KeyAgreement +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/KeyAgreementSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/KeyGenerator +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/KeyGeneratorSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/Mac +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/MacSpi +header extends java/lang/Object flags 421 + +class name javax/crypto/NoSuchPaddingException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/NullCipher +header extends javax/crypto/Cipher flags 21 + +class name javax/crypto/SealedObject +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/crypto/SecretKey +header extends java/lang/Object implements java/security/Key,javax/security/auth/Destroyable flags 601 + +class name javax/crypto/SecretKeyFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 + +class name javax/crypto/SecretKeyFactorySpi +header extends java/lang/Object flags 421 + +class name javax/crypto/ShortBufferException +header extends java/security/GeneralSecurityException flags 21 + +class name javax/crypto/interfaces/DHKey +header extends java/lang/Object flags 601 + +class name javax/crypto/interfaces/DHPrivateKey +header extends java/lang/Object implements javax/crypto/interfaces/DHKey,java/security/PrivateKey flags 601 + +class name javax/crypto/interfaces/DHPublicKey +header extends java/lang/Object implements javax/crypto/interfaces/DHKey,java/security/PublicKey flags 601 + +class name javax/crypto/interfaces/PBEKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 601 + +class name javax/crypto/spec/DESKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DESedeKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DHGenParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/DHParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/DHPrivateKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/DHPublicKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 + +class name javax/crypto/spec/GCMParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/IvParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/OAEPParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 +innerclass innerClass javax/crypto/spec/PSource$PSpecified outerClass javax/crypto/spec/PSource innerClassName PSpecified flags 19 + +class name javax/crypto/spec/PBEKeySpec +header extends java/lang/Object implements java/security/spec/KeySpec flags 21 +-method name clearPassword descriptor ()V +-method name getPassword descriptor ()[C +method name clearPassword descriptor ()V flags 31 +method name getPassword descriptor ()[C flags 31 + +class name javax/crypto/spec/PBEParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/RC2ParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name javax/crypto/spec/RC5ParameterSpec +header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 + +class name jdk/internal/event/Event +header extends java/lang/Object flags 421 +-method name descriptor ()V +-method name begin descriptor ()V +-method name end descriptor ()V +-method name commit descriptor ()V +-method name isEnabled descriptor ()Z +-method name shouldCommit descriptor ()Z +-method name set descriptor (ILjava/lang/Object;)V +method name descriptor ()V flags 4 +method name begin descriptor ()V flags 1 +method name end descriptor ()V flags 1 +method name commit descriptor ()V flags 1 +method name isEnabled descriptor ()Z flags 1 +method name shouldCommit descriptor ()Z flags 1 +method name set descriptor (ILjava/lang/Object;)V flags 1 + +class name jdk/internal/vm/vector/VectorSupport +-method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; +method name indexVector descriptor (Ljava/lang/Class;Ljava/lang/Class;ILjdk/internal/vm/vector/VectorSupport$Vector;ILjdk/internal/vm/vector/VectorSupport$VectorSpecies;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)Ljdk/internal/vm/vector/VectorSupport$Vector; flags 9 signature ;E:Ljava/lang/Object;S:Ljdk/internal/vm/vector/VectorSupport$VectorSpecies;>(Ljava/lang/Class<+TV;>;Ljava/lang/Class;ITV;ITS;Ljdk/internal/vm/vector/VectorSupport$IndexOperation;)TV; runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; + diff --git a/src/jdk.compiler/share/data/symbols/java.compiler-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.compiler-K.sym.txt new file mode 100644 index 00000000000..5a178614db0 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.compiler-K.sym.txt @@ -0,0 +1,116 @@ +# +# Copyright (c) 2022, 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 javax/annotation/processing/AbstractProcessor +header extends java/lang/Object implements javax/annotation/processing/Processor flags 421 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/annotation/processing/Generated +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;SOURCE;)@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;PACKAGE;eLjava/lang/annotation/ElementType;TYPE;eLjava/lang/annotation/ElementType;METHOD;eLjava/lang/annotation/ElementType;CONSTRUCTOR;eLjava/lang/annotation/ElementType;FIELD;eLjava/lang/annotation/ElementType;LOCAL_VARIABLE;eLjava/lang/annotation/ElementType;PARAMETER;}) + +class name javax/lang/model/SourceVersion +field name RELEASE_20 descriptor Ljavax/lang/model/SourceVersion; flags 4019 + +class name javax/lang/model/element/Modifier +header extends java/lang/Enum sealed true flags 4021 signature Ljava/lang/Enum; + +class name javax/lang/model/element/UnknownAnnotationValueException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/element/UnknownDirectiveException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass javax/lang/model/element/ModuleElement$Directive outerClass javax/lang/model/element/ModuleElement innerClassName Directive flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/element/UnknownElementException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/MirroredTypeException +header extends javax/lang/model/type/MirroredTypesException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/MirroredTypesException +header extends java/lang/RuntimeException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/type/UnknownTypeException +header extends javax/lang/model/UnknownEntityException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/lang/model/util/AbstractAnnotationValueVisitor14 +header extends javax/lang/model/util/AbstractAnnotationValueVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractAnnotationValueVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/AbstractElementVisitor14 +header extends javax/lang/model/util/AbstractElementVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractElementVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/AbstractTypeVisitor14 +header extends javax/lang/model/util/AbstractTypeVisitor9 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/AbstractTypeVisitor6 +header extends java/lang/Object implements javax/lang/model/type/TypeVisitor flags 421 signature Ljava/lang/Object;Ljavax/lang/model/type/TypeVisitor; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_6;) + +class name javax/lang/model/util/AbstractTypeVisitor7 +header extends javax/lang/model/util/AbstractTypeVisitor6 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor6; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_7;) + +class name javax/lang/model/util/AbstractTypeVisitor8 +header extends javax/lang/model/util/AbstractTypeVisitor7 flags 421 signature Ljavax/lang/model/util/AbstractTypeVisitor7; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_8;) + +class name javax/lang/model/util/ElementKindVisitor14 +header extends javax/lang/model/util/ElementKindVisitor9 flags 21 signature Ljavax/lang/model/util/ElementKindVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/ElementScanner14 +header extends javax/lang/model/util/ElementScanner9 flags 21 signature Ljavax/lang/model/util/ElementScanner9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/Elements +method name isCanonicalConstructor descriptor (Ljavax/lang/model/element/ExecutableElement;)Z flags 1 +method name isCompactConstructor descriptor (Ljavax/lang/model/element/ExecutableElement;)Z flags 1 + +class name javax/lang/model/util/SimpleAnnotationValueVisitor14 +header extends javax/lang/model/util/SimpleAnnotationValueVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleAnnotationValueVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/SimpleElementVisitor14 +header extends javax/lang/model/util/SimpleElementVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleElementVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/SimpleTypeVisitor14 +header extends javax/lang/model/util/SimpleTypeVisitor9 flags 21 signature Ljavax/lang/model/util/SimpleTypeVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/lang/model/util/TypeKindVisitor14 +header extends javax/lang/model/util/TypeKindVisitor9 flags 21 signature Ljavax/lang/model/util/TypeKindVisitor9; runtimeAnnotations @Ljavax/annotation/processing/SupportedSourceVersion;(value=eLjavax/lang/model/SourceVersion;RELEASE_20;) + +class name javax/tools/SimpleJavaFileObject +header extends java/lang/Object implements javax/tools/JavaFileObject flags 21 +innerclass innerClass javax/tools/JavaFileObject$Kind outerClass javax/tools/JavaFileObject innerClassName Kind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/tools/ToolProvider +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.datatransfer-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.datatransfer-K.sym.txt new file mode 100644 index 00000000000..fff0a5016ec --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.datatransfer-K.sym.txt @@ -0,0 +1,36 @@ +# +# Copyright (c) 2022, 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/awt/datatransfer/Clipboard +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/datatransfer/DataFlavor +header extends java/lang/Object implements java/io/Externalizable,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.desktop-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.desktop-K.sym.txt new file mode 100644 index 00000000000..6d9e205b3c1 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.desktop-K.sym.txt @@ -0,0 +1,871 @@ +# +# Copyright (c) 2022, 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/awt/AWTKeyStroke +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/AttributeValue +header extends java/lang/Object flags 420 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/BorderLayout +header extends java/lang/Object implements java/awt/LayoutManager2,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/CheckboxGroup +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Color +header extends java/lang/Object implements java/awt/Paint,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/ContainerOrderFocusTraversalPolicy +header extends java/awt/FocusTraversalPolicy implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Dimension +header extends java/awt/geom/Dimension2D implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/DisplayMode +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Event +header extends java/lang/Object implements java/io/Serializable flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/FlowLayout +header extends java/lang/Object implements java/awt/LayoutManager,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/FontMetrics +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Graphics +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/GridLayout +header extends java/lang/Object implements java/awt/LayoutManager,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/HeadlessException +header extends java/lang/UnsupportedOperationException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Insets +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/MenuShortcut +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/MultipleGradientPaint +header extends java/lang/Object implements java/awt/Paint nestMembers java/awt/MultipleGradientPaint$ColorSpaceType,java/awt/MultipleGradientPaint$CycleMethod sealed true flags 421 +innerclass innerClass java/awt/MultipleGradientPaint$ColorSpaceType outerClass java/awt/MultipleGradientPaint innerClassName ColorSpaceType flags 4019 +innerclass innerClass java/awt/MultipleGradientPaint$CycleMethod outerClass java/awt/MultipleGradientPaint innerClassName CycleMethod flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Point +header extends java/awt/geom/Point2D implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/Rectangle +header extends java/awt/geom/Rectangle2D implements java/awt/Shape,java/io/Serializable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/SystemColor +header extends java/awt/Color implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/TextComponent +header extends java/awt/Component implements javax/accessibility/Accessible nestMembers java/awt/TextComponent$AccessibleAWTTextComponent sealed true flags 21 +innerclass innerClass java/awt/TextComponent$AccessibleAWTTextComponent outerClass java/awt/TextComponent innerClassName AccessibleAWTTextComponent flags 4 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/TexturePaint +header extends java/lang/Object implements java/awt/Paint flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/color/ColorSpace +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/color/ICC_ColorSpace +header extends java/awt/color/ColorSpace flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name java/awt/color/ICC_Profile +header extends java/lang/Object implements java/io/Serializable sealed true flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/desktop/AboutEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AboutHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/AppEvent +header extends java/util/EventObject sealed true flags 21 + +class name java/awt/desktop/AppForegroundEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppForegroundListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/AppHiddenEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppHiddenListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/AppReopenedEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/AppReopenedListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/FilesEvent +header extends java/awt/desktop/AppEvent sealed true flags 21 + +class name java/awt/desktop/OpenFilesEvent +header extends java/awt/desktop/FilesEvent flags 31 + +class name java/awt/desktop/OpenFilesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/OpenURIEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/OpenURIHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/PreferencesEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/PreferencesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/PrintFilesEvent +header extends java/awt/desktop/FilesEvent flags 31 + +class name java/awt/desktop/PrintFilesHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/QuitHandler +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitResponse +header extends java/lang/Object flags 601 + +class name java/awt/desktop/QuitStrategy +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + +class name java/awt/desktop/ScreenSleepEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/ScreenSleepListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/SystemEventListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name java/awt/desktop/SystemSleepEvent +header extends java/awt/desktop/AppEvent flags 31 + +class name java/awt/desktop/SystemSleepListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/desktop/UserSessionListener +header extends java/lang/Object implements java/awt/desktop/SystemEventListener flags 601 + +class name java/awt/dnd/DragGestureEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/awt/dnd/DragGestureRecognizer +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name java/awt/dnd/DragSource +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/dnd/DropTargetDragEvent +header extends java/awt/dnd/DropTargetEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/dnd/DropTargetDropEvent +header extends java/awt/dnd/DropTargetEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ActionEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/AdjustmentEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ComponentEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ContainerEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/HierarchyEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/InputEvent +header extends java/awt/event/ComponentEvent sealed true flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/InputMethodEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/ItemEvent +header extends java/awt/AWTEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/MouseWheelEvent +header extends java/awt/event/MouseEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/PaintEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/event/WindowEvent +header extends java/awt/event/ComponentEvent flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/FontRenderContext +header extends java/lang/Object flags 21 +innerclass innerClass java/awt/RenderingHints$Key outerClass java/awt/RenderingHints innerClassName Key flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/GraphicAttribute +header extends java/lang/Object flags 421 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/ImageGraphicAttribute +header extends java/awt/font/GraphicAttribute flags 31 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/NumericShaper$Range +header extends java/lang/Enum nestHost java/awt/font/NumericShaper sealed true flags 4021 signature Ljava/lang/Enum; +innerclass innerClass java/awt/font/NumericShaper$Range outerClass java/awt/font/NumericShaper innerClassName Range flags 4009 + +class name java/awt/font/ShapeGraphicAttribute +header extends java/awt/font/GraphicAttribute flags 31 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 + +class name java/awt/font/TextHitInfo +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/font/TextMeasurer +header extends java/lang/Object implements java/lang/Cloneable flags 31 +innerclass innerClass java/text/AttributedCharacterIterator$Attribute outerClass java/text/AttributedCharacterIterator innerClassName Attribute flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/geom/AffineTransform +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/awt/geom/Point2D$Double outerClass java/awt/geom/Point2D innerClassName Double flags 9 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Path2D$Double outerClass java/awt/geom/Path2D innerClassName Double flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/geom/Area +header extends java/lang/Object implements java/awt/Shape,java/lang/Cloneable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/geom/Path2D +header extends java/lang/Object implements java/awt/Shape,java/lang/Cloneable nestMembers java/awt/geom/Path2D$Double,java/awt/geom/Path2D$Float sealed true flags 421 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 +innerclass innerClass java/awt/geom/Path2D$Double outerClass java/awt/geom/Path2D innerClassName Double flags 9 +innerclass innerClass java/awt/geom/Path2D$Float outerClass java/awt/geom/Path2D innerClassName Float flags 9 + +class name java/awt/geom/RectangularShape +header extends java/lang/Object implements java/awt/Shape,java/lang/Cloneable flags 421 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/awt/image/AbstractMultiResolutionImage +header extends java/awt/Image implements java/awt/image/MultiResolutionImage flags 421 + +class name java/awt/image/BandCombineOp +header extends java/lang/Object implements java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BandedSampleModel +header extends java/awt/image/ComponentSampleModel flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BaseMultiResolutionImage +header extends java/awt/image/AbstractMultiResolutionImage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/BufferedImageFilter +header extends java/awt/image/ImageFilter implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ByteLookupTable +header extends java/awt/image/LookupTable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ColorConvertOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 + +class name java/awt/image/ComponentColorModel +header extends java/awt/image/ColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ComponentSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ConvolveOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 + +class name java/awt/image/DataBufferUShort +header extends java/awt/image/DataBuffer flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/DirectColorModel +header extends java/awt/image/PackedColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ImageFilter +header extends java/lang/Object implements java/awt/image/ImageConsumer,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/IndexColorModel +header extends java/awt/image/ColorModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/Kernel +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/LookupOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/MultiPixelPackedSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/MultiResolutionImage +header extends java/lang/Object flags 601 + +class name java/awt/image/PackedColorModel +header extends java/awt/image/ColorModel flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/Raster +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ReplicateScaleFilter +header extends java/awt/image/ImageFilter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/RescaleOp +header extends java/lang/Object implements java/awt/image/BufferedImageOp,java/awt/image/RasterOp flags 21 +innerclass innerClass java/awt/geom/Point2D$Float outerClass java/awt/geom/Point2D innerClassName Float flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/SampleModel +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/ShortLookupTable +header extends java/awt/image/LookupTable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/image/SinglePixelPackedSampleModel +header extends java/awt/image/SampleModel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/awt/print/Paper +header extends java/lang/Object implements java/lang/Cloneable flags 21 +innerclass innerClass java/awt/geom/Rectangle2D$Double outerClass java/awt/geom/Rectangle2D innerClassName Double flags 9 + +class name java/beans/BeanProperty +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;METHOD;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name java/beans/Beans +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/DefaultPersistenceDelegate +header extends java/beans/PersistenceDelegate flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/Encoder +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/EventSetDescriptor +header extends java/beans/FeatureDescriptor flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/Expression +header extends java/beans/Statement flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/FeatureDescriptor +header extends java/lang/Object flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name java/beans/IndexedPropertyDescriptor +header extends java/beans/PropertyDescriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/JavaBean +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name java/beans/PropertyDescriptor +header extends java/beans/FeatureDescriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/beans/SimpleBeanInfo +header extends java/lang/Object implements java/beans/BeanInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/accessibility/AccessibilityProvider +header extends java/lang/Object flags 421 + +class name javax/accessibility/AccessibleBundle +header extends java/lang/Object flags 421 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name javax/accessibility/AccessibleRelationSet +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/accessibility/AccessibleStateSet +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/metadata/IIOMetadata +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/jpeg/JPEGHuffmanTable +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/jpeg/JPEGQTable +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFDirectory +header extends java/lang/Object implements java/lang/Cloneable flags 21 + +class name javax/imageio/plugins/tiff/TIFFField +header extends java/lang/Object implements java/lang/Cloneable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFImageReadParam +header extends javax/imageio/ImageReadParam flags 31 + +class name javax/imageio/plugins/tiff/TIFFTag +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/imageio/plugins/tiff/TIFFTagSet +header extends java/lang/Object flags 21 + +class name javax/imageio/spi/ImageReaderWriterSpi +header extends javax/imageio/spi/IIOServiceProvider flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/DateTimeSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/EnumSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/IntegerSyntax +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/attribute/standard/MediaPrintableArea +header extends java/lang/Object implements javax/print/attribute/DocAttribute,javax/print/attribute/PrintRequestAttribute,javax/print/attribute/PrintJobAttribute flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/print/event/PrintEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/MetaMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/MidiMessage +header extends java/lang/Object implements java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/Sequence +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/ShortMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/midi/SysexMessage +header extends javax/sound/midi/MidiMessage flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sound/sampled/ReverbType +header extends java/lang/Object flags 21 classAnnotations @Ljdk/Profile+Annotation;(value=I4) + +class name javax/sound/sampled/spi/FormatConversionProvider +header extends java/lang/Object flags 421 +innerclass innerClass javax/sound/sampled/AudioFormat$Encoding outerClass javax/sound/sampled/AudioFormat innerClassName Encoding flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/BoxLayout +header extends java/lang/Object implements java/awt/LayoutManager2,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DebugGraphics +header extends java/awt/Graphics flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DefaultBoundedRangeModel +header extends java/lang/Object implements javax/swing/BoundedRangeModel,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/DefaultListSelectionModel +header extends java/lang/Object implements javax/swing/ListSelectionModel,java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/GrayFilter +header extends java/awt/image/RGBImageFilter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/GroupLayout$Group +header extends javax/swing/GroupLayout$Spring nestHost javax/swing/GroupLayout sealed true flags 421 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a +innerclass innerClass javax/swing/GroupLayout$ParallelGroup outerClass javax/swing/GroupLayout innerClassName ParallelGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$SequentialGroup outerClass javax/swing/GroupLayout innerClassName SequentialGroup flags 11 + +class name javax/swing/GroupLayout$ParallelGroup +header extends javax/swing/GroupLayout$Group nestHost javax/swing/GroupLayout sealed true flags 21 +innerclass innerClass javax/swing/GroupLayout$ParallelGroup outerClass javax/swing/GroupLayout innerClassName ParallelGroup flags 1 +innerclass innerClass javax/swing/GroupLayout$Group outerClass javax/swing/GroupLayout innerClassName Group flags 401 +innerclass innerClass javax/swing/GroupLayout$Alignment outerClass javax/swing/GroupLayout innerClassName Alignment flags 4019 +innerclass innerClass javax/swing/GroupLayout$Spring outerClass javax/swing/GroupLayout innerClassName Spring flags 40a + +class name javax/swing/JList +-method name setLayoutOrientation descriptor (I)V +method name setLayoutOrientation descriptor (I)V flags 1 runtimeAnnotations @Ljava/beans/BeanProperty;(visualUpdate=Ztrue,enumerationValues={"JList.VERTICAL""JList.HORIZONTAL_WRAP""JList.VERTICAL_WRAP"},description="Defines\u005C;u0020;the\u005C;u0020;way\u005C;u0020;list\u005C;u0020;cells\u005C;u0020;are\u005C;u0020;laid\u005C;u0020;out.") + +class name javax/swing/JList$AccessibleJList$AccessibleJListChild +-method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; +method name getAccessibleAction descriptor ()Ljavax/accessibility/AccessibleAction; flags 1 + +class name javax/swing/JTextPane +header extends javax/swing/JEditorPane flags 21 runtimeAnnotations @Ljava/beans/JavaBean;(description="A\u005C;u0020;text\u005C;u0020;component\u005C;u0020;that\u005C;u0020;can\u005C;u0020;be\u005C;u0020;marked\u005C;u0020;up\u005C;u0020;with\u005C;u0020;attributes\u005C;u0020;that\u005C;u0020;are\u005C;u0020;graphically\u005C;u0020;represented.")@Ljavax/swing/SwingContainer; + +class name javax/swing/LookAndFeel +header extends java/lang/Object flags 421 +innerclass innerClass javax/swing/text/JTextComponent$KeyBinding outerClass javax/swing/text/JTextComponent innerClassName KeyBinding flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/MenuSelectionManager +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SizeRequirements +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SortingFocusTraversalPolicy +header extends javax/swing/InternalFrameFocusTraversalPolicy flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/SwingContainer +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;TYPE;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name javax/swing/UIClientPropertyKey +header extends java/lang/Object flags 601 + +class name javax/swing/border/LineBorder +header extends javax/swing/border/AbstractBorder flags 21 +innerclass innerClass java/awt/geom/RoundRectangle2D$Float outerClass java/awt/geom/RoundRectangle2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Rectangle2D$Float outerClass java/awt/geom/Rectangle2D innerClassName Float flags 9 +innerclass innerClass java/awt/geom/Path2D$Float outerClass java/awt/geom/Path2D innerClassName Float flags 9 + +class name javax/swing/event/EventListenerList +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/ListDataEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/ListSelectionEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/event/TreeModelEvent +header extends java/util/EventObject flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/filechooser/FileNameExtensionFilter +header extends javax/swing/filechooser/FileFilter flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicArrowButton +header extends javax/swing/JButton implements javax/swing/SwingConstants flags 21 +innerclass innerClass java/awt/geom/Path2D$Double outerClass java/awt/geom/Path2D innerClassName Double flags 9 + +class name javax/swing/plaf/basic/BasicButtonUI +header extends javax/swing/plaf/ButtonUI flags 21 +innerclass innerClass java/awt/Component$BaselineResizeBehavior outerClass java/awt/Component innerClassName BaselineResizeBehavior flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicPasswordFieldUI +header extends javax/swing/plaf/basic/BasicTextFieldUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicSplitPaneUI$BasicHorizontalLayoutManager +header extends java/lang/Object implements java/awt/LayoutManager2 nestHost javax/swing/plaf/basic/BasicSplitPaneUI sealed true flags 21 +innerclass innerClass javax/swing/plaf/basic/BasicSplitPaneUI$BasicHorizontalLayoutManager outerClass javax/swing/plaf/basic/BasicSplitPaneUI innerClassName BasicHorizontalLayoutManager flags 1 +innerclass innerClass javax/swing/plaf/basic/BasicSplitPaneUI$BasicVerticalLayoutManager outerClass javax/swing/plaf/basic/BasicSplitPaneUI innerClassName BasicVerticalLayoutManager flags 1 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/basic/BasicToolBarSeparatorUI +header extends javax/swing/plaf/basic/BasicSeparatorUI flags 21 +innerclass innerClass javax/swing/JToolBar$Separator outerClass javax/swing/JToolBar innerClassName Separator flags 9 + +class name javax/swing/plaf/metal/MetalButtonUI +header extends javax/swing/plaf/basic/BasicButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalCheckBoxUI +header extends javax/swing/plaf/metal/MetalRadioButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalRadioButtonUI +header extends javax/swing/plaf/basic/BasicRadioButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalToggleButtonUI +header extends javax/swing/plaf/basic/BasicToggleButtonUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/metal/MetalToolTipUI +header extends javax/swing/plaf/basic/BasicToolTipUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/multi/MultiLookAndFeel +header extends javax/swing/LookAndFeel flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthButtonUI +header extends javax/swing/plaf/basic/BasicButtonUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthIcon +header extends java/lang/Object implements javax/swing/Icon flags 601 + +class name javax/swing/plaf/synth/SynthMenuItemUI +header extends javax/swing/plaf/basic/BasicMenuItemUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthMenuUI +header extends javax/swing/plaf/basic/BasicMenuUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/plaf/synth/SynthPasswordFieldUI +header extends javax/swing/plaf/synth/SynthTextFieldUI flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name installDefaults descriptor ()V flags 4 + +class name javax/swing/plaf/synth/SynthSeparatorUI +header extends javax/swing/plaf/SeparatorUI implements java/beans/PropertyChangeListener,javax/swing/plaf/synth/SynthUI flags 21 +innerclass innerClass javax/swing/JToolBar$Separator outerClass javax/swing/JToolBar innerClassName Separator flags 9 + +class name javax/swing/plaf/synth/SynthStyle +header extends java/lang/Object flags 421 +innerclass innerClass javax/swing/UIDefaults$LazyInputMap outerClass javax/swing/UIDefaults innerClassName LazyInputMap flags 9 +innerclass innerClass javax/swing/UIDefaults$LazyValue outerClass javax/swing/UIDefaults innerClassName LazyValue flags 609 + +class name javax/swing/table/AbstractTableModel +header extends java/lang/Object implements javax/swing/table/TableModel,java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/AbstractWriter +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/BoxView +header extends javax/swing/text/CompositeView flags 21 +innerclass innerClass javax/swing/event/DocumentEvent$ElementChange outerClass javax/swing/event/DocumentEvent innerClassName ElementChange flags 609 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/CompositeView +header extends javax/swing/text/View flags 421 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/DateFormatter +header extends javax/swing/text/InternationalFormatter flags 21 +innerclass innerClass java/text/DateFormat$Field outerClass java/text/DateFormat innerClassName Field flags 9 + +class name javax/swing/text/DefaultEditorKit +field name beginLineUpAction descriptor Ljava/lang/String; constantValue caret-begin-line-and-up flags 19 +field name endLineDownAction descriptor Ljava/lang/String; constantValue caret-end-line-and-down flags 19 + +class name javax/swing/text/IconView +header extends javax/swing/text/View flags 21 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/LayoutQueue +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/NumberFormatter +header extends javax/swing/text/InternationalFormatter flags 21 +innerclass innerClass java/text/NumberFormat$Field outerClass java/text/NumberFormat innerClassName Field flags 9 +innerclass innerClass javax/swing/text/DocumentFilter$FilterBypass outerClass javax/swing/text/DocumentFilter innerClassName FilterBypass flags 409 +innerclass innerClass java/text/AttributedCharacterIterator$Attribute outerClass java/text/AttributedCharacterIterator innerClassName Attribute flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/Segment +header extends java/lang/Object implements java/lang/Cloneable,java/text/CharacterIterator,java/lang/CharSequence flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/StyleConstants +header extends java/lang/Object nestMembers javax/swing/text/StyleConstants$FontConstants,javax/swing/text/StyleConstants$ColorConstants,javax/swing/text/StyleConstants$CharacterConstants,javax/swing/text/StyleConstants$ParagraphConstants sealed true flags 21 +innerclass innerClass javax/swing/text/StyleConstants$CharacterConstants outerClass javax/swing/text/StyleConstants innerClassName CharacterConstants flags 19 +innerclass innerClass javax/swing/text/StyleConstants$FontConstants outerClass javax/swing/text/StyleConstants innerClassName FontConstants flags 19 +innerclass innerClass javax/swing/text/StyleConstants$ColorConstants outerClass javax/swing/text/StyleConstants innerClassName ColorConstants flags 19 +innerclass innerClass javax/swing/text/StyleConstants$ParagraphConstants outerClass javax/swing/text/StyleConstants innerClassName ParagraphConstants flags 19 + +class name javax/swing/text/TabSet +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/TabStop +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/View +header extends java/lang/Object implements javax/swing/SwingConstants flags 421 +innerclass innerClass javax/swing/text/Position$Bias outerClass javax/swing/text/Position innerClassName Bias flags 19 +innerclass innerClass javax/swing/event/DocumentEvent$ElementChange outerClass javax/swing/event/DocumentEvent innerClassName ElementChange flags 609 +innerclass innerClass javax/swing/event/DocumentEvent$EventType outerClass javax/swing/event/DocumentEvent innerClassName EventType flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/InlineView +header extends javax/swing/text/LabelView flags 21 +innerclass innerClass javax/swing/text/html/CSS$Attribute outerClass javax/swing/text/html/CSS innerClassName Attribute flags 19 + +class name javax/swing/text/html/ObjectView +header extends javax/swing/text/ComponentView flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/Option +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 + +class name javax/swing/text/html/parser/ContentModel +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/parser/DocumentParser +header extends javax/swing/text/html/parser/Parser flags 21 +innerclass innerClass javax/swing/text/html/HTMLEditorKit$ParserCallback outerClass javax/swing/text/html/HTMLEditorKit innerClassName ParserCallback flags 9 +innerclass innerClass javax/swing/text/html/HTML$Tag outerClass javax/swing/text/html/HTML innerClassName Tag flags 9 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 + +class name javax/swing/text/html/parser/Parser +header extends java/lang/Object implements javax/swing/text/html/parser/DTDConstants flags 21 +innerclass innerClass javax/swing/text/html/HTML$Attribute outerClass javax/swing/text/html/HTML innerClassName Attribute flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/text/html/parser/TagElement +header extends java/lang/Object flags 21 +innerclass innerClass javax/swing/text/html/HTML$Tag outerClass javax/swing/text/html/HTML innerClassName Tag flags 9 +innerclass innerClass javax/swing/text/html/HTML$UnknownTag outerClass javax/swing/text/html/HTML innerClassName UnknownTag flags 9 + +class name javax/swing/tree/DefaultTreeModel +header extends java/lang/Object implements java/io/Serializable,javax/swing/tree/TreeModel flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name javax/swing/tree/DefaultTreeSelectionModel +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable,javax/swing/tree/TreeSelectionModel flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/tree/TreePath +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/AbstractUndoableEdit +header extends java/lang/Object implements javax/swing/undo/UndoableEdit,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/CompoundEdit +header extends javax/swing/undo/AbstractUndoableEdit flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/swing/undo/UndoableEditSupport +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.instrument-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.instrument-K.sym.txt new file mode 100644 index 00000000000..fb591b1e065 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.instrument-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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/lang/instrument/UnmodifiableModuleException +header extends java/lang/RuntimeException flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/java.logging-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.logging-K.sym.txt new file mode 100644 index 00000000000..cbc88ccd16c --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.logging-K.sym.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2022, 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/util/logging/ErrorManager +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/LoggingMXBean +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") + +class name java/util/logging/LoggingPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/MemoryHandler +header extends java/util/logging/Handler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/SimpleFormatter +header extends java/util/logging/Formatter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/SocketHandler +header extends java/util/logging/StreamHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/util/logging/XMLFormatter +header extends java/util/logging/Formatter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt new file mode 100644 index 00000000000..2a5ab70d5c9 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt @@ -0,0 +1,268 @@ +# +# Copyright (c) 2022, 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 java.management +header exports java/lang/management,javax/management,javax/management/loading,javax/management/modelmbean,javax/management/monitor,javax/management/openmbean,javax/management/relation,javax/management/remote,javax/management/timer requires name\u0020;java.base\u0020;flags\u0020;8000 uses javax/management/remote/JMXConnectorProvider,javax/management/remote/JMXConnectorServerProvider,sun/management/spi/PlatformMBeanProvider provides interface\u0020;javax/security/auth/spi/LoginModule\u0020;impls\u0020;com/sun/jmx/remote/security/FileLoginModule target linux-amd64 flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; + +class name java/lang/management/LockInfo +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/ManagementPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/MemoryUsage +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/MonitorInfo +header extends java/lang/management/LockInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/lang/management/RuntimeMXBean +header extends java/lang/Object implements java/lang/management/PlatformManagedObject flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Attribute +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/AttributeList +header extends java/util/ArrayList flags 21 signature Ljava/util/ArrayList; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadAttributeValueExpException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadBinaryOpValueExpException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/BadStringOperationException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/ConstructorParameters +header extends java/lang/Object implements java/lang/annotation/Annotation flags 2601 runtimeAnnotations @Ljava/lang/annotation/Documented;@Ljava/lang/annotation/Target;(value={eLjava/lang/annotation/ElementType;CONSTRUCTOR;})@Ljava/lang/annotation/Retention;(value=eLjava/lang/annotation/RetentionPolicy;RUNTIME;) + +class name javax/management/ImmutableDescriptor +header extends java/lang/Object implements javax/management/Descriptor flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanAttributeInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanConstructorInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanNotificationInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanOperationInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanParameterInfo +header extends javax/management/MBeanFeatureInfo implements java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanPermission +header extends java/security/Permission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerDelegate +header extends java/lang/Object implements javax/management/MBeanServerDelegateMBean,javax/management/NotificationEmitter flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerInvocationHandler +header extends java/lang/Object implements java/lang/reflect/InvocationHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerNotification +header extends javax/management/Notification flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanServerPermission +header extends java/security/BasicPermission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/MBeanTrustPermission +header extends java/security/BasicPermission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Notification +header extends java/util/EventObject flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/ObjectInstance +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/Query +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/StandardEmitterMBean +header extends javax/management/StandardMBean implements javax/management/NotificationEmitter flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/StringValueExp +header extends java/lang/Object implements javax/management/ValueExp flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/loading/DefaultLoaderRepository +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 + +class name javax/management/loading/MLetContent +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/modelmbean/InvalidTargetObjectTypeException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/modelmbean/XMLParseException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/ArrayType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeDataInvocationHandler +header extends java/lang/Object implements java/lang/reflect/InvocationHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeDataSupport +header extends java/lang/Object implements javax/management/openmbean/CompositeData,java/io/Serializable flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/CompositeType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/OpenMBeanAttributeInfoSupport +header extends javax/management/MBeanAttributeInfo implements javax/management/openmbean/OpenMBeanAttributeInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/OpenMBeanOperationInfoSupport +header extends javax/management/MBeanOperationInfo implements javax/management/openmbean/OpenMBeanOperationInfo flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/SimpleType +header extends javax/management/openmbean/OpenType flags 31 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/TabularDataSupport +header extends java/lang/Object implements javax/management/openmbean/TabularData,java/util/Map,java/lang/Cloneable,java/io/Serializable flags 21 signature Ljava/lang/Object;Ljavax/management/openmbean/TabularData;Ljava/util/Map;Ljava/lang/Cloneable;Ljava/io/Serializable; +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/openmbean/TabularType +header extends javax/management/openmbean/OpenType flags 21 signature Ljavax/management/openmbean/OpenType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RelationNotification +header extends javax/management/Notification flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/management/relation/RelationSupport +header extends java/lang/Object implements javax/management/relation/RelationSupportMBean,javax/management/MBeanRegistration flags 21 +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 + +class name javax/management/relation/Role +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RoleInfo +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/relation/RoleResult +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/management/relation/RoleUnresolved +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXConnectorServerFactory +header extends java/lang/Object flags 21 +innerclass innerClass java/util/ServiceLoader$Provider outerClass java/util/ServiceLoader innerClassName Provider flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/JMXServiceURL +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/NotificationResult +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/TargetedNotification +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.management.rmi-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.management.rmi-K.sym.txt new file mode 100644 index 00000000000..46b3d3b6adb --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.management.rmi-K.sym.txt @@ -0,0 +1,39 @@ +# +# Copyright (c) 2022, 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 javax/management/remote/rmi/RMIConnectorServer +header extends javax/management/remote/JMXConnectorServer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/management/remote/rmi/RMIIIOPServerImpl +header extends javax/management/remote/rmi/RMIServerImpl flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name javax/management/remote/rmi/RMIServerImpl +header extends java/lang/Object implements java/io/Closeable,javax/management/remote/rmi/RMIServer flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.naming-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.naming-K.sym.txt new file mode 100644 index 00000000000..335632cea87 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.naming-K.sym.txt @@ -0,0 +1,85 @@ +# +# Copyright (c) 2022, 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 javax/naming/BinaryRefAddr +header extends javax/naming/RefAddr flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/Binding +header extends javax/naming/NameClassPair flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/CompositeName +header extends java/lang/Object implements javax/naming/Name flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/CompoundName +header extends java/lang/Object implements javax/naming/Name flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/LinkException +header extends javax/naming/NamingException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/NameClassPair +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/NamingException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/RefAddr +header extends java/lang/Object implements java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/Reference +header extends java/lang/Object implements java/lang/Cloneable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/AttributeModificationException +header extends javax/naming/NamingException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/ModificationItem +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/directory/SearchResult +header extends javax/naming/Binding flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/spi/DirectoryManager +header extends javax/naming/spi/NamingManager flags 21 +innerclass innerClass javax/naming/spi/DirStateFactory$Result outerClass javax/naming/spi/DirStateFactory innerClassName Result flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/naming/spi/NamingManager +-method name setObjectFactoryBuilder descriptor (Ljavax/naming/spi/ObjectFactoryBuilder;)V +method name setObjectFactoryBuilder descriptor (Ljavax/naming/spi/ObjectFactoryBuilder;)V thrownTypes javax/naming/NamingException flags 9 + diff --git a/src/jdk.compiler/share/data/symbols/java.rmi-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.rmi-K.sym.txt new file mode 100644 index 00000000000..20c9c678109 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.rmi-K.sym.txt @@ -0,0 +1,52 @@ +# +# Copyright (c) 2022, 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/rmi/RemoteException +header extends java/io/IOException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/dgc/VMID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/ObjID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/RemoteObject +header extends java/lang/Object implements java/rmi/Remote,java/io/Serializable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/ServerCloneException +header extends java/lang/CloneNotSupportedException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/rmi/server/UID +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.scripting-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.scripting-K.sym.txt new file mode 100644 index 00000000000..93890844c99 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.scripting-K.sym.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2022, 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 javax/script/ScriptException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.security.jgss-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.jgss-K.sym.txt new file mode 100644 index 00000000000..d200d5018b3 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.security.jgss-K.sym.txt @@ -0,0 +1,69 @@ +# +# Copyright (c) 2022, 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 javax/security/auth/kerberos/DelegationPermission +header extends java/security/BasicPermission implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/EncryptionKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosCredMessage +header extends java/lang/Object implements javax/security/auth/Destroyable flags 31 +innerclass innerClass java/util/Base64$Encoder outerClass java/util/Base64 innerClassName Encoder flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosKey +header extends java/lang/Object implements javax/crypto/SecretKey flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KerberosTicket +header extends java/lang/Object implements javax/security/auth/Destroyable,javax/security/auth/Refreshable,java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/KeyTab +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/security/auth/kerberos/ServicePermission +header extends java/security/Permission implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/ietf/jgss/GSSException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/ietf/jgss/Oid +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.security.sasl-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.security.sasl-K.sym.txt new file mode 100644 index 00000000000..b89a95b8822 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.security.sasl-K.sym.txt @@ -0,0 +1,32 @@ +# +# Copyright (c) 2022, 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 javax/security/sasl/SaslException +header extends java/io/IOException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.smartcardio-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.smartcardio-K.sym.txt new file mode 100644 index 00000000000..a6ae9dbaf51 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.smartcardio-K.sym.txt @@ -0,0 +1,62 @@ +# +# Copyright (c) 2022, 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 javax/smartcardio/ATR +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/Card +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CardChannel +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CardException +header extends java/lang/Exception flags 21 + +class name javax/smartcardio/CardNotPresentException +header extends javax/smartcardio/CardException flags 21 + +class name javax/smartcardio/CardPermission +header extends java/security/Permission flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/CardTerminal +header extends java/lang/Object flags 421 + +class name javax/smartcardio/CommandAPDU +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/ResponseAPDU +header extends java/lang/Object implements java/io/Serializable flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/smartcardio/TerminalFactorySpi +header extends java/lang/Object flags 421 + diff --git a/src/jdk.compiler/share/data/symbols/java.sql-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql-K.sym.txt new file mode 100644 index 00000000000..445e6be3d10 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.sql-K.sym.txt @@ -0,0 +1,60 @@ +# +# Copyright (c) 2022, 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/BatchUpdateException +header extends java/sql/SQLException flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name java/sql/ConnectionBuilder +header extends java/lang/Object flags 601 + +class name java/sql/JDBCType +header extends java/lang/Enum implements java/sql/SQLType flags 4031 signature Ljava/lang/Enum;Ljava/sql/SQLType; +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/sql/SQLWarning +header extends java/sql/SQLException flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name java/sql/ShardingKey +header extends java/lang/Object flags 601 + +class name java/sql/ShardingKeyBuilder +header extends java/lang/Object flags 601 + +class name java/sql/Statement +header extends java/lang/Object implements java/sql/Wrapper,java/lang/AutoCloseable flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/PooledConnectionBuilder +header extends java/lang/Object flags 601 + +class name javax/sql/XAConnectionBuilder +header extends java/lang/Object flags 601 + diff --git a/src/jdk.compiler/share/data/symbols/java.sql.rowset-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.sql.rowset-K.sym.txt new file mode 100644 index 00000000000..11a7e503a8c --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.sql.rowset-K.sym.txt @@ -0,0 +1,73 @@ +# +# Copyright (c) 2022, 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 javax/sql/rowset/BaseRowSet +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SQLOutputImpl +header extends java/lang/Object implements java/sql/SQLOutput flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialArray +header extends java/lang/Object implements java/sql/Array,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialBlob +header extends java/lang/Object implements java/sql/Blob,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialClob +header extends java/lang/Object implements java/sql/Clob,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialDatalink +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialJavaObject +header extends java/lang/Object implements java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 + +class name javax/sql/rowset/serial/SerialRef +header extends java/lang/Object implements java/sql/Ref,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/sql/rowset/serial/SerialStruct +header extends java/lang/Object implements java/sql/Struct,java/io/Serializable,java/lang/Cloneable flags 21 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.xml-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml-K.sym.txt new file mode 100644 index 00000000000..9af87b0ca2a --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.xml-K.sym.txt @@ -0,0 +1,150 @@ +# +# Copyright (c) 2022, 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 javax/xml/catalog/Catalog +header extends java/lang/Object flags 601 + +class name javax/xml/catalog/CatalogException +header extends java/lang/RuntimeException flags 21 + +class name javax/xml/catalog/CatalogManager +header extends java/lang/Object flags 31 + +class name javax/xml/catalog/CatalogResolver +header extends java/lang/Object implements org/xml/sax/EntityResolver,javax/xml/stream/XMLResolver,javax/xml/transform/URIResolver,org/w3c/dom/ls/LSResourceResolver flags 601 + +class name javax/xml/datatype/DatatypeFactory +header extends java/lang/Object flags 421 +innerclass innerClass javax/xml/datatype/DatatypeConstants$Field outerClass javax/xml/datatype/DatatypeConstants innerClassName Field flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/datatype/Duration +header extends java/lang/Object flags 421 +innerclass innerClass javax/xml/datatype/DatatypeConstants$Field outerClass javax/xml/datatype/DatatypeConstants innerClassName Field flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/namespace/QName +header extends java/lang/Object implements java/io/Serializable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/DocumentBuilder +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/DocumentBuilderFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/SAXParser +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/parsers/SAXParserFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/stream/XMLEventReader +header extends java/lang/Object implements java/util/Iterator flags 601 signature Ljava/lang/Object;Ljava/util/Iterator; + +class name javax/xml/stream/XMLInputFactory +-method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; +method name newFactory descriptor ()Ljavax/xml/stream/XMLInputFactory; thrownTypes javax/xml/stream/FactoryConfigurationError flags 9 + +class name javax/xml/stream/XMLStreamException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/transform/Transformer +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/transform/TransformerException +header extends java/lang/Exception flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/validation/SchemaFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/xpath/XPath +header extends java/lang/Object flags 601 +innerclass innerClass javax/xml/xpath/XPathEvaluationResult$XPathResultType outerClass javax/xml/xpath/XPathEvaluationResult innerClassName XPathResultType flags 4019 + +class name javax/xml/xpath/XPathException +header extends java/lang/Exception flags 21 +innerclass innerClass java/io/ObjectOutputStream$PutField outerClass java/io/ObjectOutputStream innerClassName PutField flags 409 +innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 + +class name javax/xml/xpath/XPathExpression +header extends java/lang/Object flags 601 +innerclass innerClass javax/xml/xpath/XPathEvaluationResult$XPathResultType outerClass javax/xml/xpath/XPathEvaluationResult innerClassName XPathResultType flags 4019 + +class name javax/xml/xpath/XPathFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/xpath/XPathNodes +header extends java/lang/Object implements java/lang/Iterable flags 601 signature Ljava/lang/Object;Ljava/lang/Iterable; + +class name org/w3c/dom/ElementTraversal +header extends java/lang/Object flags 601 + +class name org/xml/sax/AttributeList +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/DocumentHandler +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/HandlerBase +header extends java/lang/Object implements org/xml/sax/EntityResolver,org/xml/sax/DTDHandler,org/xml/sax/DocumentHandler,org/xml/sax/ErrorHandler flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/Parser +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/ext/Attributes2Impl +header extends org/xml/sax/helpers/AttributesImpl implements org/xml/sax/ext/Attributes2 flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/AttributeListImpl +header extends java/lang/Object implements org/xml/sax/AttributeList flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/AttributesImpl +header extends java/lang/Object implements org/xml/sax/Attributes flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/ParserFactory +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="1.5") + +class name org/xml/sax/helpers/XMLFilterImpl +header extends java/lang/Object implements org/xml/sax/XMLFilter,org/xml/sax/EntityResolver,org/xml/sax/DTDHandler,org/xml/sax/ContentHandler,org/xml/sax/ErrorHandler flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name org/xml/sax/helpers/XMLReaderFactory +header extends java/lang/Object flags 31 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(since="9") +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/java.xml.crypto-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.xml.crypto-K.sym.txt new file mode 100644 index 00000000000..af622ef859b --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/java.xml.crypto-K.sym.txt @@ -0,0 +1,46 @@ +# +# Copyright (c) 2022, 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 javax/xml/crypto/NodeSetData +header extends java/lang/Object implements javax/xml/crypto/Data,java/lang/Iterable flags 601 signature Ljava/lang/Object;Ljavax/xml/crypto/Data;Ljava/lang/Iterable; + +class name javax/xml/crypto/dom/DOMCryptoContext +header extends java/lang/Object implements javax/xml/crypto/XMLCryptoContext flags 21 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/crypto/dsig/XMLSignatureFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name javax/xml/crypto/dsig/keyinfo/KeyInfoFactory +header extends java/lang/Object flags 421 +innerclass innerClass java/security/Provider$Service outerClass java/security/Provider innerClassName Service flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.accessibility-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.accessibility-K.sym.txt new file mode 100644 index 00000000000..542df1b1734 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.accessibility-K.sym.txt @@ -0,0 +1,44 @@ +# +# Copyright (c) 2022, 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 com/sun/java/accessibility/util/AccessibilityListenerList +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/java/accessibility/util/EventID +header extends java/lang/Object flags 21 + +class name com/sun/java/accessibility/util/GUIInitializedListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name com/sun/java/accessibility/util/TopLevelWindowListener +header extends java/lang/Object implements java/util/EventListener flags 601 + +class name com/sun/java/accessibility/util/Translator +header extends javax/accessibility/AccessibleContext implements javax/accessibility/Accessible,javax/accessibility/AccessibleComponent flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.attach-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.attach-K.sym.txt new file mode 100644 index 00000000000..e27029fddda --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.attach-K.sym.txt @@ -0,0 +1,55 @@ +# +# Copyright (c) 2022, 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 com/sun/tools/attach/AgentInitializationException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AgentLoadException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AttachNotSupportedException +header extends java/lang/Exception flags 21 + +class name com/sun/tools/attach/AttachOperationFailedException +header extends java/io/IOException flags 21 + +class name com/sun/tools/attach/AttachPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/VirtualMachine +header extends java/lang/Object flags 421 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/VirtualMachineDescriptor +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/tools/attach/spi/AttachProvider +header extends java/lang/Object flags 421 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt new file mode 100644 index 00000000000..e204d40b674 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt @@ -0,0 +1,381 @@ +# +# Copyright (c) 2022, 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 com/sun/source/doctree/AuthorTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/BlockTagTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/CommentTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/DeprecatedTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/DocCommentTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/DocRootTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/DocTree$Kind +field name SPEC descriptor Lcom/sun/source/doctree/DocTree$Kind; flags 4019 + +class name com/sun/source/doctree/DocTreeVisitor +header extends java/lang/Object flags 601 signature Ljava/lang/Object; +method name visitSpec descriptor (Lcom/sun/source/doctree/SpecTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SpecTree;TP;)TR; + +class name com/sun/source/doctree/DocTypeTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/EndElementTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/EntityTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/ErroneousTree +header extends java/lang/Object implements com/sun/source/doctree/TextTree flags 601 + +class name com/sun/source/doctree/HiddenTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/IdentifierTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/IndexTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/InheritDocTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/InlineTagTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/LinkTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/LiteralTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/ParamTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ProvidesTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ReferenceTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/SeeTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialDataTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialFieldTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SerialTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SinceTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/SpecTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 +method name getURL descriptor ()Lcom/sun/source/doctree/TextTree; flags 401 +method name getTitle descriptor ()Ljava/util/List; flags 401 signature ()Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>; + +class name com/sun/source/doctree/StartElementTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/SummaryTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/TextTree +header extends java/lang/Object implements com/sun/source/doctree/DocTree flags 601 + +class name com/sun/source/doctree/ThrowsTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/UnknownBlockTagTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/UnknownInlineTagTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 + +class name com/sun/source/doctree/UsesTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/doctree/ValueTree +header extends java/lang/Object implements com/sun/source/doctree/InlineTagTree flags 601 +method name getFormat descriptor ()Lcom/sun/source/doctree/TextTree; flags 1 + +class name com/sun/source/doctree/VersionTree +header extends java/lang/Object implements com/sun/source/doctree/BlockTagTree flags 601 + +class name com/sun/source/tree/AnnotatedTypeTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/AnnotationTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ArrayAccessTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ArrayTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/AssertTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/AssignmentTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/BinaryTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/BlockTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/BreakTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/CatchTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ClassTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/CompilationUnitTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/CompoundAssignmentTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ConditionalExpressionTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ContinueTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/DirectiveTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/DoWhileLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/EmptyStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/EnhancedForLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ErroneousTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/ExportsTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/ExpressionStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ExpressionTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ForLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/IdentifierTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/IfTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ImportTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/InstanceOfTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/IntersectionTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/LabeledStatementTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/LineMap +header extends java/lang/Object flags 601 + +class name com/sun/source/tree/LiteralTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MemberSelectTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MethodInvocationTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/MethodTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ModifiersTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/NewArrayTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/NewClassTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/OpensTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/PackageTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ParameterizedTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ParenthesizedTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/PatternTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/PrimitiveTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/ProvidesTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/RequiresTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/ReturnTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/Scope +header extends java/lang/Object flags 601 + +class name com/sun/source/tree/StatementTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/SwitchTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/SynchronizedTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/ThrowTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/TreeVisitor +header extends java/lang/Object flags 601 signature Ljava/lang/Object; + +class name com/sun/source/tree/TryTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/TypeCastTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/TypeParameterTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/UnaryTree +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 + +class name com/sun/source/tree/UnionTypeTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/tree/UsesTree +header extends java/lang/Object implements com/sun/source/tree/DirectiveTree flags 601 + +class name com/sun/source/tree/VariableTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/WhileLoopTree +header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 + +class name com/sun/source/tree/WildcardTree +header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 + +class name com/sun/source/util/DocSourcePositions +header extends java/lang/Object implements com/sun/source/util/SourcePositions flags 601 + +class name com/sun/source/util/DocTreeFactory +header extends java/lang/Object flags 601 +innerclass innerClass com/sun/source/doctree/AttributeTree$ValueKind outerClass com/sun/source/doctree/AttributeTree innerClassName ValueKind flags 4019 +method name newSpecTree descriptor (Lcom/sun/source/doctree/TextTree;Ljava/util/List;)Lcom/sun/source/doctree/SpecTree; flags 401 signature (Lcom/sun/source/doctree/TextTree;Ljava/util/List<+Lcom/sun/source/doctree/DocTree;>;)Lcom/sun/source/doctree/SpecTree; +method name newValueTree descriptor (Lcom/sun/source/doctree/TextTree;Lcom/sun/source/doctree/ReferenceTree;)Lcom/sun/source/doctree/ValueTree; flags 1 + +class name com/sun/source/util/DocTreePathScanner +header extends com/sun/source/util/DocTreeScanner flags 21 signature Lcom/sun/source/util/DocTreeScanner; + +class name com/sun/source/util/DocTreeScanner +header extends java/lang/Object implements com/sun/source/doctree/DocTreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/doctree/DocTreeVisitor; +method name visitSpec descriptor (Lcom/sun/source/doctree/SpecTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SpecTree;TP;)TR; + +class name com/sun/source/util/DocTrees +header extends com/sun/source/util/Trees flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 + +class name com/sun/source/util/JavacTask +header extends java/lang/Object implements javax/tools/JavaCompiler$CompilationTask flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 + +class name com/sun/source/util/Plugin +header extends java/lang/Object flags 601 + +class name com/sun/source/util/SimpleDocTreeVisitor +header extends java/lang/Object implements com/sun/source/doctree/DocTreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/doctree/DocTreeVisitor; +method name visitSpec descriptor (Lcom/sun/source/doctree/SpecTree;Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (Lcom/sun/source/doctree/SpecTree;TP;)TR; + +class name com/sun/source/util/SimpleTreeVisitor +header extends java/lang/Object implements com/sun/source/tree/TreeVisitor flags 21 signature Ljava/lang/Object;Lcom/sun/source/tree/TreeVisitor; + +class name com/sun/source/util/SourcePositions +header extends java/lang/Object flags 601 + +class name com/sun/source/util/TaskListener +header extends java/lang/Object flags 601 + +class name com/sun/source/util/TreePathScanner +header extends com/sun/source/util/TreeScanner flags 21 signature Lcom/sun/source/util/TreeScanner; + +class name com/sun/source/util/Trees +header extends java/lang/Object flags 421 +innerclass innerClass javax/tools/JavaCompiler$CompilationTask outerClass javax/tools/JavaCompiler innerClassName CompilationTask flags 609 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 + +class name com/sun/tools/javac/Main +header extends java/lang/Object flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.dynalink-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.dynalink-K.sym.txt new file mode 100644 index 00000000000..d881760d53a --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.dynalink-K.sym.txt @@ -0,0 +1,136 @@ +# +# Copyright (c) 2022, 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/dynalink/CallSiteDescriptor +header extends jdk/dynalink/SecureLookupSupplier flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/DynamicLinker +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/StackWalker$StackFrame outerClass java/lang/StackWalker innerClassName StackFrame flags 609 +innerclass innerClass java/lang/StackWalker$Option outerClass java/lang/StackWalker innerClassName Option flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/NamedOperation +header extends java/lang/Object implements jdk/dynalink/Operation flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/Namespace +header extends java/lang/Object flags 601 + +class name jdk/dynalink/NamespaceOperation +header extends java/lang/Object implements jdk/dynalink/Operation flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/NoSuchDynamicMethodException +header extends java/lang/RuntimeException flags 21 + +class name jdk/dynalink/Operation +header extends java/lang/Object flags 601 + +class name jdk/dynalink/RelinkableCallSite +header extends java/lang/Object flags 601 + +class name jdk/dynalink/SecureLookupSupplier +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/StandardNamespace +header extends java/lang/Enum implements jdk/dynalink/Namespace flags 4031 signature Ljava/lang/Enum;Ljdk/dynalink/Namespace; + +class name jdk/dynalink/StandardOperation +header extends java/lang/Enum implements jdk/dynalink/Operation flags 4031 signature Ljava/lang/Enum;Ljdk/dynalink/Operation; + +class name jdk/dynalink/beans/MissingMemberHandlerFactory +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/GuardedInvocation +header extends java/lang/Object flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/GuardedInvocationTransformer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/GuardingDynamicLinker +header extends java/lang/Object flags 601 + +class name jdk/dynalink/linker/GuardingDynamicLinkerExporter +header extends java/lang/Object implements java/util/function/Supplier flags 421 signature Ljava/lang/Object;Ljava/util/function/Supplier;>; + +class name jdk/dynalink/linker/GuardingTypeConverterFactory +header extends java/lang/Object flags 601 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/LinkRequest +header extends java/lang/Object flags 601 + +class name jdk/dynalink/linker/LinkerServices +header extends java/lang/Object flags 601 +innerclass innerClass jdk/dynalink/linker/ConversionComparator$Comparison outerClass jdk/dynalink/linker/ConversionComparator innerClassName Comparison flags 4019 + +class name jdk/dynalink/linker/MethodHandleTransformer +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/MethodTypeConversionStrategy +header extends java/lang/Object flags 601 runtimeAnnotations @Ljava/lang/FunctionalInterface; + +class name jdk/dynalink/linker/TypeBasedGuardingDynamicLinker +header extends java/lang/Object implements jdk/dynalink/linker/GuardingDynamicLinker flags 601 + +class name jdk/dynalink/linker/support/CompositeGuardingDynamicLinker +header extends java/lang/Object implements jdk/dynalink/linker/GuardingDynamicLinker flags 21 + +class name jdk/dynalink/linker/support/DefaultInternalObjectFilter +header extends java/lang/Object implements jdk/dynalink/linker/MethodHandleTransformer flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/Guards +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/Lookup +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/linker/support/SimpleLinkRequest +header extends java/lang/Object implements jdk/dynalink/linker/LinkRequest flags 21 + +class name jdk/dynalink/linker/support/TypeUtilities +header extends java/lang/Object flags 31 +innerclass innerClass java/util/Map$Entry outerClass java/util/Map innerClassName Entry flags 609 + +class name jdk/dynalink/support/AbstractRelinkableCallSite +header extends java/lang/invoke/MutableCallSite implements jdk/dynalink/RelinkableCallSite flags 421 + +class name jdk/dynalink/support/ChainedCallSite +header extends jdk/dynalink/support/AbstractRelinkableCallSite flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/dynalink/support/SimpleRelinkableCallSite +header extends jdk/dynalink/support/AbstractRelinkableCallSite flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.httpserver-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.httpserver-K.sym.txt new file mode 100644 index 00000000000..f0e62cb28d6 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.httpserver-K.sym.txt @@ -0,0 +1,47 @@ +# +# Copyright (c) 2022, 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 com/sun/net/httpserver/HttpContext +header extends java/lang/Object flags 421 + +class name com/sun/net/httpserver/HttpHandler +header extends java/lang/Object flags 601 + +class name com/sun/net/httpserver/HttpPrincipal +header extends java/lang/Object implements java/security/Principal flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/net/httpserver/HttpsConfigurator +header extends java/lang/Object flags 21 + +class name com/sun/net/httpserver/HttpsExchange +header extends com/sun/net/httpserver/HttpExchange flags 421 + +class name com/sun/net/httpserver/HttpsParameters +header extends java/lang/Object flags 421 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt new file mode 100644 index 00000000000..16090b97cc9 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt @@ -0,0 +1,57 @@ +# +# Copyright (c) 2022, 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.incubator.concurrent +header exports jdk/incubator/concurrent requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 resolution 9 flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; + +class name jdk/incubator/concurrent/StructuredTaskScope +header extends java/lang/Object implements java/lang/AutoCloseable nestMembers jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnFailure,jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnSuccess flags 21 signature Ljava/lang/Object;Ljava/lang/AutoCloseable; +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfVirtual outerClass java/lang/Thread$Builder innerClassName OfVirtual flags 609 +innerclass innerClass java/util/concurrent/ConcurrentHashMap$KeySetView outerClass java/util/concurrent/ConcurrentHashMap innerClassName KeySetView flags 19 +innerclass innerClass java/util/concurrent/Future$State outerClass java/util/concurrent/Future innerClassName State flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +innerclass innerClass jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnFailure outerClass jdk/incubator/concurrent/StructuredTaskScope innerClassName ShutdownOnFailure flags 19 +innerclass innerClass jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnSuccess outerClass jdk/incubator/concurrent/StructuredTaskScope innerClassName ShutdownOnSuccess flags 19 + +class name jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnFailure +header extends jdk/incubator/concurrent/StructuredTaskScope nestHost jdk/incubator/concurrent/StructuredTaskScope flags 31 signature Ljdk/incubator/concurrent/StructuredTaskScope; +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfVirtual outerClass java/lang/Thread$Builder innerClassName OfVirtual flags 609 +innerclass innerClass java/util/concurrent/Future$State outerClass java/util/concurrent/Future innerClassName State flags 4019 +innerclass innerClass jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnFailure outerClass jdk/incubator/concurrent/StructuredTaskScope innerClassName ShutdownOnFailure flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnSuccess +header extends jdk/incubator/concurrent/StructuredTaskScope nestHost jdk/incubator/concurrent/StructuredTaskScope flags 31 signature Ljdk/incubator/concurrent/StructuredTaskScope; +innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 +innerclass innerClass java/lang/Thread$Builder$OfVirtual outerClass java/lang/Thread$Builder innerClassName OfVirtual flags 609 +innerclass innerClass java/util/concurrent/Future$State outerClass java/util/concurrent/Future innerClassName State flags 4019 +innerclass innerClass jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnSuccess outerClass jdk/incubator/concurrent/StructuredTaskScope innerClassName ShutdownOnSuccess flags 19 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt new file mode 100644 index 00000000000..4eb5322874d --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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.incubator.vector +header exports jdk/incubator/vector requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 resolution 9 flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jartool-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jartool-K.sym.txt new file mode 100644 index 00000000000..4ae64921cf6 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jartool-K.sym.txt @@ -0,0 +1,34 @@ +# +# Copyright (c) 2022, 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.jartool +header exports com/sun/jarsigner,jdk/security/jarsigner requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.opt\u0020;flags\u0020;0 provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;sun/tools/jar/JarToolProvider target linux-amd64 flags 8000 + +class name jdk/security/jarsigner/JarSignerException +header extends java/lang/RuntimeException flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.javadoc-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.javadoc-K.sym.txt new file mode 100644 index 00000000000..8fdfd448540 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.javadoc-K.sym.txt @@ -0,0 +1,36 @@ +# +# Copyright (c) 2022, 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/javadoc/doclet/Reporter +header extends java/lang/Object flags 601 +innerclass innerClass javax/tools/Diagnostic$Kind outerClass javax/tools/Diagnostic innerClassName Kind flags 4019 + +class name jdk/javadoc/doclet/StandardDoclet +header extends java/lang/Object implements jdk/javadoc/doclet/Doclet flags 21 +innerclass innerClass jdk/javadoc/doclet/Doclet$Option outerClass jdk/javadoc/doclet/Doclet innerClassName Option flags 609 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jconsole-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jconsole-K.sym.txt new file mode 100644 index 00000000000..3bb0dfa82c5 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jconsole-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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 com/sun/tools/jconsole/JConsolePlugin +header extends java/lang/Object flags 421 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jdi-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jdi-K.sym.txt new file mode 100644 index 00000000000..0f1be41e51d --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jdi-K.sym.txt @@ -0,0 +1,395 @@ +# +# Copyright (c) 2022, 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 com/sun/jdi/AbsentInformationException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/Accessible +header extends java/lang/Object flags 601 + +class name com/sun/jdi/ArrayReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ArrayType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/BooleanType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/BooleanValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue flags 601 + +class name com/sun/jdi/Bootstrap +header extends java/lang/Object flags 21 + +class name com/sun/jdi/ByteType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/ByteValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/CharType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/CharValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/ClassLoaderReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ClassNotLoadedException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/ClassNotPreparedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/ClassObjectReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ClassType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/DoubleType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/DoubleValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/Field +header extends java/lang/Object implements com/sun/jdi/TypeComponent,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/TypeComponent;Ljava/lang/Comparable; + +class name com/sun/jdi/FloatType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/FloatValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/IncompatibleThreadStateException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/InconsistentDebugInfoException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/IntegerType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/IntegerValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/InterfaceType +header extends java/lang/Object implements com/sun/jdi/ReferenceType flags 601 + +class name com/sun/jdi/InternalException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidCodeIndexException +header extends java/lang/RuntimeException flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name com/sun/jdi/InvalidLineNumberException +header extends java/lang/RuntimeException flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated; + +class name com/sun/jdi/InvalidModuleException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidStackFrameException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/InvalidTypeException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/InvocationException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/JDIPermission +header extends java/security/BasicPermission flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/jdi/LocalVariable +header extends java/lang/Object implements com/sun/jdi/Mirror,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/lang/Comparable; + +class name com/sun/jdi/Locatable +header extends java/lang/Object flags 601 + +class name com/sun/jdi/Location +header extends java/lang/Object implements com/sun/jdi/Mirror,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/lang/Comparable; + +class name com/sun/jdi/LongType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/LongValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/Method +header extends java/lang/Object implements com/sun/jdi/TypeComponent,com/sun/jdi/Locatable,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/TypeComponent;Lcom/sun/jdi/Locatable;Ljava/lang/Comparable; + +class name com/sun/jdi/Mirror +header extends java/lang/Object flags 601 + +class name com/sun/jdi/ModuleReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/MonitorInfo +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/ObjectCollectedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/ObjectReference +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/OpaqueFrameException +header extends java/lang/RuntimeException sealed true flags 21 + +class name com/sun/jdi/PathSearchingVirtualMachine +header extends java/lang/Object implements com/sun/jdi/VirtualMachine flags 601 + +class name com/sun/jdi/PrimitiveType +header extends java/lang/Object implements com/sun/jdi/Type flags 601 + +class name com/sun/jdi/PrimitiveValue +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/ReferenceType +header extends java/lang/Object implements com/sun/jdi/Type,java/lang/Comparable,com/sun/jdi/Accessible flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Type;Ljava/lang/Comparable;Lcom/sun/jdi/Accessible; + +class name com/sun/jdi/ShortType +header extends java/lang/Object implements com/sun/jdi/PrimitiveType flags 601 + +class name com/sun/jdi/ShortValue +header extends java/lang/Object implements com/sun/jdi/PrimitiveValue,java/lang/Comparable flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/PrimitiveValue;Ljava/lang/Comparable; + +class name com/sun/jdi/StackFrame +header extends java/lang/Object implements com/sun/jdi/Mirror,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/StringReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ThreadGroupReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/ThreadReference +header extends java/lang/Object implements com/sun/jdi/ObjectReference flags 601 + +class name com/sun/jdi/Type +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/TypeComponent +header extends java/lang/Object implements com/sun/jdi/Mirror,com/sun/jdi/Accessible flags 601 + +class name com/sun/jdi/VMCannotBeModifiedException +header extends java/lang/UnsupportedOperationException flags 21 + +class name com/sun/jdi/VMDisconnectedException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/VMMismatchException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/VMOutOfMemoryException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/Value +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/VirtualMachine +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/VirtualMachineManager +header extends java/lang/Object flags 601 + +class name com/sun/jdi/VoidType +header extends java/lang/Object implements com/sun/jdi/Type flags 601 + +class name com/sun/jdi/VoidValue +header extends java/lang/Object implements com/sun/jdi/Value flags 601 + +class name com/sun/jdi/connect/AttachingConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/IllegalConnectorArgumentsException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/connect/LaunchingConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/ListeningConnector +header extends java/lang/Object implements com/sun/jdi/connect/Connector flags 601 +innerclass innerClass com/sun/jdi/connect/Connector$Argument outerClass com/sun/jdi/connect/Connector innerClassName Argument flags 609 + +class name com/sun/jdi/connect/Transport +header extends java/lang/Object flags 601 + +class name com/sun/jdi/connect/TransportTimeoutException +header extends java/io/IOException flags 21 + +class name com/sun/jdi/connect/VMStartException +header extends java/lang/Exception flags 21 + +class name com/sun/jdi/connect/spi/ClosedConnectionException +header extends java/io/IOException flags 21 + +class name com/sun/jdi/connect/spi/Connection +header extends java/lang/Object flags 421 + +class name com/sun/jdi/event/AccessWatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/WatchpointEvent flags 601 + +class name com/sun/jdi/event/BreakpointEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ClassPrepareEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/ClassUnloadEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/Event +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/event/EventIterator +header extends java/lang/Object implements java/util/Iterator flags 601 signature Ljava/lang/Object;Ljava/util/Iterator; + +class name com/sun/jdi/event/EventQueue +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/event/EventSet +header extends java/lang/Object implements com/sun/jdi/Mirror,java/util/Set flags 601 signature Ljava/lang/Object;Lcom/sun/jdi/Mirror;Ljava/util/Set; + +class name com/sun/jdi/event/ExceptionEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/LocatableEvent +header extends java/lang/Object implements com/sun/jdi/event/Event,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/event/MethodEntryEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MethodExitEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ModificationWatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/WatchpointEvent flags 601 + +class name com/sun/jdi/event/MonitorContendedEnterEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorContendedEnteredEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorWaitEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/MonitorWaitedEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/StepEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/event/ThreadDeathEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/ThreadStartEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMDeathEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMDisconnectEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/VMStartEvent +header extends java/lang/Object implements com/sun/jdi/event/Event flags 601 + +class name com/sun/jdi/event/WatchpointEvent +header extends java/lang/Object implements com/sun/jdi/event/LocatableEvent flags 601 + +class name com/sun/jdi/request/AccessWatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/WatchpointRequest flags 601 + +class name com/sun/jdi/request/BreakpointRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest,com/sun/jdi/Locatable flags 601 + +class name com/sun/jdi/request/ClassPrepareRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ClassUnloadRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/DuplicateRequestException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/request/EventRequest +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/request/EventRequestManager +header extends java/lang/Object implements com/sun/jdi/Mirror flags 601 + +class name com/sun/jdi/request/ExceptionRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/InvalidRequestStateException +header extends java/lang/RuntimeException flags 21 + +class name com/sun/jdi/request/MethodEntryRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MethodExitRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ModificationWatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/WatchpointRequest flags 601 + +class name com/sun/jdi/request/MonitorContendedEnterRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorContendedEnteredRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorWaitRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/MonitorWaitedRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/StepRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ThreadDeathRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/ThreadStartRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/VMDeathRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + +class name com/sun/jdi/request/WatchpointRequest +header extends java/lang/Object implements com/sun/jdi/request/EventRequest flags 601 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt new file mode 100644 index 00000000000..56113904721 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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/jfr/consumer/RecordedObject +header extends java/lang/Object sealed true flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jlink-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jlink-K.sym.txt new file mode 100644 index 00000000000..b5698018f6e --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jlink-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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.jlink +header requires name\u0020;java.base\u0020;flags\u0020;8000,name\u0020;jdk.internal.opt\u0020;flags\u0020;0,name\u0020;jdk.jdeps\u0020;flags\u0020;0 uses jdk/tools/jlink/plugin/Plugin provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/tools/jmod/Main$JmodToolProvider\u005C;u002C;jdk/tools/jlink/internal/Main$JlinkToolProvider,interface\u0020;jdk/tools/jlink/plugin/Plugin\u0020;impls\u0020;jdk/tools/jlink/internal/plugins/DefaultStripDebugPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripJavaDebugAttributesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeFilesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeJmodSectionPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/LegalNoticeFilePlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/SystemModulesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripNativeCommandsPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/OrderResourcesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/DefaultCompressPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ExcludeVMPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/IncludeLocalesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/GenerateJLIClassesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/ReleaseInfoPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/AddOptionsPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorBugURLPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorVMBugURLPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/VendorVersionPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/CDSPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/SaveJlinkArgfilesPlugin\u005C;u002C;jdk/tools/jlink/internal/plugins/StripNativeDebugSymbolsPlugin target linux-amd64 flags 8000 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jpackage-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jpackage-K.sym.txt new file mode 100644 index 00000000000..5c26a60de10 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jpackage-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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.desktop\u0020;flags\u0020;0 uses jdk/jpackage/internal/Bundler,jdk/jpackage/internal/Bundlers provides interface\u0020;java/util/spi/ToolProvider\u0020;impls\u0020;jdk/jpackage/internal/JPackageToolProvider,interface\u0020;jdk/jpackage/internal/Bundler\u0020;impls\u0020;jdk/jpackage/internal/LinuxAppBundler\u005C;u002C;jdk/jpackage/internal/LinuxDebBundler\u005C;u002C;jdk/jpackage/internal/LinuxRpmBundler,interface\u0020;jdk/jpackage/internal/Bundlers\u0020;impls\u0020;jdk/jpackage/internal/BasicBundlers target linux-amd64 flags 8000 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jshell-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jshell-K.sym.txt new file mode 100644 index 00000000000..71fc8bbf6eb --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jshell-K.sym.txt @@ -0,0 +1,135 @@ +# +# Copyright (c) 2022, 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/jshell/DeclarationSnippet +header extends jdk/jshell/PersistentSnippet flags 421 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/Diag +header extends java/lang/Object flags 421 + +class name jdk/jshell/EvalException +header extends jdk/jshell/JShellException flags 21 + +class name jdk/jshell/ExpressionSnippet +header extends jdk/jshell/Snippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/ImportSnippet +header extends jdk/jshell/PersistentSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/JShellException +header extends java/lang/Exception flags 21 + +class name jdk/jshell/MethodSnippet +header extends jdk/jshell/DeclarationSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/PersistentSnippet +header extends jdk/jshell/Snippet flags 421 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/SnippetEvent +header extends java/lang/Object flags 21 +innerclass innerClass jdk/jshell/Snippet$Status outerClass jdk/jshell/Snippet innerClassName Status flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/StatementSnippet +header extends jdk/jshell/Snippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/TypeDeclSnippet +header extends jdk/jshell/DeclarationSnippet flags 21 +innerclass innerClass jdk/jshell/Snippet$SubKind outerClass jdk/jshell/Snippet innerClassName SubKind flags 4019 + +class name jdk/jshell/execution/DirectExecutionControl +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControl flags 21 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassBytecodes outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassBytecodes flags 19 +innerclass innerClass jdk/jshell/spi/ExecutionControl$NotImplementedException outerClass jdk/jshell/spi/ExecutionControl innerClassName NotImplementedException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$RunException outerClass jdk/jshell/spi/ExecutionControl innerClassName RunException flags 409 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass java/util/PrimitiveIterator$OfInt outerClass java/util/PrimitiveIterator innerClassName OfInt flags 609 +innerclass innerClass java/lang/Character$UnicodeBlock outerClass java/lang/Character innerClassName UnicodeBlock flags 19 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ResolutionException outerClass jdk/jshell/spi/ExecutionControl innerClassName ResolutionException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$UserException outerClass jdk/jshell/spi/ExecutionControl innerClassName UserException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassInstallException outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassInstallException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ExecutionControlException outerClass jdk/jshell/spi/ExecutionControl innerClassName ExecutionControlException flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/execution/FailOverExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/execution/JdiDefaultExecutionControl +header extends jdk/jshell/execution/JdiExecutionControl flags 21 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$RunException outerClass jdk/jshell/spi/ExecutionControl innerClassName RunException flags 409 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/jshell/execution/JdiExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 + +class name jdk/jshell/execution/LoaderDelegate +header extends java/lang/Object flags 601 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassBytecodes outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassBytecodes flags 19 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassInstallException outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassInstallException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$NotImplementedException outerClass jdk/jshell/spi/ExecutionControl innerClassName NotImplementedException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 + +class name jdk/jshell/execution/LocalExecutionControl +header extends jdk/jshell/execution/DirectExecutionControl flags 21 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassBytecodes outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassBytecodes flags 19 +innerclass innerClass java/lang/Thread$UncaughtExceptionHandler outerClass java/lang/Thread innerClassName UncaughtExceptionHandler flags 609 +innerclass innerClass jdk/jshell/spi/ExecutionControl$StoppedException outerClass jdk/jshell/spi/ExecutionControl innerClassName StoppedException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$InternalException outerClass jdk/jshell/spi/ExecutionControl innerClassName InternalException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$ClassInstallException outerClass jdk/jshell/spi/ExecutionControl innerClassName ClassInstallException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$NotImplementedException outerClass jdk/jshell/spi/ExecutionControl innerClassName NotImplementedException flags 9 +innerclass innerClass jdk/jshell/spi/ExecutionControl$EngineTerminationException outerClass jdk/jshell/spi/ExecutionControl innerClassName EngineTerminationException flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name load descriptor ([Ljdk/jshell/spi/ExecutionControl$ClassBytecodes;)V thrownTypes jdk/jshell/spi/ExecutionControl$ClassInstallException,jdk/jshell/spi/ExecutionControl$NotImplementedException,jdk/jshell/spi/ExecutionControl$EngineTerminationException flags 1 + +class name jdk/jshell/execution/LocalExecutionControlProvider +header extends java/lang/Object implements jdk/jshell/spi/ExecutionControlProvider flags 21 + +class name jdk/jshell/spi/ExecutionControlProvider +header extends java/lang/Object flags 601 + +class name jdk/jshell/spi/ExecutionEnv +header extends java/lang/Object flags 601 + +class name jdk/jshell/spi/SPIResolutionException +header extends java/lang/RuntimeException flags 21 + +class name jdk/jshell/tool/JavaShellToolBuilder +header extends java/lang/Object flags 601 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jsobject-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jsobject-K.sym.txt new file mode 100644 index 00000000000..314bea0bf72 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.jsobject-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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 netscape/javascript/JSException +header extends java/lang/RuntimeException flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.management-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management-K.sym.txt new file mode 100644 index 00000000000..582c8b3e2b8 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.management-K.sym.txt @@ -0,0 +1,46 @@ +# +# Copyright (c) 2022, 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 com/sun/management/GarbageCollectionNotificationInfo +header extends java/lang/Object implements javax/management/openmbean/CompositeDataView flags 21 + +class name com/sun/management/GarbageCollectorMXBean +header extends java/lang/Object implements java/lang/management/GarbageCollectorMXBean flags 601 + +class name com/sun/management/GcInfo +header extends java/lang/Object implements javax/management/openmbean/CompositeData,javax/management/openmbean/CompositeDataView flags 21 + +class name com/sun/management/OperatingSystemMXBean +header extends java/lang/Object implements java/lang/management/OperatingSystemMXBean flags 601 + +class name com/sun/management/ThreadMXBean +header extends java/lang/Object implements java/lang/management/ThreadMXBean flags 601 + +class name com/sun/management/UnixOperatingSystemMXBean +header extends java/lang/Object implements com/sun/management/OperatingSystemMXBean flags 601 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.net-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.net-K.sym.txt new file mode 100644 index 00000000000..ce0ac598b1b --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.net-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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/net/NetworkPermission +header extends java/security/BasicPermission flags 31 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.sctp-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.sctp-K.sym.txt new file mode 100644 index 00000000000..62cac0259cd --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.sctp-K.sym.txt @@ -0,0 +1,73 @@ +# +# Copyright (c) 2022, 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 com/sun/nio/sctp/AbstractNotificationHandler +header extends java/lang/Object implements com/sun/nio/sctp/NotificationHandler flags 21 signature Ljava/lang/Object;Lcom/sun/nio/sctp/NotificationHandler; + +class name com/sun/nio/sctp/Association +header extends java/lang/Object flags 21 + +class name com/sun/nio/sctp/HandlerResult +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + +class name com/sun/nio/sctp/IllegalReceiveException +header extends java/lang/IllegalStateException flags 21 + +class name com/sun/nio/sctp/IllegalUnbindException +header extends java/lang/IllegalStateException flags 21 + +class name com/sun/nio/sctp/InvalidStreamException +header extends java/lang/IllegalArgumentException flags 21 + +class name com/sun/nio/sctp/MessageInfo +header extends java/lang/Object flags 421 + +class name com/sun/nio/sctp/Notification +header extends java/lang/Object flags 601 + +class name com/sun/nio/sctp/NotificationHandler +header extends java/lang/Object flags 601 signature Ljava/lang/Object; + +class name com/sun/nio/sctp/SctpChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpMultiChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpServerChannel +header extends java/nio/channels/spi/AbstractSelectableChannel flags 421 + +class name com/sun/nio/sctp/SctpSocketOption +header extends java/lang/Object implements java/net/SocketOption flags 601 signature Ljava/lang/Object;Ljava/net/SocketOption; + +class name com/sun/nio/sctp/SendFailedNotification +header extends java/lang/Object implements com/sun/nio/sctp/Notification flags 421 + +class name com/sun/nio/sctp/ShutdownNotification +header extends java/lang/Object implements com/sun/nio/sctp/Notification flags 421 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.security.auth-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.auth-K.sym.txt new file mode 100644 index 00000000000..7fca7055334 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.security.auth-K.sym.txt @@ -0,0 +1,106 @@ +# +# Copyright (c) 2022, 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 com/sun/security/auth/LdapPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 + +class name com/sun/security/auth/NTDomainPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/NTNumericCredential +header extends java/lang/Object flags 21 + +class name com/sun/security/auth/NTSid +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/NTSidDomainPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidGroupPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidPrimaryGroupPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTSidUserPrincipal +header extends com/sun/security/auth/NTSid flags 21 + +class name com/sun/security/auth/NTUserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/PrincipalComparator +header extends java/lang/Object flags 601 + +class name com/sun/security/auth/UnixNumericGroupPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UnixNumericUserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UnixPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 21 + +class name com/sun/security/auth/UserPrincipal +header extends java/lang/Object implements java/security/Principal,java/io/Serializable flags 31 + +class name com/sun/security/auth/callback/TextCallbackHandler +header extends java/lang/Object implements javax/security/auth/callback/CallbackHandler flags 21 + +class name com/sun/security/auth/login/ConfigFile +header extends javax/security/auth/login/Configuration flags 21 + +class name com/sun/security/auth/module/JndiLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/KeyStoreLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/Krb5LoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/LdapLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/NTLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/NTSystem +header extends java/lang/Object flags 21 + +class name com/sun/security/auth/module/UnixLoginModule +header extends java/lang/Object implements javax/security/auth/spi/LoginModule flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/auth/module/UnixSystem +header extends java/lang/Object flags 21 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.security.jgss-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-K.sym.txt new file mode 100644 index 00000000000..eef803edf53 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.security.jgss-K.sym.txt @@ -0,0 +1,47 @@ +# +# Copyright (c) 2022, 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 com/sun/security/jgss/AuthorizationDataEntry +header extends java/lang/Object flags 31 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name com/sun/security/jgss/ExtendedGSSContext +header extends java/lang/Object implements org/ietf/jgss/GSSContext flags 601 + +class name com/sun/security/jgss/ExtendedGSSCredential +header extends java/lang/Object implements org/ietf/jgss/GSSCredential flags 601 + +class name com/sun/security/jgss/GSSUtil +header extends java/lang/Object flags 21 + +class name com/sun/security/jgss/InquireSecContextPermission +header extends java/security/BasicPermission flags 31 + +class name com/sun/security/jgss/InquireType +header extends java/lang/Enum flags 4031 signature Ljava/lang/Enum; + diff --git a/src/jdk.compiler/share/data/symbols/jdk.unsupported-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.unsupported-K.sym.txt new file mode 100644 index 00000000000..fc08e61ed12 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.unsupported-K.sym.txt @@ -0,0 +1,48 @@ +# +# Copyright (c) 2022, 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 com/sun/nio/file/ExtendedCopyOption +header extends java/lang/Enum implements java/nio/file/CopyOption flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/CopyOption; classAnnotations @Lsun/Proprietary+Annotation; + +class name com/sun/nio/file/ExtendedOpenOption +header extends java/lang/Enum implements java/nio/file/OpenOption flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/OpenOption; classAnnotations @Lsun/Proprietary+Annotation; + +class name com/sun/nio/file/ExtendedWatchEventModifier +header extends java/lang/Enum implements java/nio/file/WatchEvent$Modifier flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/WatchEvent$Modifier; classAnnotations @Lsun/Proprietary+Annotation; +innerclass innerClass java/nio/file/WatchEvent$Modifier outerClass java/nio/file/WatchEvent innerClassName Modifier flags 609 + +class name com/sun/nio/file/SensitivityWatchEventModifier +header extends java/lang/Enum implements java/nio/file/WatchEvent$Modifier flags 4031 signature Ljava/lang/Enum;Ljava/nio/file/WatchEvent$Modifier; classAnnotations @Lsun/Proprietary+Annotation; +innerclass innerClass java/nio/file/WatchEvent$Modifier outerClass java/nio/file/WatchEvent innerClassName Modifier flags 609 + +class name sun/misc/SignalHandler +header extends java/lang/Object flags 601 classAnnotations @Lsun/Proprietary+Annotation; + +class name sun/reflect/ReflectionFactory +header extends java/lang/Object flags 21 classAnnotations @Lsun/Proprietary+Annotation; + diff --git a/src/jdk.compiler/share/data/symbols/jdk.xml.dom-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-K.sym.txt new file mode 100644 index 00000000000..66599facd5e --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.xml.dom-K.sym.txt @@ -0,0 +1,295 @@ +# +# Copyright (c) 2022, 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 org/w3c/dom/css/CSS2Properties +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSCharsetRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSFontFaceRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSImportRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSMediaRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSPageRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSPrimitiveValue +header extends java/lang/Object implements org/w3c/dom/css/CSSValue flags 601 + +class name org/w3c/dom/css/CSSRule +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSRuleList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSStyleDeclaration +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSStyleRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSStyleSheet +header extends java/lang/Object implements org/w3c/dom/stylesheets/StyleSheet flags 601 + +class name org/w3c/dom/css/CSSUnknownRule +header extends java/lang/Object implements org/w3c/dom/css/CSSRule flags 601 + +class name org/w3c/dom/css/CSSValue +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/CSSValueList +header extends java/lang/Object implements org/w3c/dom/css/CSSValue flags 601 + +class name org/w3c/dom/css/Counter +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/DOMImplementationCSS +header extends java/lang/Object implements org/w3c/dom/DOMImplementation flags 601 + +class name org/w3c/dom/css/DocumentCSS +header extends java/lang/Object implements org/w3c/dom/stylesheets/DocumentStyle flags 601 + +class name org/w3c/dom/css/ElementCSSInlineStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/RGBColor +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/Rect +header extends java/lang/Object flags 601 + +class name org/w3c/dom/css/ViewCSS +header extends java/lang/Object implements org/w3c/dom/views/AbstractView flags 601 + +class name org/w3c/dom/html/HTMLAnchorElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLAppletElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLAreaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBRElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBaseElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBaseFontElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLBodyElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLButtonElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLCollection +header extends java/lang/Object flags 601 + +class name org/w3c/dom/html/HTMLDListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDOMImplementation +header extends java/lang/Object implements org/w3c/dom/DOMImplementation flags 601 + +class name org/w3c/dom/html/HTMLDirectoryElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDivElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLDocument +header extends java/lang/Object implements org/w3c/dom/Document flags 601 + +class name org/w3c/dom/html/HTMLElement +header extends java/lang/Object implements org/w3c/dom/Element flags 601 + +class name org/w3c/dom/html/HTMLFieldSetElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFontElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFormElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFrameElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLFrameSetElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHRElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHeadElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHeadingElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLHtmlElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLIFrameElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLImageElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLInputElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLIsIndexElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLIElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLabelElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLegendElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLLinkElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMapElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMenuElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLMetaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLModElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLObjectElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOptGroupElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLOptionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLParagraphElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLParamElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLPreElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLQuoteElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLScriptElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLSelectElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLStyleElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableCaptionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableCellElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableColElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableRowElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTableSectionElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTextAreaElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLTitleElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/html/HTMLUListElement +header extends java/lang/Object implements org/w3c/dom/html/HTMLElement flags 601 + +class name org/w3c/dom/stylesheets/DocumentStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/LinkStyle +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/MediaList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/StyleSheet +header extends java/lang/Object flags 601 + +class name org/w3c/dom/stylesheets/StyleSheetList +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathEvaluator +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathException +header extends java/lang/RuntimeException flags 21 + +class name org/w3c/dom/xpath/XPathExpression +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathNSResolver +header extends java/lang/Object flags 601 + +class name org/w3c/dom/xpath/XPathNamespace +header extends java/lang/Object implements org/w3c/dom/Node flags 601 + +class name org/w3c/dom/xpath/XPathResult +header extends java/lang/Object flags 601 + diff --git a/src/jdk.compiler/share/data/symbols/symbols b/src/jdk.compiler/share/data/symbols/symbols index edc2c6ac2ee..14ed3ee01d5 100644 --- a/src/jdk.compiler/share/data/symbols/symbols +++ b/src/jdk.compiler/share/data/symbols/symbols @@ -29,7 +29,7 @@ #command used to generate this file: #build.tools.symbolgenerator.CreateSymbols build-description-incremental symbols include.list # -generate platforms 8:9:A:B:C:D:E:F:G:H:I:J +generate platforms 8:9:A:B:C:D:E:F:G:H:I:J:K platform version 8 files java.activation-8.sym.txt:java.base-8.sym.txt:java.compiler-8.sym.txt:java.corba-8.sym.txt:java.datatransfer-8.sym.txt:java.desktop-8.sym.txt:java.instrument-8.sym.txt:java.logging-8.sym.txt:java.management-8.sym.txt:java.management.rmi-8.sym.txt:java.naming-8.sym.txt:java.prefs-8.sym.txt:java.rmi-8.sym.txt:java.scripting-8.sym.txt:java.security.jgss-8.sym.txt:java.security.sasl-8.sym.txt:java.sql-8.sym.txt:java.sql.rowset-8.sym.txt:java.transaction-8.sym.txt:java.xml-8.sym.txt:java.xml.bind-8.sym.txt:java.xml.crypto-8.sym.txt:java.xml.ws-8.sym.txt:java.xml.ws.annotation-8.sym.txt:jdk.httpserver-8.sym.txt:jdk.management-8.sym.txt:jdk.scripting.nashorn-8.sym.txt:jdk.sctp-8.sym.txt:jdk.security.auth-8.sym.txt:jdk.security.jgss-8.sym.txt platform version 9 base 8 files java.activation-9.sym.txt:java.base-9.sym.txt:java.compiler-9.sym.txt:java.corba-9.sym.txt:java.datatransfer-9.sym.txt:java.desktop-9.sym.txt:java.instrument-9.sym.txt:java.logging-9.sym.txt:java.management-9.sym.txt:java.management.rmi-9.sym.txt:java.naming-9.sym.txt:java.prefs-9.sym.txt:java.rmi-9.sym.txt:java.scripting-9.sym.txt:java.se-9.sym.txt:java.se.ee-9.sym.txt:java.security.jgss-9.sym.txt:java.security.sasl-9.sym.txt:java.smartcardio-9.sym.txt:java.sql-9.sym.txt:java.sql.rowset-9.sym.txt:java.transaction-9.sym.txt:java.xml-9.sym.txt:java.xml.bind-9.sym.txt:java.xml.crypto-9.sym.txt:java.xml.ws-9.sym.txt:java.xml.ws.annotation-9.sym.txt:jdk.accessibility-9.sym.txt:jdk.attach-9.sym.txt:jdk.charsets-9.sym.txt:jdk.compiler-9.sym.txt:jdk.crypto.cryptoki-9.sym.txt:jdk.crypto.ec-9.sym.txt:jdk.dynalink-9.sym.txt:jdk.editpad-9.sym.txt:jdk.hotspot.agent-9.sym.txt:jdk.httpserver-9.sym.txt:jdk.incubator.httpclient-9.sym.txt:jdk.jartool-9.sym.txt:jdk.javadoc-9.sym.txt:jdk.jcmd-9.sym.txt:jdk.jconsole-9.sym.txt:jdk.jdeps-9.sym.txt:jdk.jdi-9.sym.txt:jdk.jdwp.agent-9.sym.txt:jdk.jlink-9.sym.txt:jdk.jshell-9.sym.txt:jdk.jsobject-9.sym.txt:jdk.jstatd-9.sym.txt:jdk.localedata-9.sym.txt:jdk.management-9.sym.txt:jdk.management.agent-9.sym.txt:jdk.naming.dns-9.sym.txt:jdk.naming.rmi-9.sym.txt:jdk.net-9.sym.txt:jdk.pack-9.sym.txt:jdk.policytool-9.sym.txt:jdk.rmic-9.sym.txt:jdk.scripting.nashorn-9.sym.txt:jdk.sctp-9.sym.txt:jdk.security.auth-9.sym.txt:jdk.security.jgss-9.sym.txt:jdk.unsupported-9.sym.txt:jdk.xml.dom-9.sym.txt:jdk.zipfs-9.sym.txt platform version A base 9 files java.activation-A.sym.txt:java.base-A.sym.txt:java.compiler-A.sym.txt:java.corba-A.sym.txt:java.datatransfer-A.sym.txt:java.desktop-A.sym.txt:java.instrument-A.sym.txt:java.logging-A.sym.txt:java.management-A.sym.txt:java.management.rmi-A.sym.txt:java.naming-A.sym.txt:java.prefs-A.sym.txt:java.rmi-A.sym.txt:java.scripting-A.sym.txt:java.se-A.sym.txt:java.se.ee-A.sym.txt:java.security.jgss-A.sym.txt:java.security.sasl-A.sym.txt:java.smartcardio-A.sym.txt:java.sql-A.sym.txt:java.sql.rowset-A.sym.txt:java.transaction-A.sym.txt:java.xml-A.sym.txt:java.xml.bind-A.sym.txt:java.xml.crypto-A.sym.txt:java.xml.ws-A.sym.txt:java.xml.ws.annotation-A.sym.txt:jdk.accessibility-A.sym.txt:jdk.attach-A.sym.txt:jdk.charsets-A.sym.txt:jdk.compiler-A.sym.txt:jdk.crypto.cryptoki-A.sym.txt:jdk.crypto.ec-A.sym.txt:jdk.dynalink-A.sym.txt:jdk.editpad-A.sym.txt:jdk.hotspot.agent-A.sym.txt:jdk.httpserver-A.sym.txt:jdk.incubator.httpclient-A.sym.txt:jdk.jartool-A.sym.txt:jdk.javadoc-A.sym.txt:jdk.jcmd-A.sym.txt:jdk.jconsole-A.sym.txt:jdk.jdeps-A.sym.txt:jdk.jdi-A.sym.txt:jdk.jdwp.agent-A.sym.txt:jdk.jlink-A.sym.txt:jdk.jshell-A.sym.txt:jdk.jsobject-A.sym.txt:jdk.jstatd-A.sym.txt:jdk.localedata-A.sym.txt:jdk.management-A.sym.txt:jdk.management.agent-A.sym.txt:jdk.naming.dns-A.sym.txt:jdk.naming.rmi-A.sym.txt:jdk.net-A.sym.txt:jdk.pack-A.sym.txt:jdk.policytool-A.sym.txt:jdk.rmic-A.sym.txt:jdk.scripting.nashorn-A.sym.txt:jdk.sctp-A.sym.txt:jdk.security.auth-A.sym.txt:jdk.security.jgss-A.sym.txt:jdk.unsupported-A.sym.txt:jdk.xml.dom-A.sym.txt:jdk.zipfs-A.sym.txt @@ -42,3 +42,4 @@ platform version G base F files java.base-G.sym.txt:java.compiler-G.sym.txt:java platform version H base G files java.base-H.sym.txt:java.compiler-H.sym.txt:java.datatransfer-H.sym.txt:java.desktop-H.sym.txt:java.instrument-H.sym.txt:java.logging-H.sym.txt:java.management-H.sym.txt:java.management.rmi-H.sym.txt:java.naming-H.sym.txt:java.rmi-H.sym.txt:java.scripting-H.sym.txt:java.security.jgss-H.sym.txt:java.security.sasl-H.sym.txt:java.smartcardio-H.sym.txt:java.sql-H.sym.txt:java.sql.rowset-H.sym.txt:java.xml-H.sym.txt:java.xml.crypto-H.sym.txt:jdk.accessibility-H.sym.txt:jdk.attach-H.sym.txt:jdk.compiler-H.sym.txt:jdk.dynalink-H.sym.txt:jdk.httpserver-H.sym.txt:jdk.incubator.foreign-H.sym.txt:jdk.incubator.vector-H.sym.txt:jdk.jartool-H.sym.txt:jdk.javadoc-H.sym.txt:jdk.jconsole-H.sym.txt:jdk.jdi-H.sym.txt:jdk.jfr-H.sym.txt:jdk.jshell-H.sym.txt:jdk.jsobject-H.sym.txt:jdk.management-H.sym.txt:jdk.management.jfr-H.sym.txt:jdk.net-H.sym.txt:jdk.sctp-H.sym.txt:jdk.security.auth-H.sym.txt:jdk.security.jgss-H.sym.txt:jdk.unsupported-H.sym.txt:jdk.xml.dom-H.sym.txt platform version I base H files java.base-I.sym.txt:java.compiler-I.sym.txt:java.datatransfer-I.sym.txt:java.desktop-I.sym.txt:java.instrument-I.sym.txt:java.logging-I.sym.txt:java.management-I.sym.txt:java.management.rmi-I.sym.txt:java.naming-I.sym.txt:java.net.http-I.sym.txt:java.rmi-I.sym.txt:java.scripting-I.sym.txt:java.security.jgss-I.sym.txt:java.security.sasl-I.sym.txt:java.smartcardio-I.sym.txt:java.sql-I.sym.txt:java.sql.rowset-I.sym.txt:java.xml-I.sym.txt:java.xml.crypto-I.sym.txt:jdk.accessibility-I.sym.txt:jdk.attach-I.sym.txt:jdk.compiler-I.sym.txt:jdk.dynalink-I.sym.txt:jdk.httpserver-I.sym.txt:jdk.incubator.foreign-I.sym.txt:jdk.incubator.vector-I.sym.txt:jdk.jartool-I.sym.txt:jdk.javadoc-I.sym.txt:jdk.jconsole-I.sym.txt:jdk.jdi-I.sym.txt:jdk.jlink-I.sym.txt:jdk.jshell-I.sym.txt:jdk.jsobject-I.sym.txt:jdk.management-I.sym.txt:jdk.management.jfr-I.sym.txt:jdk.net-I.sym.txt:jdk.sctp-I.sym.txt:jdk.security.auth-I.sym.txt:jdk.security.jgss-I.sym.txt:jdk.unsupported-I.sym.txt:jdk.xml.dom-I.sym.txt platform version J base I files java.base-J.sym.txt:java.compiler-J.sym.txt:java.datatransfer-J.sym.txt:java.desktop-J.sym.txt:java.instrument-J.sym.txt:java.logging-J.sym.txt:java.management-J.sym.txt:java.management.rmi-J.sym.txt:java.naming-J.sym.txt:java.net.http-J.sym.txt:java.rmi-J.sym.txt:java.scripting-J.sym.txt:java.security.jgss-J.sym.txt:java.security.sasl-J.sym.txt:java.smartcardio-J.sym.txt:java.sql-J.sym.txt:java.sql.rowset-J.sym.txt:java.xml-J.sym.txt:java.xml.crypto-J.sym.txt:jdk.accessibility-J.sym.txt:jdk.attach-J.sym.txt:jdk.compiler-J.sym.txt:jdk.dynalink-J.sym.txt:jdk.httpserver-J.sym.txt:jdk.incubator.concurrent-J.sym.txt:jdk.incubator.foreign-J.sym.txt:jdk.incubator.vector-J.sym.txt:jdk.jartool-J.sym.txt:jdk.javadoc-J.sym.txt:jdk.jconsole-J.sym.txt:jdk.jdi-J.sym.txt:jdk.jfr-J.sym.txt:jdk.jshell-J.sym.txt:jdk.jsobject-J.sym.txt:jdk.management-J.sym.txt:jdk.management.agent-J.sym.txt:jdk.net-J.sym.txt:jdk.sctp-J.sym.txt:jdk.security.auth-J.sym.txt:jdk.security.jgss-J.sym.txt:jdk.unsupported-J.sym.txt:jdk.xml.dom-J.sym.txt +platform version K base J files java.base-K.sym.txt:java.compiler-K.sym.txt:java.datatransfer-K.sym.txt:java.desktop-K.sym.txt:java.instrument-K.sym.txt:java.logging-K.sym.txt:java.management-K.sym.txt:java.management.rmi-K.sym.txt:java.naming-K.sym.txt:java.rmi-K.sym.txt:java.scripting-K.sym.txt:java.security.jgss-K.sym.txt:java.security.sasl-K.sym.txt:java.smartcardio-K.sym.txt:java.sql-K.sym.txt:java.sql.rowset-K.sym.txt:java.xml-K.sym.txt:java.xml.crypto-K.sym.txt:jdk.accessibility-K.sym.txt:jdk.attach-K.sym.txt:jdk.compiler-K.sym.txt:jdk.dynalink-K.sym.txt:jdk.httpserver-K.sym.txt:jdk.incubator.concurrent-K.sym.txt:jdk.incubator.vector-K.sym.txt:jdk.jartool-K.sym.txt:jdk.javadoc-K.sym.txt:jdk.jconsole-K.sym.txt:jdk.jdi-K.sym.txt:jdk.jfr-K.sym.txt:jdk.jlink-K.sym.txt:jdk.jpackage-K.sym.txt:jdk.jshell-K.sym.txt:jdk.jsobject-K.sym.txt:jdk.management-K.sym.txt:jdk.net-K.sym.txt:jdk.sctp-K.sym.txt:jdk.security.auth-K.sym.txt:jdk.security.jgss-K.sym.txt:jdk.unsupported-K.sym.txt:jdk.xml.dom-K.sym.txt diff --git a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java index 0c41fe75791..d380419632c 100644 --- a/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java +++ b/test/hotspot/jtreg/runtime/ClassFile/ClassFileVersionTest.java @@ -77,11 +77,11 @@ public static void main(String argv[]) throws Throwable { // test primitive array. should return latest version. int ver = (int)m.invoke((new int[3]).getClass()); - if (ver != 64) { + if (ver != latestMajor) { int got_minor = (ver >> 16) & LOWER_16; int got_major = ver & LOWER_16; throw new RuntimeException( - "Expected 0:64, but got " + got_minor + ":" + got_major + " for primitive array"); + "Expected 0:" + latestMajor + ", but got " + got_minor + ":" + got_major + " for primitive array"); } // test object array. should return class file version of component. diff --git a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java index 1544e18c9d2..0029304f9de 100644 --- a/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java +++ b/test/hotspot/jtreg/runtime/CommandLine/VMDeprecatedOptions.java @@ -61,7 +61,6 @@ public class VMDeprecatedOptions { {"InitialRAMFraction", "64"}, {"TLABStats", "false"}, {"AllowRedefinitionToAddDeleteMethods", "true"}, - {"EnableWaitForParallelLoad", "false"}, // deprecated alias flags (see also aliased_jvm_flags): {"DefaultMaxRAMFraction", "4"}, diff --git a/test/langtools/tools/javac/api/TestGetSourceVersions.java b/test/langtools/tools/javac/api/TestGetSourceVersions.java index befdcac7d7a..168e76f330f 100644 --- a/test/langtools/tools/javac/api/TestGetSourceVersions.java +++ b/test/langtools/tools/javac/api/TestGetSourceVersions.java @@ -35,7 +35,7 @@ * @run main TestGetSourceVersions RELEASE_3 RELEASE_4 RELEASE_5 RELEASE_6 RELEASE_7 * RELEASE_8 RELEASE_9 RELEASE_10 RELEASE_11 RELEASE_12 * RELEASE_13 RELEASE_14 RELEASE_15 RELEASE_16 RELEASE_17 - * RELEASE_18 RELEASE_19 RELEASE_20 + * RELEASE_18 RELEASE_19 RELEASE_20 RELEASE_21 */ import java.util.EnumSet; diff --git a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java index fad440c0880..d54b8da4e3f 100644 --- a/test/langtools/tools/javac/classfiles/ClassVersionChecker.java +++ b/test/langtools/tools/javac/classfiles/ClassVersionChecker.java @@ -54,7 +54,8 @@ private static enum Version { SEVENTEEN("17", 61), EIGHTEEN("18", 62), NINETEEN("19", 63), - TWENTY("20", 64); + TWENTY("20", 64), + TWENTY_ONE("21", 65); private Version(String release, int classFileVer) { this.release = release; diff --git a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java index b1afc5d7cbc..cba0bd23e1f 100644 --- a/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java +++ b/test/langtools/tools/javac/lib/JavacTestingAbstractProcessor.java @@ -112,7 +112,7 @@ protected void addExports(String moduleName, String... packageNames) { * corresponding platform visitor type. */ - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractAnnotationValueVisitor extends AbstractAnnotationValueVisitor14 { /** @@ -123,7 +123,7 @@ protected AbstractAnnotationValueVisitor() { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractElementVisitor extends AbstractElementVisitor14 { /** * Constructor for concrete subclasses to call. @@ -133,7 +133,7 @@ protected AbstractElementVisitor(){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static abstract class AbstractTypeVisitor extends AbstractTypeVisitor14 { /** * Constructor for concrete subclasses to call. @@ -143,7 +143,7 @@ protected AbstractTypeVisitor() { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class ElementKindVisitor extends ElementKindVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -164,7 +164,7 @@ protected ElementKindVisitor(R defaultValue) { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class ElementScanner extends ElementScanner14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -183,7 +183,7 @@ protected ElementScanner(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleAnnotationValueVisitor extends SimpleAnnotationValueVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -204,7 +204,7 @@ protected SimpleAnnotationValueVisitor(R defaultValue) { } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleElementVisitor extends SimpleElementVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -225,7 +225,7 @@ protected SimpleElementVisitor(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class SimpleTypeVisitor extends SimpleTypeVisitor14 { /** * Constructor for concrete subclasses; uses {@code null} for the @@ -246,7 +246,7 @@ protected SimpleTypeVisitor(R defaultValue){ } } - @SupportedSourceVersion(RELEASE_20) + @SupportedSourceVersion(RELEASE_21) public static class TypeKindVisitor extends TypeKindVisitor14 { /** * Constructor for concrete subclasses to call; uses {@code null} diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out index 8e8e88b4bcc..d6e16a69307 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.nopreview.out @@ -1,2 +1,2 @@ -- compiler.err.preview.feature.disabled.classfile: Bar.class, 20 +- compiler.err.preview.feature.disabled.classfile: Bar.class, 21 1 error diff --git a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out index af28e2f1cf0..d05eeb0ebee 100644 --- a/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out +++ b/test/langtools/tools/javac/preview/classReaderTest/Client.preview.out @@ -1,4 +1,4 @@ -- compiler.warn.preview.feature.use.classfile: Bar.class, 20 +- compiler.warn.preview.feature.use.classfile: Bar.class, 21 - compiler.err.warnings.and.werror 1 error 1 warning diff --git a/test/langtools/tools/javac/versions/Versions.java b/test/langtools/tools/javac/versions/Versions.java index 99fe34c9424..1a7f618b9f2 100644 --- a/test/langtools/tools/javac/versions/Versions.java +++ b/test/langtools/tools/javac/versions/Versions.java @@ -71,24 +71,25 @@ public static void main(String... args) throws IOException { public static final Set VALID_SOURCES = Set.of("1.8", "1.9", "1.10", "11", "12", "13", "14", - "15", "16", "17", "18", "19", "20"); + "15", "16", "17", "18", "19", "20", "21"); - public static final String LATEST_MAJOR_VERSION = "64.0"; + public static final String LATEST_MAJOR_VERSION = "65.0"; static enum SourceTarget { - EIGHT(true, "52.0", "8", Versions::checksrc8), - NINE(true, "53.0", "9", Versions::checksrc9), - TEN(true, "54.0", "10", Versions::checksrc10), - ELEVEN(false, "55.0", "11", Versions::checksrc11), - TWELVE(false, "56.0", "12", Versions::checksrc12), - THIRTEEN(false, "57.0", "13", Versions::checksrc13), - FOURTEEN(false, "58.0", "14", Versions::checksrc14), - FIFTEEN(false, "59.0", "15", Versions::checksrc15), - SIXTEEN(false, "60.0", "16", Versions::checksrc16), + EIGHT(true, "52.0", "8", Versions::checksrc8), + NINE(true, "53.0", "9", Versions::checksrc9), + TEN(true, "54.0", "10", Versions::checksrc10), + ELEVEN(false, "55.0", "11", Versions::checksrc11), + TWELVE(false, "56.0", "12", Versions::checksrc12), + THIRTEEN(false, "57.0", "13", Versions::checksrc13), + FOURTEEN(false, "58.0", "14", Versions::checksrc14), + FIFTEEN(false, "59.0", "15", Versions::checksrc15), + SIXTEEN(false, "60.0", "16", Versions::checksrc16), SEVENTEEN(false, "61.0", "17", Versions::checksrc17), EIGHTEEN(false, "62.0", "18", Versions::checksrc18), NINETEEN(false, "63.0", "19", Versions::checksrc19), - TWENTY(false, "64.0", "20", Versions::checksrc20); + TWENTY(false, "64.0", "20", Versions::checksrc20), + TWENTY_ONE(false,"65.0", "21", Versions::checksrc20); private final boolean dotOne; private final String classFileVer; From d35e840024b80f9f686fb5522dc03b2c9233a6d3 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 8 Dec 2022 18:17:58 +0000 Subject: [PATCH 136/494] 8297295: Remove ThreadGroup.allowThreadSuspension Reviewed-by: jpai, smarks, chegar, darcy --- .../share/classes/java/lang/ThreadGroup.java | 17 ----------------- test/jdk/java/lang/ThreadGroup/BasicTests.java | 7 ------- 2 files changed, 24 deletions(-) diff --git a/src/java.base/share/classes/java/lang/ThreadGroup.java b/src/java.base/share/classes/java/lang/ThreadGroup.java index 607d1f92d5d..48467f86e1e 100644 --- a/src/java.base/share/classes/java/lang/ThreadGroup.java +++ b/src/java.base/share/classes/java/lang/ThreadGroup.java @@ -700,23 +700,6 @@ public void uncaughtException(Thread t, Throwable e) { } } - /** - * Does nothing. - * - * @return false - * - * @param b ignored - * - * @deprecated This method was originally intended for controlling suspension - * in low memory conditions. It was never specified. - * - * @since 1.1 - */ - @Deprecated(since="1.2", forRemoval=true) - public boolean allowThreadSuspension(boolean b) { - return false; - } - /** * Returns a string representation of this Thread group. * diff --git a/test/jdk/java/lang/ThreadGroup/BasicTests.java b/test/jdk/java/lang/ThreadGroup/BasicTests.java index 857983eacbb..4829a547848 100644 --- a/test/jdk/java/lang/ThreadGroup/BasicTests.java +++ b/test/jdk/java/lang/ThreadGroup/BasicTests.java @@ -750,13 +750,6 @@ public void testStop() { assertThrows(UnsupportedOperationException.class, () -> group.stop()); } - @Test - public void testAllowThreadSuspension() { - ThreadGroup group = new ThreadGroup("foo"); - assertFalse(group.allowThreadSuspension(false)); - assertFalse(group.allowThreadSuspension(true)); - } - @Test public void testNull1() { assertThrows(NullPointerException.class, From 553ba65dc44b601e048c53cd1c48d668de9dcf1e Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Thu, 8 Dec 2022 20:19:18 +0000 Subject: [PATCH 137/494] 8298402: ProblemList javax/swing/JFileChooser/4847375/bug4847375.java on windows-x64 8298414: ProblemList gc/TestFullGCCount.java on linux-x64 8298417: ProblemList vmTestbase/nsk/stress/strace/strace004.java on 2 platforms 8298419: ProblemList vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java on windows-x64 Reviewed-by: rriggs --- test/hotspot/jtreg/ProblemList.txt | 3 +++ test/jdk/ProblemList.txt | 1 + 2 files changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index fec8dfa1a7c..1cd805f7450 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -80,6 +80,7 @@ gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293,8298073 macosx-x64,macosx-aarch64 gc/stress/TestStressG1Humongous.java 8286554 windows-x64 +gc/TestFullGCCount.java 8298296 linux-x64 ############################################################################# @@ -164,3 +165,5 @@ vmTestbase/vm/mlvm/indy/func/jvmti/mergeCP_indy2manySame_b/TestDescription.java vmTestbase/nsk/jdwp/ThreadReference/ForceEarlyReturn/forceEarlyReturn001/forceEarlyReturn001.java 7199837 generic-all vmTestbase/nsk/stress/except/except012.java 8297977 generic-all +vmTestbase/nsk/stress/strace/strace004.java 8297824 macosx-x64,windows-x64 +vmTestbase/nsk/monitoring/ThreadMXBean/ThreadInfo/Multi/Multi005/TestDescription.java 8076494 windows-x64 diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8edd5818c96..d94e0b77c0b 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -672,6 +672,7 @@ javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8297296 macosx-all javax/swing/JFileChooser/8046391/bug8046391.java 8293862 windows-x64 +javax/swing/JFileChooser/4847375/bug4847375.java 8293862 windows-x64 java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392 windows-x64 java/awt/Mixing/AWT_Mixing/OpaqueOverlapping.java 8294264 windows-x64 java/awt/Mixing/AWT_Mixing/ViewportOverlapping.java 8253184,8295813 windows-x64 From 3dfadeebd023efb03a400f2b2656567a4154421a Mon Sep 17 00:00:00 2001 From: Quan Anh Mai Date: Thu, 8 Dec 2022 20:25:20 +0000 Subject: [PATCH 138/494] 8292289: [vectorapi] Improve the implementation of VectorTestNode Reviewed-by: xgong, kvn --- src/hotspot/cpu/aarch64/aarch64_vector.ad | 43 ++--- src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 | 43 ++--- src/hotspot/cpu/aarch64/matcher_aarch64.hpp | 10 + src/hotspot/cpu/arm/matcher_arm.hpp | 10 + src/hotspot/cpu/ppc/matcher_ppc.hpp | 10 + src/hotspot/cpu/riscv/matcher_riscv.hpp | 10 + src/hotspot/cpu/s390/matcher_s390.hpp | 10 + src/hotspot/cpu/x86/assembler_x86.cpp | 31 ++- src/hotspot/cpu/x86/assembler_x86.hpp | 3 + src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 78 +++----- src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp | 3 +- src/hotspot/cpu/x86/macroAssembler_x86.cpp | 20 -- src/hotspot/cpu/x86/macroAssembler_x86.hpp | 3 - src/hotspot/cpu/x86/matcher_x86.hpp | 19 ++ src/hotspot/cpu/x86/x86.ad | 177 ++++-------------- src/hotspot/share/opto/matcher.hpp | 1 + src/hotspot/share/opto/phaseX.cpp | 5 + src/hotspot/share/opto/subnode.cpp | 19 +- src/hotspot/share/opto/vectorIntrinsics.cpp | 18 +- src/hotspot/share/opto/vectornode.hpp | 12 +- src/hotspot/share/runtime/vmStructs.cpp | 2 +- .../compiler/lib/ir_framework/IRNode.java | 5 + .../compiler/vectorapi/TestVectorTest.java | 71 +++++++ 23 files changed, 324 insertions(+), 279 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java diff --git a/src/hotspot/cpu/aarch64/aarch64_vector.ad b/src/hotspot/cpu/aarch64/aarch64_vector.ad index 0a64d35dd47..ed84c5da109 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector.ad +++ b/src/hotspot/cpu/aarch64/aarch64_vector.ad @@ -5869,67 +5869,62 @@ instruct vroundD(vReg dst, vReg src, immI rmode) %{ // anytrue -instruct vtest_anytrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_anytrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP tmp, KILL cr); - format %{ "vtest_anytrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_anytrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ addv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, zr); - __ csetw($dst$$Register, Assembler::NE); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, zr); %} ins_pipe(pipe_slow); %} -instruct vtest_anytrue_sve(iRegINoSp dst, pReg src1, pReg src2, rFlagsReg cr) %{ +instruct vtest_anytrue_sve(rFlagsReg cr, pReg src1, pReg src2) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vtest_anytrue_sve $dst, $src1\t# KILL cr" %} + match(Set cr (VectorTest src1 src2)); + format %{ "vtest_anytrue_sve $src1" %} ins_encode %{ // "src2" is not used for sve. __ sve_ptest(ptrue, $src1$$PRegister); - __ csetw($dst$$Register, Assembler::NE); %} ins_pipe(pipe_slow); %} // alltrue -instruct vtest_alltrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_alltrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP tmp, KILL cr); - format %{ "vtest_alltrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_alltrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ uminv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, 0xff); - __ csetw($dst$$Register, Assembler::EQ); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, 0xff); %} ins_pipe(pipe_slow); %} -instruct vtest_alltrue_sve(iRegINoSp dst, pReg src1, pReg src2, pReg ptmp, rFlagsReg cr) %{ +instruct vtest_alltrue_sve(rFlagsReg cr, pReg src1, pReg src2, pReg ptmp) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP ptmp, KILL cr); - format %{ "vtest_alltrue_sve $dst, $src1, $src2\t# KILL $ptmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP ptmp); + format %{ "vtest_alltrue_sve $src1, $src2\t# KILL $ptmp" %} ins_encode %{ __ sve_eors($ptmp$$PRegister, ptrue, $src1$$PRegister, $src2$$PRegister); - __ csetw($dst$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 index 65adf7d6ee0..83b2d512f52 100644 --- a/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 +++ b/src/hotspot/cpu/aarch64/aarch64_vector_ad.m4 @@ -4241,67 +4241,62 @@ instruct vroundD(vReg dst, vReg src, immI rmode) %{ // anytrue -instruct vtest_anytrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_anytrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP tmp, KILL cr); - format %{ "vtest_anytrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_anytrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ addv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, zr); - __ csetw($dst$$Register, Assembler::NE); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, zr); %} ins_pipe(pipe_slow); %} -instruct vtest_anytrue_sve(iRegINoSp dst, pReg src1, pReg src2, rFlagsReg cr) %{ +instruct vtest_anytrue_sve(rFlagsReg cr, pReg src1, pReg src2) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vtest_anytrue_sve $dst, $src1\t# KILL cr" %} + match(Set cr (VectorTest src1 src2)); + format %{ "vtest_anytrue_sve $src1" %} ins_encode %{ // "src2" is not used for sve. __ sve_ptest(ptrue, $src1$$PRegister); - __ csetw($dst$$Register, Assembler::NE); %} ins_pipe(pipe_slow); %} // alltrue -instruct vtest_alltrue_neon(iRegINoSp dst, vReg src1, vReg src2, vReg tmp, rFlagsReg cr) %{ +instruct vtest_alltrue_neon(rFlagsReg cr, vReg src1, vReg src2, vReg tmp) %{ predicate(UseSVE == 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP tmp, KILL cr); - format %{ "vtest_alltrue_neon $dst, $src1\t# KILL $tmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "vtest_alltrue_neon $src1\t# KILL $tmp" %} ins_encode %{ // No need to use src2. uint length_in_bytes = Matcher::vector_length_in_bytes(this, $src1); assert(length_in_bytes == 8 || length_in_bytes == 16, "must be"); __ uminv($tmp$$FloatRegister, length_in_bytes == 16 ? __ T16B : __ T8B, $src1$$FloatRegister); - __ umov($dst$$Register, $tmp$$FloatRegister, __ B, 0); - __ cmpw($dst$$Register, 0xff); - __ csetw($dst$$Register, Assembler::EQ); + __ umov(rscratch1, $tmp$$FloatRegister, __ B, 0); + __ cmpw(rscratch1, 0xff); %} ins_pipe(pipe_slow); %} -instruct vtest_alltrue_sve(iRegINoSp dst, pReg src1, pReg src2, pReg ptmp, rFlagsReg cr) %{ +instruct vtest_alltrue_sve(rFlagsReg cr, pReg src1, pReg src2, pReg ptmp) %{ predicate(UseSVE > 0 && static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2)); - effect(TEMP ptmp, KILL cr); - format %{ "vtest_alltrue_sve $dst, $src1, $src2\t# KILL $ptmp, cr" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP ptmp); + format %{ "vtest_alltrue_sve $src1, $src2\t# KILL $ptmp" %} ins_encode %{ __ sve_eors($ptmp$$PRegister, ptrue, $src1$$PRegister, $src2$$PRegister); - __ csetw($dst$$Register, Assembler::EQ); %} ins_pipe(pipe_slow); %} diff --git a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp index a7dfe47ffb8..45b7dbf8c56 100644 --- a/src/hotspot/cpu/aarch64/matcher_aarch64.hpp +++ b/src/hotspot/cpu/aarch64/matcher_aarch64.hpp @@ -163,6 +163,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // An all-set mask is used for the alltrue vector test with SVE + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return is_predicate && is_alltrue; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return is_alltrue ? BoolTest::eq : BoolTest::ne; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/arm/matcher_arm.hpp b/src/hotspot/cpu/arm/matcher_arm.hpp index 3959d61e71c..1e8f7683e76 100644 --- a/src/hotspot/cpu/arm/matcher_arm.hpp +++ b/src/hotspot/cpu/arm/matcher_arm.hpp @@ -155,6 +155,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = false; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/ppc/matcher_ppc.hpp b/src/hotspot/cpu/ppc/matcher_ppc.hpp index 05e06a21b1c..f78cb2d7803 100644 --- a/src/hotspot/cpu/ppc/matcher_ppc.hpp +++ b/src/hotspot/cpu/ppc/matcher_ppc.hpp @@ -164,6 +164,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/riscv/matcher_riscv.hpp b/src/hotspot/cpu/riscv/matcher_riscv.hpp index ff93ddf80a4..7d234d42b9b 100644 --- a/src/hotspot/cpu/riscv/matcher_riscv.hpp +++ b/src/hotspot/cpu/riscv/matcher_riscv.hpp @@ -161,6 +161,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = false; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/s390/matcher_s390.hpp b/src/hotspot/cpu/s390/matcher_s390.hpp index 436271c3022..d683f35a8a4 100644 --- a/src/hotspot/cpu/s390/matcher_s390.hpp +++ b/src/hotspot/cpu/s390/matcher_s390.hpp @@ -153,6 +153,16 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Some architecture needs a helper to check for alltrue vector + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return false; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + return BoolTest::illegal; + } + // Returns pre-selection estimated size of a vector operation. static int vector_op_pre_select_sz_estimate(int vopc, BasicType ety, int vlen) { switch(vopc) { diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index e1a68906d8d..020f8739317 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -5447,13 +5447,38 @@ void Assembler::vptest(XMMRegister dst, XMMRegister src, int vector_len) { emit_int16(0x17, (0xC0 | encode)); } +void Assembler::vtestps(XMMRegister dst, XMMRegister src, int vector_len) { + assert(VM_Version::supports_avx(), ""); + InstructionAttr attributes(vector_len, /* rex_w */ false, /* legacy_mode */ true, /* no_mask_reg */ true, /* uses_vl */ false); + int encode = vex_prefix_and_encode(dst->encoding(), 0, src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x0E, (0xC0 | encode)); +} + void Assembler::evptestmb(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { - assert(VM_Version::supports_avx512vlbw(), ""); - // Encoding: EVEX.NDS.XXX.66.0F.W0 DB /r + assert(vector_len == AVX_512bit ? VM_Version::supports_avx512bw() : VM_Version::supports_avx512vlbw(), ""); + // Encoding: EVEX.NDS.XXX.66.0F38.W0 DB /r + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x26, (0xC0 | encode)); +} + +void Assembler::evptestmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx512vl(), ""); + // Encoding: EVEX.NDS.XXX.66.0F38.W0 DB /r InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); attributes.set_is_evex_instruction(); int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_66, VEX_OPCODE_0F_38, &attributes); - emit_int16((unsigned char)0x26, (0xC0 | encode)); + emit_int16(0x27, (0xC0 | encode)); +} + +void Assembler::evptestnmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len) { + assert(vector_len == AVX_512bit ? VM_Version::supports_evex() : VM_Version::supports_avx512vl(), ""); + // Encoding: EVEX.NDS.XXX.F3.0F38.W0 DB /r + InstructionAttr attributes(vector_len, /* vex_w */ false, /* legacy_mode */ false, /* no_mask_reg */ true, /* uses_vl */ true); + attributes.set_is_evex_instruction(); + int encode = vex_prefix_and_encode(dst->encoding(), nds->encoding(), src->encoding(), VEX_SIMD_F3, VEX_OPCODE_0F_38, &attributes); + emit_int16(0x27, (0xC0 | encode)); } void Assembler::punpcklbw(XMMRegister dst, Address src) { diff --git a/src/hotspot/cpu/x86/assembler_x86.hpp b/src/hotspot/cpu/x86/assembler_x86.hpp index a5d8f2dabfc..a300dc91dc2 100644 --- a/src/hotspot/cpu/x86/assembler_x86.hpp +++ b/src/hotspot/cpu/x86/assembler_x86.hpp @@ -1973,9 +1973,12 @@ class Assembler : public AbstractAssembler { void vptest(XMMRegister dst, Address src); void evptestmb(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evptestmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); + void evptestnmd(KRegister dst, XMMRegister nds, XMMRegister src, int vector_len); // Vector compare void vptest(XMMRegister dst, XMMRegister src, int vector_len); + void vtestps(XMMRegister dst, XMMRegister src, int vector_len); // Interleave Low Bytes void punpcklbw(XMMRegister dst, XMMRegister src); diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 26c19ee6f1d..7436322f878 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -2415,58 +2415,32 @@ void C2_MacroAssembler::evpblend(BasicType typ, XMMRegister dst, KRegister kmask } } -void C2_MacroAssembler::vectortest(int bt, int vlen, XMMRegister src1, XMMRegister src2, - XMMRegister vtmp1, XMMRegister vtmp2, KRegister mask) { - switch(vlen) { - case 4: - assert(vtmp1 != xnoreg, "required."); - // Broadcast lower 32 bits to 128 bits before ptest - pshufd(vtmp1, src1, 0x0); - if (bt == BoolTest::overflow) { - assert(vtmp2 != xnoreg, "required."); - pshufd(vtmp2, src2, 0x0); - } else { - assert(vtmp2 == xnoreg, "required."); - vtmp2 = src2; - } - ptest(vtmp1, vtmp2); - break; - case 8: - assert(vtmp1 != xnoreg, "required."); - // Broadcast lower 64 bits to 128 bits before ptest - pshufd(vtmp1, src1, 0x4); - if (bt == BoolTest::overflow) { - assert(vtmp2 != xnoreg, "required."); - pshufd(vtmp2, src2, 0x4); - } else { - assert(vtmp2 == xnoreg, "required."); - vtmp2 = src2; - } - ptest(vtmp1, vtmp2); - break; - case 16: - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - ptest(src1, src2); - break; - case 32: - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - vptest(src1, src2, Assembler::AVX_256bit); - break; - case 64: - { - assert((vtmp1 == xnoreg) && (vtmp2 == xnoreg), "required."); - evpcmpeqb(mask, src1, src2, Assembler::AVX_512bit); - if (bt == BoolTest::ne) { - ktestql(mask, mask); - } else { - assert(bt == BoolTest::overflow, "required"); - kortestql(mask, mask); - } - } - break; - default: - assert(false,"Should not reach here."); - break; +void C2_MacroAssembler::vectortest(BasicType bt, XMMRegister src1, XMMRegister src2, XMMRegister vtmp, int vlen_in_bytes) { + assert(vlen_in_bytes <= 32, ""); + int esize = type2aelembytes(bt); + if (vlen_in_bytes == 32) { + assert(vtmp == xnoreg, "required."); + if (esize >= 4) { + vtestps(src1, src2, AVX_256bit); + } else { + vptest(src1, src2, AVX_256bit); + } + return; + } + if (vlen_in_bytes < 16) { + // Duplicate the lower part to fill the whole register, + // Don't need to do so for src2 + assert(vtmp != xnoreg, "required"); + int shuffle_imm = (vlen_in_bytes == 4) ? 0x00 : 0x04; + pshufd(vtmp, src1, shuffle_imm); + } else { + assert(vtmp == xnoreg, "required"); + vtmp = src1; + } + if (esize >= 4 && VM_Version::supports_avx()) { + vtestps(vtmp, src2, AVX_128bit); + } else { + ptest(vtmp, src2); } } diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp index 029918a4f36..2bd90fc24ea 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.hpp @@ -138,8 +138,7 @@ void get_elem(BasicType typ, XMMRegister dst, XMMRegister src, int elemindex, XMMRegister vtmp = xnoreg); // vector test - void vectortest(int bt, int vlen, XMMRegister src1, XMMRegister src2, - XMMRegister vtmp1 = xnoreg, XMMRegister vtmp2 = xnoreg, KRegister mask = knoreg); + void vectortest(BasicType bt, XMMRegister src1, XMMRegister src2, XMMRegister vtmp, int vlen_in_bytes); // Covert B2X void vconvert_b2x(BasicType to_elem_bt, XMMRegister dst, XMMRegister src, int vlen_enc); diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.cpp b/src/hotspot/cpu/x86/macroAssembler_x86.cpp index 76d348b6a05..ecdefad32a5 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.cpp @@ -9013,26 +9013,6 @@ void MacroAssembler::evand(BasicType type, XMMRegister dst, KRegister mask, XMMR } } -void MacroAssembler::anytrue(Register dst, uint masklen, KRegister src1, KRegister src2) { - masklen = masklen < 8 ? 8 : masklen; - ktest(masklen, src1, src2); - setb(Assembler::notZero, dst); - movzbl(dst, dst); -} - -void MacroAssembler::alltrue(Register dst, uint masklen, KRegister src1, KRegister src2, KRegister kscratch) { - if (masklen < 8) { - knotbl(kscratch, src2); - kortestbl(src1, kscratch); - setb(Assembler::carrySet, dst); - movzbl(dst, dst); - } else { - ktest(masklen, src1, src2); - setb(Assembler::carrySet, dst); - movzbl(dst, dst); - } -} - void MacroAssembler::kortest(uint masklen, KRegister src1, KRegister src2) { switch(masklen) { case 8: diff --git a/src/hotspot/cpu/x86/macroAssembler_x86.hpp b/src/hotspot/cpu/x86/macroAssembler_x86.hpp index 5a0a3d8c9a1..2baff498df6 100644 --- a/src/hotspot/cpu/x86/macroAssembler_x86.hpp +++ b/src/hotspot/cpu/x86/macroAssembler_x86.hpp @@ -1768,9 +1768,6 @@ class MacroAssembler: public Assembler { using Assembler::vpternlogq; void vpternlogq(XMMRegister dst, int imm8, XMMRegister src2, AddressLiteral src3, int vector_len, Register rscratch = noreg); - void alltrue(Register dst, uint masklen, KRegister src1, KRegister src2, KRegister kscratch); - void anytrue(Register dst, uint masklen, KRegister src, KRegister kscratch); - void cmov32( Condition cc, Register dst, Address src); void cmov32( Condition cc, Register dst, Register src); diff --git a/src/hotspot/cpu/x86/matcher_x86.hpp b/src/hotspot/cpu/x86/matcher_x86.hpp index bc6524aed55..82a39fe8b1d 100644 --- a/src/hotspot/cpu/x86/matcher_x86.hpp +++ b/src/hotspot/cpu/x86/matcher_x86.hpp @@ -183,6 +183,25 @@ // Implements a variant of EncodeISOArrayNode that encode ASCII only static const bool supports_encode_ascii_array = true; + // Without predicated input, an all-one vector is needed for the alltrue vector test + static constexpr bool vectortest_needs_second_argument(bool is_alltrue, bool is_predicate) { + return is_alltrue && !is_predicate; + } + + // BoolTest mask for vector test intrinsics + static constexpr BoolTest::mask vectortest_mask(bool is_alltrue, bool is_predicate, int vlen) { + if (!is_alltrue) { + return BoolTest::ne; + } + if (!is_predicate) { + return BoolTest::lt; + } + if ((vlen == 8 && !VM_Version::supports_avx512dq()) || vlen < 8) { + return BoolTest::eq; + } + return BoolTest::lt; + } + // Returns pre-selection estimated size of a vector operation. // Currently, it's a rudimentary heuristic based on emitted code size for complex // IR nodes used by unroll policy. Idea is to constrain unrolling factor and prevent diff --git a/src/hotspot/cpu/x86/x86.ad b/src/hotspot/cpu/x86/x86.ad index d70389245ad..80f0c0f4b49 100644 --- a/src/hotspot/cpu/x86/x86.ad +++ b/src/hotspot/cpu/x86/x86.ad @@ -1850,8 +1850,6 @@ const bool Matcher::match_rule_supported_vector(int opcode, int vlen, BasicType return false; // Implementation limitation } else if (size_in_bits < 32) { return false; // Implementation limitation - } else if (size_in_bits == 512 && (VM_Version::supports_avx512bw() == false)) { - return false; // Implementation limitation } break; case Op_VectorLoadShuffle: @@ -8048,169 +8046,70 @@ instruct vabsnegD(vec dst, vec src) %{ //------------------------------------- VectorTest -------------------------------------------- #ifdef _LP64 -instruct vptest_alltrue_lt16(rRegI dst, legVec src1, legVec src2, legVec vtmp1, legVec vtmp2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)) < 16 && - static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP vtmp1, TEMP vtmp2, KILL cr); - format %{ "vptest_alltrue_lt16 $dst,$src1, $src2\t! using $vtmp1, $vtmp2 and $cr as TEMP" %} +instruct vptest_lt16(rFlagsRegU cr, legVec src1, legVec src2, legVec vtmp) %{ + predicate(Matcher::vector_length_in_bytes(n->in(1)) < 16); + match(Set cr (VectorTest src1 src2)); + effect(TEMP vtmp); + format %{ "vptest_lt16 $src1, $src2\t! using $vtmp as TEMP" %} ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src1); int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::overflow, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp1$$XMMRegister, $vtmp2$$XMMRegister); - __ setb(Assembler::carrySet, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); + __ vectortest(bt, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister, vlen); %} ins_pipe( pipe_slow ); %} -instruct vptest_alltrue_ge16(rRegI dst, legVec src1, legVec src2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)) < 64 && - static_cast(n)->get_predicate() == BoolTest::overflow); - match(Set dst (VectorTest src1 src2 )); - effect(KILL cr); - format %{ "vptest_alltrue_ge16 $dst,$src1, $src2\t! using $cr as TEMP" %} +instruct vptest_ge16(rFlagsRegU cr, legVec src1, legVec src2) %{ + predicate(Matcher::vector_length_in_bytes(n->in(1)) >= 16); + match(Set cr (VectorTest src1 src2)); + format %{ "vptest_ge16 $src1, $src2\n\t" %} ins_encode %{ + BasicType bt = Matcher::vector_element_basic_type(this, $src1); int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::overflow, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); - __ setb(Assembler::carrySet, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); - %} - ins_pipe( pipe_slow ); -%} - -instruct vptest_alltrue_lt8_evex(rRegI dst, kReg src1, kReg src2, kReg kscratch, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::overflow && - n->in(1)->bottom_type()->isa_vectmask() && - Matcher::vector_length(n->in(1)) < 8); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr, TEMP kscratch); - format %{ "vptest_alltrue_lt8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - uint masklen = Matcher::vector_length(this, $src1); - __ alltrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister, $kscratch$$KRegister); + __ vectortest(bt, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, vlen); %} ins_pipe( pipe_slow ); %} - -instruct vptest_alltrue_ge8_evex(rRegI dst, kReg src1, kReg src2, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::overflow && - n->in(1)->bottom_type()->isa_vectmask() && - Matcher::vector_length(n->in(1)) >= 8); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vptest_alltrue_ge8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} +instruct ktest_alltrue_le8(rFlagsRegU cr, kReg src1, kReg src2, rRegI tmp) %{ + predicate((Matcher::vector_length(n->in(1)) < 8 || + (Matcher::vector_length(n->in(1)) == 8 && !VM_Version::supports_avx512dq())) && + static_cast(n)->get_predicate() == BoolTest::overflow); + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "ktest_alltrue_le8 $src1, $src2\t! using $tmp as TEMP" %} ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); uint masklen = Matcher::vector_length(this, $src1); - __ alltrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister, knoreg); - %} - ins_pipe( pipe_slow ); -%} - - -instruct vptest_anytrue_lt16(rRegI dst, legVec src1, legVec src2, legVec vtmp, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)) < 16 && - static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(TEMP vtmp, KILL cr); - format %{ "vptest_anytrue_lt16 $dst,$src1,$src2\t! using $vtmp, $cr as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister); - __ setb(Assembler::notZero, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); + __ kmovwl($tmp$$Register, $src1$$KRegister); + __ andl($tmp$$Register, (1 << masklen) - 1); + __ cmpl($tmp$$Register, (1 << masklen) - 1); %} ins_pipe( pipe_slow ); %} -instruct vptest_anytrue_ge16(rRegI dst, legVec src1, legVec src2, rFlagsReg cr) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)) < 64 && +instruct ktest_anytrue_le8(rFlagsRegU cr, kReg src1, kReg src2, rRegI tmp) %{ + predicate((Matcher::vector_length(n->in(1)) < 8 || + (Matcher::vector_length(n->in(1)) == 8 && !VM_Version::supports_avx512dq())) && static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2 )); - effect(KILL cr); - format %{ "vptest_anytrue_ge16 $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); - __ setb(Assembler::notZero, $dst$$Register); - __ movzbl($dst$$Register, $dst$$Register); - %} - ins_pipe( pipe_slow ); -%} - -instruct vptest_anytrue_evex(rRegI dst, kReg src1, kReg src2, rFlagsReg cr) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n)->get_predicate() == BoolTest::ne); - match(Set dst (VectorTest src1 src2)); - effect(KILL cr); - format %{ "vptest_anytrue_lt8_evex $dst,$src1,$src2\t! using $cr as TEMP" %} - ins_encode %{ - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - uint masklen = Matcher::vector_length(this, $src1); - __ anytrue($dst$$Register, masklen, $src1$$KRegister, $src2$$KRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct cmpvptest_anytrue_lt16(rFlagsReg cr, legVec src1, legVec src2, immI_0 zero, legVec vtmp) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 4 && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) < 16 && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - effect(TEMP vtmp); - format %{ "cmpvptest_anytrue_lt16 $src1,$src2\t! using $vtmp as TEMP" %} - ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, $vtmp$$XMMRegister); - %} - ins_pipe( pipe_slow ); -%} - -instruct cmpvptest_anytrue_ge16(rFlagsReg cr, legVec src1, legVec src2, immI_0 zero) %{ - predicate(!VM_Version::supports_avx512bwdq() && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) >= 16 && - Matcher::vector_length_in_bytes(n->in(1)->in(1)) < 64 && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - format %{ "cmpvptest_anytrue_ge16 $src1,$src2\t!" %} + match(Set cr (VectorTest src1 src2)); + effect(TEMP tmp); + format %{ "ktest_anytrue_le8 $src1, $src2\t! using $tmp as TEMP" %} ins_encode %{ - int vlen = Matcher::vector_length_in_bytes(this, $src1); - __ vectortest(BoolTest::ne, vlen, $src1$$XMMRegister, $src2$$XMMRegister, xnoreg, xnoreg, knoreg); + uint masklen = Matcher::vector_length(this, $src1); + __ kmovwl($tmp$$Register, $src1$$KRegister); + __ andl($tmp$$Register, (1 << masklen) - 1); %} ins_pipe( pipe_slow ); %} -instruct cmpvptest_anytrue_evex(rFlagsReg cr, kReg src1, kReg src2, immI_0 zero) %{ - predicate(VM_Version::supports_avx512bwdq() && - static_cast(n->in(1))->get_predicate() == BoolTest::ne); - match(Set cr (CmpI (VectorTest src1 src2) zero)); - format %{ "cmpvptest_anytrue_evex $src1,$src2\t!" %} +instruct ktest_ge8(rFlagsRegU cr, kReg src1, kReg src2) %{ + predicate(Matcher::vector_length(n->in(1)) >= 16 || + (Matcher::vector_length(n->in(1)) == 8 && VM_Version::supports_avx512dq())); + match(Set cr (VectorTest src1 src2)); + format %{ "ktest_ge8 $src1, $src2\n\t" %} ins_encode %{ uint masklen = Matcher::vector_length(this, $src1); - const MachNode* mask1 = static_cast(this->in(this->operand_index($src1))); - const MachNode* mask2 = static_cast(this->in(this->operand_index($src2))); - assert(0 == Type::cmp(mask1->bottom_type(), mask2->bottom_type()), ""); - masklen = masklen < 8 ? 8 : masklen; - __ ktest(masklen, $src1$$KRegister, $src2$$KRegister); + __ kortest(masklen, $src1$$KRegister, $src1$$KRegister); %} ins_pipe( pipe_slow ); %} diff --git a/src/hotspot/share/opto/matcher.hpp b/src/hotspot/share/opto/matcher.hpp index 9a6dab741b4..2de901c6135 100644 --- a/src/hotspot/share/opto/matcher.hpp +++ b/src/hotspot/share/opto/matcher.hpp @@ -31,6 +31,7 @@ #include "opto/node.hpp" #include "opto/phaseX.hpp" #include "opto/regmask.hpp" +#include "opto/subnode.hpp" #include "runtime/vm_version.hpp" class Compile; diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index beafcb3beb9..d5c861e14aa 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1248,6 +1248,11 @@ Node *PhaseIterGVN::transform_old(Node* n) { assert(!_table.find_index(n->_idx), "found duplicate entry in table"); } + // Allow Bool -> Cmp idealisation in late inlining intrinsics that return a bool + if (n->is_Cmp()) { + add_users_to_worklist(n); + } + // Apply the Ideal call in a loop until it no longer applies Node* k = n; DEBUG_ONLY(dead_loop_check(k);) diff --git a/src/hotspot/share/opto/subnode.cpp b/src/hotspot/share/opto/subnode.cpp index 0f9f5483b66..c326d2ce527 100644 --- a/src/hotspot/share/opto/subnode.cpp +++ b/src/hotspot/share/opto/subnode.cpp @@ -1427,7 +1427,10 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { Node *cmp = in(1); if( !cmp->is_Sub() ) return NULL; int cop = cmp->Opcode(); - if( cop == Op_FastLock || cop == Op_FastUnlock || cmp->is_SubTypeCheck()) return NULL; + if( cop == Op_FastLock || cop == Op_FastUnlock || + cmp->is_SubTypeCheck() || cop == Op_VectorTest ) { + return NULL; + } Node *cmp1 = cmp->in(1); Node *cmp2 = cmp->in(2); if( !cmp1 ) return NULL; @@ -1459,6 +1462,20 @@ Node *BoolNode::Ideal(PhaseGVN *phase, bool can_reshape) { return new BoolNode( cmp, _test.commute() ); } + // Change "bool eq/ne (cmp (cmove (bool tst (cmp2)) 1 0) 0)" into "bool tst/~tst (cmp2)" + if (cop == Op_CmpI && + (_test._test == BoolTest::eq || _test._test == BoolTest::ne) && + cmp1_op == Op_CMoveI && cmp2->find_int_con(1) == 0) { + // 0 should be on the true branch + if (cmp1->in(CMoveNode::IfTrue)->find_int_con(1) == 0 && + cmp1->in(CMoveNode::IfFalse)->find_int_con(0) != 0) { + BoolNode* target = cmp1->in(CMoveNode::Condition)->as_Bool(); + return new BoolNode(target->in(1), + (_test._test == BoolTest::eq) ? target->_test._test : + target->_test.negate()); + } + } + // Change "bool eq/ne (cmp (and X 16) 16)" into "bool ne/eq (cmp (and X 16) 0)". if (cop == Op_CmpI && (_test._test == BoolTest::eq || _test._test == BoolTest::ne) && diff --git a/src/hotspot/share/opto/vectorIntrinsics.cpp b/src/hotspot/share/opto/vectorIntrinsics.cpp index ec4ed774ada..8447ad5a871 100644 --- a/src/hotspot/share/opto/vectorIntrinsics.cpp +++ b/src/hotspot/share/opto/vectorIntrinsics.cpp @@ -1799,14 +1799,24 @@ bool LibraryCallKit::inline_vector_test() { } Node* opd1 = unbox_vector(argument(4), vbox_type, elem_bt, num_elem); - Node* opd2 = unbox_vector(argument(5), vbox_type, elem_bt, num_elem); + Node* opd2; + if (Matcher::vectortest_needs_second_argument(booltest == BoolTest::overflow, + opd1->bottom_type()->isa_vectmask())) { + opd2 = unbox_vector(argument(5), vbox_type, elem_bt, num_elem); + } else { + opd2 = opd1; + } if (opd1 == NULL || opd2 == NULL) { return false; // operand unboxing failed } - Node* test = new VectorTestNode(opd1, opd2, booltest); - test = gvn().transform(test); - set_result(test); + Node* cmp = gvn().transform(new VectorTestNode(opd1, opd2, booltest)); + BoolTest::mask test = Matcher::vectortest_mask(booltest == BoolTest::overflow, + opd1->bottom_type()->isa_vectmask(), num_elem); + Node* bol = gvn().transform(new BoolNode(cmp, test)); + Node* res = gvn().transform(new CMoveINode(bol, gvn().intcon(0), gvn().intcon(1), TypeInt::BOOL)); + + set_result(res); C->set_max_vector_size(MAX2(C->max_vector_size(), (uint)(num_elem * type2aelembytes(elem_bt)))); return true; } diff --git a/src/hotspot/share/opto/vectornode.hpp b/src/hotspot/share/opto/vectornode.hpp index 21a8a8737a6..5d643e8eb5a 100644 --- a/src/hotspot/share/opto/vectornode.hpp +++ b/src/hotspot/share/opto/vectornode.hpp @@ -1422,7 +1422,7 @@ class VectorMaskWrapperNode : public VectorNode { Node* vector_mask() const { return in(2); } }; -class VectorTestNode : public Node { +class VectorTestNode : public CmpNode { private: BoolTest::mask _predicate; @@ -1430,18 +1430,18 @@ class VectorTestNode : public Node { uint size_of() const { return sizeof(*this); } public: - VectorTestNode(Node* in1, Node* in2, BoolTest::mask predicate) : Node(NULL, in1, in2), _predicate(predicate) { + VectorTestNode(Node* in1, Node* in2, BoolTest::mask predicate) : CmpNode(in1, in2), _predicate(predicate) { assert(in2->bottom_type()->is_vect() == in2->bottom_type()->is_vect(), "same vector type"); } virtual int Opcode() const; virtual uint hash() const { return Node::hash() + _predicate; } + virtual const Type* Value(PhaseGVN* phase) const { return TypeInt::CC; } + virtual const Type* sub(const Type*, const Type*) const { return TypeInt::CC; } + BoolTest::mask get_predicate() const { return _predicate; } + virtual bool cmp( const Node &n ) const { return Node::cmp(n) && _predicate == ((VectorTestNode&)n)._predicate; } - virtual const Type *bottom_type() const { return TypeInt::BOOL; } - virtual uint ideal_reg() const { return Op_RegI; } // TODO Should be RegFlags but due to missing comparison flags for BoolTest - // in middle-end, we make it boolean result directly. - BoolTest::mask get_predicate() const { return _predicate; } }; class VectorBlendNode : public VectorNode { diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index aeb2d640648..ebf187a03ce 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -1875,7 +1875,7 @@ declare_c2_type(XorVMaskNode, VectorNode) \ declare_c2_type(VectorBoxNode, Node) \ declare_c2_type(VectorBoxAllocateNode, CallStaticJavaNode) \ - declare_c2_type(VectorTestNode, Node) \ + declare_c2_type(VectorTestNode, CmpNode) \ \ /*********************/ \ /* Adapter Blob Entries */ \ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java index 7e08baab74c..328c5ba4f1b 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/IRNode.java @@ -1114,6 +1114,11 @@ public class IRNode { beforeMatchingNameRegex(VECTOR_UCAST_S2X, "VectorUCastS2X"); } + public static final String VECTOR_TEST = PREFIX + "VECTOR_TEST" + POSTFIX; + static { + beforeMatchingNameRegex(VECTOR_TEST, "VectorTest"); + } + public static final String VFABD = PREFIX + "VFABD" + POSTFIX; static { machOnlyNameRegex(VFABD, "vfabd"); diff --git a/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java new file mode 100644 index 00000000000..35f357c22f2 --- /dev/null +++ b/test/hotspot/jtreg/compiler/vectorapi/TestVectorTest.java @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, 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.vectorapi; + +import compiler.lib.ir_framework.*; +import jdk.incubator.vector.ByteVector; +import jdk.incubator.vector.VectorMask; + +/* + * @test + * @bug 8292289 + * @summary Test idealization of VectorTest intrinsics to eliminate + * the materialization of the result as an int + * @modules jdk.incubator.vector + * @library /test/lib / + * @requires (os.simpleArch == "x64" & vm.cpu.features ~= ".*sse4.*" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) + * | os.arch == "aarch64" + * @run driver compiler.vectorapi.TestVectorTest + */ +public class TestVectorTest { + public static void main(String[] args) { + TestFramework.runWithFlags("--add-modules=jdk.incubator.vector"); + } + + @DontInline + public int call() { return 1; } + + @Test + @IR(failOn = {IRNode.CMP_I, IRNode.CMOVE_I}) + @IR(counts = {IRNode.VECTOR_TEST, "1"}) + public int branch(long maskLong) { + var mask = VectorMask.fromLong(ByteVector.SPECIES_PREFERRED, maskLong); + return mask.allTrue() ? call() : 0; + } + + @Test + @IR(failOn = {IRNode.CMP_I}) + @IR(counts = {IRNode.VECTOR_TEST, "1", IRNode.CMOVE_I, "1"}) + public int cmove(long maskLong) { + var mask = VectorMask.fromLong(ByteVector.SPECIES_PREFERRED, maskLong); + return mask.allTrue() ? 1 : 0; + } + + @Run(test = {"branch", "cmove"}) + public void run() { + branch(-1); + branch(100); + cmove(-1); + cmove(100); + } +} From c16eb89ce0d59f2ff83b6db0bee3e384ec8d5efe Mon Sep 17 00:00:00 2001 From: "Y. Srinivas Ramakrishna" Date: Thu, 8 Dec 2022 21:54:16 +0000 Subject: [PATCH 139/494] 8298138: Shenandoah: HdrSeq asserts "sub-bucket index (512) overflow for value ( 1.00)" Reviewed-by: rkennke, shade --- .../gc/shenandoah/shenandoahNumberSeq.cpp | 4 +- .../gc/shenandoah/shenandoahNumberSeq.hpp | 2 +- .../shenandoah/test_shenandoahNumberSeq.cpp | 74 +++++++++++++++++++ 3 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 test/hotspot/gtest/gc/shenandoah/test_shenandoahNumberSeq.cpp diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp index 33d5df425b3..c0fc3aca5a7 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.cpp @@ -56,7 +56,7 @@ void HdrSeq::add(double val) { int mag; if (v > 0) { mag = 0; - while (v > 1) { + while (v >= 1) { mag++; v /= 10; } @@ -71,7 +71,7 @@ void HdrSeq::add(double val) { int bucket = -MagMinimum + mag; int sub_bucket = (int) (v * ValBuckets); - // Defensively saturate for product bits: + // Defensively saturate for product bits if (bucket < 0) { assert (false, "bucket index (%d) underflow for value (%8.2f)", bucket, val); bucket = 0; diff --git a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp index 9f9cb2ecaaf..42f91f6a9b8 100644 --- a/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp +++ b/src/hotspot/share/gc/shenandoah/shenandoahNumberSeq.hpp @@ -55,7 +55,7 @@ class HdrSeq: public NumberSeq { // Binary magnitude sequence stores the power-of-two histogram. // It has very low memory requirements, and is thread-safe. When accuracy // is not needed, it is preferred over HdrSeq. -class BinaryMagnitudeSeq { +class BinaryMagnitudeSeq : public CHeapObj { private: size_t _sum; size_t* _mags; diff --git a/test/hotspot/gtest/gc/shenandoah/test_shenandoahNumberSeq.cpp b/test/hotspot/gtest/gc/shenandoah/test_shenandoahNumberSeq.cpp new file mode 100644 index 00000000000..eddc11daca1 --- /dev/null +++ b/test/hotspot/gtest/gc/shenandoah/test_shenandoahNumberSeq.cpp @@ -0,0 +1,74 @@ +/* + * Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "gc/shenandoah/shenandoahNumberSeq.hpp" +#include +#include "unittest.hpp" +#include "utilities/ostream.hpp" + +class ShenandoahNumberSeqTest: public ::testing::Test { + protected: + HdrSeq seq; +}; + +class BasicShenandoahNumberSeqTest: public ShenandoahNumberSeqTest { + protected: + const double err = 0.5; + BasicShenandoahNumberSeqTest() { + seq.add(0); + seq.add(1); + seq.add(10); + for (int i = 0; i < 7; i++) { + seq.add(100); + } + std::cout << " p0 = " << seq.percentile(0); + std::cout << " p10 = " << seq.percentile(10); + std::cout << " p20 = " << seq.percentile(20); + std::cout << " p30 = " << seq.percentile(30); + std::cout << " p50 = " << seq.percentile(50); + std::cout << " p80 = " << seq.percentile(80); + std::cout << " p90 = " << seq.percentile(90); + std::cout << " p100 = " << seq.percentile(100); + } +}; + +TEST_VM_F(BasicShenandoahNumberSeqTest, maximum_test) { + EXPECT_EQ(seq.maximum(), 100); +} + +TEST_VM_F(BasicShenandoahNumberSeqTest, minimum_test) { + EXPECT_EQ(0, seq.percentile(0)); +} + +TEST_VM_F(BasicShenandoahNumberSeqTest, percentile_test) { + EXPECT_NEAR(0, seq.percentile(10), err); + EXPECT_NEAR(1, seq.percentile(20), err); + EXPECT_NEAR(10, seq.percentile(30), err); + EXPECT_NEAR(100, seq.percentile(40), err); + EXPECT_NEAR(100, seq.percentile(50), err); + EXPECT_NEAR(100, seq.percentile(75), err); + EXPECT_NEAR(100, seq.percentile(90), err); + EXPECT_NEAR(100, seq.percentile(100), err); +} From 5540a8c5b7160ab5c67bb84631e3de54fa5aeceb Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Thu, 8 Dec 2022 23:28:48 +0000 Subject: [PATCH 140/494] 8298083: The "CheckBox/RadioButton[Enabled/Disabled].textForeground" stoped working Reviewed-by: psadhukhan --- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 14 +------ .../javax/swing/plaf/synth/SynthStyle.java | 10 +---- test/jdk/ProblemList.txt | 1 + .../JRadioButton/4314194/bug4314194.java | 40 +++++++++++++------ 4 files changed, 31 insertions(+), 34 deletions(-) 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 f645add8f45..9f1b468007f 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -286,18 +286,6 @@ else if (type == ColorType.TEXT_FOREGROUND) { } } } - - if ((c instanceof JCheckBox) && (state & SynthConstants.DISABLED) != 0) { - if (UIManager.getColor("CheckBox.disabledText") != null) { - return UIManager.getColor("CheckBox.disabledText"); - } - } else if ((c instanceof JRadioButton) && - (state & SynthConstants.DISABLED) != 0) { - if (UIManager.getColor("RadioButton.disabledText") != null) { - return UIManager.getColor("RadioButton.disabledText"); - } - } - return getColorForState(context, type); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java index e648fbf108e..f25b25166bc 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -779,14 +779,6 @@ public Color getColor(SynthContext context, ColorType type) { (type == ColorType.FOREGROUND || type == ColorType.TEXT_FOREGROUND)) { return getColorForState(context, type); - } else if (c instanceof JCheckBox) { - if (UIManager.getColor("CheckBox.disabledText") != null) { - return UIManager.getColor("CheckBox.disabledText"); - } - } else if (c instanceof JRadioButton) { - if (UIManager.getColor("RadioButton.disabledText") != null) { - return UIManager.getColor("RadioButton.disabledText"); - } } } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 8edd5818c96..1c9e89f6447 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -664,6 +664,7 @@ javax/swing/JFileChooser/6798062/bug6798062.java 8146446 windows-all javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all +javax/swing/JRadioButton/4314194/bug4314194.java 8298153 linux-all # Several tests which fail on some hidpi systems/macosx12-aarch64 system java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 diff --git a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java index e783b147ca6..57ee1a2bb3f 100644 --- a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java +++ b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java @@ -23,7 +23,7 @@ /* * @test * @key headful - * @bug 4314194 8075916 + * @bug 4314194 8075916 8298083 * @summary Verifies disabled color for JCheckbox and JRadiobutton is honored in all L&F * @run main bug4314194 */ @@ -40,13 +40,14 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.synth.SynthLookAndFeel; public class bug4314194 { - private static JFrame frame; - private static JRadioButton radioButton; - private static JCheckBox checkBox; - private static Point point; - private static Rectangle rect; + private static volatile JFrame frame; + private static volatile JRadioButton radioButton; + private static volatile JCheckBox checkBox; + private static volatile Point point; + private static volatile Rectangle rect; private static Robot robot; private static final Color radioButtonColor = Color.RED; private static final Color checkboxColor = Color.GREEN; @@ -87,9 +88,25 @@ private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { } } - private static void createUI() { - UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); - UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + private static void createUI(String laf) { + if (UIManager.getLookAndFeel() instanceof SynthLookAndFeel) { + // reset "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", null); + UIManager.getDefaults().put("RadioButton.disabledText", null); + // set "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", checkboxColor); + // for some reason the RadioButton[Disabled] does not work + // see https://bugs.openjdk.org/browse/JDK-8298149 + //UIManager.getDefaults().put("RadioButton[Disabled].textForeground", radioButtonColor); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", radioButtonColor); + } else { + // reset "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", null); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", null); + // set "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); + UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + } checkBox = new JCheckBox("\u2588".repeat(5)); radioButton = new JRadioButton("\u2588".repeat(5)); @@ -98,7 +115,7 @@ private static void createUI() { checkBox.setEnabled(false); radioButton.setEnabled(false); - frame = new JFrame("bug4314194"); + frame = new JFrame(laf); frame.getContentPane().add(radioButton, BorderLayout.SOUTH); frame.getContentPane().add(checkBox, BorderLayout.NORTH); frame.pack(); @@ -122,7 +139,7 @@ public static void main(String[] args) throws Exception { System.out.println("Testing L&F: " + laf.getClassName()); SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); try { - SwingUtilities.invokeAndWait(() -> createUI()); + SwingUtilities.invokeAndWait(() -> createUI(laf.getName())); robot.waitForIdle(); robot.delay(1000); @@ -141,4 +158,3 @@ public static void main(String[] args) throws Exception { } } } - From 7f9c6ce3318aedfd85f12f4002dc442b0b468c27 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 9 Dec 2022 00:29:08 +0000 Subject: [PATCH 141/494] 8297679: InvocationTargetException field named target is not declared final Reviewed-by: alanb --- .../classes/java/lang/reflect/InvocationTargetException.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java b/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java index 4db453c9b7f..a6ef4fa289c 100644 --- a/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java +++ b/src/java.base/share/classes/java/lang/reflect/InvocationTargetException.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 2022, 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,7 +48,7 @@ public class InvocationTargetException extends ReflectiveOperationException { * @serial * */ - private Throwable target; + private final Throwable target; /** * Constructs an {@code InvocationTargetException} with @@ -56,6 +56,7 @@ public class InvocationTargetException extends ReflectiveOperationException { */ protected InvocationTargetException() { super((Throwable)null); // Disallow initCause + this.target = null; } /** From 11aece21f4eb5b18af357b265bc27b80bcdbfbcb Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Fri, 9 Dec 2022 07:11:57 +0000 Subject: [PATCH 142/494] 8257197: Add additional verification code to PhaseCCP Reviewed-by: chagedorn, kvn, thartmann --- src/hotspot/share/opto/phaseX.cpp | 48 +++++++++++++++++++++++++++++++ src/hotspot/share/opto/phaseX.hpp | 4 +++ 2 files changed, 52 insertions(+) diff --git a/src/hotspot/share/opto/phaseX.cpp b/src/hotspot/share/opto/phaseX.cpp index d5c861e14aa..2c260ebf4f9 100644 --- a/src/hotspot/share/opto/phaseX.cpp +++ b/src/hotspot/share/opto/phaseX.cpp @@ -1782,6 +1782,7 @@ void PhaseCCP::analyze() { // Push root onto worklist Unique_Node_List worklist; worklist.push(C->root()); + DEBUG_ONLY(Unique_Node_List worklist_verify;) assert(_root_and_safepoints.size() == 0, "must be empty (unused)"); _root_and_safepoints.push(C->root()); @@ -1790,6 +1791,7 @@ void PhaseCCP::analyze() { // This loop is the meat of CCP. while (worklist.size() != 0) { Node* n = fetch_next_node(worklist); + DEBUG_ONLY(worklist_verify.push(n);) if (n->is_SafePoint()) { // Make sure safepoints are processed by PhaseCCP::transform even if they are // not reachable from the bottom. Otherwise, infinite loops would be removed. @@ -1803,8 +1805,54 @@ void PhaseCCP::analyze() { push_child_nodes_to_worklist(worklist, n); } } + DEBUG_ONLY(verify_analyze(worklist_verify);) } +#ifdef ASSERT +// For every node n on verify list, check if type(n) == n->Value() +// We have a list of exceptions, see comments in code. +void PhaseCCP::verify_analyze(Unique_Node_List& worklist_verify) { + bool failure = false; + while (worklist_verify.size()) { + Node* n = worklist_verify.pop(); + const Type* told = type(n); + const Type* tnew = n->Value(this); + if (told != tnew) { + // Check special cases that are ok + if (told->isa_integer(tnew->basic_type()) != nullptr) { // both either int or long + const TypeInteger* t0 = told->is_integer(tnew->basic_type()); + const TypeInteger* t1 = tnew->is_integer(tnew->basic_type()); + if (t0->lo_as_long() == t1->lo_as_long() && + t0->hi_as_long() == t1->hi_as_long()) { + continue; // ignore integer widen + } + } + if (n->is_Load()) { + // MemNode::can_see_stored_value looks up through many memory nodes, + // which means we would need to notify modifications from far up in + // the inputs all the way down to the LoadNode. We don't do that. + continue; + } + tty->cr(); + tty->print_cr("Missed optimization (PhaseCCP):"); + n->dump_bfs(1, 0, ""); + tty->print_cr("Current type:"); + told->dump_on(tty); + tty->cr(); + tty->print_cr("Optimized type:"); + tnew->dump_on(tty); + tty->cr(); + failure = true; + } + } + // If we get this assert, check why the reported nodes were not processed again in CCP. + // We should either make sure that these nodes are properly added back to the CCP worklist + // in PhaseCCP::push_child_nodes_to_worklist() to update their type 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 PhaseCCP"); +} +#endif + // Fetch next node from worklist to be examined in this iteration. Node* PhaseCCP::fetch_next_node(Unique_Node_List& worklist) { if (StressCCP) { diff --git a/src/hotspot/share/opto/phaseX.hpp b/src/hotspot/share/opto/phaseX.hpp index c51aed5b762..883dc92e7ef 100644 --- a/src/hotspot/share/opto/phaseX.hpp +++ b/src/hotspot/share/opto/phaseX.hpp @@ -603,6 +603,10 @@ class PhaseCCP : public PhaseIterGVN { // Worklist algorithm identifies constants void analyze(); +#ifdef ASSERT + // For every node n on verify list, check if type(n) == n->Value() + void verify_analyze(Unique_Node_List& worklist_verify); +#endif // Recursive traversal of program. Used analysis to modify program. virtual Node *transform( Node *n ); // Do any transformation after analysis From cb766c553557b718683d492280beba772d81bb5b Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Fri, 9 Dec 2022 09:46:50 +0000 Subject: [PATCH 143/494] 8297778: Modernize and improve module jdk.sctp Reviewed-by: dfuchs, stsypanov --- .../com/sun/nio/sctp/HandlerResult.java | 2 +- .../sun/nio/sctp/IllegalReceiveException.java | 3 + .../sun/nio/sctp/IllegalUnbindException.java | 3 + .../sun/nio/sctp/InvalidStreamException.java | 3 + .../nio/sctp/SctpStandardSocketOptions.java | 74 ++++----- .../sun/nio/sctp/SendFailedNotification.java | 4 +- .../sun/nio/ch/sctp/MessageInfoImpl.java | 18 +-- .../sun/nio/ch/sctp/SctpStdSocketOption.java | 7 +- .../sun/nio/ch/sctp/AssociationChange.java | 47 +++--- .../sun/nio/ch/sctp/AssociationImpl.java | 16 +- .../sun/nio/ch/sctp/PeerAddrChange.java | 50 +++--- .../sun/nio/ch/sctp/ResultContainer.java | 36 ++--- .../sun/nio/ch/sctp/SctpChannelImpl.java | 116 ++++++-------- .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 143 ++++++++---------- .../unix/classes/sun/nio/ch/sctp/SctpNet.java | 13 +- .../sun/nio/ch/sctp/SctpNotification.java | 4 +- .../nio/ch/sctp/SctpServerChannelImpl.java | 24 +-- .../classes/sun/nio/ch/sctp/SendFailed.java | 26 ++-- .../classes/sun/nio/ch/sctp/Shutdown.java | 10 +- 19 files changed, 260 insertions(+), 339 deletions(-) diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/HandlerResult.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/HandlerResult.java index a037264d056..bf81e8f8f2b 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/HandlerResult.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/HandlerResult.java @@ -36,7 +36,7 @@ */ public enum HandlerResult { /** - * Try to receieve another message or notification. + * Try to receive another message or notification. */ CONTINUE, diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalReceiveException.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalReceiveException.java index a007c9ecebd..c344933e5ad 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalReceiveException.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalReceiveException.java @@ -24,6 +24,8 @@ */ package com.sun.nio.sctp; +import java.io.Serial; + /** * Unchecked exception thrown when an attempt is made to invoke the * {@code receive} method of {@link SctpChannel} or {@link SctpMultiChannel} @@ -32,6 +34,7 @@ * @since 1.7 */ public class IllegalReceiveException extends IllegalStateException { + @Serial private static final long serialVersionUID = 2296619040988576224L; /** diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalUnbindException.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalUnbindException.java index 3d4a3de5fbf..17c7ed40bc7 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalUnbindException.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/IllegalUnbindException.java @@ -24,6 +24,8 @@ */ package com.sun.nio.sctp; +import java.io.Serial; + /** * Unchecked exception thrown when an attempt is made to remove an * address that is not bound to the channel, or remove an address from a @@ -32,6 +34,7 @@ * @since 1.7 */ public class IllegalUnbindException extends IllegalStateException { + @Serial private static final long serialVersionUID = -310540883995532224L; /** diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/InvalidStreamException.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/InvalidStreamException.java index 9c0437228dd..ab6da93a805 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/InvalidStreamException.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/InvalidStreamException.java @@ -24,6 +24,8 @@ */ package com.sun.nio.sctp; +import java.io.Serial; + /** * Unchecked exception thrown when an attempt is made to send a * message to an invalid stream. @@ -31,6 +33,7 @@ * @since 1.7 */ public class InvalidStreamException extends IllegalArgumentException { + @Serial private static final long serialVersionUID = -9172703378046665558L; /** diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java index b7c1d870f29..1f1a464f9be 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/SctpStandardSocketOptions.java @@ -34,23 +34,24 @@ * * @since 1.7 */ -public class SctpStandardSocketOptions { +public final class SctpStandardSocketOptions { private SctpStandardSocketOptions() {} /** * Enables or disables message fragmentation. * *

    The value of this socket option is a {@code Boolean} that represents * whether the option is enabled or disabled. If enabled no SCTP message - * fragmentation will be performed. Instead if a message being sent + * fragmentation will be performed. Instead, if a message being sent * exceeds the current PMTU size, the message will NOT be sent and * an error will be indicated to the user. * *

    It is implementation specific whether or not this option is * supported. */ - public static final SctpSocketOption SCTP_DISABLE_FRAGMENTS = new - SctpStdSocketOption("SCTP_DISABLE_FRAGMENTS", Boolean.class, - sun.nio.ch.sctp.SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS); + public static final SctpSocketOption SCTP_DISABLE_FRAGMENTS = + new SctpStdSocketOption<>("SCTP_DISABLE_FRAGMENTS", + Boolean.class, + SctpStdSocketOption.SCTP_DISABLE_FRAGMENTS); /** * Enables or disables explicit message completion. @@ -67,9 +68,10 @@ private SctpStandardSocketOptions() {} * option is disabled. It is implementation specific whether or not this * option is supported. */ - public static final SctpSocketOption SCTP_EXPLICIT_COMPLETE = new - SctpStdSocketOption("SCTP_EXPLICIT_COMPLETE", Boolean.class, - sun.nio.ch.sctp.SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE); + public static final SctpSocketOption SCTP_EXPLICIT_COMPLETE = + new SctpStdSocketOption<>("SCTP_EXPLICIT_COMPLETE", + Boolean.class, + SctpStdSocketOption.SCTP_EXPLICIT_COMPLETE); /** * Fragmented interleave controls how the presentation of messages occur @@ -118,9 +120,9 @@ private SctpStandardSocketOptions() {} * supported. */ public static final SctpSocketOption SCTP_FRAGMENT_INTERLEAVE = - new SctpStdSocketOption("SCTP_FRAGMENT_INTERLEAVE", + new SctpStdSocketOption<>("SCTP_FRAGMENT_INTERLEAVE", Integer.class, - sun.nio.ch.sctp.SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE); + SctpStdSocketOption.SCTP_FRAGMENT_INTERLEAVE); /** * The maximum number of streams requested by the local endpoint during @@ -158,8 +160,8 @@ private SctpStandardSocketOptions() {} */ public static final SctpSocketOption SCTP_INIT_MAXSTREAMS = - new SctpStdSocketOption( - "SCTP_INIT_MAXSTREAMS", SctpStandardSocketOptions.InitMaxStreams.class); + new SctpStdSocketOption<>("SCTP_INIT_MAXSTREAMS", + SctpStandardSocketOptions.InitMaxStreams.class); /** * Enables or disables a Nagle-like algorithm. @@ -170,8 +172,9 @@ private SctpStandardSocketOptions() {} * improve network efficiency. */ public static final SctpSocketOption SCTP_NODELAY = - new SctpStdSocketOption("SCTP_NODELAY", Boolean.class, - sun.nio.ch.sctp.SctpStdSocketOption.SCTP_NODELAY); + new SctpStdSocketOption<>("SCTP_NODELAY", + Boolean.class, + SctpStdSocketOption.SCTP_NODELAY); /** * Requests that the local SCTP stack use the given peer address as @@ -191,8 +194,8 @@ private SctpStandardSocketOptions() {} * set or queried directly. */ public static final SctpSocketOption SCTP_PRIMARY_ADDR = - new SctpStdSocketOption - ("SCTP_PRIMARY_ADDR", SocketAddress.class); + new SctpStdSocketOption<>("SCTP_PRIMARY_ADDR", + SocketAddress.class); /** * Requests that the peer mark the enclosed address as the association @@ -216,8 +219,8 @@ private SctpStandardSocketOptions() {} * option is supported. */ public static final SctpSocketOption SCTP_SET_PEER_PRIMARY_ADDR = - new SctpStdSocketOption - ("SCTP_SET_PEER_PRIMARY_ADDR", SocketAddress.class); + new SctpStdSocketOption<>("SCTP_SET_PEER_PRIMARY_ADDR", + SocketAddress.class); /** * The size of the socket send buffer. @@ -245,8 +248,9 @@ private SctpStandardSocketOptions() {} * dependent. */ public static final SctpSocketOption SO_SNDBUF = - new SctpStdSocketOption("SO_SNDBUF", Integer.class, - sun.nio.ch.sctp.SctpStdSocketOption.SO_SNDBUF); + new SctpStdSocketOption<>("SO_SNDBUF", + Integer.class, + SctpStdSocketOption.SO_SNDBUF); /** * The size of the socket receive buffer. @@ -272,8 +276,9 @@ private SctpStandardSocketOptions() {} * dependent. */ public static final SctpSocketOption SO_RCVBUF = - new SctpStdSocketOption("SO_RCVBUF", Integer.class, - sun.nio.ch.sctp.SctpStdSocketOption.SO_RCVBUF); + new SctpStdSocketOption<>("SO_RCVBUF", + Integer.class, + SctpStdSocketOption.SO_RCVBUF); /** * Linger on close if data is present. @@ -303,8 +308,9 @@ private SctpStandardSocketOptions() {} * its maximum value. */ public static final SctpSocketOption SO_LINGER = - new SctpStdSocketOption("SO_LINGER", Integer.class, - sun.nio.ch.sctp.SctpStdSocketOption.SO_LINGER); + new SctpStdSocketOption<>("SO_LINGER", + Integer.class, + SctpStdSocketOption.SO_LINGER); /** * This class is used to set the maximum number of inbound/outbound streams @@ -316,8 +322,8 @@ private SctpStandardSocketOptions() {} * @since 1.7 */ public static class InitMaxStreams { - private int maxInStreams; - private int maxOutStreams; + private final int maxInStreams; + private final int maxOutStreams; private InitMaxStreams(int maxInStreams, int maxOutStreams) { this.maxInStreams = maxInStreams; @@ -378,11 +384,9 @@ public int maxOutStreams() { */ @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append(" ["); - sb.append("maxInStreams:").append(maxInStreams); - sb.append("maxOutStreams:").append(maxOutStreams).append("]"); - return sb.toString(); + return super.toString() + " [" + + "maxInStreams:" + maxInStreams + + "maxOutStreams:" + maxOutStreams + "]"; } /** @@ -398,11 +402,9 @@ public String toString() { */ @Override public boolean equals(Object obj) { - if (obj != null && obj instanceof InitMaxStreams) { - InitMaxStreams that = (InitMaxStreams) obj; - if (this.maxInStreams == that.maxInStreams && - this.maxOutStreams == that.maxOutStreams) - return true; + if (obj instanceof InitMaxStreams that) { + return this.maxInStreams == that.maxInStreams && + this.maxOutStreams == that.maxOutStreams; } return false; } diff --git a/src/jdk.sctp/share/classes/com/sun/nio/sctp/SendFailedNotification.java b/src/jdk.sctp/share/classes/com/sun/nio/sctp/SendFailedNotification.java index 22abe888612..e847c81c38c 100644 --- a/src/jdk.sctp/share/classes/com/sun/nio/sctp/SendFailedNotification.java +++ b/src/jdk.sctp/share/classes/com/sun/nio/sctp/SendFailedNotification.java @@ -31,7 +31,7 @@ * Notification emitted when a send failed notification has been received. * *

    A send failed notification indicates that a message cannot be delivered. - * Typically this is because the association has been shutdown with unsent data + * Typically, this is because the association has been shutdown with unsent data * in the socket output buffer, or in the case of a {@link SctpMultiChannel} * the association failed to setup. * @@ -81,7 +81,7 @@ protected SendFailedNotification() {} public abstract int errorCode(); /** - * Returns the stream number that the messge was to be sent on. + * Returns the stream number that the message was to be sent on. * * @return The stream number */ diff --git a/src/jdk.sctp/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java index b8584f1650b..29893d00ae7 100644 --- a/src/jdk.sctp/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/MessageInfoImpl.java @@ -156,15 +156,13 @@ public MessageInfo timeToLive(long millis) { @Override public String toString() { - StringBuilder sb = new StringBuilder(super.toString()); - sb.append( "[Address: ").append(address) - .append(", Association: ").append(association) - .append(", Assoc ID: ").append(assocId) - .append(", Bytes: ").append(bytes) - .append(", Stream Number: ").append(streamNumber) - .append(", Complete: ").append(complete) - .append(", isUnordered: ").append(unordered) - .append("]"); - return sb.toString(); + return super.toString() + "[Address: " + address + + ", Association: " + association + + ", Assoc ID: " + assocId + + ", Bytes: " + bytes + + ", Stream Number: " + streamNumber + + ", Complete: " + complete + + ", isUnordered: " + unordered + + "]"; } } diff --git a/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java index 8bcc1c48c1e..cc11effd75a 100644 --- a/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpStdSocketOption.java @@ -27,7 +27,7 @@ import com.sun.nio.sctp.SctpSocketOption; import java.lang.annotation.Native; -public class SctpStdSocketOption +public final class SctpStdSocketOption implements SctpSocketOption { /* for native mapping of int options */ @@ -43,11 +43,10 @@ public class SctpStdSocketOption private final Class type; /* for native mapping of int options */ - private int constValue; + private final int constValue; public SctpStdSocketOption(String name, Class type) { - this.name = name; - this.type = type; + this(name, type, 0); } public SctpStdSocketOption(String name, Class type, int constValue) { diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java index c83b1324714..b20d0e7e14f 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationChange.java @@ -43,38 +43,27 @@ public class AssociationChange extends AssociationChangeNotification private Association association; - /* assocId is used to lookup the association before the notification is + /* assocId is used to look up the association before the notification is * returned to user code */ - private int assocId; - private AssocChangeEvent event; - private int maxOutStreams; - private int maxInStreams; + private final int assocId; + private final AssocChangeEvent event; + private final int maxOutStreams; + private final int maxInStreams; /* Invoked from native */ private AssociationChange(int assocId, int intEvent, int maxOutStreams, int maxInStreams) { - switch (intEvent) { - case SCTP_COMM_UP : - this.event = AssocChangeEvent.COMM_UP; - break; - case SCTP_COMM_LOST : - this.event = AssocChangeEvent.COMM_LOST; - break; - case SCTP_RESTART : - this.event = AssocChangeEvent.RESTART; - break; - case SCTP_SHUTDOWN : - this.event = AssocChangeEvent.SHUTDOWN; - break; - case SCTP_CANT_START : - this.event = AssocChangeEvent.CANT_START; - break; - default : - throw new AssertionError( - "Unknown Association Change Event type: " + intEvent); - } + this.event = switch (intEvent) { + case SCTP_COMM_UP -> AssocChangeEvent.COMM_UP; + case SCTP_COMM_LOST -> AssocChangeEvent.COMM_LOST; + case SCTP_RESTART -> AssocChangeEvent.RESTART; + case SCTP_SHUTDOWN -> AssocChangeEvent.SHUTDOWN; + case SCTP_CANT_START -> AssocChangeEvent.CANT_START; + default -> throw new AssertionError( + "Unknown Association Change Event type: " + intEvent); + }; this.assocId = assocId; this.maxOutStreams = maxOutStreams; @@ -112,10 +101,8 @@ int maxInStreams() { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append(" ["); - sb.append("Association:").append(association); - sb.append(", Event: ").append(event).append("]"); - return sb.toString(); + return super.toString() + " [" + + "Association:" + association + + ", Event: " + event + "]"; } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationImpl.java index 56653d01c4f..2771ce3115e 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/AssociationImpl.java @@ -38,15 +38,13 @@ public AssociationImpl(int associationID, @Override public String toString() { - StringBuffer sb = new StringBuffer(super.toString()); - return sb.append("[associationID:") - .append(associationID()) - .append(", maxIn:") - .append(maxInboundStreams()) - .append(", maxOut:") - .append(maxOutboundStreams()) - .append("]") - .toString(); + return super.toString() + "[associationID:" + + associationID() + + ", maxIn:" + + maxInboundStreams() + + ", maxOut:" + + maxOutboundStreams() + + "]"; } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/PeerAddrChange.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/PeerAddrChange.java index 5111c94d029..87bb1a6a12d 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/PeerAddrChange.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/PeerAddrChange.java @@ -45,36 +45,23 @@ public class PeerAddrChange extends PeerAddressChangeNotification private Association association; - /* assocId is used to lookup the association before the notification is + /* assocId is used to look up the association before the notification is * returned to user code */ - private int assocId; - private SocketAddress address; - private AddressChangeEvent event; + private final int assocId; + private final SocketAddress address; + private final AddressChangeEvent event; /* Invoked from native */ private PeerAddrChange(int assocId, SocketAddress address, int intEvent) { - switch (intEvent) { - case SCTP_ADDR_AVAILABLE : - this.event = AddressChangeEvent.ADDR_AVAILABLE; - break; - case SCTP_ADDR_UNREACHABLE : - this.event = AddressChangeEvent.ADDR_UNREACHABLE; - break; - case SCTP_ADDR_REMOVED : - this.event = AddressChangeEvent.ADDR_REMOVED; - break; - case SCTP_ADDR_ADDED : - this.event = AddressChangeEvent.ADDR_ADDED; - break; - case SCTP_ADDR_MADE_PRIM : - this.event = AddressChangeEvent.ADDR_MADE_PRIMARY; - break; - case SCTP_ADDR_CONFIRMED : - this.event = AddressChangeEvent.ADDR_CONFIRMED; - break; - default: - throw new AssertionError("Unknown event type"); - } + this.event = switch (intEvent) { + case SCTP_ADDR_AVAILABLE -> AddressChangeEvent.ADDR_AVAILABLE; + case SCTP_ADDR_UNREACHABLE -> AddressChangeEvent.ADDR_UNREACHABLE; + case SCTP_ADDR_REMOVED -> AddressChangeEvent.ADDR_REMOVED; + case SCTP_ADDR_ADDED -> AddressChangeEvent.ADDR_ADDED; + case SCTP_ADDR_MADE_PRIM -> AddressChangeEvent.ADDR_MADE_PRIMARY; + case SCTP_ADDR_CONFIRMED -> AddressChangeEvent.ADDR_CONFIRMED; + default -> throw new AssertionError("Unknown event type"); + }; this.assocId = assocId; this.address = address; } @@ -103,18 +90,15 @@ public Association association() { @Override public AddressChangeEvent event() { - assert event != null; return event; } @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append(" ["); - sb.append("Address: ").append(address); - sb.append(", Association:").append(association); - sb.append(", Event: ").append(event).append("]"); - return sb.toString(); + return super.toString() + " [" + + "Address: " + address + + ", Association:" + association + + ", Event: " + event + "]"; } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/ResultContainer.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/ResultContainer.java index 229899f4dea..b0145e4f5b9 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/ResultContainer.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/ResultContainer.java @@ -51,7 +51,7 @@ boolean hasSomething() { } boolean isNotification() { - return type() != MESSAGE && type() != NOTHING ? true : false; + return type() != MESSAGE && type() != NOTHING; } void clear() { @@ -68,8 +68,8 @@ SctpNotification notification() { MessageInfoImpl getMessageInfo() { assert type() == MESSAGE; - if (value instanceof MessageInfoImpl) - return (MessageInfoImpl) value; + if (value instanceof MessageInfoImpl messageInfo) + return messageInfo; return null; } @@ -77,8 +77,8 @@ MessageInfoImpl getMessageInfo() { SendFailed getSendFailed() { assert type() == SEND_FAILED; - if (value instanceof SendFailed) - return (SendFailed) value; + if (value instanceof SendFailed sendFailed) + return sendFailed; return null; } @@ -86,8 +86,8 @@ SendFailed getSendFailed() { AssociationChange getAssociationChanged() { assert type() == ASSOCIATION_CHANGED; - if (value instanceof AssociationChange) - return (AssociationChange) value; + if (value instanceof AssociationChange associationChanged) + return associationChanged; return null; } @@ -95,8 +95,8 @@ AssociationChange getAssociationChanged() { PeerAddrChange getPeerAddressChanged() { assert type() == PEER_ADDRESS_CHANGED; - if (value instanceof PeerAddrChange) - return (PeerAddrChange) value; + if (value instanceof PeerAddrChange peerAddressChanged) + return peerAddressChanged; return null; } @@ -104,8 +104,8 @@ PeerAddrChange getPeerAddressChanged() { Shutdown getShutdown() { assert type() == SHUTDOWN; - if (value instanceof Shutdown) - return (Shutdown) value; + if (value instanceof Shutdown shutdown) + return shutdown; return null; } @@ -115,13 +115,13 @@ public String toString() { StringBuilder sb = new StringBuilder(); sb.append("Type: "); switch (type) { - case NOTHING: sb.append("NOTHING"); break; - case MESSAGE: sb.append("MESSAGE"); break; - case SEND_FAILED: sb.append("SEND FAILED"); break; - case ASSOCIATION_CHANGED: sb.append("ASSOCIATION CHANGE"); break; - case PEER_ADDRESS_CHANGED: sb.append("PEER ADDRESS CHANGE"); break; - case SHUTDOWN: sb.append("SHUTDOWN"); break; - default : sb.append("Unknown result type"); + case NOTHING -> sb.append("NOTHING"); + case MESSAGE -> sb.append("MESSAGE"); + case SEND_FAILED -> sb.append("SEND FAILED"); + case ASSOCIATION_CHANGED -> sb.append("ASSOCIATION CHANGE"); + case PEER_ADDRESS_CHANGED -> sb.append("PEER ADDRESS CHANGE"); + case SHUTDOWN -> sb.append("SHUTDOWN"); + default -> sb.append("Unknown result type"); } sb.append(", Value: "); sb.append((value == null) ? "null" : value.toString()); diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 6ad541b36a3..4355605e258 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -30,6 +30,8 @@ import java.net.InetSocketAddress; import java.io.FileDescriptor; import java.io.IOException; +import java.security.AccessController; +import java.security.PrivilegedAction; import java.util.Collections; import java.util.Set; import java.util.HashSet; @@ -83,9 +85,9 @@ public class SctpChannelImpl extends SctpChannel private final int fdVal; - /* IDs of native threads doing send and receivess, for signalling */ - private volatile long receiverThread = 0; - private volatile long senderThread = 0; + /* IDs of native threads doing send and receive, for signalling */ + private volatile long receiverThread; + private volatile long senderThread; /* Lock held by current receiving or connecting thread */ private final Object receiveLock = new Object(); @@ -94,7 +96,7 @@ public class SctpChannelImpl extends SctpChannel private final Object sendLock = new Object(); private final ThreadLocal receiveInvoked = - new ThreadLocal() { + new ThreadLocal<>() { @Override protected Boolean initialValue() { return Boolean.FALSE; } @@ -113,11 +115,11 @@ private enum ChannelState { KILLED, } /* -- The following fields are protected by stateLock -- */ - private ChannelState state = ChannelState.UNINITIALIZED; + private ChannelState state; /* Binding; Once bound the port will remain constant. */ int port = -1; - private HashSet localAddresses = new HashSet(); + private final Set localAddresses = new HashSet<>(); /* Has the channel been bound to the wildcard address */ private boolean wildcard; /* false */ //private InetSocketAddress remoteAddress = null; @@ -225,7 +227,7 @@ public SctpChannel unbindAddress(InetAddress address) return this; } - private SctpChannel bindUnbindAddress(InetAddress address, boolean add) + private void bindUnbindAddress(InetAddress address, boolean add) throws IOException { if (address == null) throw new IllegalArgumentException(); @@ -281,12 +283,11 @@ private SctpChannel bindUnbindAddress(InetAddress address, boolean add) } } } - return this; } private boolean isBound() { synchronized (stateLock) { - return port == -1 ? false : true; + return port != -1; } } @@ -696,28 +697,22 @@ public T getOption(SctpSocketOption name) throws IOException { } } - private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); - - private static Set> defaultOptions() { - HashSet> set = new HashSet>(10); - set.add(SCTP_DISABLE_FRAGMENTS); - set.add(SCTP_EXPLICIT_COMPLETE); - set.add(SCTP_FRAGMENT_INTERLEAVE); - set.add(SCTP_INIT_MAXSTREAMS); - set.add(SCTP_NODELAY); - set.add(SCTP_PRIMARY_ADDR); - set.add(SCTP_SET_PEER_PRIMARY_ADDR); - set.add(SO_SNDBUF); - set.add(SO_RCVBUF); - set.add(SO_LINGER); - return Collections.unmodifiableSet(set); - } - } - @Override public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; + final class Holder { + static final Set> DEFAULT_OPTIONS = Set.of( + SCTP_DISABLE_FRAGMENTS, + SCTP_EXPLICIT_COMPLETE, + SCTP_FRAGMENT_INTERLEAVE, + SCTP_INIT_MAXSTREAMS, + SCTP_NODELAY, + SCTP_PRIMARY_ADDR, + SCTP_SET_PEER_PRIMARY_ADDR, + SO_SNDBUF, + SO_RCVBUF, + SO_LINGER); + } + return Holder.DEFAULT_OPTIONS; } @Override @@ -856,23 +851,20 @@ private int receiveIntoNativeBuffer(int fd, } } - private InternalNotificationHandler internalNotificationHandler = + private final InternalNotificationHandler internalNotificationHandler = new InternalNotificationHandler(); - private void handleNotificationInternal(ResultContainer resultContainer) - { + private void handleNotificationInternal(ResultContainer resultContainer) { invokeNotificationHandler(resultContainer, internalNotificationHandler, null); } - private class InternalNotificationHandler - extends AbstractNotificationHandler - { + private final class InternalNotificationHandler + extends AbstractNotificationHandler { @Override - public HandlerResult handleNotification( - AssociationChangeNotification not, Object unused) { - if (not.event().equals( - AssociationChangeNotification.AssocChangeEvent.COMM_UP) && + public HandlerResult handleNotification(AssociationChangeNotification not, + Object unused) { + if (not.event().equals(AssociationChangeNotification.AssocChangeEvent.COMM_UP) && association == null) { AssociationChange sac = (AssociationChange) not; association = new AssociationImpl @@ -882,40 +874,32 @@ public HandlerResult handleNotification( } } - private HandlerResult invokeNotificationHandler - (ResultContainer resultContainer, - NotificationHandler handler, - T attachment) { + private HandlerResult invokeNotificationHandler(ResultContainer resultContainer, + NotificationHandler handler, + T attachment) { SctpNotification notification = resultContainer.notification(); synchronized (stateLock) { notification.setAssociation(association); } - if (!(handler instanceof AbstractNotificationHandler)) { + if (!(handler instanceof AbstractNotificationHandler absHandler)) { return handler.handleNotification(notification, attachment); } /* AbstractNotificationHandler */ - AbstractNotificationHandler absHandler = - (AbstractNotificationHandler)handler; - switch(resultContainer.type()) { - case ASSOCIATION_CHANGED : - return absHandler.handleNotification( - resultContainer.getAssociationChanged(), attachment); - case PEER_ADDRESS_CHANGED : - return absHandler.handleNotification( - resultContainer.getPeerAddressChanged(), attachment); - case SEND_FAILED : - return absHandler.handleNotification( - resultContainer.getSendFailed(), attachment); - case SHUTDOWN : - return absHandler.handleNotification( - resultContainer.getShutdown(), attachment); - default : - /* implementation specific handlers */ - return absHandler.handleNotification( - resultContainer.notification(), attachment); - } + return switch (resultContainer.type()) { + case ASSOCIATION_CHANGED -> absHandler.handleNotification( + resultContainer.getAssociationChanged(), attachment); + case PEER_ADDRESS_CHANGED -> absHandler.handleNotification( + resultContainer.getPeerAddressChanged(), attachment); + case SEND_FAILED -> absHandler.handleNotification( + resultContainer.getSendFailed(), attachment); + case SHUTDOWN -> absHandler.handleNotification( + resultContainer.getShutdown(), attachment); + /* implementation specific handlers */ + default -> absHandler.handleNotification( + resultContainer.notification(), attachment); + }; } private void checkAssociation(Association sendAssociation) { @@ -1113,8 +1097,8 @@ static native int send0(int fd, long address, int length, @SuppressWarnings("removal") private static void loadSctpLibrary() { IOUtil.load(); /* loads nio & net native libraries */ - java.security.AccessController.doPrivileged( - new java.security.PrivilegedAction() { + AccessController.doPrivileged( + new PrivilegedAction<>() { public Void run() { System.loadLibrary("sctp"); return null; diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index ca55e553e6a..b1b721c9976 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -36,6 +36,7 @@ import java.util.Set; import java.util.HashSet; import java.util.HashMap; +import java.util.Map; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.ClosedChannelException; @@ -80,8 +81,8 @@ public class SctpMultiChannelImpl extends SctpMultiChannel private final int fdVal; /* IDs of native threads doing send and receives, for signalling */ - private volatile long receiverThread = 0; - private volatile long senderThread = 0; + private volatile long receiverThread; + private volatile long senderThread; /* Lock held by current receiving thread */ private final Object receiveLock = new Object(); @@ -104,30 +105,25 @@ private enum ChannelState { /* Binding: Once bound the port will remain constant. */ int port = -1; - private HashSet localAddresses = new HashSet(); + private final Set localAddresses = new HashSet<>(); /* Has the channel been bound to the wildcard address */ private boolean wildcard; /* false */ - /* Keeps a map of addresses to association, and visa versa */ - private HashMap addressMap = - new HashMap(); - private HashMap> associationMap = - new HashMap>(); + /* Keeps a map of addresses to association, and vice versa */ + private final Map addressMap = + new HashMap<>(); + private final Map> associationMap = + new HashMap<>(); /* -- End of fields protected by stateLock -- */ /* If an association has been shutdown mark it for removal after * the user handler has been invoked */ - private final ThreadLocal associationToRemove = - new ThreadLocal() { - @Override protected Association initialValue() { - return null; - } - }; + private final ThreadLocal associationToRemove = new ThreadLocal<>(); /* A notification handler cannot invoke receive */ private final ThreadLocal receiveInvoked = - new ThreadLocal() { + new ThreadLocal<>() { @Override protected Boolean initialValue() { return Boolean.FALSE; } @@ -259,7 +255,7 @@ public Set associations() private boolean isBound() { synchronized (stateLock) { - return port == -1 ? false : true; + return port != -1; } } @@ -440,28 +436,23 @@ public T getOption(SctpSocketOption name, Association association) } } - private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); - - private static Set> defaultOptions() { - HashSet> set = new HashSet>(10); - set.add(SCTP_DISABLE_FRAGMENTS); - set.add(SCTP_EXPLICIT_COMPLETE); - set.add(SCTP_FRAGMENT_INTERLEAVE); - set.add(SCTP_INIT_MAXSTREAMS); - set.add(SCTP_NODELAY); - set.add(SCTP_PRIMARY_ADDR); - set.add(SCTP_SET_PEER_PRIMARY_ADDR); - set.add(SO_SNDBUF); - set.add(SO_RCVBUF); - set.add(SO_LINGER); - return Collections.unmodifiableSet(set); - } - } - @Override public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; + final class Holder { + static final Set> DEFAULT_OPTIONS = Set.of( + SCTP_DISABLE_FRAGMENTS, + SCTP_EXPLICIT_COMPLETE, + SCTP_FRAGMENT_INTERLEAVE, + SCTP_INIT_MAXSTREAMS, + SCTP_NODELAY, + SCTP_PRIMARY_ADDR, + SCTP_SET_PEER_PRIMARY_ADDR, + SO_SNDBUF, + SO_RCVBUF, + SO_LINGER); + + } + return Holder.DEFAULT_OPTIONS; } @Override @@ -598,7 +589,7 @@ private int receiveIntoNativeBuffer(int fd, } } - private InternalNotificationHandler internalNotificationHandler = + private final InternalNotificationHandler internalNotificationHandler = new InternalNotificationHandler(); private void handleNotificationInternal(ResultContainer resultContainer) @@ -607,66 +598,53 @@ private void handleNotificationInternal(ResultContainer resultContainer) internalNotificationHandler, null); } - private class InternalNotificationHandler + private final class InternalNotificationHandler extends AbstractNotificationHandler { @Override - public HandlerResult handleNotification( - AssociationChangeNotification not, Object unused) { + public HandlerResult handleNotification(AssociationChangeNotification not, + Object unused) { AssociationChange sac = (AssociationChange) not; /* Update map to reflect change in association */ switch (not.event()) { - case COMM_UP : + case COMM_UP -> { Association newAssociation = new AssociationImpl - (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams()); + (sac.assocId(), sac.maxInStreams(), sac.maxOutStreams()); addAssociation(newAssociation); - break; - case SHUTDOWN : - case COMM_LOST : - //case RESTART: ??? + } + case SHUTDOWN, COMM_LOST -> + //case RESTART: ??? /* mark association for removal after user handler invoked*/ - associationToRemove.set(lookupAssociation(sac.assocId())); + associationToRemove.set(lookupAssociation(sac.assocId())); } return HandlerResult.CONTINUE; } } - private HandlerResult invokeNotificationHandler( - ResultContainer resultContainer, - NotificationHandler handler, - T attachment) { + private HandlerResult invokeNotificationHandler(ResultContainer resultContainer, + NotificationHandler handler, + T attachment) { HandlerResult result; SctpNotification notification = resultContainer.notification(); notification.setAssociation(lookupAssociation(notification.assocId())); - if (!(handler instanceof AbstractNotificationHandler)) { + if (!(handler instanceof AbstractNotificationHandler absHandler)) { result = handler.handleNotification(notification, attachment); } else { /* AbstractNotificationHandler */ - AbstractNotificationHandler absHandler = - (AbstractNotificationHandler)handler; - switch(resultContainer.type()) { - case ASSOCIATION_CHANGED : - result = absHandler.handleNotification( - resultContainer.getAssociationChanged(), attachment); - break; - case PEER_ADDRESS_CHANGED : - result = absHandler.handleNotification( - resultContainer.getPeerAddressChanged(), attachment); - break; - case SEND_FAILED : - result = absHandler.handleNotification( - resultContainer.getSendFailed(), attachment); - break; - case SHUTDOWN : - result = absHandler.handleNotification( - resultContainer.getShutdown(), attachment); - break; - default : - /* implementation specific handlers */ - result = absHandler.handleNotification( - resultContainer.notification(), attachment); - } + result = switch (resultContainer.type()) { + case ASSOCIATION_CHANGED -> absHandler.handleNotification( + resultContainer.getAssociationChanged(), attachment); + case PEER_ADDRESS_CHANGED -> absHandler.handleNotification( + resultContainer.getPeerAddressChanged(), attachment); + case SEND_FAILED -> absHandler.handleNotification( + resultContainer.getSendFailed(), attachment); + case SHUTDOWN -> absHandler.handleNotification( + resultContainer.getShutdown(), attachment); + /* implementation specific handlers */ + default -> absHandler.handleNotification( + resultContainer.notification(), attachment); + }; } if (!(handler instanceof InternalNotificationHandler)) { @@ -754,17 +732,15 @@ private void removeAssociation(Association association) { } /** - * @throws IllegalArgumentException - * If the given association is not controlled by this channel + * Checks if the given association is controlled by this channel. * - * @return {@code true} if, and only if, the given association is one - * of the current associations controlled by this channel + * @throws IllegalArgumentException If the given association is not controlled by this channel */ - private boolean checkAssociation(Association messageAssoc) { + private void checkAssociation(Association messageAssoc) { synchronized (stateLock) { for (Association association : associationMap.keySet()) { if (messageAssoc.equals(association)) { - return true; + return; } } } @@ -967,8 +943,7 @@ public Set getRemoteAddresses(Association association) return SctpNet.getRemoteAddresses(fdVal, association.associationID()); } catch (SocketException se) { /* a valid association should always have remote addresses */ - Set addrs = associationMap.get(association); - return addrs != null ? addrs : Collections.emptySet(); + return associationMap.getOrDefault(association, Collections.emptySet()); } } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java index e3b5c1b60c1..70996ffd788 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNet.java @@ -132,11 +132,11 @@ private static SocketAddress getRevealedLocalAddress(SocketAddress sa, static Set getRemoteAddresses(int fd, int assocId) throws IOException { - HashSet set = null; + Set set = null; SocketAddress[] saa = getRemoteAddresses0(fd, assocId); if (saa != null) { - set = new HashSet(saa.length); + set = new HashSet<>(saa.length); for (SocketAddress sa : saa) set.add(sa); } @@ -160,8 +160,6 @@ static void setSocketOption(int fd, name.equals(SCTP_SET_PEER_PRIMARY_ADDR)) { SocketAddress addr = (SocketAddress) value; - if (addr == null) - throw new IllegalArgumentException("Invalid option value"); Net.checkAddress(addr); InetSocketAddress netAddr = (InetSocketAddress)addr; @@ -257,7 +255,7 @@ static void setIntOption(int fd, SctpSocketOption name, Object value) arg = (b) ? 1 : 0; } - setIntOption0(fd, ((SctpStdSocketOption)name).constValue(), arg); + setIntOption0(fd, ((SctpStdSocketOption)name).constValue(), arg); } static Object getIntOption(int fd, SctpSocketOption name) @@ -267,11 +265,10 @@ static Object getIntOption(int fd, SctpSocketOption name) if (type != Integer.class && type != Boolean.class) throw new AssertionError("Should not reach here"); - if (!(name instanceof SctpStdSocketOption)) + if (!(name instanceof SctpStdSocketOption option)) throw new AssertionError("Should not reach here"); - int value = getIntOption0(fd, - ((SctpStdSocketOption)name).constValue()); + int value = getIntOption0(fd, option.constValue()); if (type == Integer.class) { return Integer.valueOf(value); diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNotification.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNotification.java index 6227e9ec20b..bfa851d526a 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNotification.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpNotification.java @@ -28,8 +28,8 @@ import com.sun.nio.sctp.Notification; /** - * All Notification implemenations MUST implement this interface to provide - * access to the native association identidier. + * All Notification implementations MUST implement this interface to provide + * access to the native association identifier. */ interface SctpNotification extends Notification { int assocId(); diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java index 1722bf90eeb..0f710a4c670 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java @@ -41,14 +41,12 @@ import com.sun.nio.sctp.SctpServerChannel; import com.sun.nio.sctp.SctpSocketOption; import com.sun.nio.sctp.SctpStandardSocketOptions; -import sun.nio.ch.DirectBuffer; import sun.nio.ch.NativeThread; import sun.nio.ch.IOStatus; import sun.nio.ch.IOUtil; import sun.nio.ch.Net; import sun.nio.ch.SelChImpl; import sun.nio.ch.SelectionKeyImpl; -import sun.nio.ch.Util; /** * An implementation of SctpServerChannel @@ -61,7 +59,7 @@ public class SctpServerChannelImpl extends SctpServerChannel private final int fdVal; /* IDs of native thread doing accept, for signalling */ - private volatile long thread = 0; + private volatile long thread; /* Lock held by thread currently blocked in this channel */ private final Object lock = new Object(); @@ -81,7 +79,7 @@ private enum ChannelState { /* Binding: Once bound the port will remain constant. */ int port = -1; - private HashSet localAddresses = new HashSet(); + private final HashSet localAddresses = new HashSet<>(); /* Has the channel been bound to the wildcard address */ private boolean wildcard; /* false */ @@ -200,7 +198,7 @@ private SctpServerChannel bindUnbindAddress(InetAddress address, boolean add) private boolean isBound() { synchronized (stateLock) { - return port == -1 ? false : true; + return port != -1; } } @@ -389,19 +387,13 @@ public T getOption(SctpSocketOption name) throws IOException { } } - private static class DefaultOptionsHolder { - static final Set> defaultOptions = defaultOptions(); - - private static Set> defaultOptions() { - HashSet> set = new HashSet>(1); - set.add(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS); - return Collections.unmodifiableSet(set); - } - } - @Override public final Set> supportedOptions() { - return DefaultOptionsHolder.defaultOptions; + final class Holder { + static final Set> DEFAULT_OPTIONS = + Set.of(SctpStandardSocketOptions.SCTP_INIT_MAXSTREAMS); + } + return Holder.DEFAULT_OPTIONS; } @Override diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SendFailed.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SendFailed.java index b152e82b29c..b053db084f5 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SendFailed.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/SendFailed.java @@ -38,11 +38,11 @@ public class SendFailed extends SendFailedNotification private Association association; /* assocId is used to lookup the association before the notification is * returned to user code */ - private int assocId; - private SocketAddress address; - private ByteBuffer buffer; - private int errorCode; - private int streamNumber; + private final int assocId; + private final SocketAddress address; + private final ByteBuffer buffer; + private final int errorCode; + private final int streamNumber; /* Invoked from native */ private SendFailed(int assocId, @@ -97,14 +97,12 @@ public int streamNumber() { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append(" ["); - sb.append("Association:").append(association); - sb.append(", Address: ").append(address); - sb.append(", buffer: ").append(buffer); - sb.append(", errorCode: ").append(errorCode); - sb.append(", streamNumber: ").append(streamNumber); - sb.append("]"); - return sb.toString(); + return super.toString() + " [" + + "Association:" + association + + ", Address: " + address + + ", buffer: " + buffer + + ", errorCode: " + errorCode + + ", streamNumber: " + streamNumber + + "]"; } } diff --git a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/Shutdown.java b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/Shutdown.java index 1b20317d136..411dea05eb4 100644 --- a/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/Shutdown.java +++ b/src/jdk.sctp/unix/classes/sun/nio/ch/sctp/Shutdown.java @@ -34,9 +34,9 @@ public class Shutdown extends ShutdownNotification implements SctpNotification { private Association association; - /* assocId is used to lookup the association before the notification is + /* assocId is used to look up the association before the notification is * returned to user code */ - private int assocId; + private final int assocId; /* Invoked from native */ private Shutdown(int assocId) { @@ -61,9 +61,7 @@ public Association association() { @Override public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()).append(" ["); - sb.append("Association:").append(association).append("]"); - return sb.toString(); + return super.toString() + " [" + + "Association:" + association + "]"; } } From 133ad8e1734f002f013dd3c73d496e323e9e881e Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 9 Dec 2022 11:11:46 +0000 Subject: [PATCH 144/494] 8297988: NPE in JavacTypes.getOverriddenMethods from doclint Reviewed-by: vromero, jjg --- .../sun/tools/javac/main/JavaCompiler.java | 15 ++- .../tools/javac/modules/EdgeCases.java | 104 +++++++++++++++++- 2 files changed, 115 insertions(+), 4 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java index 8f1cb2df1b5..47e70f5321f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/main/JavaCompiler.java @@ -608,13 +608,22 @@ public CharSequence readSource(JavaFileObject filename) { * @param content The characters to be parsed. */ protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) { + return parse(filename, content, false); + } + + /** Parse contents of input stream. + * @param filename The name of the file from which input stream comes. + * @param content The characters to be parsed. + * @param silent true if TaskListeners should not be notified + */ + private JCCompilationUnit parse(JavaFileObject filename, CharSequence content, boolean silent) { long msec = now(); JCCompilationUnit tree = make.TopLevel(List.nil()); if (content != null) { if (verbose) { log.printVerbose("parsing.started", filename); } - if (!taskListener.isEmpty()) { + if (!taskListener.isEmpty() && !silent) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, filename); taskListener.started(e); keepComments = true; @@ -630,7 +639,7 @@ protected JCCompilationUnit parse(JavaFileObject filename, CharSequence content) tree.sourcefile = filename; - if (content != null && !taskListener.isEmpty()) { + if (content != null && !taskListener.isEmpty() && !silent) { TaskEvent e = new TaskEvent(TaskEvent.Kind.PARSE, tree); taskListener.finished(e); } @@ -1800,7 +1809,7 @@ private Name parseAndGetName(JavaFileObject fo, DiagnosticHandler dh = new DiscardDiagnosticHandler(log); JavaFileObject prevSource = log.useSource(fo); try { - JCTree.JCCompilationUnit t = parse(fo, fo.getCharContent(false)); + JCTree.JCCompilationUnit t = parse(fo, fo.getCharContent(false), true); return tree2Name.apply(t); } catch (IOException e) { return null; diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index 5d699b04b10..ae142f32ccd 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311 8241519 + * @bug 8154283 8167320 8171098 8172809 8173068 8173117 8176045 8177311 8241519 8297988 * @summary tests for multi-module mode compilation * @library /tools/lib * @modules @@ -65,10 +65,13 @@ import javax.tools.ToolProvider; import com.sun.source.tree.CompilationUnitTree; +import com.sun.source.util.TaskEvent; +import com.sun.source.util.TaskListener; //import com.sun.source.util.JavacTask; // conflicts with toolbox.JavacTask import com.sun.tools.javac.api.JavacTaskImpl; import com.sun.tools.javac.code.Symbol.ModuleSymbol; import com.sun.tools.javac.code.Symtab; +import java.util.ArrayList; import toolbox.JarTask; import toolbox.JavacTask; @@ -1047,4 +1050,103 @@ public void testMisnamedModuleInfoClass(Path base) throws Exception { throw new Exception("expected output not found: " + log); } + @Test //JDK-8297988 + public void testExportedNameCheckFromSourceNoEvent(Path base) throws Exception { + //when validating "exports", javac may parse source(s) from the package to check their + //package name. The AST produced by this parse are thrown away, so listeners should not + //be notified: + Path src = base.resolve("src"); + Path m = src.resolve("m"); + tb.writeJavaFiles(m, + """ + module m { + exports test; + } + """, + """ + package test; + public class Test {} + """, + """ + package impl; + public class Impl { + void t() { + test.Test t; + } + } + """); + Path classes = base.resolve("classes"); + tb.createDirectories(classes); + + record TestCase(Path[] files, String... expectedLog){} + + TestCase[] testCases = new TestCase[] { + new TestCase(new Path[] {m.resolve("module-info.java")}, + "COMPILATION:started:", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "COMPILATION:finished:"), + new TestCase(new Path[] {m.resolve("module-info.java"), + m.resolve("impl").resolve("Impl.java")}, + "COMPILATION:started:", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/module-info.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "PARSE:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "PARSE:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ENTER:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ENTER:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/impl/Impl.java", + "ANALYZE:started:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "ANALYZE:finished:testExportedNameCheckFromSourceNoEvent/src/m/test/Test.java", + "COMPILATION:finished:") + }; + + for (TestCase tc : testCases) { + List log = new ArrayList<>(); + + new JavacTask(tb) + .outdir(classes) + .options("--source-path", m.toString(), + "-XDshould-stop.ifNoError=FLOW") + .callback(task -> { + task.addTaskListener(new TaskListener() { + @Override + public void started(TaskEvent e) { + record(e, "started"); + } + @Override + public void finished(TaskEvent e) { + record(e, "finished"); + } + private void record(TaskEvent e, String phase) { + JavaFileObject source = e.getSourceFile(); + String sourceName = source != null ? source.getName() : ""; + log.add(e.getKind() + ":" + phase + ":" + sourceName); + } + }); + }) + .files(tc.files) + .run() + .writeAll(); + + if (!List.of(tc.expectedLog).equals(log)) { + throw new AssertionError("Unexpected log, got: " + log + + ", expected: " + List.of(tc.expectedLog)); + } + } + } + } From 33d955ad6e46eecd947e958ce295f6a6c348b2a6 Mon Sep 17 00:00:00 2001 From: Gui Cao Date: Fri, 9 Dec 2022 12:43:47 +0000 Subject: [PATCH 145/494] 8298345: Fix another two C2 IR matching tests for RISC-V Reviewed-by: fyang, dzhang, fjiang --- .../compiler/c2/irTests/TestAutoVectorization2DArray.java | 4 +++- .../jtreg/compiler/lib/ir_framework/TestFramework.java | 1 + .../jtreg/compiler/vectorization/TestAutoVecIntMinMax.java | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java index 51c7ce670d2..31fc5361b6b 100644 --- a/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java +++ b/test/hotspot/jtreg/compiler/c2/irTests/TestAutoVectorization2DArray.java @@ -29,7 +29,9 @@ * @test * @bug 8279258 * @summary Auto-vectorization enhancement for two-dimensional array operations - * @requires (os.arch != "x86" & os.arch != "i386") | vm.opt.UseSSE == "null" | vm.opt.UseSSE >= 2 + * @requires ((os.arch == "x86" | os.arch == "i386") & (vm.opt.UseSSE == "null" | vm.opt.UseSSE >= 2)) + * | (os.arch != "x86" & os.arch != "i386" & os.arch != "riscv64") + * | (os.arch == "riscv64" & vm.opt.UseRVV == true) * @library /test/lib / * @run driver compiler.c2.irTests.TestAutoVectorization2DArray */ diff --git a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java index 76b9fdb5c0e..c67d765a2e4 100644 --- a/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java +++ b/test/hotspot/jtreg/compiler/lib/ir_framework/TestFramework.java @@ -140,6 +140,7 @@ public class TestFramework { "UseSSE", "UseSVE", "UseZbb", + "UseRVV", "Xlog", "LogCompilation" ) diff --git a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java index 7a71a00e6e9..e15a4c834cd 100644 --- a/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java +++ b/test/hotspot/jtreg/compiler/vectorization/TestAutoVecIntMinMax.java @@ -34,7 +34,7 @@ * @library /test/lib / * @requires vm.compiler2.enabled * @requires (os.simpleArch == "x64" & (vm.opt.UseSSE == "null" | vm.opt.UseSSE > 3)) - * | os.arch == "aarch64" | os.arch == "riscv64" + * | os.arch == "aarch64" | (os.arch == "riscv64" & vm.opt.UseRVV == true) * @run driver compiler.c2.irTests.TestAutoVecIntMinMax */ From e3c6cf8eaf931d9eb46b429a5ba8d3bbded3728a Mon Sep 17 00:00:00 2001 From: Sergey Tsypanov Date: Fri, 9 Dec 2022 12:50:55 +0000 Subject: [PATCH 146/494] 8298380: Clean up redundant array length checks in JDK code base Reviewed-by: dholmes, amenkov, serb, vtewari --- .../classes/sun/nio/fs/LinuxWatchService.java | 16 +++++------- .../java/nio/file/spi/FileSystemProvider.java | 12 ++++----- .../classes/jdk/internal/jrtfs/JrtPath.java | 8 +++--- .../sun/nio/fs/PollingWatchService.java | 26 +++++++++---------- .../com/apple/laf/AquaFileChooserUI.java | 8 +++--- .../src/jdk/vm/ci/meta/Assumptions.java | 8 +++--- .../sun/tools/jconsole/inspector/XTree.java | 4 +-- .../share/classes/jdk/nio/zipfs/ZipPath.java | 8 +++--- 8 files changed, 38 insertions(+), 52 deletions(-) diff --git a/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java b/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java index 41d9fbb0816..863b8cd7aff 100644 --- a/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java +++ b/src/java.base/linux/classes/sun/nio/fs/LinuxWatchService.java @@ -226,15 +226,13 @@ Object implRegister(Path obj, } // no modifiers supported at this time - if (modifiers.length > 0) { - for (WatchEvent.Modifier modifier: modifiers) { - if (modifier == null) - return new NullPointerException(); - if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) && - !ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) && - !ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) { - return new UnsupportedOperationException("Modifier not supported"); - } + for (WatchEvent.Modifier modifier : modifiers) { + if (modifier == null) + return new NullPointerException(); + if (!ExtendedOptions.SENSITIVITY_HIGH.matches(modifier) && + !ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier) && + !ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) { + return new UnsupportedOperationException("Modifier not supported"); } } diff --git a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java index 448843ba547..17caff30b03 100644 --- a/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java +++ b/src/java.base/share/classes/java/nio/file/spi/FileSystemProvider.java @@ -411,13 +411,11 @@ public FileSystem newFileSystem(Path path, Map env) public InputStream newInputStream(Path path, OpenOption... options) throws IOException { - if (options.length > 0) { - for (OpenOption opt: options) { - // All OpenOption values except for APPEND and WRITE are allowed - if (opt == StandardOpenOption.APPEND || - opt == StandardOpenOption.WRITE) - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } + for (OpenOption opt : options) { + // All OpenOption values except for APPEND and WRITE are allowed + if (opt == StandardOpenOption.APPEND || + opt == StandardOpenOption.WRITE) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); } ReadableByteChannel rbc = Files.newByteChannel(path, options); if (rbc instanceof FileChannelImpl) { diff --git a/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java index 93157421e5c..663e30cb0c5 100644 --- a/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java +++ b/src/java.base/share/classes/jdk/internal/jrtfs/JrtPath.java @@ -627,11 +627,9 @@ final void createDirectory(FileAttribute... attrs) } final InputStream newInputStream(OpenOption... options) throws IOException { - if (options.length > 0) { - for (OpenOption opt : options) { - if (opt != READ) { - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } + for (OpenOption opt : options) { + if (opt != READ) { + throw new UnsupportedOperationException("'" + opt + "' not allowed"); } } return jrtfs.newInputStream(this); diff --git a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java index 582462c36c1..f86626d196a 100644 --- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java +++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java @@ -119,20 +119,18 @@ WatchKey register(final Path path, // Extended modifiers may be used to specify the sensitivity level int sensitivity = DEFAULT_POLLING_INTERVAL; - if (modifiers.length > 0) { - for (WatchEvent.Modifier modifier: modifiers) { - if (modifier == null) - throw new NullPointerException(); - - if (ExtendedOptions.SENSITIVITY_HIGH.matches(modifier)) { - sensitivity = ExtendedOptions.SENSITIVITY_HIGH.parameter(); - } else if (ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier)) { - sensitivity = ExtendedOptions.SENSITIVITY_MEDIUM.parameter(); - } else if (ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) { - sensitivity = ExtendedOptions.SENSITIVITY_LOW.parameter(); - } else { - throw new UnsupportedOperationException("Modifier not supported"); - } + for (WatchEvent.Modifier modifier : modifiers) { + if (modifier == null) + throw new NullPointerException(); + + if (ExtendedOptions.SENSITIVITY_HIGH.matches(modifier)) { + sensitivity = ExtendedOptions.SENSITIVITY_HIGH.parameter(); + } else if (ExtendedOptions.SENSITIVITY_MEDIUM.matches(modifier)) { + sensitivity = ExtendedOptions.SENSITIVITY_MEDIUM.parameter(); + } else if (ExtendedOptions.SENSITIVITY_LOW.matches(modifier)) { + sensitivity = ExtendedOptions.SENSITIVITY_LOW.parameter(); + } else { + throw new UnsupportedOperationException("Modifier not supported"); } } diff --git a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java index d8bfca02fe7..2cfaa5a36ca 100644 --- a/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java +++ b/src/java.desktop/macosx/classes/com/apple/laf/AquaFileChooserUI.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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 @@ -653,10 +653,8 @@ public void valueChanged(final ListSelectionEvent e) { int selectableCount = 0; // Double-check that all the list selections are valid for this mode // Directories can be selected in the list regardless of mode - if (rows.length > 0) { - for (final int element : rows) { - if (isSelectableForMode(chooser, (File)fFileList.getValueAt(element, 0))) selectableCount++; - } + for (final int element : rows) { + if (isSelectableForMode(chooser, (File) fFileList.getValueAt(element, 0))) selectableCount++; } if (selectableCount > 0) { final File[] files = new File[selectableCount]; diff --git a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java index 688d1e732c3..ddbd7ba9805 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk.vm.ci.meta/src/jdk/vm/ci/meta/Assumptions.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2011, 2022, 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,10 +89,8 @@ public boolean canRecordTo(Assumptions target) { public void recordTo(Assumptions target) { assert canRecordTo(target); - if (assumptions.length > 0) { - for (Assumption assumption : assumptions) { - target.record(assumption); - } + for (Assumption assumption : assumptions) { + target.record(assumption); } } diff --git a/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XTree.java b/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XTree.java index aaa1ab6a6bd..d133e1cf8bb 100644 --- a/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XTree.java +++ b/src/jdk.jconsole/share/classes/sun/tools/jconsole/inspector/XTree.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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 @@ -649,7 +649,7 @@ private void addMBeanInfoNodes( Messages.NOTIFICATIONS, null); notifications.setUserObject(notificationsUO); node.insert(notifications, childIndex++); - if (ni != null && ni.length > 0) { + if (ni != null) { for (MBeanNotificationInfo mbni : ni) { DefaultMutableTreeNode notification = new DefaultMutableTreeNode(); diff --git a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java index e14eba3863e..806c8d352bf 100644 --- a/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java +++ b/src/jdk.zipfs/share/classes/jdk/nio/zipfs/ZipPath.java @@ -744,11 +744,9 @@ void createDirectory(FileAttribute... attrs) InputStream newInputStream(OpenOption... options) throws IOException { - if (options.length > 0) { - for (OpenOption opt : options) { - if (opt != READ) - throw new UnsupportedOperationException("'" + opt + "' not allowed"); - } + for (OpenOption opt : options) { + if (opt != READ) + throw new UnsupportedOperationException("'" + opt + "' not allowed"); } return zfs.newInputStream(getResolvedPath()); } From 05b0a018c736f79acc99043d5e0e556658b93ab8 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Fri, 9 Dec 2022 13:26:12 +0000 Subject: [PATCH 147/494] 8298281: Serial: Refactor MarkAndPushClosure Reviewed-by: stefank, sjohanss --- src/hotspot/share/gc/serial/markSweep.cpp | 2 +- src/hotspot/share/gc/serial/markSweep.hpp | 16 ++++------------ src/hotspot/share/gc/serial/markSweep.inline.hpp | 12 +----------- 3 files changed, 6 insertions(+), 24 deletions(-) diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp index e9667d4e346..717d931b929 100644 --- a/src/hotspot/share/gc/serial/markSweep.cpp +++ b/src/hotspot/share/gc/serial/markSweep.cpp @@ -61,7 +61,7 @@ StringDedup::Requests* MarkSweep::_string_dedup_requests = NULL; MarkSweep::FollowRootClosure MarkSweep::follow_root_closure; -MarkAndPushClosure MarkSweep::mark_and_push_closure; +MarkAndPushClosure MarkSweep::mark_and_push_closure(ClassLoaderData::_claim_stw_fullgc_mark); CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_stw_fullgc_mark); CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_stw_fullgc_adjust); diff --git a/src/hotspot/share/gc/serial/markSweep.hpp b/src/hotspot/share/gc/serial/markSweep.hpp index 17e4692ce73..32ae63c12f5 100644 --- a/src/hotspot/share/gc/serial/markSweep.hpp +++ b/src/hotspot/share/gc/serial/markSweep.hpp @@ -38,8 +38,6 @@ class ReferenceProcessor; class DataLayout; -class Method; -class nmethod; class SerialOldTracer; class STWGCTimer; @@ -152,8 +150,6 @@ class MarkSweep : AllStatic { static void follow_klass(Klass* klass); - static void follow_cld(ClassLoaderData* cld); - template static inline void adjust_pointer(T* p); // Check mark and maybe push on marking stack @@ -174,18 +170,14 @@ class MarkSweep : AllStatic { static void follow_array_chunk(objArrayOop array, int index); }; -class MarkAndPushClosure: public OopIterateClosure { +class MarkAndPushClosure: public ClaimMetadataVisitingOopIterateClosure { public: + MarkAndPushClosure(int claim) : ClaimMetadataVisitingOopIterateClosure(claim) {} + template void do_oop_work(T* p); - virtual void do_oop(oop* p); + virtual void do_oop( oop* p); virtual void do_oop(narrowOop* p); - virtual bool do_metadata() { return true; } - virtual void do_klass(Klass* k); - virtual void do_cld(ClassLoaderData* cld); - virtual void do_method(Method* m); - virtual void do_nmethod(nmethod* nm); - void set_ref_discoverer(ReferenceDiscoverer* rd) { set_ref_discoverer_internal(rd); } diff --git a/src/hotspot/share/gc/serial/markSweep.inline.hpp b/src/hotspot/share/gc/serial/markSweep.inline.hpp index 71a61c7263b..0f4a12af0f9 100644 --- a/src/hotspot/share/gc/serial/markSweep.inline.hpp +++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp @@ -29,14 +29,12 @@ #include "classfile/classLoaderData.inline.hpp" #include "classfile/javaClasses.inline.hpp" -#include "code/nmethod.hpp" #include "gc/shared/continuationGCSupport.inline.hpp" #include "gc/serial/serialStringDedup.hpp" #include "memory/universe.hpp" #include "oops/markWord.hpp" #include "oops/access.inline.hpp" #include "oops/compressedOops.inline.hpp" -#include "oops/method.hpp" #include "oops/oop.inline.hpp" #include "utilities/align.hpp" #include "utilities/stack.inline.hpp" @@ -76,18 +74,10 @@ inline void MarkSweep::follow_klass(Klass* klass) { MarkSweep::mark_and_push(&op); } -inline void MarkSweep::follow_cld(ClassLoaderData* cld) { - MarkSweep::follow_cld_closure.do_cld(cld); -} - template inline void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); } -inline void MarkAndPushClosure::do_oop(oop* p) { do_oop_work(p); } +inline void MarkAndPushClosure::do_oop( oop* p) { do_oop_work(p); } inline void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } -inline void MarkAndPushClosure::do_klass(Klass* k) { MarkSweep::follow_klass(k); } -inline void MarkAndPushClosure::do_cld(ClassLoaderData* cld) { MarkSweep::follow_cld(cld); } -inline void MarkAndPushClosure::do_method(Method* m) { m->record_gc_epoch(); } -inline void MarkAndPushClosure::do_nmethod(nmethod* nm) { nm->follow_nmethod(this); } template inline void MarkSweep::adjust_pointer(T* p) { T heap_oop = RawAccess<>::oop_load(p); From b30b464d054716bbc3d4d70633b740b227b8775d Mon Sep 17 00:00:00 2001 From: Roman Kennke Date: Fri, 9 Dec 2022 14:52:27 +0000 Subject: [PATCH 148/494] 8297036: Generalize C2 stub mechanism Co-authored-by: Aleksey Shipilev Co-authored-by: Xiaolin Zheng Reviewed-by: eosterlund, kvn, fyang --- src/hotspot/cpu/aarch64/aarch64.ad | 9 +- ...e_aarch64.cpp => c2_CodeStubs_aarch64.cpp} | 36 ++++-- .../cpu/aarch64/c2_MacroAssembler_aarch64.cpp | 15 --- ...StubTable_ppc.cpp => c2_CodeStubs_ppc.cpp} | 21 ++-- src/hotspot/cpu/ppc/ppc.ad | 5 +- ...Table_riscv.cpp => c2_CodeStubs_riscv.cpp} | 41 ++++-- .../cpu/riscv/c2_MacroAssembler_riscv.cpp | 33 +---- src/hotspot/cpu/riscv/riscv.ad | 9 +- ...StubTable_x86.cpp => c2_CodeStubs_x86.cpp} | 31 +++-- src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp | 15 +-- src/hotspot/cpu/x86/x86_32.ad | 4 +- src/hotspot/cpu/x86/x86_64.ad | 4 +- src/hotspot/share/opto/c2_CodeStubs.cpp | 54 ++++++++ src/hotspot/share/opto/c2_CodeStubs.hpp | 89 +++++++++++++ src/hotspot/share/opto/c2_MacroAssembler.hpp | 3 +- src/hotspot/share/opto/output.cpp | 117 +----------------- src/hotspot/share/opto/output.hpp | 82 +----------- 17 files changed, 275 insertions(+), 293 deletions(-) rename src/hotspot/cpu/aarch64/{c2_safepointPollStubTable_aarch64.cpp => c2_CodeStubs_aarch64.cpp} (65%) rename src/hotspot/cpu/ppc/{c2_safepointPollStubTable_ppc.cpp => c2_CodeStubs_ppc.cpp} (80%) rename src/hotspot/cpu/riscv/{c2_safepointPollStubTable_riscv.cpp => c2_CodeStubs_riscv.cpp} (63%) rename src/hotspot/cpu/x86/{c2_safepointPollStubTable_x86.cpp => c2_CodeStubs_x86.cpp} (72%) create mode 100644 src/hotspot/share/opto/c2_CodeStubs.cpp create mode 100644 src/hotspot/share/opto/c2_CodeStubs.hpp diff --git a/src/hotspot/cpu/aarch64/aarch64.ad b/src/hotspot/cpu/aarch64/aarch64.ad index c162baad936..252c277e2c7 100644 --- a/src/hotspot/cpu/aarch64/aarch64.ad +++ b/src/hotspot/cpu/aarch64/aarch64.ad @@ -1796,8 +1796,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label* guard = &dummy_guard; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for the purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); guard = &stub->guard(); } @@ -1879,7 +1880,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); diff --git a/src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp similarity index 65% rename from src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp rename to src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp index fb36406fbde..009883d6082 100644 --- a/src/hotspot/cpu/aarch64/c2_safepointPollStubTable_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_CodeStubs_aarch64.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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,24 +23,44 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 20; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(masm.pc() - masm.offset() + _safepoint_offset); __ adr(rscratch1, safepoint_pc); __ str(rscratch1, Address(rthread, JavaThread::saved_exception_pc_offset())); __ far_jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + return 24; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + __ movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier()); + __ blr(rscratch1); + __ b(continuation()); + + __ bind(guard()); + __ relocate(entry_guard_Relocation::spec()); + __ emit_int32(0); // nmethod guard value +} + #undef __ diff --git a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp index 93495e0fc58..0bf4233841d 100644 --- a/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/c2_MacroAssembler_aarch64.cpp @@ -45,21 +45,6 @@ typedef void (MacroAssembler::* chr_insn)(Register Rt, const Address &adr); -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - bind(stub->slow_path()); - movptr(rscratch1, (uintptr_t) StubRoutines::aarch64::method_entry_barrier()); - blr(rscratch1); - b(stub->continuation()); - - bind(stub->guard()); - relocate(entry_guard_Relocation::spec()); - emit_int32(0); // nmethod guard value -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 4 * 6; -} - // Search for str1 in str2 and return index or -1 void C2_MacroAssembler::string_indexof(Register str2, Register str1, Register cnt2, Register cnt1, diff --git a/src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp b/src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp similarity index 80% rename from src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp rename to src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp index b65b91df1b8..f99f9e978cf 100644 --- a/src/hotspot/cpu/ppc/c2_safepointPollStubTable_ppc.cpp +++ b/src/hotspot/cpu/ppc/c2_CodeStubs_ppc.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2020, 2021, Oracle and/or its affiliates. All rights reserved. - * Copyright (c) 2021 SAP SE. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2022, SAP SE. All rights reserved. * 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,22 @@ */ #include "precompiled.hpp" -#include "macroAssembler_ppc.inline.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 56; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); - __ bind(entry->_stub_label); + __ bind(entry()); // Using pc relative address computation. { Label next_pc; @@ -45,7 +48,7 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP } int current_offset = __ offset(); // Code size should not depend on offset: see _stub_size computation in output.cpp - __ load_const32(R12, entry->_safepoint_offset - current_offset); + __ load_const32(R12, _safepoint_offset - current_offset); __ mflr(R0); __ add(R12, R12, R0); __ std(R12, in_bytes(JavaThread::saved_exception_pc_offset()), R16_thread); diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 296bf160089..32e80028c6f 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -982,6 +982,7 @@ source_hpp %{ source %{ +#include "opto/c2_CodeStubs.hpp" #include "oops/klass.inline.hpp" void PhaseOutput::pd_perform_mach_node_analysis() { @@ -1616,7 +1617,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!UseSIGTRAP && !C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); __ relocate(relocInfo::poll_return_type); } __ safepoint_poll(*code_stub, temp, true /* at_return */, true /* in_nmethod */); diff --git a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp b/src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp similarity index 63% rename from src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp rename to src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp index e68b8d0486e..4ddd6f3c2c3 100644 --- a/src/hotspot/cpu/riscv/c2_safepointPollStubTable_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_CodeStubs_riscv.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, Oracle and/or its affiliates. All rights reserved. * Copyright (c) 2020, 2022, Huawei Technologies Co., Ltd. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -24,21 +24,25 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_CodeStubs.hpp" +#include "opto/c2_MacroAssembler.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 13 * 4; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(__ pc() - __ offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(__ pc() - __ offset() + _safepoint_offset); __ relocate(safepoint_pc.rspec(), [&] { int32_t offset; __ la_patchable(t0, safepoint_pc.target(), offset); @@ -47,4 +51,25 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP __ sd(t0, Address(xthread, JavaThread::saved_exception_pc_offset())); __ far_jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + // 4 bytes for alignment + return 8 * 4 + 4; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + + int32_t offset = 0; + __ movptr(t0, StubRoutines::riscv::method_entry_barrier(), offset); + __ jalr(ra, t0, offset); + __ j(continuation()); + + // make guard value 4-byte aligned so that it can be accessed by atomic instructions on RISC-V + __ align(4); + __ bind(guard()); + __ relocate(entry_guard_Relocation::spec()); + __ emit_int32(0); // nmethod guard value +} + #undef __ diff --git a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp index e4c892280d6..b87fe003542 100644 --- a/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/c2_MacroAssembler_riscv.cpp @@ -243,37 +243,6 @@ void C2_MacroAssembler::string_indexof_char(Register str1, Register cnt1, typedef void (MacroAssembler::* load_chr_insn)(Register rd, const Address &adr, Register temp); -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - IncompressibleRegion ir(this); // Fixed length: see C2_MacroAssembler::entry_barrier_stub_size() - - // make guard value 4-byte aligned so that it can be accessed by atomic instructions on riscv - int alignment_bytes = align(4); - - bind(stub->slow_path()); - - int32_t offset = 0; - movptr(t0, StubRoutines::riscv::method_entry_barrier(), offset); - jalr(ra, t0, offset); - j(stub->continuation()); - - bind(stub->guard()); - relocate(entry_guard_Relocation::spec()); - assert_alignment(pc()); - emit_int32(0); // nmethod guard value - // make sure the stub with a fixed code size - if (alignment_bytes == 2) { - assert(UseRVC, "bad alignment"); - c_nop(); - } else { - assert(alignment_bytes == 0, "bad alignment"); - nop(); - } -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 8 * 4 + 4; // 4 bytes for alignment margin -} - // Search for needle in haystack and return index or -1 // x10: result // x11: haystack @@ -1726,4 +1695,4 @@ void C2_MacroAssembler::rvv_reduce_integral(Register dst, VectorRegister tmp, } vmv_x_s(dst, tmp); -} \ No newline at end of file +} diff --git a/src/hotspot/cpu/riscv/riscv.ad b/src/hotspot/cpu/riscv/riscv.ad index a9693980441..cf9d6bc556f 100644 --- a/src/hotspot/cpu/riscv/riscv.ad +++ b/src/hotspot/cpu/riscv/riscv.ad @@ -1361,8 +1361,9 @@ void MachPrologNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label* guard = &dummy_guard; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); guard = &stub->guard(); } @@ -1443,7 +1444,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, true /* at_return */, false /* acquire */, true /* in_nmethod */); diff --git a/src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp similarity index 72% rename from src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp rename to src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp index c3d4850a5db..acae574bcf3 100644 --- a/src/hotspot/cpu/x86/c2_safepointPollStubTable_x86.cpp +++ b/src/hotspot/cpu/x86/c2_CodeStubs_x86.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2020, 2022, 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,22 +23,26 @@ */ #include "precompiled.hpp" -#include "asm/macroAssembler.hpp" -#include "opto/compile.hpp" -#include "opto/node.hpp" -#include "opto/output.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/c2_CodeStubs.hpp" #include "runtime/sharedRuntime.hpp" +#include "runtime/stubRoutines.hpp" #define __ masm. -void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const { + +int C2SafepointPollStub::max_size() const { + return 33; +} + +void C2SafepointPollStub::emit(C2_MacroAssembler& masm) { assert(SharedRuntime::polling_page_return_handler_blob() != NULL, "polling page return stub not created yet"); address stub = SharedRuntime::polling_page_return_handler_blob()->entry_point(); RuntimeAddress callback_addr(stub); - __ bind(entry->_stub_label); - InternalAddress safepoint_pc(masm.pc() - masm.offset() + entry->_safepoint_offset); + __ bind(entry()); + InternalAddress safepoint_pc(masm.pc() - masm.offset() + _safepoint_offset); #ifdef _LP64 __ lea(rscratch1, safepoint_pc); __ movptr(Address(r15_thread, JavaThread::saved_exception_pc_offset()), rscratch1); @@ -57,4 +61,15 @@ void C2SafepointPollStubTable::emit_stub_impl(MacroAssembler& masm, C2SafepointP #endif __ jump(callback_addr); } + +int C2EntryBarrierStub::max_size() const { + return 10; +} + +void C2EntryBarrierStub::emit(C2_MacroAssembler& masm) { + __ bind(entry()); + __ call(RuntimeAddress(StubRoutines::x86::method_entry_barrier())); + __ jmp(continuation(), false /* maybe_short */); +} + #undef __ diff --git a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp index 7436322f878..91949213a20 100644 --- a/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp +++ b/src/hotspot/cpu/x86/c2_MacroAssembler_x86.cpp @@ -138,8 +138,9 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool Label* continuation = &dummy_continuation; if (!Compile::current()->output()->in_scratch_emit_size()) { // Use real labels from actual stub when not emitting code for the purpose of measuring its size - C2EntryBarrierStub* stub = Compile::current()->output()->entry_barrier_table()->add_entry_barrier(); - slow_path = &stub->slow_path(); + C2EntryBarrierStub* stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); + Compile::current()->output()->add_stub(stub); + slow_path = &stub->entry(); continuation = &stub->continuation(); } bs->nmethod_entry_barrier(this, slow_path, continuation); @@ -151,16 +152,6 @@ void C2_MacroAssembler::verified_entry(int framesize, int stack_bang_size, bool } } -void C2_MacroAssembler::emit_entry_barrier_stub(C2EntryBarrierStub* stub) { - bind(stub->slow_path()); - call(RuntimeAddress(StubRoutines::x86::method_entry_barrier())); - jmp(stub->continuation(), false /* maybe_short */); -} - -int C2_MacroAssembler::entry_barrier_stub_size() { - return 10; -} - inline Assembler::AvxVectorLen C2_MacroAssembler::vector_length_encoding(int vlen_in_bytes) { switch (vlen_in_bytes) { case 4: // fall-through diff --git a/src/hotspot/cpu/x86/x86_32.ad b/src/hotspot/cpu/x86/x86_32.ad index 017ce230ba4..979494e4cb1 100644 --- a/src/hotspot/cpu/x86/x86_32.ad +++ b/src/hotspot/cpu/x86/x86_32.ad @@ -708,7 +708,9 @@ void MachEpilogNode::emit(CodeBuffer &cbuf, PhaseRegAlloc *ra_) const { Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, thread, true /* at_return */, true /* in_nmethod */); diff --git a/src/hotspot/cpu/x86/x86_64.ad b/src/hotspot/cpu/x86/x86_64.ad index e78d416a044..a102fc77358 100644 --- a/src/hotspot/cpu/x86/x86_64.ad +++ b/src/hotspot/cpu/x86/x86_64.ad @@ -1020,7 +1020,9 @@ void MachEpilogNode::emit(CodeBuffer& cbuf, PhaseRegAlloc* ra_) const Label dummy_label; Label* code_stub = &dummy_label; if (!C->output()->in_scratch_emit_size()) { - code_stub = &C->output()->safepoint_poll_table()->add_safepoint(__ offset()); + C2SafepointPollStub* stub = new (C->comp_arena()) C2SafepointPollStub(__ offset()); + C->output()->add_stub(stub); + code_stub = &stub->entry(); } __ relocate(relocInfo::poll_return_type); __ safepoint_poll(*code_stub, r15_thread, true /* at_return */, true /* in_nmethod */); diff --git a/src/hotspot/share/opto/c2_CodeStubs.cpp b/src/hotspot/share/opto/c2_CodeStubs.cpp new file mode 100644 index 00000000000..52dea559045 --- /dev/null +++ b/src/hotspot/share/opto/c2_CodeStubs.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022, 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 "precompiled.hpp" +#include "asm/codeBuffer.hpp" +#include "code/codeBlob.hpp" +#include "opto/c2_CodeStubs.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "opto/compile.hpp" +#include "opto/output.hpp" + +C2CodeStubList::C2CodeStubList() : + _stubs(Compile::current()->comp_arena(), 2, 0, NULL) {} + +void C2CodeStubList::emit(CodeBuffer& cb) { + C2_MacroAssembler masm(&cb); + for (int i = _stubs.length() - 1; i >= 0; i--) { + C2CodeStub* stub = _stubs.at(i); + int max_size = stub->max_size(); + // Make sure there is enough space in the code buffer + if (cb.insts()->maybe_expand_to_ensure_remaining(max_size) && cb.blob() == NULL) { + ciEnv::current()->record_failure("CodeCache is full"); + return; + } + + DEBUG_ONLY(int size_before = cb.insts_size();) + + stub->emit(masm); + + DEBUG_ONLY(int actual_size = cb.insts_size() - size_before;) + assert(max_size >= actual_size, "Expected stub size (%d) must be larger than or equal to actual stub size (%d)", max_size, actual_size); + } +} diff --git a/src/hotspot/share/opto/c2_CodeStubs.hpp b/src/hotspot/share/opto/c2_CodeStubs.hpp new file mode 100644 index 00000000000..5ef6966656b --- /dev/null +++ b/src/hotspot/share/opto/c2_CodeStubs.hpp @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2022, 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 "asm/assembler.hpp" +#include "asm/codeBuffer.hpp" +#include "memory/allocation.hpp" +#include "opto/c2_MacroAssembler.hpp" +#include "utilities/growableArray.hpp" + +#ifndef SHARE_OPTO_C2_CODESTUBS_HPP +#define SHARE_OPTO_C2_CODESTUBS_HPP + +class C2CodeStub : public ArenaObj { +private: + Label _entry; + Label _continuation; + +protected: + C2CodeStub() : + _entry(), + _continuation() {} + +public: + Label& entry() { return _entry; } + Label& continuation() { return _continuation; } + + virtual void emit(C2_MacroAssembler& masm) = 0; + virtual int max_size() const = 0; +}; + +class C2CodeStubList { +private: + GrowableArray _stubs; + +public: + C2CodeStubList(); + + void add_stub(C2CodeStub* stub) { _stubs.append(stub); } + void emit(CodeBuffer& cb); +}; + +class C2SafepointPollStub : public C2CodeStub { +private: + uintptr_t _safepoint_offset; + +public: + C2SafepointPollStub(uintptr_t safepoint_offset) : + _safepoint_offset(safepoint_offset) {} + int max_size() const; + void emit(C2_MacroAssembler& masm); +}; + +// We move non-hot code of the nmethod entry barrier to an out-of-line stub +class C2EntryBarrierStub: public C2CodeStub { +private: + Label _guard; // Used on AArch64 and RISCV + +public: + C2EntryBarrierStub() : C2CodeStub(), + _guard() {} + + Label& guard() { return _guard; } + + int max_size() const; + void emit(C2_MacroAssembler& masm); +}; + +#endif // SHARE_OPTO_C2_CODESTUBS_HPP diff --git a/src/hotspot/share/opto/c2_MacroAssembler.hpp b/src/hotspot/share/opto/c2_MacroAssembler.hpp index e86edb0798c..41347313a8c 100644 --- a/src/hotspot/share/opto/c2_MacroAssembler.hpp +++ b/src/hotspot/share/opto/c2_MacroAssembler.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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,7 @@ #include "asm/macroAssembler.hpp" #include "asm/macroAssembler.inline.hpp" +#include "utilities/globalDefinitions.hpp" #include "utilities/macros.hpp" class C2EntryBarrierStub; diff --git a/src/hotspot/share/opto/output.cpp b/src/hotspot/share/opto/output.cpp index 6f756133445..0b5cc251bbd 100644 --- a/src/hotspot/share/opto/output.cpp +++ b/src/hotspot/share/opto/output.cpp @@ -218,118 +218,13 @@ class Scheduling { }; -volatile int C2SafepointPollStubTable::_stub_size = 0; - -Label& C2SafepointPollStubTable::add_safepoint(uintptr_t safepoint_offset) { - C2SafepointPollStub* entry = new (Compile::current()->comp_arena()) C2SafepointPollStub(safepoint_offset); - _safepoints.append(entry); - return entry->_stub_label; -} - -void C2SafepointPollStubTable::emit(CodeBuffer& cb) { - MacroAssembler masm(&cb); - for (int i = _safepoints.length() - 1; i >= 0; i--) { - // Make sure there is enough space in the code buffer - if (cb.insts()->maybe_expand_to_ensure_remaining(PhaseOutput::MAX_inst_size) && cb.blob() == NULL) { - ciEnv::current()->record_failure("CodeCache is full"); - return; - } - - C2SafepointPollStub* entry = _safepoints.at(i); - emit_stub(masm, entry); - } -} - -int C2SafepointPollStubTable::stub_size_lazy() const { - int size = Atomic::load(&_stub_size); - - if (size != 0) { - return size; - } - - Compile* const C = Compile::current(); - BufferBlob* const blob = C->output()->scratch_buffer_blob(); - CodeBuffer cb(blob->content_begin(), C->output()->scratch_buffer_code_size()); - MacroAssembler masm(&cb); - C2SafepointPollStub* entry = _safepoints.at(0); - emit_stub(masm, entry); - size += cb.insts_size(); - - Atomic::store(&_stub_size, size); - - return size; -} - -int C2SafepointPollStubTable::estimate_stub_size() const { - if (_safepoints.length() == 0) { - return 0; - } - - int result = stub_size_lazy() * _safepoints.length(); - -#ifdef ASSERT - Compile* const C = Compile::current(); - BufferBlob* const blob = C->output()->scratch_buffer_blob(); - int size = 0; - - for (int i = _safepoints.length() - 1; i >= 0; i--) { - CodeBuffer cb(blob->content_begin(), C->output()->scratch_buffer_code_size()); - MacroAssembler masm(&cb); - C2SafepointPollStub* entry = _safepoints.at(i); - emit_stub(masm, entry); - size += cb.insts_size(); - } - assert(size == result, "stubs should not have variable size"); -#endif - - return result; -} - -// Nmethod entry barrier stubs -C2EntryBarrierStub* C2EntryBarrierStubTable::add_entry_barrier() { - assert(_stub == NULL, "There can only be one entry barrier stub"); - _stub = new (Compile::current()->comp_arena()) C2EntryBarrierStub(); - return _stub; -} - -void C2EntryBarrierStubTable::emit(CodeBuffer& cb) { - if (_stub == NULL) { - // No stub - nothing to do - return; - } - - C2_MacroAssembler masm(&cb); - // Make sure there is enough space in the code buffer - if (cb.insts()->maybe_expand_to_ensure_remaining(PhaseOutput::MAX_inst_size) && cb.blob() == NULL) { - ciEnv::current()->record_failure("CodeCache is full"); - return; - } - - intptr_t before = masm.offset(); - masm.emit_entry_barrier_stub(_stub); - intptr_t after = masm.offset(); - int actual_size = (int)(after - before); - int expected_size = masm.entry_barrier_stub_size(); - assert(actual_size == expected_size, "Estimated size is wrong, expected %d, was %d", expected_size, actual_size); -} - -int C2EntryBarrierStubTable::estimate_stub_size() const { - if (BarrierSet::barrier_set()->barrier_set_nmethod() == NULL) { - // No nmethod entry barrier? - return 0; - } - - return C2_MacroAssembler::entry_barrier_stub_size(); -} - PhaseOutput::PhaseOutput() : Phase(Phase::Output), _code_buffer("Compile::Fill_buffer"), _first_block_size(0), _handler_table(), _inc_table(), - _safepoint_poll_table(), - _entry_barrier_table(), + _stub_list(), _oop_map_set(NULL), _scratch_buffer_blob(NULL), _scratch_locs_memory(NULL), @@ -1349,8 +1244,6 @@ CodeBuffer* PhaseOutput::init_buffer() { BarrierSetC2* bs = BarrierSet::barrier_set()->barrier_set_c2(); stub_req += bs->estimate_stub_size(); - stub_req += safepoint_poll_table()->estimate_stub_size(); - stub_req += entry_barrier_table()->estimate_stub_size(); // nmethod and CodeBuffer count stubs & constants as part of method's code. // class HandlerImpl is platform-specific and defined in the *.ad files. @@ -1857,12 +1750,8 @@ void PhaseOutput::fill_buffer(CodeBuffer* cb, uint* blk_starts) { bs->emit_stubs(*cb); if (C->failing()) return; - // Fill in stubs for calling the runtime from safepoint polls. - safepoint_poll_table()->emit(*cb); - if (C->failing()) return; - - // Fill in stubs for calling the runtime from nmethod entries. - entry_barrier_table()->emit(*cb); + // Fill in stubs. + _stub_list.emit(*cb); if (C->failing()) return; #ifndef PRODUCT diff --git a/src/hotspot/share/opto/output.hpp b/src/hotspot/share/opto/output.hpp index 555dcde06b1..09e012d34c3 100644 --- a/src/hotspot/share/opto/output.hpp +++ b/src/hotspot/share/opto/output.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2022, 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,6 +29,7 @@ #include "code/exceptionHandlerTable.hpp" #include "metaprogramming/enableIf.hpp" #include "opto/ad.hpp" +#include "opto/c2_CodeStubs.hpp" #include "opto/constantTable.hpp" #include "opto/phase.hpp" #include "runtime/vm_version.hpp" @@ -73,75 +74,6 @@ class BufferSizingData { { }; }; -class C2SafepointPollStubTable { -private: - struct C2SafepointPollStub: public ArenaObj { - uintptr_t _safepoint_offset; - Label _stub_label; - Label _trampoline_label; - C2SafepointPollStub(uintptr_t safepoint_offset) : - _safepoint_offset(safepoint_offset), - _stub_label(), - _trampoline_label() {} - }; - - GrowableArray _safepoints; - - static volatile int _stub_size; - - void emit_stub_impl(MacroAssembler& masm, C2SafepointPollStub* entry) const; - - // The selection logic below relieves the need to add dummy files to unsupported platforms. - template - typename EnableIf::type - select_emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const { - emit_stub_impl(masm, entry); - } - - template - typename EnableIf::type - select_emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const {} - - void emit_stub(MacroAssembler& masm, C2SafepointPollStub* entry) const { - select_emit_stub(masm, entry); - } - - int stub_size_lazy() const; - -public: - Label& add_safepoint(uintptr_t safepoint_offset); - int estimate_stub_size() const; - void emit(CodeBuffer& cb); -}; - -// We move non-hot code of the nmethod entry barrier to an out-of-line stub -class C2EntryBarrierStub: public ArenaObj { - Label _slow_path; - Label _continuation; - Label _guard; // Used on AArch64 and RISCV - -public: - C2EntryBarrierStub() : - _slow_path(), - _continuation(), - _guard() {} - - Label& slow_path() { return _slow_path; } - Label& continuation() { return _continuation; } - Label& guard() { return _guard; } - -}; - -class C2EntryBarrierStubTable { - C2EntryBarrierStub* _stub; - -public: - C2EntryBarrierStubTable() : _stub(NULL) {} - C2EntryBarrierStub* add_entry_barrier(); - int estimate_stub_size() const; - void emit(CodeBuffer& cb); -}; - class PhaseOutput : public Phase { private: // Instruction bits passed off to the VM @@ -150,8 +82,7 @@ class PhaseOutput : public Phase { int _first_block_size; // Size of unvalidated entry point code / OSR poison code ExceptionHandlerTable _handler_table; // Table of native-code exception handlers ImplicitExceptionTable _inc_table; // Table of implicit null checks in native code - C2SafepointPollStubTable _safepoint_poll_table;// Table for safepoint polls - C2EntryBarrierStubTable _entry_barrier_table; // Table for entry barrier stubs + C2CodeStubList _stub_list; // List of code stubs OopMapSet* _oop_map_set; // Table of oop maps (one for each safepoint location) BufferBlob* _scratch_buffer_blob; // For temporary code buffers. relocInfo* _scratch_locs_memory; // For temporary code buffers. @@ -199,11 +130,8 @@ class PhaseOutput : public Phase { // Constant table ConstantTable& constant_table() { return _constant_table; } - // Safepoint poll table - C2SafepointPollStubTable* safepoint_poll_table() { return &_safepoint_poll_table; } - - // Entry barrier table - C2EntryBarrierStubTable* entry_barrier_table() { return &_entry_barrier_table; } + // Code stubs list + void add_stub(C2CodeStub* stub) { _stub_list.add_stub(stub); } // Code emission iterator Block* block() { return _block; } From 5a92bee1858f4d08392158217302d3703bb3c770 Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Fri, 9 Dec 2022 15:21:59 +0000 Subject: [PATCH 149/494] 8298455: JFR: Add logging to TestClose.java Reviewed-by: mgronlun --- test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java index 93b892880d6..8b3fbe88b90 100644 --- a/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java +++ b/test/jdk/jdk/jfr/api/consumer/recordingstream/TestClose.java @@ -38,7 +38,7 @@ * @key jfr * @requires vm.hasJFR * @library /test/lib /test/jdk - * @run main/othervm jdk.jfr.api.consumer.recordingstream.TestClose + * @run main/othervm -Xlog:jfr+streaming+system=trace jdk.jfr.api.consumer.recordingstream.TestClose */ public class TestClose { From 05d67f69e34a76702406b36436ddb5db18e8fa68 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Fri, 9 Dec 2022 15:23:22 +0000 Subject: [PATCH 150/494] 8298340: java/net/httpclient/CancelRequestTest.java fails with AssertionError: Found some subscribers for testPostInterrupt Reviewed-by: jpai --- .../internal/net/http/Http2Connection.java | 1 + .../classes/jdk/internal/net/http/Stream.java | 43 +++++++++++++++++-- .../common/HttpBodySubscriberWrapper.java | 9 +++- .../net/httpclient/CancelRequestTest.java | 2 +- 4 files changed, 50 insertions(+), 5 deletions(-) diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java index 717b41679d3..f4cfabacd8f 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/Http2Connection.java @@ -1008,6 +1008,7 @@ synchronized void decrementStreamsCount(int streamid) { // This method is called when the HTTP/2 client is being // stopped. Do not call it from anywhere else. void closeAllStreams() { + if (debug.on()) debug.log("Close all streams"); for (var streamId : streams.keySet()) { // safe to call without locking - see Stream::deRegister decrementStreamsCount(streamId); 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 09df38c7178..c787959b069 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 @@ -273,6 +273,7 @@ void nullBody(HttpResponse resp, Throwable t) { if (debug.on()) debug.log("nullBody: streamid=%d", streamid); // We should have an END_STREAM data frame waiting in the inputQ. // We need a subscriber to force the scheduler to process it. + assert pendingResponseSubscriber == null; pendingResponseSubscriber = HttpResponse.BodySubscribers.replacing(null); sched.runOrSchedule(); } @@ -472,8 +473,14 @@ void incoming(Http2Frame frame) throws IOException { receiveDataFrame(new DataFrame(streamid, DataFrame.END_STREAM, List.of())); } } else if (frame instanceof DataFrame) { - if (cancelled) connection.dropDataFrame((DataFrame) frame); - else receiveDataFrame((DataFrame) frame); + if (cancelled) { + if (debug.on()) { + debug.log("request cancelled or stream closed: dropping data frame"); + } + connection.dropDataFrame((DataFrame) frame); + } else { + receiveDataFrame((DataFrame) frame); + } } else { if (!cancelled) otherFrame(frame); } @@ -1283,10 +1290,24 @@ private void cancelImpl(final Throwable e, final int resetFrameErrCode) { } } } + if (closing) { // true if the stream has not been closed yet - if (responseSubscriber != null || pendingResponseSubscriber != null) + if (responseSubscriber != null || pendingResponseSubscriber != null) { + if (debug.on()) + debug.log("stream %s closing due to %s", streamid, (Object)errorRef.get()); sched.runOrSchedule(); + } else { + if (debug.on()) + debug.log("stream %s closing due to %s before subscriber registered", + streamid, (Object)errorRef.get()); + } + } else { + if (debug.on()) { + debug.log("stream %s already closed due to %s", + streamid, (Object)errorRef.get()); + } } + completeResponseExceptionally(e); if (!requestBodyCF.isDone()) { requestBodyCF.completeExceptionally(errorRef.get()); // we may be sending the body.. @@ -1330,6 +1351,20 @@ void close() { if (debug.on()) debug.log("close stream %d", streamid); Log.logTrace("Closing stream {0}", streamid); connection.closeStream(streamid); + var s = responseSubscriber == null + ? pendingResponseSubscriber + : responseSubscriber; + if (debug.on()) debug.log("subscriber is %s", s); + if (s instanceof Http2StreamResponseSubscriber sw) { + if (debug.on()) debug.log("closing response subscriber stream %s", streamid); + // if the subscriber has already completed, + // there is nothing to do... + if (!sw.completed()) { + // otherwise make sure it will be completed + var cause = errorRef.get(); + sw.complete(cause == null ? new IOException("stream closed") : cause); + } + } Log.logTrace("Stream {0} closed", streamid); } @@ -1554,10 +1589,12 @@ protected void complete(Throwable t) { super.complete(t); } } + @Override protected void onCancel() { unregisterResponseSubscriber(this); } + } private static final VarHandle STREAM_STATE; diff --git a/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java b/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java index 78185bcbcfc..a896a8eb084 100644 --- a/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java +++ b/src/java.net.http/share/classes/jdk/internal/net/http/common/HttpBodySubscriberWrapper.java @@ -30,7 +30,6 @@ import java.util.Comparator; import java.util.List; import java.util.Objects; -import java.util.concurrent.CompletableFuture; import java.util.concurrent.CompletionStage; import java.util.concurrent.Flow; import java.util.concurrent.Flow.Subscription; @@ -176,6 +175,14 @@ protected void complete(Throwable t) { } } + /** + * {@return true if this subscriber has already completed, either normally + * or abnormally} + */ + public boolean completed() { + return completed.get(); + } + @Override public CompletionStage getBody() { return userSubscriber.getBody(); diff --git a/test/jdk/java/net/httpclient/CancelRequestTest.java b/test/jdk/java/net/httpclient/CancelRequestTest.java index 0768ddb7aab..c134f3cd99d 100644 --- a/test/jdk/java/net/httpclient/CancelRequestTest.java +++ b/test/jdk/java/net/httpclient/CancelRequestTest.java @@ -23,7 +23,7 @@ /* * @test - * @bug 8245462 8229822 8254786 8297075 8297149 + * @bug 8245462 8229822 8254786 8297075 8297149 8298340 * @summary Tests cancelling the request. * @library /test/lib http2/server * @key randomness From b7b996cb9475f8191d4085a2f7f68187b6f015d5 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Fri, 9 Dec 2022 15:33:09 +0000 Subject: [PATCH 151/494] 8298353: C2 fails with assert(opaq->outcnt() == 1 && opaq->in(1) == limit) failed Reviewed-by: chagedorn, thartmann, kvn --- src/hotspot/share/opto/loopopts.cpp | 2 +- .../loopopts/TestBadCountedLoopLimit.java | 79 +++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestBadCountedLoopLimit.java diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 5dea9537497..79d6531b627 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -1733,7 +1733,7 @@ Node* PhaseIdealLoop::compute_early_ctrl(Node* n, Node* n_ctrl) { bool PhaseIdealLoop::ctrl_of_all_uses_out_of_loop(const Node* n, Node* n_ctrl, IdealLoopTree* n_loop) { for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { Node* u = n->fast_out(i); - if (u->Opcode() == Op_Opaque1) { + if (u->is_Opaque1()) { return false; // Found loop limit, bugfix for 4677003 } // We can't reuse tags in PhaseIdealLoop::dom_lca_for_get_late_ctrl_internal() so make sure calls to diff --git a/test/hotspot/jtreg/compiler/loopopts/TestBadCountedLoopLimit.java b/test/hotspot/jtreg/compiler/loopopts/TestBadCountedLoopLimit.java new file mode 100644 index 00000000000..7d2f865a9e8 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestBadCountedLoopLimit.java @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2022, 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 8298353 + * @summary C2 fails with assert(opaq->outcnt() == 1 && opaq->in(1) == limit) failed + * + * @run main/othervm -XX:-TieredCompilation -XX:-UseOnStackReplacement -XX:-BackgroundCompilation TestBadCountedLoopLimit + * + */ + +import java.util.Arrays; + +public class TestBadCountedLoopLimit { + private static volatile int barrier; + private static int field; + + public static void main(String[] args) { + boolean[] flag1 = new boolean[100]; + boolean[] flag2 = new boolean[100]; + Arrays.fill(flag2, true); + for (int i = 0; i < 20_000; i++) { + test(0, flag1, flag1); + test(0, flag2, flag2); + testHelper(true, 0, 0); + testHelper(false, 0, 0); + } + } + + private static int test(int v, boolean[] flag, boolean[] flag2) { + int j = testHelper(flag2[0], 0, 1); + int i = 1; + int limit = 0; + for (;;) { + synchronized (new Object()) { + } + limit = j; + if (i >= 100) { + break; + } + + if (flag[i]) { + return limit - 3; + } + + j = testHelper(flag2[i], 100, 101); + i *= 2; + }; + for (int k = 0; k < limit; k++) { + barrier = 0x42; + } + return j; + } + + private static int testHelper(boolean flag2, int x, int x1) { + return flag2 ? x : x1; + } +} From 52fffdd2c8426e98d3a0198ef4607750732bab93 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Fri, 9 Dec 2022 16:41:26 +0000 Subject: [PATCH 152/494] 8298463: tools/javac/modules/EdgeCases.java fails on Windows after JDK-8297988 Reviewed-by: jjg --- test/langtools/tools/javac/modules/EdgeCases.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/test/langtools/tools/javac/modules/EdgeCases.java b/test/langtools/tools/javac/modules/EdgeCases.java index ae142f32ccd..0262066d7b8 100644 --- a/test/langtools/tools/javac/modules/EdgeCases.java +++ b/test/langtools/tools/javac/modules/EdgeCases.java @@ -39,6 +39,7 @@ import java.io.BufferedWriter; import java.io.Writer; import java.nio.file.Files; +import java.nio.file.FileSystems; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; @@ -1079,6 +1080,7 @@ void t() { tb.createDirectories(classes); record TestCase(Path[] files, String... expectedLog){} + String nameSeparator = FileSystems.getDefault().getSeparator(); TestCase[] testCases = new TestCase[] { new TestCase(new Path[] {m.resolve("module-info.java")}, @@ -1133,7 +1135,9 @@ public void finished(TaskEvent e) { } private void record(TaskEvent e, String phase) { JavaFileObject source = e.getSourceFile(); - String sourceName = source != null ? source.getName() : ""; + String sourceName = source != null ? source.getName() + .replace(nameSeparator, "/") + : ""; log.add(e.getKind() + ":" + phase + ":" + sourceName); } }); From 9346535415b158aaaa679ef8c3c147595b5206e9 Mon Sep 17 00:00:00 2001 From: Xin Liu Date: Fri, 9 Dec 2022 16:49:47 +0000 Subject: [PATCH 153/494] 8298320: Typo in the comment block of catch_inline_exception Reviewed-by: thartmann --- src/hotspot/share/opto/doCall.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/doCall.cpp b/src/hotspot/share/opto/doCall.cpp index 278a0fc0f15..e79d1431c53 100644 --- a/src/hotspot/share/opto/doCall.cpp +++ b/src/hotspot/share/opto/doCall.cpp @@ -894,7 +894,7 @@ void Parse::catch_call_exceptions(ciExceptionHandlerStream& handlers) { // Common case 1: we have no handler, so all exceptions merge right into // the rethrow case. // Case 2: we have some handlers, with loaded exception klasses that have -// no subklasses. We do a Deutsch-Shiffman style type-check on the incoming +// no subklasses. We do a Deutsch-Schiffman style type-check on the incoming // exception oop and branch to the handler directly. // Case 3: We have some handlers with subklasses or are not loaded at // compile-time. We have to call the runtime to resolve the exception. From a8946490e2b362d241c61cc459dbaba93fc93ca4 Mon Sep 17 00:00:00 2001 From: Tyler Steele Date: Fri, 9 Dec 2022 17:04:11 +0000 Subject: [PATCH 154/494] 8298225: [AIX] Disable PPC64LE continuations on AIX Reviewed-by: rrich, mdoerr --- src/hotspot/cpu/ppc/globals_ppc.hpp | 2 +- src/hotspot/cpu/ppc/ppc.ad | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/hotspot/cpu/ppc/globals_ppc.hpp b/src/hotspot/cpu/ppc/globals_ppc.hpp index 44b321635e1..527e5f5b4da 100644 --- a/src/hotspot/cpu/ppc/globals_ppc.hpp +++ b/src/hotspot/cpu/ppc/globals_ppc.hpp @@ -54,7 +54,7 @@ define_pd_global(intx, StackRedPages, DEFAULT_STACK_RED_PAGES); define_pd_global(intx, StackShadowPages, DEFAULT_STACK_SHADOW_PAGES); define_pd_global(intx, StackReservedPages, DEFAULT_STACK_RESERVED_PAGES); -define_pd_global(bool, VMContinuations, true); +define_pd_global(bool, VMContinuations, AIX_ONLY(false) NOT_AIX(true)); // Use large code-entry alignment. define_pd_global(uintx, CodeCacheSegmentSize, 128); diff --git a/src/hotspot/cpu/ppc/ppc.ad b/src/hotspot/cpu/ppc/ppc.ad index 296bf160089..fd17bfe0682 100644 --- a/src/hotspot/cpu/ppc/ppc.ad +++ b/src/hotspot/cpu/ppc/ppc.ad @@ -14374,6 +14374,12 @@ instruct safePoint_poll(iRegPdst poll) %{ // Call Java Static Instruction +source %{ + +#include "runtime/continuation.hpp" + +%} + // Schedulable version of call static node. instruct CallStaticJavaDirect(method meth) %{ match(CallStaticJava); From f729f5b6d01b0d3a0ee21f50199ca30935c8237a Mon Sep 17 00:00:00 2001 From: Thomas Stuefe Date: Fri, 9 Dec 2022 17:46:28 +0000 Subject: [PATCH 155/494] 8298298: NMT: count deltas are printed with 32-bit signed size Reviewed-by: shade, dholmes --- src/hotspot/share/services/memReporter.cpp | 45 ++++++++++++------- .../share/utilities/globalDefinitions.hpp | 1 + .../utilities/globalDefinitions_visCPP.hpp | 10 +++++ .../utilities/test_globalDefinitions.cpp | 7 +++ 4 files changed, 48 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp index 7aa7311fdf4..92dbb801e02 100644 --- a/src/hotspot/share/services/memReporter.cpp +++ b/src/hotspot/share/services/memReporter.cpp @@ -31,6 +31,16 @@ #include "services/virtualMemoryTracker.hpp" #include "utilities/globalDefinitions.hpp" +// Diff two counters, express them as signed, with range checks +static ssize_t counter_diff(size_t c1, size_t c2) { + assert(c1 <= SSIZE_MAX, "counter out of range: " SIZE_FORMAT ".", c1); + assert(c2 <= SSIZE_MAX, "counter out of range: " SIZE_FORMAT ".", c2); + if (c1 > SSIZE_MAX || c2 > SSIZE_MAX) { + return 0; + } + return c1 - c2; +} + size_t MemReporterBase::reserved_total(const MallocMemory* malloc, const VirtualMemory* vm) { return malloc->malloc_size() + malloc->arena_size() + vm->reserved(); } @@ -462,8 +472,9 @@ void MemSummaryDiffReporter::print_malloc_diff(size_t current_amount, size_t cur } if (current_count > 0) { out->print(" #" SIZE_FORMAT "", current_count); - if (current_count != early_count) { - out->print(" %+d", (int)(current_count - early_count)); + const ssize_t delta_count = counter_diff(current_count, early_count); + if (delta_count != 0) { + out->print(" " SSIZE_PLUS_FORMAT, delta_count); } } } @@ -478,8 +489,9 @@ void MemSummaryDiffReporter::print_arena_diff(size_t current_amount, size_t curr } out->print(" #" SIZE_FORMAT "", current_count); - if (current_count != early_count) { - out->print(" %+d", (int)(current_count - early_count)); + const ssize_t delta_count = counter_diff(current_count, early_count); + if (delta_count != 0) { + out->print(" " SSIZE_PLUS_FORMAT, delta_count); } } @@ -551,30 +563,33 @@ void MemSummaryDiffReporter::diff_summary_of_type(MEMFLAGS flag, if (flag == mtClass) { // report class count out->print("%27s (classes #" SIZE_FORMAT "", " ", _current_baseline.class_count()); - int class_count_diff = (int)(_current_baseline.class_count() - - _early_baseline.class_count()); - if (_current_baseline.class_count() != _early_baseline.class_count()) { - out->print(" %+d", (int)(_current_baseline.class_count() - _early_baseline.class_count())); + const ssize_t class_count_diff = + counter_diff(_current_baseline.class_count(), _early_baseline.class_count()); + if (class_count_diff != 0) { + out->print(" " SSIZE_PLUS_FORMAT, class_count_diff); } out->print_cr(")"); out->print("%27s ( instance classes #" SIZE_FORMAT, " ", _current_baseline.instance_class_count()); - if (_current_baseline.instance_class_count() != _early_baseline.instance_class_count()) { - out->print(" %+d", (int)(_current_baseline.instance_class_count() - _early_baseline.instance_class_count())); + const ssize_t instance_class_count_diff = + counter_diff(_current_baseline.instance_class_count(), _early_baseline.instance_class_count()); + if (instance_class_count_diff != 0) { + out->print(" " SSIZE_PLUS_FORMAT, instance_class_count_diff); } out->print(", array classes #" SIZE_FORMAT, _current_baseline.array_class_count()); - if (_current_baseline.array_class_count() != _early_baseline.array_class_count()) { - out->print(" %+d", (int)(_current_baseline.array_class_count() - _early_baseline.array_class_count())); + const ssize_t array_class_count_diff = + counter_diff(_current_baseline.array_class_count(), _early_baseline.array_class_count()); + if (array_class_count_diff != 0) { + out->print(" " SSIZE_PLUS_FORMAT, array_class_count_diff); } out->print_cr(")"); } else if (flag == mtThread) { // report thread count out->print("%27s (thread #" SIZE_FORMAT "", " ", _current_baseline.thread_count()); - int thread_count_diff = (int)(_current_baseline.thread_count() - - _early_baseline.thread_count()); + const ssize_t thread_count_diff = counter_diff(_current_baseline.thread_count(), _early_baseline.thread_count()); if (thread_count_diff != 0) { - out->print(" %+d", thread_count_diff); + out->print(" " SSIZE_PLUS_FORMAT, thread_count_diff); } out->print_cr(")"); diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 3771ac0f277..99eab62d2cf 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -130,6 +130,7 @@ class oopDesc; // Format integers which change size between 32- and 64-bit. #define SSIZE_FORMAT "%" PRIdPTR +#define SSIZE_PLUS_FORMAT "%+" PRIdPTR #define SSIZE_FORMAT_W(width) "%" #width PRIdPTR #define SIZE_FORMAT "%" PRIuPTR #define SIZE_FORMAT_X "0x%" PRIxPTR diff --git a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp index 2208953ee8b..9ea81ae7174 100644 --- a/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_visCPP.hpp @@ -129,4 +129,14 @@ inline int g_isfinite(jdouble f) { return _finite(f); } #define USE_VECTORED_EXCEPTION_HANDLING #endif +#ifndef SSIZE_MAX +#ifdef _LP64 +#define SSIZE_MIN LLONG_MIN +#define SSIZE_MAX LLONG_MAX +#else +#define SSIZE_MIN INT_MIN +#define SSIZE_MAX INT_MAX +#endif +#endif // SSIZE_MAX missing + #endif // SHARE_UTILITIES_GLOBALDEFINITIONS_VISCPP_HPP diff --git a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp index ff18a1bd8f8..783bb6d326a 100644 --- a/test/hotspot/gtest/utilities/test_globalDefinitions.cpp +++ b/test/hotspot/gtest/utilities/test_globalDefinitions.cpp @@ -264,6 +264,13 @@ TEST(globalDefinitions, format_specifiers) { check_format(UINT64_FORMAT_W(-5), (uint64_t)123, "123 "); check_format(SSIZE_FORMAT, (ssize_t)123, "123"); + check_format(SSIZE_FORMAT, (ssize_t)-123, "-123"); + check_format(SSIZE_FORMAT, (ssize_t)2147483647, "2147483647"); + check_format(SSIZE_FORMAT, (ssize_t)-2147483647, "-2147483647"); + check_format(SSIZE_PLUS_FORMAT, (ssize_t)123, "+123"); + check_format(SSIZE_PLUS_FORMAT, (ssize_t)-123, "-123"); + check_format(SSIZE_PLUS_FORMAT, (ssize_t)2147483647, "+2147483647"); + check_format(SSIZE_PLUS_FORMAT, (ssize_t)-2147483647, "-2147483647"); check_format(SSIZE_FORMAT_W(5), (ssize_t)123, " 123"); check_format(SSIZE_FORMAT_W(-5), (ssize_t)123, "123 "); check_format(SIZE_FORMAT, (size_t)123u, "123"); From 99a6c47855ad82e81a80726cf3aa4522c547716d Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Fri, 9 Dec 2022 18:42:35 +0000 Subject: [PATCH 156/494] 8298073: gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java causes test task timeout on macosx 8241293: CompressedClassSpaceSizeInJmapHeap.java time out after 8 minutes Reviewed-by: ayang, sspitsyn --- test/hotspot/jtreg/ProblemList.txt | 1 - .../metaspace/CompressedClassSpaceSizeInJmapHeap.java | 11 ++++++++--- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index fec8dfa1a7c..ccb8a562e0b 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -78,7 +78,6 @@ gc/stress/gclocker/TestExcessGCLockerCollections.java 8229120 generic-all gc/stress/gclocker/TestGCLockerWithParallel.java 8180622 generic-all gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all -gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293,8298073 macosx-x64,macosx-aarch64 gc/stress/TestStressG1Humongous.java 8286554 windows-x64 ############################################################################# diff --git a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java index 91ddd45573d..30553a7b8c6 100644 --- a/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java +++ b/test/hotspot/jtreg/gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, 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,10 +32,11 @@ * @library /test/lib * @modules java.base/jdk.internal.misc * java.management - * @run main/othervm -XX:CompressedClassSpaceSize=48m gc.metaspace.CompressedClassSpaceSizeInJmapHeap + * @run main/timeout=240 gc.metaspace.CompressedClassSpaceSizeInJmapHeap */ import jdk.test.lib.JDKToolLauncher; +import jdk.test.lib.apps.LingeredApp; import jdk.test.lib.process.OutputAnalyzer; import jdk.test.lib.process.ProcessTools; import jdk.test.lib.SA.SATestUtils; @@ -49,7 +50,9 @@ public class CompressedClassSpaceSizeInJmapHeap { public static void main(String[] args) throws Exception { SATestUtils.skipIfCannotAttach(); // throws SkippedException if attach not expected to work. - String pid = Long.toString(ProcessTools.getProcessId()); + LingeredApp theApp = new LingeredApp(); + LingeredApp.startApp(theApp, "-XX:CompressedClassSpaceSize=48m"); + String pid = Long.toString(theApp.getPid()); JDKToolLauncher jmap = JDKToolLauncher.create("jhsdb") .addToolArg("jmap") @@ -69,6 +72,8 @@ public static void main(String[] args) throws Exception { OutputAnalyzer output = new OutputAnalyzer(read(out)); output.shouldContain("CompressedClassSpaceSize = 50331648 (48.0MB)"); out.delete(); + + LingeredApp.stopApp(theApp); } private static void run(ProcessBuilder pb) throws Exception { From 7dbdd83da0eefd56927bdb68d7aedfee5c0c0ab5 Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Fri, 9 Dec 2022 19:54:46 +0000 Subject: [PATCH 157/494] 8298190: Update --release 20 symbol information for JDK 20 build 27 Reviewed-by: iris --- .../share/data/symbols/java.base-K.sym.txt | 506 +++++++++++++++--- .../data/symbols/java.management-K.sym.txt | 14 +- .../share/data/symbols/jdk.compiler-K.sym.txt | 28 +- .../jdk.incubator.concurrent-K.sym.txt | 21 + .../symbols/jdk.incubator.vector-K.sym.txt | 102 ++++ .../share/data/symbols/jdk.jfr-K.sym.txt | 3 + .../data/symbols/jdk.management.jfr-K.sym.txt | 31 ++ src/jdk.compiler/share/data/symbols/symbols | 2 +- 8 files changed, 643 insertions(+), 64 deletions(-) create mode 100644 src/jdk.compiler/share/data/symbols/jdk.management.jfr-K.sym.txt diff --git a/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt index e0716a1b796..e2101df2a23 100644 --- a/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.base-K.sym.txt @@ -26,9 +26,17 @@ # ### THIS FILE IS AUTOMATICALLY GENERATED. DO NOT EDIT. ### # ########################################################## # +module name java.base +header exports java/io,java/lang,java/lang/annotation,java/lang/constant,java/lang/foreign,java/lang/invoke,java/lang/module,java/lang/ref,java/lang/reflect,java/lang/runtime,java/math,java/net,java/net/spi,java/nio,java/nio/channels,java/nio/channels/spi,java/nio/charset,java/nio/charset/spi,java/nio/file,java/nio/file/attribute,java/nio/file/spi,java/security,java/security/cert,java/security/interfaces,java/security/spec,java/text,java/text/spi,java/time,java/time/chrono,java/time/format,java/time/temporal,java/time/zone,java/util,java/util/concurrent,java/util/concurrent/atomic,java/util/concurrent/locks,java/util/function,java/util/jar,java/util/random,java/util/regex,java/util/spi,java/util/stream,java/util/zip,javax/crypto,javax/crypto/interfaces,javax/crypto/spec,javax/net,javax/net/ssl,javax/security/auth,javax/security/auth/callback,javax/security/auth/login,javax/security/auth/spi,javax/security/auth/x500,javax/security/cert,jdk/internal/event[jdk.jfr],jdk/internal/vm/vector[jdk.incubator.vector] uses java/lang/System$LoggerFinder,java/net/ContentHandlerFactory,java/net/spi/InetAddressResolverProvider,java/net/spi/URLStreamHandlerProvider,java/nio/channels/spi/AsynchronousChannelProvider,java/nio/channels/spi/SelectorProvider,java/nio/charset/spi/CharsetProvider,java/nio/file/spi/FileSystemProvider,java/nio/file/spi/FileTypeDetector,java/security/Provider,java/text/spi/BreakIteratorProvider,java/text/spi/CollatorProvider,java/text/spi/DateFormatProvider,java/text/spi/DateFormatSymbolsProvider,java/text/spi/DecimalFormatSymbolsProvider,java/text/spi/NumberFormatProvider,java/time/chrono/AbstractChronology,java/time/chrono/Chronology,java/time/zone/ZoneRulesProvider,java/util/random/RandomGenerator,java/util/spi/CalendarDataProvider,java/util/spi/CalendarNameProvider,java/util/spi/CurrencyNameProvider,java/util/spi/LocaleNameProvider,java/util/spi/ResourceBundleControlProvider,java/util/spi/ResourceBundleProvider,java/util/spi/TimeZoneNameProvider,java/util/spi/ToolProvider,javax/security/auth/spi/LoginModule,jdk/internal/io/JdkConsoleProvider,jdk/internal/logger/DefaultLoggerFinder,sun/text/spi/JavaTimeDateTimePatternProvider,sun/util/locale/provider/LocaleDataMetaInfo,sun/util/resources/LocaleData$CommonResourceBundleProvider,sun/util/resources/LocaleData$SupplementaryResourceBundleProvider,sun/util/spi/CalendarProvider provides interface\u0020;java/nio/file/spi/FileSystemProvider\u0020;impls\u0020;jdk/internal/jrtfs/JrtFileSystemProvider,interface\u0020;java/util/random/RandomGenerator\u0020;impls\u0020;java/security/SecureRandom\u005C;u002C;java/util/Random\u005C;u002C;java/util/SplittableRandom target linux-amd64 flags 8000 + class name java/io/BufferedInputStream method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 +class name java/io/Console +header extends java/lang/Object implements java/io/Flushable flags 21 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +innerclass innerClass java/util/ServiceLoader$Provider outerClass java/util/ServiceLoader innerClassName Provider flags 609 + class name java/io/PrintStream header extends java/io/FilterOutputStream implements java/lang/Appendable,java/io/Closeable flags 21 innerclass innerClass java/util/Locale$Category outerClass java/util/Locale innerClassName Category flags 4019 @@ -36,6 +44,9 @@ innerclass innerClass java/util/Locale$Category outerClass java/util/Locale inne class name java/io/PushbackInputStream method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 +class name java/io/SequenceInputStream +method name transferTo descriptor (Ljava/io/OutputStream;)J thrownTypes java/io/IOException flags 1 + class name java/lang/AbstractStringBuilder header extends java/lang/Object implements java/lang/Appendable,java/lang/CharSequence sealed true flags 420 innerclass innerClass java/util/Spliterator$OfInt outerClass java/util/Spliterator innerClassName OfInt flags 609 @@ -96,6 +107,12 @@ class name java/lang/Long method name compareUnsigned descriptor (JJ)I flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; method name reverse descriptor (J)J flags 9 runtimeAnnotations @Ljdk/internal/vm/annotation/IntrinsicCandidate; +class name java/lang/Module +method name isNativeAccessEnabled descriptor ()Z flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) + +class name java/lang/ModuleLayer$Controller +method name enableNativeAccess descriptor (Ljava/lang/Module;)Ljava/lang/ModuleLayer$Controller; flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; + class name java/lang/NamedPackage header extends java/lang/Object flags 20 @@ -144,41 +161,111 @@ innerclass innerClass java/lang/invoke/TypeDescriptor$OfMethod outerClass java/l innerclass innerClass java/lang/invoke/TypeDescriptor$OfField outerClass java/lang/invoke/TypeDescriptor innerClassName OfField flags 609 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 -class name java/lang/foreign/Addressable -header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +-class name java/lang/foreign/AbstractLayout + +-class name java/lang/foreign/Addressable + +class name java/lang/foreign/Arena +header extends java/lang/Object implements java/lang/foreign/SegmentAllocator,java/lang/AutoCloseable flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +method name allocate descriptor (JJ)Ljava/lang/foreign/MemorySegment; flags 1 +method name scope descriptor ()Ljava/lang/foreign/SegmentScope; flags 401 +method name close descriptor ()V flags 401 +method name isCloseableBy descriptor (Ljava/lang/Thread;)Z flags 401 +method name openConfined descriptor ()Ljava/lang/foreign/Arena; flags 9 +method name openShared descriptor ()Ljava/lang/foreign/Arena; flags 9 class name java/lang/foreign/FunctionDescriptor -header extends java/lang/Object sealed true flags 21 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) -innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +-method name returnLayout descriptor ()Ljava/util/Optional; +-method name argumentLayouts descriptor ()Ljava/util/List; +-method name asVariadic descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; +-method name firstVariadicArgumentIndex descriptor ()I +-method name appendArgumentLayouts descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; +-method name insertArgumentLayouts descriptor (I[Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; +-method name changeReturnLayout descriptor (Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; +-method name dropReturnLayout descriptor ()Ljava/lang/foreign/FunctionDescriptor; +-method name toString descriptor ()Ljava/lang/String; +-method name equals descriptor (Ljava/lang/Object;)Z +-method name hashCode descriptor ()I +method name returnLayout descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name argumentLayouts descriptor ()Ljava/util/List; flags 401 signature ()Ljava/util/List; +method name appendArgumentLayouts descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; flags 481 +method name insertArgumentLayouts descriptor (I[Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; flags 481 +method name changeReturnLayout descriptor (Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/FunctionDescriptor; flags 401 +method name dropReturnLayout descriptor ()Ljava/lang/foreign/FunctionDescriptor; flags 401 +method name toMethodType descriptor ()Ljava/lang/invoke/MethodType; flags 401 + +class name java/lang/foreign/GroupLayout +header extends java/lang/Object implements java/lang/foreign/MemoryLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +-method name memberLayouts descriptor ()Ljava/util/List; +-method name toString descriptor ()Ljava/lang/String; +-method name isStruct descriptor ()Z +-method name isUnion descriptor ()Z +-method name equals descriptor (Ljava/lang/Object;)Z +-method name hashCode descriptor ()I +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/GroupLayout; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/GroupLayout; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name memberLayouts descriptor ()Ljava/util/List; flags 401 signature ()Ljava/util/List; +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/GroupLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/GroupLayout; flags 401 class name java/lang/foreign/Linker -header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +header extends java/lang/Object nestMembers java/lang/foreign/Linker$Option,java/lang/foreign/Linker$Option$CaptureCallState sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/Linker$Option outerClass java/lang/foreign/Linker innerClassName Option flags 609 +innerclass innerClass java/lang/foreign/Linker$Option$CaptureCallState outerClass java/lang/foreign/Linker$Option innerClassName CaptureCallState flags 609 +-method name downcallHandle descriptor (Ljava/lang/foreign/Addressable;Ljava/lang/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; +-method name downcallHandle descriptor (Ljava/lang/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodHandle; +-method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljava/lang/foreign/FunctionDescriptor;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +-method name downcallType descriptor (Ljava/lang/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodType; +-method name upcallType descriptor (Ljava/lang/foreign/FunctionDescriptor;)Ljava/lang/invoke/MethodType; +method name downcallHandle descriptor (Ljava/lang/foreign/MemorySegment;Ljava/lang/foreign/FunctionDescriptor;[Ljava/lang/foreign/Linker$Option;)Ljava/lang/invoke/MethodHandle; flags 81 +method name downcallHandle descriptor (Ljava/lang/foreign/FunctionDescriptor;[Ljava/lang/foreign/Linker$Option;)Ljava/lang/invoke/MethodHandle; flags 481 +method name upcallStub descriptor (Ljava/lang/invoke/MethodHandle;Ljava/lang/foreign/FunctionDescriptor;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; flags 401 + +class name java/lang/foreign/Linker$Option +header extends java/lang/Object nestHost java/lang/foreign/Linker sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/Linker$Option outerClass java/lang/foreign/Linker innerClassName Option flags 609 +innerclass innerClass java/lang/foreign/Linker$Option$CaptureCallState outerClass java/lang/foreign/Linker$Option innerClassName CaptureCallState flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name firstVariadicArg descriptor (I)Ljava/lang/foreign/Linker$Option; flags 9 +method name captureCallState descriptor ([Ljava/lang/String;)Ljava/lang/foreign/Linker$Option$CaptureCallState; flags 89 + +class name java/lang/foreign/Linker$Option$CaptureCallState +header extends java/lang/Object implements java/lang/foreign/Linker$Option nestHost java/lang/foreign/Linker sealed true flags 601 +innerclass innerClass java/lang/foreign/Linker$Option outerClass java/lang/foreign/Linker innerClassName Option flags 609 +innerclass innerClass java/lang/foreign/Linker$Option$CaptureCallState outerClass java/lang/foreign/Linker$Option innerClassName CaptureCallState flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +method name layout descriptor ()Ljava/lang/foreign/StructLayout; flags 401 +method name supported descriptor ()Ljava/util/Set; flags 9 signature ()Ljava/util/Set; -class name java/lang/foreign/MemoryAddress -header extends java/lang/Object implements java/lang/foreign/Addressable sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) -innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +-class name java/lang/foreign/MemoryAddress class name java/lang/foreign/MemoryLayout header extends java/lang/Object nestMembers java/lang/foreign/MemoryLayout$PathElement sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 -innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +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$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte 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/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name isPadding descriptor ()Z +-method name paddingLayout descriptor (J)Ljava/lang/foreign/MemoryLayout; +-method name structLayout descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/GroupLayout; +-method name unionLayout descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/GroupLayout; +method name paddingLayout descriptor (J)Ljava/lang/foreign/PaddingLayout; flags 9 +method name sequenceLayout descriptor (Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/SequenceLayout; flags 9 +method name structLayout descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/StructLayout; flags 89 +method name unionLayout descriptor ([Ljava/lang/foreign/MemoryLayout;)Ljava/lang/foreign/UnionLayout; flags 89 class name java/lang/foreign/MemoryLayout$PathElement header extends java/lang/Object nestHost java/lang/foreign/MemoryLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) @@ -186,48 +273,336 @@ innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 class name java/lang/foreign/MemorySegment -header extends java/lang/Object implements java/lang/foreign/Addressable sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) -innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 - -class name java/lang/foreign/MemorySession -header extends java/lang/Object implements java/lang/AutoCloseable,java/lang/foreign/SegmentAllocator sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte 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/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 609 +-method name address descriptor ()Ljava/lang/foreign/MemoryAddress; +-method name session descriptor ()Ljava/lang/foreign/MemorySession; +-method name mismatch descriptor (Ljava/lang/foreign/MemorySegment;)J +-method name ofAddress descriptor (Ljava/lang/foreign/MemoryAddress;JLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +-method name allocateNative descriptor (Ljava/lang/foreign/MemoryLayout;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +-method name allocateNative descriptor (JLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +-method name allocateNative descriptor (JJLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +-method name get descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;J)Ljava/lang/foreign/MemoryAddress; +-method name set descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;JLjava/lang/foreign/Addressable;)V +-method name getAtIndex descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;J)Ljava/lang/foreign/MemoryAddress; +-method name setAtIndex descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;JLjava/lang/foreign/Addressable;)V +field name NULL descriptor Ljava/lang/foreign/MemorySegment; flags 19 +method name address descriptor ()J flags 401 +method name array descriptor ()Ljava/util/Optional; flags 401 signature ()Ljava/util/Optional; +method name scope descriptor ()Ljava/lang/foreign/SegmentScope; flags 401 +method name mismatch descriptor (Ljava/lang/foreign/MemorySegment;)J flags 1 +method name ofAddress descriptor (J)Ljava/lang/foreign/MemorySegment; flags 9 +method name ofAddress descriptor (JJ)Ljava/lang/foreign/MemorySegment; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name ofAddress descriptor (JJLjava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive;@Ljdk/internal/vm/annotation/ForceInline; +method name ofAddress descriptor (JJLjava/lang/foreign/SegmentScope;Ljava/lang/Runnable;)Ljava/lang/foreign/MemorySegment; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name allocateNative descriptor (Ljava/lang/foreign/MemoryLayout;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; flags 9 +method name allocateNative descriptor (JLjava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; flags 9 +method name allocateNative descriptor (JJLjava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; flags 9 +method name get descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;J)Ljava/lang/foreign/MemorySegment; flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name set descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;JLjava/lang/foreign/MemorySegment;)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name getAtIndex descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;J)Ljava/lang/foreign/MemorySegment; flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name setAtIndex descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;JLjava/lang/foreign/MemorySegment;)V flags 1 runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name mismatch descriptor (Ljava/lang/foreign/MemorySegment;JJLjava/lang/foreign/MemorySegment;JJ)J flags 9 + +-class name java/lang/foreign/MemorySession + +class name java/lang/foreign/PaddingLayout +header extends java/lang/Object implements java/lang/foreign/MemoryLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/PaddingLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/PaddingLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/MemoryLayout; flags 1041 + +class name java/lang/foreign/SegmentAllocator +header extends java/lang/Object flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) runtimeAnnotations @Ljava/lang/FunctionalInterface; +innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte 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/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +-method name allocate descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;Ljava/lang/foreign/Addressable;)Ljava/lang/foreign/MemorySegment; +-method name newNativeArena descriptor (Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/SegmentAllocator; +-method name newNativeArena descriptor (JLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/SegmentAllocator; +-method name newNativeArena descriptor (JJLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/SegmentAllocator; +-method name implicitAllocator descriptor ()Ljava/lang/foreign/SegmentAllocator; +method name allocate descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;Ljava/lang/foreign/MemorySegment;)Ljava/lang/foreign/MemorySegment; flags 1 +method name slicingAllocator descriptor (Ljava/lang/foreign/MemorySegment;)Ljava/lang/foreign/SegmentAllocator; flags 9 +method name nativeAllocator descriptor (Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/SegmentAllocator; flags 9 + +class name java/lang/foreign/SegmentScope +header extends java/lang/Object sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +method name auto descriptor ()Ljava/lang/foreign/SegmentScope; flags 9 +method name global descriptor ()Ljava/lang/foreign/SegmentScope; flags 9 +method name isAlive descriptor ()Z flags 401 +method name isAccessibleBy descriptor (Ljava/lang/Thread;)Z flags 401 +method name whileAlive descriptor (Ljava/lang/Runnable;)V flags 401 + +class name java/lang/foreign/SequenceLayout +header extends java/lang/Object implements java/lang/foreign/MemoryLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +-method name elementLayout descriptor ()Ljava/lang/foreign/MemoryLayout; +-method name elementCount descriptor ()J +-method name withElementCount descriptor (J)Ljava/lang/foreign/SequenceLayout; +-method name reshape descriptor ([J)Ljava/lang/foreign/SequenceLayout; +-method name flatten descriptor ()Ljava/lang/foreign/SequenceLayout; +-method name toString descriptor ()Ljava/lang/String; +-method name equals descriptor (Ljava/lang/Object;)Z +-method name hashCode descriptor ()I +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/SequenceLayout; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/SequenceLayout; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name elementLayout descriptor ()Ljava/lang/foreign/MemoryLayout; flags 401 +method name elementCount descriptor ()J flags 401 +method name withElementCount descriptor (J)Ljava/lang/foreign/SequenceLayout; flags 401 +method name reshape descriptor ([J)Ljava/lang/foreign/SequenceLayout; flags 481 +method name flatten descriptor ()Ljava/lang/foreign/SequenceLayout; flags 401 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/SequenceLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/SequenceLayout; flags 401 + +class name java/lang/foreign/StructLayout +header extends java/lang/Object implements java/lang/foreign/GroupLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/StructLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/StructLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/GroupLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/GroupLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/MemoryLayout; flags 1041 + +class name java/lang/foreign/SymbolLookup +-method name lookup descriptor (Ljava/lang/String;)Ljava/util/Optional; +-method name libraryLookup descriptor (Ljava/lang/String;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/SymbolLookup; +-method name libraryLookup descriptor (Ljava/nio/file/Path;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/SymbolLookup; +method name find descriptor (Ljava/lang/String;)Ljava/util/Optional; flags 401 signature (Ljava/lang/String;)Ljava/util/Optional; +method name libraryLookup descriptor (Ljava/lang/String;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name libraryLookup descriptor (Ljava/nio/file/Path;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/SymbolLookup; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; + +class name java/lang/foreign/UnionLayout +header extends java/lang/Object implements java/lang/foreign/GroupLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/UnionLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/UnionLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/GroupLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/GroupLayout; flags 1041 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/MemoryLayout; flags 1041 +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/MemoryLayout; flags 1041 class name java/lang/foreign/VaList -header extends java/lang/Object implements java/lang/foreign/Addressable nestMembers java/lang/foreign/VaList$Builder sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +header extends java/lang/Object nestMembers java/lang/foreign/VaList$Builder sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) innerclass innerClass java/lang/foreign/VaList$Builder outerClass java/lang/foreign/VaList innerClassName Builder flags 609 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt 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/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +-method name session descriptor ()Ljava/lang/foreign/MemorySession; +-method name nextVarg descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;)Ljava/lang/foreign/MemoryAddress; +-method name address descriptor ()Ljava/lang/foreign/MemoryAddress; +-method name ofAddress descriptor (Ljava/lang/foreign/MemoryAddress;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/VaList; +-method name make descriptor (Ljava/util/function/Consumer;Ljava/lang/foreign/MemorySession;)Ljava/lang/foreign/VaList; +method name nextVarg descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;)Ljava/lang/foreign/MemorySegment; flags 401 +method name segment descriptor ()Ljava/lang/foreign/MemorySegment; flags 401 +method name ofAddress descriptor (JLjava/lang/foreign/SegmentScope;)Ljava/lang/foreign/VaList; flags 9 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name make descriptor (Ljava/util/function/Consumer;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/VaList; flags 9 signature (Ljava/util/function/Consumer;Ljava/lang/foreign/SegmentScope;)Ljava/lang/foreign/VaList; class name java/lang/foreign/VaList$Builder header extends java/lang/Object nestHost java/lang/foreign/VaList sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) innerclass innerClass java/lang/foreign/VaList$Builder outerClass java/lang/foreign/VaList innerClassName Builder flags 609 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt 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/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +-method name addVarg descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;Ljava/lang/foreign/Addressable;)Ljava/lang/foreign/VaList$Builder; +method name addVarg descriptor (Ljava/lang/foreign/ValueLayout$OfAddress;Ljava/lang/foreign/MemorySegment;)Ljava/lang/foreign/VaList$Builder; flags 401 class name java/lang/foreign/ValueLayout -header extends java/lang/foreign/AbstractLayout implements java/lang/foreign/MemoryLayout nestMembers java/lang/foreign/ValueLayout$OfAddress,java/lang/foreign/ValueLayout$OfDouble,java/lang/foreign/ValueLayout$OfLong,java/lang/foreign/ValueLayout$OfFloat,java/lang/foreign/ValueLayout$OfInt,java/lang/foreign/ValueLayout$OfShort,java/lang/foreign/ValueLayout$OfChar,java/lang/foreign/ValueLayout$OfByte,java/lang/foreign/ValueLayout$OfBoolean sealed true flags 21 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) -innerclass innerClass java/lang/foreign/MemoryLayout$PathElement outerClass java/lang/foreign/MemoryLayout innerClassName PathElement flags 609 -innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 19 -innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 19 +header extends java/lang/Object implements java/lang/foreign/MemoryLayout nestMembers java/lang/foreign/ValueLayout$OfAddress,java/lang/foreign/ValueLayout$OfDouble,java/lang/foreign/ValueLayout$OfLong,java/lang/foreign/ValueLayout$OfFloat,java/lang/foreign/ValueLayout$OfInt,java/lang/foreign/ValueLayout$OfShort,java/lang/foreign/ValueLayout$OfChar,java/lang/foreign/ValueLayout$OfByte,java/lang/foreign/ValueLayout$OfBoolean sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +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$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 609 +-method name order descriptor ()Ljava/nio/ByteOrder; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout; +-method name toString descriptor ()Ljava/lang/String; +-method name equals descriptor (Ljava/lang/Object;)Z +-method name arrayElementVarHandle descriptor ([I)Ljava/lang/invoke/VarHandle; +-method name carrier descriptor ()Ljava/lang/Class; +-method name hashCode descriptor ()I +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +field name ADDRESS_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfAddress; flags 19 +field name JAVA_CHAR_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfChar; flags 19 +field name JAVA_SHORT_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfShort; flags 19 +field name JAVA_INT_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfInt; flags 19 +field name JAVA_LONG_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfLong; flags 19 +field name JAVA_FLOAT_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfFloat; flags 19 +field name JAVA_DOUBLE_UNALIGNED descriptor Ljava/lang/foreign/ValueLayout$OfDouble; flags 19 +method name order descriptor ()Ljava/nio/ByteOrder; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout; flags 401 +method name arrayElementVarHandle descriptor ([I)Ljava/lang/invoke/VarHandle; flags 481 +method name carrier descriptor ()Ljava/lang/Class; flags 401 signature ()Ljava/lang/Class<*>; +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout; flags 401 + +class name java/lang/foreign/ValueLayout$OfAddress +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfAddress outerClass java/lang/foreign/ValueLayout innerClassName OfAddress flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfAddress; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfAddress; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfAddress; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfAddress; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfAddress; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfAddress; flags 401 +method name asUnbounded descriptor ()Ljava/lang/foreign/ValueLayout$OfAddress; flags 401 runtimeAnnotations @Ljdk/internal/reflect/CallerSensitive; +method name isUnbounded descriptor ()Z flags 401 + +class name java/lang/foreign/ValueLayout$OfBoolean +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfBoolean outerClass java/lang/foreign/ValueLayout innerClassName OfBoolean flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfBoolean; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfBoolean; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfBoolean; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfBoolean; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfBoolean; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfBoolean; flags 401 + +class name java/lang/foreign/ValueLayout$OfByte +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfByte; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfByte; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfByte; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfByte; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfByte; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfByte; flags 401 + +class name java/lang/foreign/ValueLayout$OfChar +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfChar outerClass java/lang/foreign/ValueLayout innerClassName OfChar flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfChar; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfChar; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfChar; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfChar; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfChar; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfChar; flags 401 + +class name java/lang/foreign/ValueLayout$OfDouble +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfDouble; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfDouble; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfDouble; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfDouble; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfDouble; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfDouble; flags 401 + +class name java/lang/foreign/ValueLayout$OfFloat +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfFloat; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfFloat; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfFloat; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfFloat; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfFloat; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfFloat; flags 401 + +class name java/lang/foreign/ValueLayout$OfInt +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfInt; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfInt; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfInt; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfInt; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfInt; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfInt; flags 401 + +class name java/lang/foreign/ValueLayout$OfLong +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfLong; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfLong; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfLong; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfLong; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfLong; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfLong; flags 401 + +class name java/lang/foreign/ValueLayout$OfShort +header extends java/lang/Object implements java/lang/foreign/ValueLayout nestHost java/lang/foreign/ValueLayout sealed true flags 601 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 609 +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfShort; +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfShort; +-method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfShort; +-method name isPadding descriptor ()Z +-method name bitSize descriptor ()J +-method name withBitAlignment descriptor (J)Ljava/lang/foreign/AbstractLayout; +-method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/AbstractLayout; +-method name byteSize descriptor ()J +method name withName descriptor (Ljava/lang/String;)Ljava/lang/foreign/ValueLayout$OfShort; flags 401 +method name withBitAlignment descriptor (J)Ljava/lang/foreign/ValueLayout$OfShort; flags 401 +method name withOrder descriptor (Ljava/nio/ByteOrder;)Ljava/lang/foreign/ValueLayout$OfShort; flags 401 class name java/lang/invoke/CallSite header extends java/lang/Object sealed true flags 421 @@ -502,8 +877,9 @@ header extends java/nio/ByteBuffer sealed true flags 421 class name java/nio/ShortBuffer header extends java/nio/Buffer implements java/lang/Comparable sealed true flags 421 signature Ljava/nio/Buffer;Ljava/lang/Comparable; -class name java/nio/file/Path -method name getExtension descriptor ()Ljava/lang/String; flags 1 +class name java/nio/channels/FileChannel +-method name map descriptor (Ljava/nio/channels/FileChannel$MapMode;JJLjava/lang/foreign/MemorySession;)Ljava/lang/foreign/MemorySegment; +method name map descriptor (Ljava/nio/channels/FileChannel$MapMode;JJLjava/lang/foreign/SegmentScope;)Ljava/lang/foreign/MemorySegment; thrownTypes java/io/IOException flags 1 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;FOREIGN;) class name java/nio/file/spi/FileSystemProvider method name exists descriptor (Ljava/nio/file/Path;[Ljava/nio/file/LinkOption;)Z flags 81 @@ -726,6 +1102,12 @@ innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang class name java/util/concurrent/CountedCompleter header extends java/util/concurrent/ForkJoinTask flags 421 signature Ljava/util/concurrent/ForkJoinTask; classAnnotations @Ljdk/Profile+Annotation;(value=I1) +class name java/util/concurrent/ForkJoinPool +method name externalSubmit descriptor (Ljava/util/concurrent/ForkJoinTask;)Ljava/util/concurrent/ForkJoinTask; flags 1 signature (Ljava/util/concurrent/ForkJoinTask;)Ljava/util/concurrent/ForkJoinTask; + +class name java/util/concurrent/ForkJoinWorkerThread +method name getQueuedTaskCount descriptor ()I flags 1 + class name java/util/concurrent/atomic/AtomicBoolean header extends java/lang/Object implements java/io/Serializable flags 21 innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 @@ -993,6 +1375,10 @@ header extends java/lang/Object implements java/security/spec/AlgorithmParameter class name javax/crypto/spec/RC5ParameterSpec header extends java/lang/Object implements java/security/spec/AlgorithmParameterSpec flags 21 +class name javax/net/ssl/SSLParameters +method name getNamedGroups descriptor ()[Ljava/lang/String; flags 1 +method name setNamedGroups descriptor ([Ljava/lang/String;)V flags 1 + class name jdk/internal/event/Event header extends java/lang/Object flags 421 -method name descriptor ()V diff --git a/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt b/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt index 2a5ab70d5c9..492b1d05199 100644 --- a/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/java.management-K.sym.txt @@ -157,10 +157,22 @@ header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Lja innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +class name javax/management/loading/MLet +header extends java/net/URLClassLoader implements javax/management/loading/MLetMBean,javax/management/MBeanRegistration,java/io/Externalizable flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="20") +innerclass innerClass java/lang/System$Logger outerClass java/lang/System innerClassName Logger flags 609 +innerclass innerClass java/lang/System$Logger$Level outerClass java/lang/System$Logger innerClassName Level flags 4019 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + class name javax/management/loading/MLetContent -header extends java/lang/Object flags 21 +header extends java/lang/Object flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="20") innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 +class name javax/management/loading/MLetMBean +header extends java/lang/Object flags 601 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="20") + +class name javax/management/loading/PrivateMLet +header extends javax/management/loading/MLet implements javax/management/loading/PrivateClassLoader flags 21 deprecated true runtimeAnnotations @Ljava/lang/Deprecated;(forRemoval=Ztrue,since="20") + class name javax/management/modelmbean/InvalidTargetObjectTypeException header extends java/lang/Exception flags 21 innerclass innerClass java/io/ObjectInputStream$GetField outerClass java/io/ObjectInputStream innerClassName GetField flags 409 diff --git a/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt index e204d40b674..b55f0c82adb 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.compiler-K.sym.txt @@ -186,6 +186,9 @@ header extends java/lang/Object implements com/sun/source/tree/ExpressionTree fl class name com/sun/source/tree/ContinueTree header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 +class name com/sun/source/tree/DeconstructionPatternTree +-method name getVariable descriptor ()Lcom/sun/source/tree/VariableTree; + class name com/sun/source/tree/DirectiveTree header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 @@ -196,7 +199,18 @@ class name com/sun/source/tree/EmptyStatementTree header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 class name com/sun/source/tree/EnhancedForLoopTree -header extends java/lang/Object implements com/sun/source/tree/StatementTree flags 601 +header extends java/lang/Object implements com/sun/source/tree/StatementTree nestMembers com/sun/source/tree/EnhancedForLoopTree$DeclarationKind flags 601 +innerclass innerClass com/sun/source/tree/EnhancedForLoopTree$DeclarationKind outerClass com/sun/source/tree/EnhancedForLoopTree innerClassName DeclarationKind flags 4019 +method name getVariableOrRecordPattern descriptor ()Lcom/sun/source/tree/Tree; flags 401 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;RECORD_PATTERNS;,reflective=Ztrue) +method name getDeclarationKind descriptor ()Lcom/sun/source/tree/EnhancedForLoopTree$DeclarationKind; flags 401 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;RECORD_PATTERNS;,reflective=Ztrue) + +class name com/sun/source/tree/EnhancedForLoopTree$DeclarationKind +header extends java/lang/Enum nestHost com/sun/source/tree/EnhancedForLoopTree flags 4031 signature Ljava/lang/Enum; classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;RECORD_PATTERNS;,reflective=Ztrue) +innerclass innerClass com/sun/source/tree/EnhancedForLoopTree$DeclarationKind outerClass com/sun/source/tree/EnhancedForLoopTree innerClassName DeclarationKind flags 4019 +field name VARIABLE descriptor Lcom/sun/source/tree/EnhancedForLoopTree$DeclarationKind; flags 4019 +field name PATTERN descriptor Lcom/sun/source/tree/EnhancedForLoopTree$DeclarationKind; flags 4019 +method name values descriptor ()[Lcom/sun/source/tree/EnhancedForLoopTree$DeclarationKind; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Lcom/sun/source/tree/EnhancedForLoopTree$DeclarationKind; flags 9 class name com/sun/source/tree/ErroneousTree header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 @@ -223,7 +237,17 @@ class name com/sun/source/tree/ImportTree header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 class name com/sun/source/tree/InstanceOfTree -header extends java/lang/Object implements com/sun/source/tree/ExpressionTree flags 601 +header extends java/lang/Object implements com/sun/source/tree/ExpressionTree nestMembers com/sun/source/tree/InstanceOfTree$TestKind flags 601 +innerclass innerClass com/sun/source/tree/InstanceOfTree$TestKind outerClass com/sun/source/tree/InstanceOfTree innerClassName TestKind flags 4019 +method name getTestKind descriptor ()Lcom/sun/source/tree/InstanceOfTree$TestKind; flags 401 classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;RECORD_PATTERNS;,reflective=Ztrue) + +class name com/sun/source/tree/InstanceOfTree$TestKind +header extends java/lang/Enum nestHost com/sun/source/tree/InstanceOfTree flags 4031 signature Ljava/lang/Enum; classAnnotations @Ljdk/internal/javac/PreviewFeature;(feature=eLjdk/internal/javac/PreviewFeature$Feature;RECORD_PATTERNS;,reflective=Ztrue) +innerclass innerClass com/sun/source/tree/InstanceOfTree$TestKind outerClass com/sun/source/tree/InstanceOfTree innerClassName TestKind flags 4019 +field name TYPE descriptor Lcom/sun/source/tree/InstanceOfTree$TestKind; flags 4019 +field name PATTERN descriptor Lcom/sun/source/tree/InstanceOfTree$TestKind; flags 4019 +method name values descriptor ()[Lcom/sun/source/tree/InstanceOfTree$TestKind; flags 9 +method name valueOf descriptor (Ljava/lang/String;)Lcom/sun/source/tree/InstanceOfTree$TestKind; flags 9 class name com/sun/source/tree/IntersectionTypeTree header extends java/lang/Object implements com/sun/source/tree/Tree flags 601 diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt index 16090b97cc9..99ba0f00782 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.concurrent-K.sym.txt @@ -29,6 +29,27 @@ module name jdk.incubator.concurrent header exports jdk/incubator/concurrent requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 resolution 9 flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; +class name jdk/incubator/concurrent/ScopedValue +header extends java/lang/Object nestMembers jdk/incubator/concurrent/ScopedValue$Carrier flags 31 signature Ljava/lang/Object; +innerclass innerClass jdk/incubator/concurrent/ScopedValue$Carrier outerClass jdk/incubator/concurrent/ScopedValue innerClassName Carrier flags 19 +method name hashCode descriptor ()I flags 1 +method name where descriptor (Ljdk/incubator/concurrent/ScopedValue;Ljava/lang/Object;)Ljdk/incubator/concurrent/ScopedValue$Carrier; flags 9 signature (Ljdk/incubator/concurrent/ScopedValue;TT;)Ljdk/incubator/concurrent/ScopedValue$Carrier; +method name where descriptor (Ljdk/incubator/concurrent/ScopedValue;Ljava/lang/Object;Ljava/util/concurrent/Callable;)Ljava/lang/Object; thrownTypes java/lang/Exception flags 9 signature (Ljdk/incubator/concurrent/ScopedValue;TT;Ljava/util/concurrent/Callable<+TR;>;)TR; +method name where descriptor (Ljdk/incubator/concurrent/ScopedValue;Ljava/lang/Object;Ljava/lang/Runnable;)V flags 9 signature (Ljdk/incubator/concurrent/ScopedValue;TT;Ljava/lang/Runnable;)V +method name newInstance descriptor ()Ljdk/incubator/concurrent/ScopedValue; flags 9 signature ()Ljdk/incubator/concurrent/ScopedValue; +method name get descriptor ()Ljava/lang/Object; flags 1 signature ()TT; runtimeAnnotations @Ljdk/internal/vm/annotation/ForceInline; +method name isBound descriptor ()Z flags 1 +method name orElse descriptor (Ljava/lang/Object;)Ljava/lang/Object; flags 1 signature (TT;)TT; +method name orElseThrow descriptor (Ljava/util/function/Supplier;)Ljava/lang/Object; thrownTypes java/lang/Throwable flags 1 signature (Ljava/util/function/Supplier<+TX;>;)TT;^TX; + +class name jdk/incubator/concurrent/ScopedValue$Carrier +header extends java/lang/Object nestHost jdk/incubator/concurrent/ScopedValue flags 31 +innerclass innerClass jdk/incubator/concurrent/ScopedValue$Carrier outerClass jdk/incubator/concurrent/ScopedValue innerClassName Carrier flags 19 +method name where descriptor (Ljdk/incubator/concurrent/ScopedValue;Ljava/lang/Object;)Ljdk/incubator/concurrent/ScopedValue$Carrier; flags 1 signature (Ljdk/incubator/concurrent/ScopedValue;TT;)Ljdk/incubator/concurrent/ScopedValue$Carrier; +method name get descriptor (Ljdk/incubator/concurrent/ScopedValue;)Ljava/lang/Object; flags 1 signature (Ljdk/incubator/concurrent/ScopedValue;)TT; +method name call descriptor (Ljava/util/concurrent/Callable;)Ljava/lang/Object; thrownTypes java/lang/Exception flags 1 signature (Ljava/util/concurrent/Callable<+TR;>;)TR; +method name run descriptor (Ljava/lang/Runnable;)V flags 1 + class name jdk/incubator/concurrent/StructuredTaskScope header extends java/lang/Object implements java/lang/AutoCloseable nestMembers jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnFailure,jdk/incubator/concurrent/StructuredTaskScope$ShutdownOnSuccess flags 21 signature Ljava/lang/Object;Ljava/lang/AutoCloseable; innerclass innerClass java/lang/Thread$Builder outerClass java/lang/Thread innerClassName Builder flags 609 diff --git a/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt index 4eb5322874d..0f1da4ca016 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.incubator.vector-K.sym.txt @@ -29,3 +29,105 @@ module name jdk.incubator.vector header exports jdk/incubator/vector requires name\u0020;java.base\u0020;flags\u0020;8000 target linux-amd64 resolution 9 flags 8000 classAnnotations @Ljdk/internal/javac/ParticipatesInPreview; +class name jdk/incubator/vector/ByteVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfByte outerClass java/lang/foreign/ValueLayout innerClassName OfByte flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/DoubleVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfDouble outerClass java/lang/foreign/ValueLayout innerClassName OfDouble flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/FloatVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfFloat outerClass java/lang/foreign/ValueLayout innerClassName OfFloat flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/IntVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfInt outerClass java/lang/foreign/ValueLayout innerClassName OfInt flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/LongVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfLong outerClass java/lang/foreign/ValueLayout innerClassName OfLong flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + +class name jdk/incubator/vector/ShortVector +header extends jdk/incubator/vector/AbstractVector flags 421 signature Ljdk/incubator/vector/AbstractVector; +innerclass innerClass jdk/incubator/vector/VectorOperators$Operator outerClass jdk/incubator/vector/VectorOperators innerClassName Operator flags 609 +innerclass innerClass java/lang/foreign/ValueLayout$OfShort outerClass java/lang/foreign/ValueLayout innerClassName OfShort flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorSpecies outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorSpecies flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorPayload outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorPayload flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Unary outerClass jdk/incubator/vector/VectorOperators innerClassName Unary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Comparison outerClass jdk/incubator/vector/VectorOperators innerClassName Comparison flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Associative outerClass jdk/incubator/vector/VectorOperators innerClassName Associative flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Binary outerClass jdk/incubator/vector/VectorOperators innerClassName Binary flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$Vector outerClass jdk/internal/vm/vector/VectorSupport innerClassName Vector flags 9 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorMask outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorMask flags 9 +innerclass innerClass jdk/incubator/vector/VectorOperators$Ternary outerClass jdk/incubator/vector/VectorOperators innerClassName Ternary flags 609 +innerclass innerClass jdk/incubator/vector/VectorOperators$Test outerClass jdk/incubator/vector/VectorOperators innerClassName Test flags 609 +innerclass innerClass jdk/internal/vm/vector/VectorSupport$VectorShuffle outerClass jdk/internal/vm/vector/VectorSupport innerClassName VectorShuffle flags 9 +innerclass innerClass java/lang/invoke/MethodHandles$Lookup outerClass java/lang/invoke/MethodHandles innerClassName Lookup flags 19 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt index 56113904721..b40804b4f21 100644 --- a/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt +++ b/src/jdk.compiler/share/data/symbols/jdk.jfr-K.sym.txt @@ -29,3 +29,6 @@ class name jdk/jfr/consumer/RecordedObject header extends java/lang/Object sealed true flags 21 +class name jdk/jfr/consumer/RecordingStream +method name stop descriptor ()Z flags 1 + diff --git a/src/jdk.compiler/share/data/symbols/jdk.management.jfr-K.sym.txt b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-K.sym.txt new file mode 100644 index 00000000000..67bd28031c6 --- /dev/null +++ b/src/jdk.compiler/share/data/symbols/jdk.management.jfr-K.sym.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2022, 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/management/jfr/RemoteRecordingStream +method name stop descriptor ()Z flags 1 + diff --git a/src/jdk.compiler/share/data/symbols/symbols b/src/jdk.compiler/share/data/symbols/symbols index 14ed3ee01d5..0a6e58d97e1 100644 --- a/src/jdk.compiler/share/data/symbols/symbols +++ b/src/jdk.compiler/share/data/symbols/symbols @@ -42,4 +42,4 @@ platform version G base F files java.base-G.sym.txt:java.compiler-G.sym.txt:java platform version H base G files java.base-H.sym.txt:java.compiler-H.sym.txt:java.datatransfer-H.sym.txt:java.desktop-H.sym.txt:java.instrument-H.sym.txt:java.logging-H.sym.txt:java.management-H.sym.txt:java.management.rmi-H.sym.txt:java.naming-H.sym.txt:java.rmi-H.sym.txt:java.scripting-H.sym.txt:java.security.jgss-H.sym.txt:java.security.sasl-H.sym.txt:java.smartcardio-H.sym.txt:java.sql-H.sym.txt:java.sql.rowset-H.sym.txt:java.xml-H.sym.txt:java.xml.crypto-H.sym.txt:jdk.accessibility-H.sym.txt:jdk.attach-H.sym.txt:jdk.compiler-H.sym.txt:jdk.dynalink-H.sym.txt:jdk.httpserver-H.sym.txt:jdk.incubator.foreign-H.sym.txt:jdk.incubator.vector-H.sym.txt:jdk.jartool-H.sym.txt:jdk.javadoc-H.sym.txt:jdk.jconsole-H.sym.txt:jdk.jdi-H.sym.txt:jdk.jfr-H.sym.txt:jdk.jshell-H.sym.txt:jdk.jsobject-H.sym.txt:jdk.management-H.sym.txt:jdk.management.jfr-H.sym.txt:jdk.net-H.sym.txt:jdk.sctp-H.sym.txt:jdk.security.auth-H.sym.txt:jdk.security.jgss-H.sym.txt:jdk.unsupported-H.sym.txt:jdk.xml.dom-H.sym.txt platform version I base H files java.base-I.sym.txt:java.compiler-I.sym.txt:java.datatransfer-I.sym.txt:java.desktop-I.sym.txt:java.instrument-I.sym.txt:java.logging-I.sym.txt:java.management-I.sym.txt:java.management.rmi-I.sym.txt:java.naming-I.sym.txt:java.net.http-I.sym.txt:java.rmi-I.sym.txt:java.scripting-I.sym.txt:java.security.jgss-I.sym.txt:java.security.sasl-I.sym.txt:java.smartcardio-I.sym.txt:java.sql-I.sym.txt:java.sql.rowset-I.sym.txt:java.xml-I.sym.txt:java.xml.crypto-I.sym.txt:jdk.accessibility-I.sym.txt:jdk.attach-I.sym.txt:jdk.compiler-I.sym.txt:jdk.dynalink-I.sym.txt:jdk.httpserver-I.sym.txt:jdk.incubator.foreign-I.sym.txt:jdk.incubator.vector-I.sym.txt:jdk.jartool-I.sym.txt:jdk.javadoc-I.sym.txt:jdk.jconsole-I.sym.txt:jdk.jdi-I.sym.txt:jdk.jlink-I.sym.txt:jdk.jshell-I.sym.txt:jdk.jsobject-I.sym.txt:jdk.management-I.sym.txt:jdk.management.jfr-I.sym.txt:jdk.net-I.sym.txt:jdk.sctp-I.sym.txt:jdk.security.auth-I.sym.txt:jdk.security.jgss-I.sym.txt:jdk.unsupported-I.sym.txt:jdk.xml.dom-I.sym.txt platform version J base I files java.base-J.sym.txt:java.compiler-J.sym.txt:java.datatransfer-J.sym.txt:java.desktop-J.sym.txt:java.instrument-J.sym.txt:java.logging-J.sym.txt:java.management-J.sym.txt:java.management.rmi-J.sym.txt:java.naming-J.sym.txt:java.net.http-J.sym.txt:java.rmi-J.sym.txt:java.scripting-J.sym.txt:java.security.jgss-J.sym.txt:java.security.sasl-J.sym.txt:java.smartcardio-J.sym.txt:java.sql-J.sym.txt:java.sql.rowset-J.sym.txt:java.xml-J.sym.txt:java.xml.crypto-J.sym.txt:jdk.accessibility-J.sym.txt:jdk.attach-J.sym.txt:jdk.compiler-J.sym.txt:jdk.dynalink-J.sym.txt:jdk.httpserver-J.sym.txt:jdk.incubator.concurrent-J.sym.txt:jdk.incubator.foreign-J.sym.txt:jdk.incubator.vector-J.sym.txt:jdk.jartool-J.sym.txt:jdk.javadoc-J.sym.txt:jdk.jconsole-J.sym.txt:jdk.jdi-J.sym.txt:jdk.jfr-J.sym.txt:jdk.jshell-J.sym.txt:jdk.jsobject-J.sym.txt:jdk.management-J.sym.txt:jdk.management.agent-J.sym.txt:jdk.net-J.sym.txt:jdk.sctp-J.sym.txt:jdk.security.auth-J.sym.txt:jdk.security.jgss-J.sym.txt:jdk.unsupported-J.sym.txt:jdk.xml.dom-J.sym.txt -platform version K base J files java.base-K.sym.txt:java.compiler-K.sym.txt:java.datatransfer-K.sym.txt:java.desktop-K.sym.txt:java.instrument-K.sym.txt:java.logging-K.sym.txt:java.management-K.sym.txt:java.management.rmi-K.sym.txt:java.naming-K.sym.txt:java.rmi-K.sym.txt:java.scripting-K.sym.txt:java.security.jgss-K.sym.txt:java.security.sasl-K.sym.txt:java.smartcardio-K.sym.txt:java.sql-K.sym.txt:java.sql.rowset-K.sym.txt:java.xml-K.sym.txt:java.xml.crypto-K.sym.txt:jdk.accessibility-K.sym.txt:jdk.attach-K.sym.txt:jdk.compiler-K.sym.txt:jdk.dynalink-K.sym.txt:jdk.httpserver-K.sym.txt:jdk.incubator.concurrent-K.sym.txt:jdk.incubator.vector-K.sym.txt:jdk.jartool-K.sym.txt:jdk.javadoc-K.sym.txt:jdk.jconsole-K.sym.txt:jdk.jdi-K.sym.txt:jdk.jfr-K.sym.txt:jdk.jlink-K.sym.txt:jdk.jpackage-K.sym.txt:jdk.jshell-K.sym.txt:jdk.jsobject-K.sym.txt:jdk.management-K.sym.txt:jdk.net-K.sym.txt:jdk.sctp-K.sym.txt:jdk.security.auth-K.sym.txt:jdk.security.jgss-K.sym.txt:jdk.unsupported-K.sym.txt:jdk.xml.dom-K.sym.txt +platform version K base J files java.base-K.sym.txt:java.compiler-K.sym.txt:java.datatransfer-K.sym.txt:java.desktop-K.sym.txt:java.instrument-K.sym.txt:java.logging-K.sym.txt:java.management-K.sym.txt:java.management.rmi-K.sym.txt:java.naming-K.sym.txt:java.rmi-K.sym.txt:java.scripting-K.sym.txt:java.security.jgss-K.sym.txt:java.security.sasl-K.sym.txt:java.smartcardio-K.sym.txt:java.sql-K.sym.txt:java.sql.rowset-K.sym.txt:java.xml-K.sym.txt:java.xml.crypto-K.sym.txt:jdk.accessibility-K.sym.txt:jdk.attach-K.sym.txt:jdk.compiler-K.sym.txt:jdk.dynalink-K.sym.txt:jdk.httpserver-K.sym.txt:jdk.incubator.concurrent-K.sym.txt:jdk.incubator.vector-K.sym.txt:jdk.jartool-K.sym.txt:jdk.javadoc-K.sym.txt:jdk.jconsole-K.sym.txt:jdk.jdi-K.sym.txt:jdk.jfr-K.sym.txt:jdk.jlink-K.sym.txt:jdk.jpackage-K.sym.txt:jdk.jshell-K.sym.txt:jdk.jsobject-K.sym.txt:jdk.management-K.sym.txt:jdk.management.jfr-K.sym.txt:jdk.net-K.sym.txt:jdk.sctp-K.sym.txt:jdk.security.auth-K.sym.txt:jdk.security.jgss-K.sym.txt:jdk.unsupported-K.sym.txt:jdk.xml.dom-K.sym.txt From 9749a436418a2e2bcd1571e2fd6f16e3461cf883 Mon Sep 17 00:00:00 2001 From: Artem Semenov Date: Fri, 9 Dec 2022 20:05:19 +0000 Subject: [PATCH 158/494] 8298457: Instructions in a11y manual tests need to be updated Reviewed-by: kizune, serb --- test/jdk/java/awt/a11y/AccessibleActionsTest.java | 4 ++-- test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java | 2 +- test/jdk/java/awt/a11y/AccessibleTextTest.java | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/test/jdk/java/awt/a11y/AccessibleActionsTest.java b/test/jdk/java/awt/a11y/AccessibleActionsTest.java index 8a916d5527f..3f3f191a099 100644 --- a/test/jdk/java/awt/a11y/AccessibleActionsTest.java +++ b/test/jdk/java/awt/a11y/AccessibleActionsTest.java @@ -57,7 +57,7 @@ void createTest() { + "Check a11y actions.\n\n" + "Turn screen reader on, and Tab to the label.\n\n" + "Perform the VO action \"Press\" (VO+space)\n" - + "Perform the VO action \"Show menu\" (VO+Shift+m)\n\n" + + "Perform the VO action \"Show menu\" (Shift+VO+m)\n\n" + "If after the first action the text of the label has changed, and after the second action the menu appears tab further and press PASS, otherwise press FAIL."; exceptionString = "AccessibleAction test failed!"; @@ -67,7 +67,7 @@ void createTest() { void createTree() { INSTRUCTIONS = "INSTRUCTIONS:\n" + "Check a11y actions.\n\n" - + "Turn screen reader on, and Tab to the label.\n\n" + + "Turn screen reader on, and Tab to the tree.\n\n" + "Perform the VO action \"Press\" (VO+space) on tree nodes\n\n" + "If after press the tree node is expanded tab further and press PASS, otherwise press FAIL."; diff --git a/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java b/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java index f03af5d3a09..28da76bc17c 100644 --- a/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java +++ b/test/jdk/java/awt/a11y/AccessibleJTabbedPaneTest.java @@ -52,7 +52,7 @@ void createTabPane() { INSTRUCTIONS = "INSTRUCTIONS:\n" + "Check a11y of JTabbedPane.\n\n" + "Turn screen reader on, and tab to the JTabbedPane.\n" - + "Use page up and page down arrow buttons to move through the tabs.\n\n" + + "Use the left and right arrow buttons to move through the tabs.\n\n" + "If you can hear selected tab names tab further and press PASS, otherwise press FAIL.\n"; JTabbedPane tabbedPane = new JTabbedPane(); diff --git a/test/jdk/java/awt/a11y/AccessibleTextTest.java b/test/jdk/java/awt/a11y/AccessibleTextTest.java index 542d7bde082..0acb14ff694 100644 --- a/test/jdk/java/awt/a11y/AccessibleTextTest.java +++ b/test/jdk/java/awt/a11y/AccessibleTextTest.java @@ -58,8 +58,8 @@ private void createSimpleLabel() { + "Check a11y of JLabel.\n\n" + "Turn screen reader on.\n" + "On MacOS, use the VO navigation keys to read the label text;\n" - + "ON Windows with JAWS, use window virtualization (insert+alt+w and arrows) to read the label text;\n" - + "ON Windows with NVDA, use the browse cursor (insert+num4 or insert+num6) to read the label text;\n\n" + + "On Windows with JAWS, use JAWS cursor (num_minus and arrows) to read the label text;\n" + + "On Windows with NVDA, use the object navigation (insert+num4 or insert+num6) to read the label text;\n\n" + "If you can hear text from label tab further and press PASS, otherwise press FAIL."; JLabel label = new JLabel("this is a label"); From 478ef389dc3767edfbe21d10a7f7f1522c648c2e Mon Sep 17 00:00:00 2001 From: Xue-Lei Andrew Fan Date: Fri, 9 Dec 2022 22:37:20 +0000 Subject: [PATCH 159/494] 8296812: sprintf is deprecated in Xcode 14 Reviewed-by: stuefe, prr, kbarrett, lucy --- .../cpu/aarch64/vm_version_aarch64.cpp | 4 +- src/hotspot/os/bsd/attachListener_bsd.cpp | 12 ++-- src/hotspot/os/bsd/os_bsd.cpp | 25 ++++---- src/hotspot/share/adlc/adlc.hpp | 4 ++ src/hotspot/share/adlc/adlparse.cpp | 25 ++++---- src/hotspot/share/adlc/archDesc.cpp | 4 +- src/hotspot/share/adlc/dfa.cpp | 6 +- src/hotspot/share/adlc/formssel.cpp | 11 ++-- src/hotspot/share/adlc/main.cpp | 2 +- src/hotspot/share/adlc/output_c.cpp | 57 ++++++++++++------- src/hotspot/share/c1/c1_Runtime1.cpp | 4 +- src/hotspot/share/cds/filemap.cpp | 2 +- src/hotspot/share/classfile/javaClasses.cpp | 17 +++--- src/hotspot/share/code/dependencies.cpp | 3 +- src/hotspot/share/compiler/compileBroker.cpp | 8 +-- .../share/interpreter/bootstrapInfo.cpp | 8 +-- .../share/jfr/support/jfrSymbolTable.cpp | 2 +- .../share/jvmci/jvmciCompilerToVMInit.cpp | 6 +- .../share/prims/wbtestmethods/parserTests.cpp | 2 +- src/hotspot/share/runtime/deoptimization.cpp | 6 +- src/hotspot/share/runtime/os.cpp | 12 +++- src/hotspot/share/runtime/os.hpp | 4 ++ src/hotspot/share/runtime/perfData.cpp | 7 ++- src/hotspot/share/utilities/debug.cpp | 2 +- src/hotspot/share/utilities/utf8.cpp | 6 +- .../libjsound/PLATFORM_API_MacOSX_Ports.cpp | 2 +- 26 files changed, 141 insertions(+), 100 deletions(-) diff --git a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp index 25853cc38b1..046f9e29c3e 100644 --- a/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/vm_version_aarch64.cpp @@ -222,8 +222,8 @@ void VM_Version::initialize() { } char buf[512]; - sprintf(buf, "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); - if (_model2) sprintf(buf+strlen(buf), "(0x%03x)", _model2); + int buf_used_len = os::snprintf_checked(buf, sizeof(buf), "0x%02x:0x%x:0x%03x:%d", _cpu, _variant, _model, _revision); + if (_model2) os::snprintf_checked(buf + buf_used_len, sizeof(buf) - buf_used_len, "(0x%03x)", _model2); #define ADD_FEATURE_IF_SUPPORTED(id, name, bit) if (VM_Version::supports_##name()) strcat(buf, ", " #name); CPU_FEATURE_FLAGS(ADD_FEATURE_IF_SUPPORTED) #undef ADD_FEATURE_IF_SUPPORTED diff --git a/src/hotspot/os/bsd/attachListener_bsd.cpp b/src/hotspot/os/bsd/attachListener_bsd.cpp index 7999210bc3e..779b439d16b 100644 --- a/src/hotspot/os/bsd/attachListener_bsd.cpp +++ b/src/hotspot/os/bsd/attachListener_bsd.cpp @@ -248,7 +248,7 @@ int BsdAttachListener::init() { // BsdAttachOperation* BsdAttachListener::read_request(int s) { char ver_str[8]; - sprintf(ver_str, "%d", ATTACH_PROTOCOL_VER); + size_t ver_str_len = os::snprintf_checked(ver_str, sizeof(ver_str), "%d", ATTACH_PROTOCOL_VER); // The request is a sequence of strings so we first figure out the // expected count and the maximum possible length of the request. @@ -288,11 +288,11 @@ BsdAttachOperation* BsdAttachListener::read_request(int s) { // The first string is so check it now to // check for protocol mismatch if (str_count == 1) { - if ((strlen(buf) != strlen(ver_str)) || + if ((strlen(buf) != ver_str_len) || (atoi(buf) != ATTACH_PROTOCOL_VER)) { char msg[32]; - sprintf(msg, "%d\n", ATTACH_ERROR_BADVERSION); - write_fully(s, msg, strlen(msg)); + int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", ATTACH_ERROR_BADVERSION); + write_fully(s, msg, msg_len); return NULL; } } @@ -411,8 +411,8 @@ void BsdAttachOperation::complete(jint result, bufferedStream* st) { // write operation result char msg[32]; - sprintf(msg, "%d\n", result); - int rc = BsdAttachListener::write_fully(this->socket(), msg, strlen(msg)); + int msg_len = os::snprintf_checked(msg, sizeof(msg), "%d\n", result); + int rc = BsdAttachListener::write_fully(this->socket(), msg, msg_len); // write any result data if (rc == 0) { diff --git a/src/hotspot/os/bsd/os_bsd.cpp b/src/hotspot/os/bsd/os_bsd.cpp index a0cf536134e..c9b21f2cabb 100644 --- a/src/hotspot/os/bsd/os_bsd.cpp +++ b/src/hotspot/os/bsd/os_bsd.cpp @@ -320,7 +320,7 @@ void os::init_system_properties_values() { #ifndef __APPLE__ - // Buffer that fits several sprintfs. + // Buffer that fits several snprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize = @@ -376,17 +376,16 @@ void os::init_system_properties_values() { const char *v_colon = ":"; if (v == NULL) { v = ""; v_colon = ""; } // That's +1 for the colon and +1 for the trailing '\0'. - char *ld_library_path = NEW_C_HEAP_ARRAY(char, - strlen(v) + 1 + - sizeof(SYS_EXT_DIR) + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1, - mtInternal); - sprintf(ld_library_path, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch); + const size_t ld_library_path_size = strlen(v) + 1 + sizeof(SYS_EXT_DIR) + + sizeof("/lib/") + strlen(cpu_arch) + sizeof(DEFAULT_LIBPATH) + 1; + char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal); + os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s" SYS_EXT_DIR "/lib/%s:" DEFAULT_LIBPATH, v, v_colon, cpu_arch); Arguments::set_library_path(ld_library_path); FREE_C_HEAP_ARRAY(char, ld_library_path); } // Extensions directories. - sprintf(buf, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home()); + os::snprintf_checked(buf, bufsize, "%s" EXTENSIONS_DIR ":" SYS_EXT_DIR EXTENSIONS_DIR, Arguments::get_java_home()); Arguments::set_ext_dirs(buf); FREE_C_HEAP_ARRAY(char, buf); @@ -401,7 +400,7 @@ void os::init_system_properties_values() { size_t system_ext_size = strlen(user_home_dir) + sizeof(SYS_EXTENSIONS_DIR) + sizeof(SYS_EXTENSIONS_DIRS); - // Buffer that fits several sprintfs. + // Buffer that fits several snprintfs. // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator. const size_t bufsize = @@ -471,11 +470,9 @@ void os::init_system_properties_values() { // could cause a change in behavior, but Apple's Java6 behavior // can be achieved by putting "." at the beginning of the // JAVA_LIBRARY_PATH environment variable. - char *ld_library_path = NEW_C_HEAP_ARRAY(char, - strlen(v) + 1 + strlen(l) + 1 + - system_ext_size + 3, - mtInternal); - sprintf(ld_library_path, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.", + const size_t ld_library_path_size = strlen(v) + 1 + strlen(l) + 1 + system_ext_size + 3; + char *ld_library_path = NEW_C_HEAP_ARRAY(char, ld_library_path_size, mtInternal); + os::snprintf_checked(ld_library_path, ld_library_path_size, "%s%s%s%s%s" SYS_EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS ":.", v, v_colon, l, l_colon, user_home_dir); Arguments::set_library_path(ld_library_path); FREE_C_HEAP_ARRAY(char, ld_library_path); @@ -486,7 +483,7 @@ void os::init_system_properties_values() { // Note that the space for the colon and the trailing null are provided // by the nulls included by the sizeof operator (so actually one byte more // than necessary is allocated). - sprintf(buf, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, + os::snprintf_checked(buf, bufsize, "%s" SYS_EXTENSIONS_DIR ":%s" EXTENSIONS_DIR ":" SYS_EXTENSIONS_DIRS, user_home_dir, Arguments::get_java_home()); Arguments::set_ext_dirs(buf); diff --git a/src/hotspot/share/adlc/adlc.hpp b/src/hotspot/share/adlc/adlc.hpp index 555029fdbb6..8812066bafa 100644 --- a/src/hotspot/share/adlc/adlc.hpp +++ b/src/hotspot/share/adlc/adlc.hpp @@ -100,4 +100,8 @@ typedef unsigned int uintptr_t; // it everywhere it needs to be available. extern ArchDesc* globalAD; +// Performs snprintf and asserts the result is non-negative (so there was not +// an encoding error) and that the output was not truncated. +extern int snprintf_checked(char* buf, size_t len, const char* fmt, ...); + #endif // SHARE_ADLC_ADLC_HPP diff --git a/src/hotspot/share/adlc/adlparse.cpp b/src/hotspot/share/adlc/adlparse.cpp index adf5b731589..8190f82a050 100644 --- a/src/hotspot/share/adlc/adlparse.cpp +++ b/src/hotspot/share/adlc/adlparse.cpp @@ -211,8 +211,9 @@ void ADLParser::instr_parse(void) { return; } assert(match_rules_cnt < 100," too many match rule clones"); - char* buf = (char*) AdlAllocateHeap(strlen(instr->_ident) + 4); - sprintf(buf, "%s_%d", instr->_ident, match_rules_cnt++); + const size_t buf_size = strlen(instr->_ident) + 4; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "%s_%d", instr->_ident, match_rules_cnt++); rule->_result = buf; // Check for commutative operations with tree operands. matchrule_clone_and_swap(rule, instr->_ident, match_rules_cnt); @@ -2876,8 +2877,9 @@ void ADLParser::ins_encode_parse_block(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__ins_encode_"; - char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); - sprintf(ec_name, "%s%s", prefix, inst._ident); + const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1; + char* ec_name = (char*) AdlAllocateHeap(ec_name_size); + snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass* encoding = _AD._encode->add_EncClass(ec_name); @@ -3347,8 +3349,9 @@ void ADLParser::constant_parse(InstructForm& inst) { // Create a new encoding name based on the name of the instruction // definition, which should be unique. const char* prefix = "__constant_"; - char* ec_name = (char*) AdlAllocateHeap(strlen(inst._ident) + strlen(prefix) + 1); - sprintf(ec_name, "%s%s", prefix, inst._ident); + const size_t ec_name_size = strlen(inst._ident) + strlen(prefix) + 1; + char* ec_name = (char*) AdlAllocateHeap(ec_name_size); + snprintf_checked(ec_name, ec_name_size, "%s%s", prefix, inst._ident); assert(_AD._encode->encClass(ec_name) == NULL, "shouldn't already exist"); EncClass* encoding = _AD._encode->add_EncClass(ec_name); @@ -4667,8 +4670,9 @@ char *ADLParser::get_ident_or_literal_constant(const char* description) { // Grab a constant expression. param = get_paren_expr(description); if (param[0] != '(') { - char* buf = (char*) AdlAllocateHeap(strlen(param) + 3); - sprintf(buf, "(%s)", param); + const size_t buf_size = strlen(param) + 3; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "(%s)", param); param = buf; } assert(is_literal_constant(param), @@ -5275,8 +5279,9 @@ void ADLParser::next_line() { char* ADLParser::get_line_string(int linenum) { const char* file = _AD._ADL_file._name; int line = linenum ? linenum : this->linenum(); - char* location = (char *)AdlAllocateHeap(strlen(file) + 100); - sprintf(location, "\n#line %d \"%s\"\n", line, file); + const size_t location_size = strlen(file) + 100; + char* location = (char *)AdlAllocateHeap(location_size); + snprintf_checked(location, location_size, "\n#line %d \"%s\"\n", line, file); return location; } diff --git a/src/hotspot/share/adlc/archDesc.cpp b/src/hotspot/share/adlc/archDesc.cpp index a437dd29c75..890b266d58d 100644 --- a/src/hotspot/share/adlc/archDesc.cpp +++ b/src/hotspot/share/adlc/archDesc.cpp @@ -815,7 +815,7 @@ static const char *getRegMask(const char *reg_class_name) { const char *mask = "_mask"; int length = (int)strlen(rc_name) + (int)strlen(mask) + 5; char *regMask = new char[length]; - sprintf(regMask,"%s%s()", rc_name, mask); + snprintf_checked(regMask, length, "%s%s()", rc_name, mask); delete[] rc_name; return regMask; } @@ -908,7 +908,7 @@ char *ArchDesc::stack_or_reg_mask(OperandForm &opForm) { const char *stack_or = "STACK_OR_"; int length = (int)strlen(stack_or) + (int)strlen(reg_mask_name) + 1; char *result = new char[length]; - sprintf(result,"%s%s", stack_or, reg_mask_name); + snprintf_checked(result, length, "%s%s", stack_or, reg_mask_name); return result; } diff --git a/src/hotspot/share/adlc/dfa.cpp b/src/hotspot/share/adlc/dfa.cpp index 36cba614878..e3a92ec1e5b 100644 --- a/src/hotspot/share/adlc/dfa.cpp +++ b/src/hotspot/share/adlc/dfa.cpp @@ -212,13 +212,13 @@ Expr *ArchDesc::calc_cost(FILE *fp, const char *spaces, MatchList &mList, Produc Expr *c = new Expr("0"); if (mList._lchild) { // If left child, add it in const char* lchild_to_upper = ArchDesc::getMachOperEnum(mList._lchild); - sprintf(Expr::buffer(), "_kids[0]->_cost[%s]", lchild_to_upper); + snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[0]->_cost[%s]", lchild_to_upper); c->add(Expr::buffer()); delete[] lchild_to_upper; } if (mList._rchild) { // If right child, add it in const char* rchild_to_upper = ArchDesc::getMachOperEnum(mList._rchild); - sprintf(Expr::buffer(), "_kids[1]->_cost[%s]", rchild_to_upper); + snprintf_checked(Expr::buffer(), STRING_BUFFER_LENGTH, "_kids[1]->_cost[%s]", rchild_to_upper); c->add(Expr::buffer()); delete[] rchild_to_upper; } @@ -757,7 +757,7 @@ const char *Expr::compute_expr(const Expr *c1, const Expr *c2) { snprintf(string_buffer, STRING_BUFFER_LENGTH, "%s", c2->_expr); } else { - sprintf( string_buffer, "0"); + snprintf_checked(string_buffer, STRING_BUFFER_LENGTH, "0"); } string_buffer[STRING_BUFFER_LENGTH - 1] = '\0'; char *cost = strdup(string_buffer); diff --git a/src/hotspot/share/adlc/formssel.cpp b/src/hotspot/share/adlc/formssel.cpp index 21a01306333..d6d13478339 100644 --- a/src/hotspot/share/adlc/formssel.cpp +++ b/src/hotspot/share/adlc/formssel.cpp @@ -25,6 +25,8 @@ // FORMS.CPP - Definitions for ADL Parser Forms Classes #include "adlc.hpp" +#define remaining_buflen(buffer, position) (sizeof(buffer) - ((position) - (buffer))) + //==============================Instructions=================================== //------------------------------InstructForm----------------------------------- InstructForm::InstructForm(const char *id, bool ideal_only) @@ -1533,7 +1535,7 @@ Predicate *InstructForm::build_predicate() { s += strlen(s); } // Add predicate to working buffer - sprintf(s,"/*%s*/(",(char*)i._key); + snprintf_checked(s, remaining_buflen(buf, s), "/*%s*/(",(char*)i._key); s += strlen(s); mnode->build_instr_pred(s,(char*)i._key, 0, path_bitmask, 0); s += strlen(s); @@ -3472,7 +3474,7 @@ void MatchNode::build_internalop( ) { _rChild->_internalop : _rChild->_opType) : ""; len += (int)strlen(lstr) + (int)strlen(rstr); subtree = (char *)AdlAllocateHeap(len); - sprintf(subtree,"_%s_%s_%s", _opType, lstr, rstr); + snprintf_checked(subtree, len, "_%s_%s_%s", _opType, lstr, rstr); // Hash the subtree string in _internalOps; if a name exists, use it iop = (char *)_AD._internalOps[subtree]; // Else create a unique name, and add it to the hash table @@ -3919,8 +3921,9 @@ void MatchRule::matchrule_swap_commutative_op(const char* instr_ident, int count MatchRule* clone = new MatchRule(_AD, this); // Swap operands of commutative operation ((MatchNode*)clone)->swap_commutative_op(true, count); - char* buf = (char*) AdlAllocateHeap(strlen(instr_ident) + 4); - sprintf(buf, "%s_%d", instr_ident, match_rules_cnt++); + const size_t buf_size = strlen(instr_ident) + 4; + char* buf = (char*) AdlAllocateHeap(buf_size); + snprintf_checked(buf, buf_size, "%s_%d", instr_ident, match_rules_cnt++); clone->_result = buf; clone->_next = this->_next; diff --git a/src/hotspot/share/adlc/main.cpp b/src/hotspot/share/adlc/main.cpp index 5016c540f11..dce3f2309f8 100644 --- a/src/hotspot/share/adlc/main.cpp +++ b/src/hotspot/share/adlc/main.cpp @@ -466,7 +466,7 @@ static char *base_plus_suffix(const char* base, const char *suffix) int len = (int)strlen(base) + (int)strlen(suffix) + 1; char* fname = new char[len]; - sprintf(fname,"%s%s",base,suffix); + snprintf_checked(fname,len,"%s%s",base,suffix); return fname; } diff --git a/src/hotspot/share/adlc/output_c.cpp b/src/hotspot/share/adlc/output_c.cpp index 264012b8f15..93b32b73cbd 100644 --- a/src/hotspot/share/adlc/output_c.cpp +++ b/src/hotspot/share/adlc/output_c.cpp @@ -26,6 +26,8 @@ #include "adlc.hpp" +#define remaining_buflen(buffer, position) (sizeof(buffer) - (position - buffer)) + // Utilities to characterize effect statements static bool is_def(int usedef) { switch(usedef) { @@ -35,6 +37,16 @@ static bool is_def(int usedef) { return false; } +int snprintf_checked(char* buf, size_t len, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + int result = vsnprintf(buf, len, fmt, args); + va_end(args); + assert(result >= 0, "snprintf error"); + assert(static_cast(result) < len, "snprintf truncated"); + return result; +} + // Define an array containing the machine register names, strings. static void defineRegNames(FILE *fp, RegisterForm *registers) { if (registers) { @@ -197,7 +209,8 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi return -1; } - char *operand_stages = new char [templen]; + const size_t operand_stages_size = templen; + char *operand_stages = new char [operand_stages_size]; operand_stages[0] = 0; int i = 0; templen = 0; @@ -211,7 +224,7 @@ static int pipeline_reads_initializer(FILE *fp_cpp, NameList &pipeline_reads, Pi while ( (paramname = pipeclass->_parameters.iter()) != NULL ) { const PipeClassOperandForm *tmppipeopnd = (const PipeClassOperandForm *)pipeclass->_localUsage[paramname]; - templen += sprintf(&operand_stages[templen], " stage_%s%c\n", + templen += snprintf_checked(&operand_stages[templen], operand_stages_size - templen, " stage_%s%c\n", tmppipeopnd ? tmppipeopnd->_stage : "undefined", (++i < paramcount ? ',' : ' ') ); } @@ -278,6 +291,7 @@ static int pipeline_res_stages_initializer( int templen = 1 + commentlen + pipeline->_rescount * (max_stage + 14); // Allocate space for the resource list + const size_t resource_stages_size = templen; char * resource_stages = new char [templen]; templen = 0; @@ -285,7 +299,7 @@ static int pipeline_res_stages_initializer( const char * const resname = res_stages[i] == 0 ? "undefined" : pipeline->_stages.name(res_stages[i]-1); - templen += sprintf(&resource_stages[templen], " stage_%s%-*s // %s\n", + templen += snprintf_checked(&resource_stages[templen], resource_stages_size - templen, " stage_%s%-*s // %s\n", resname, max_stage - (int)strlen(resname) + 1, (i < pipeline->_rescount-1) ? "," : "", pipeline->_reslist.name(i)); @@ -344,7 +358,7 @@ static int pipeline_res_cycles_initializer( for (i = 0; i < pipeline->_rescount; i++) { if (max_cycles < res_cycles[i]) max_cycles = res_cycles[i]; - templen = sprintf(temp, "%d", res_cycles[i]); + templen = snprintf_checked(temp, sizeof(temp), "%d", res_cycles[i]); if (cyclelen < templen) cyclelen = templen; commentlen += (int)strlen(pipeline->_reslist.name(i)); @@ -353,12 +367,13 @@ static int pipeline_res_cycles_initializer( templen = 1 + commentlen + (cyclelen + 8) * pipeline->_rescount; // Allocate space for the resource list - char * resource_cycles = new char [templen]; + const size_t resource_cycles_size = templen; + char * resource_cycles = new char [resource_cycles_size]; templen = 0; for (i = 0; i < pipeline->_rescount; i++) { - templen += sprintf(&resource_cycles[templen], " %*d%c // %s\n", + templen += snprintf_checked(&resource_cycles[templen], resource_cycles_size - templen, " %*d%c // %s\n", cyclelen, res_cycles[i], (i < pipeline->_rescount-1) ? ',' : ' ', pipeline->_reslist.name(i)); } @@ -431,7 +446,8 @@ static int pipeline_res_mask_initializer( (cyclemasksize * 12) + masklen + (cycledigit * 2) + 30) * element_count; // Allocate space for the resource list - char * resource_mask = new char [templen]; + const size_t resource_mask_size = templen; + char * resource_mask = new char [resource_mask_size]; char * last_comma = NULL; templen = 0; @@ -456,7 +472,7 @@ static int pipeline_res_mask_initializer( } int formatlen = - sprintf(&resource_mask[templen], " %s(0x%0*x, %*d, %*d, %s %s(", + snprintf_checked(&resource_mask[templen], resource_mask_size - templen, " %s(0x%0*x, %*d, %*d, %s %s(", pipeline_use_element, masklen, used_mask, cycledigit, lb, cycledigit, ub, @@ -496,7 +512,7 @@ static int pipeline_res_mask_initializer( for (j = cyclemasksize-1; j >= 0; j--) { formatlen = - sprintf(&resource_mask[templen], "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); + snprintf_checked(&resource_mask[templen], resource_mask_size - templen, "0x%08x%s", res_mask[j], j > 0 ? ", " : ""); templen += formatlen; } @@ -527,9 +543,8 @@ static int pipeline_res_mask_initializer( // "0x012345678, 0x012345678, 4294967295" char* args = new char [36 + 1]; - int printed = sprintf(args, "0x%x, 0x%x, %u", - resources_used, resources_used_exclusively, element_count); - assert(printed <= 36, "overflow"); + snprintf_checked(args, 36 + 1, "0x%x, 0x%x, %u", + resources_used, resources_used_exclusively, element_count); pipeline_res_args.addName(args); } @@ -1066,9 +1081,9 @@ static void build_instruction_index_mapping( FILE *fp, FormDict &globals, PeepMa InstructForm *inst = globals[inst_name]->is_instruction(); if( inst != NULL ) { char inst_prefix[] = "instXXXX_"; - sprintf(inst_prefix, "inst%d_", inst_position); + snprintf_checked(inst_prefix, sizeof(inst_prefix), "inst%d_", inst_position); char receiver[] = "instXXXX->"; - sprintf(receiver, "inst%d->", inst_position); + snprintf_checked(receiver, sizeof(receiver), "inst%d->", inst_position); inst->index_temps( fp, globals, inst_prefix, receiver ); } } @@ -1162,7 +1177,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch char left_reg_index[] = ",inst4294967295_idx4294967295"; if( left_op_index != 0 ) { // Must have index into operands - sprintf(left_reg_index,",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index); + snprintf_checked(left_reg_index, sizeof(left_reg_index), ",inst%u_idx%u", (unsigned)left_index, (unsigned)left_op_index); } else { strcpy(left_reg_index, ""); } @@ -1174,7 +1189,7 @@ static void check_peepconstraints(FILE *fp, FormDict &globals, PeepMatch *pmatch char right_reg_index[] = ",inst4294967295_idx4294967295"; if( right_op_index != 0 ) { // Must have index into operands - sprintf(right_reg_index,",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index); + snprintf_checked(right_reg_index, sizeof(right_reg_index), ",inst%u_idx%u", (unsigned)right_index, (unsigned)right_op_index); } else { strcpy(right_reg_index, ""); } @@ -2563,19 +2578,19 @@ void ArchDesc::define_postalloc_expand(FILE *fp, InstructForm &inst) { const char* arg_name = ins_encode->rep_var_name(inst, param_no); int idx = inst.operand_position_format(arg_name); if (strcmp(arg_name, "constanttablebase") == 0) { - ib += sprintf(ib, " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", + ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = mach_constant_base_node_input(); \t// %s, \t%s\n", name, type, arg_name); - nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); + nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name); // There is no operand for the constanttablebase. } else if (inst.is_noninput_operand(idx)) { globalAD->syntax_err(inst._linenum, "In %s: you can not pass the non-input %s to a postalloc expand encoding.\n", inst._ident, arg_name); } else { - ib += sprintf(ib, " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", + ib += snprintf_checked(ib, remaining_buflen(idxbuf, ib), " unsigned idx_%-5s = idx%d; \t// %s, \t%s\n", name, idx, type, arg_name); - nb += sprintf(nb, " Node *n_%-7s = lookup(idx_%s);\n", name, name); - ob += sprintf(ob, " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); + nb += snprintf_checked(nb, remaining_buflen(nbuf, nb), " Node *n_%-7s = lookup(idx_%s);\n", name, name); + ob += snprintf_checked(ob, remaining_buflen(opbuf, ob), " %sOper *op_%s = (%sOper *)opnd_array(%d);\n", type, name, type, idx); } param_no++; } diff --git a/src/hotspot/share/c1/c1_Runtime1.cpp b/src/hotspot/share/c1/c1_Runtime1.cpp index 9e02d9f323d..4efb95fff80 100644 --- a/src/hotspot/share/c1/c1_Runtime1.cpp +++ b/src/hotspot/share/c1/c1_Runtime1.cpp @@ -688,7 +688,7 @@ JRT_ENTRY(void, Runtime1::throw_range_check_exception(JavaThread* current, int i const int len = 35; assert(len < strlen("Index %d out of bounds for length %d"), "Must allocate more space for message."); char message[2 * jintAsStringSize + len]; - sprintf(message, "Index %d out of bounds for length %d", index, a->length()); + os::snprintf_checked(message, sizeof(message), "Index %d out of bounds for length %d", index, a->length()); SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_ArrayIndexOutOfBoundsException(), message); JRT_END @@ -700,7 +700,7 @@ JRT_ENTRY(void, Runtime1::throw_index_exception(JavaThread* current, int index)) } #endif char message[16]; - sprintf(message, "%d", index); + os::snprintf_checked(message, sizeof(message), "%d", index); SharedRuntime::throw_and_post_jvmti_exception(current, vmSymbols::java_lang_IndexOutOfBoundsException(), message); JRT_END diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index e08917aa30b..72a7bb021c3 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -169,7 +169,7 @@ template static void get_header_version(char (&header_version) [N]) { strncpy(header_version, vm_version, JVM_IDENT_MAX-9); // Append the hash code as eight hex digits. - sprintf(&header_version[JVM_IDENT_MAX-9], "%08x", hash); + os::snprintf_checked(&header_version[JVM_IDENT_MAX-9], 9, "%08x", hash); header_version[JVM_IDENT_MAX-1] = 0; // Null terminate. } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index c133a8346eb..0d2092a893a 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -2492,17 +2492,18 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } // Allocate temporary buffer with extra space for formatting and line number - char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64); + const size_t buf_size = buf_len + 64; + char* buf = NEW_RESOURCE_ARRAY(char, buf_size); // Print stack trace line in buffer - sprintf(buf, "\tat %s.%s(", klass_name, method_name); + size_t buf_off = os::snprintf_checked(buf, buf_size, "\tat %s.%s(", klass_name, method_name); // Print module information if (module_name != NULL) { if (module_version != NULL) { - sprintf(buf + (int)strlen(buf), "%s@%s/", module_name, module_version); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s@%s/", module_name, module_version); } else { - sprintf(buf + (int)strlen(buf), "%s/", module_name); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s/", module_name); } } @@ -2517,17 +2518,17 @@ static void print_stack_element_to_stream(outputStream* st, Handle mirror, int m } else { if (source_file_name != NULL && (line_number != -1)) { // Sourcename and linenumber - sprintf(buf + (int)strlen(buf), "%s:%d)", source_file_name, line_number); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s:%d)", source_file_name, line_number); } else if (source_file_name != NULL) { // Just sourcename - sprintf(buf + (int)strlen(buf), "%s)", source_file_name); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "%s)", source_file_name); } else { // Neither sourcename nor linenumber - sprintf(buf + (int)strlen(buf), "Unknown Source)"); + buf_off += os::snprintf_checked(buf + buf_off, buf_size - buf_off, "Unknown Source)"); } CompiledMethod* nm = method->code(); if (WizardMode && nm != NULL) { - sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); + os::snprintf_checked(buf + buf_off, buf_size - buf_off, "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm); } } } diff --git a/src/hotspot/share/code/dependencies.cpp b/src/hotspot/share/code/dependencies.cpp index 19d51ba111e..6909aa6b2d0 100644 --- a/src/hotspot/share/code/dependencies.cpp +++ b/src/hotspot/share/code/dependencies.cpp @@ -777,7 +777,8 @@ void Dependencies::write_dependency_to(xmlStream* xtty, xtty->object("x", arg.metadata_value()); } } else { - char xn[12]; sprintf(xn, "x%d", j); + char xn[12]; + os::snprintf_checked(xn, sizeof(xn), "x%d", j); if (arg.is_oop()) { xtty->object(xn, Handle(thread, arg.oop_value())); } else { diff --git a/src/hotspot/share/compiler/compileBroker.cpp b/src/hotspot/share/compiler/compileBroker.cpp index 0f6cde1c0f4..2231b949c68 100644 --- a/src/hotspot/share/compiler/compileBroker.cpp +++ b/src/hotspot/share/compiler/compileBroker.cpp @@ -932,7 +932,7 @@ void CompileBroker::init_compiler_threads() { // for JVMCI compiler which can create further ones on demand. JVMCI_ONLY(if (!UseJVMCICompiler || !UseDynamicNumberOfCompilerThreads || i == 0) {) // Create a name for our thread. - sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i); Handle thread_oop = create_thread_oop(name_buffer, CHECK); thread_handle = JNIHandles::make_global(thread_oop); JVMCI_ONLY(}) @@ -954,7 +954,7 @@ void CompileBroker::init_compiler_threads() { for (int i = 0; i < _c1_count; i++) { // Create a name for our thread. - sprintf(name_buffer, "C1 CompilerThread%d", i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "C1 CompilerThread%d", i); Handle thread_oop = create_thread_oop(name_buffer, CHECK); jobject thread_handle = JNIHandles::make_global(thread_oop); _compiler1_objects[i] = thread_handle; @@ -1018,7 +1018,7 @@ void CompileBroker::possibly_add_compiler_threads(JavaThread* THREAD) { // transitions if we bind them to new JavaThreads. if (!THREAD->can_call_java()) break; char name_buffer[256]; - sprintf(name_buffer, "%s CompilerThread%d", _compilers[1]->name(), i); + os::snprintf_checked(name_buffer, sizeof(name_buffer), "%s CompilerThread%d", _compilers[1]->name(), i); Handle thread_oop; { // We have to give up the lock temporarily for the Java calls. @@ -2600,7 +2600,7 @@ void CompileBroker::print_times(bool per_compiler, bool aggregate) { char tier_name[256]; for (int tier = CompLevel_simple; tier <= CompilationPolicy::highest_compile_level(); tier++) { CompilerStatistics* stats = &_stats_per_level[tier-1]; - sprintf(tier_name, "Tier%d", tier); + os::snprintf_checked(tier_name, sizeof(tier_name), "Tier%d", tier); print_times(tier_name, stats); } } diff --git a/src/hotspot/share/interpreter/bootstrapInfo.cpp b/src/hotspot/share/interpreter/bootstrapInfo.cpp index 24e9afff78b..e37363aeb44 100644 --- a/src/hotspot/share/interpreter/bootstrapInfo.cpp +++ b/src/hotspot/share/interpreter/bootstrapInfo.cpp @@ -230,9 +230,9 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { st = st ? st : tty; if (_indy_index != -1) - sprintf(what, "indy#%d", decode_indy_index()); + os::snprintf_checked(what, sizeof(what), "indy#%d", decode_indy_index()); else - sprintf(what, "condy"); + os::snprintf_checked(what, sizeof(what), "condy"); bool have_msg = (msg != NULL && strlen(msg) > 0); st->print_cr("%s%sBootstrap in %s %s@CP[%d] %s:%s%s BSMS[%d] BSM@CP[%d]%s argc=%d%s", (have_msg ? msg : ""), (have_msg ? " " : ""), @@ -251,11 +251,11 @@ void BootstrapInfo::print_msg_on(outputStream* st, const char* msg) { for (int i = 0; i < _argc; i++) { int pos = (int) strlen(argbuf); if (pos + 20 > (int)sizeof(argbuf)) { - sprintf(argbuf + pos, "..."); + os::snprintf_checked(argbuf + pos, sizeof(argbuf) - pos, "..."); break; } if (i > 0) argbuf[pos++] = ','; - sprintf(argbuf+pos, "%d", arg_index(i)); + os::snprintf_checked(argbuf+pos, sizeof(argbuf) - pos, "%d", arg_index(i)); } st->print_cr(" argument indexes: {%s}", argbuf); } diff --git a/src/hotspot/share/jfr/support/jfrSymbolTable.cpp b/src/hotspot/share/jfr/support/jfrSymbolTable.cpp index 786fff37efd..5a580c0c3d3 100644 --- a/src/hotspot/share/jfr/support/jfrSymbolTable.cpp +++ b/src/hotspot/share/jfr/support/jfrSymbolTable.cpp @@ -259,7 +259,7 @@ static const char* create_hidden_klass_symbol(const InstanceKlass* ik, uintptr_t const oop mirror = ik->java_mirror_no_keepalive(); assert(mirror != NULL, "invariant"); char hash_buf[40]; - sprintf(hash_buf, "/" UINTX_FORMAT, hash); + os::snprintf_checked(hash_buf, sizeof(hash_buf), "/" UINTX_FORMAT, hash); const size_t hash_len = strlen(hash_buf); const size_t result_len = ik->name()->utf8_length(); hidden_symbol = NEW_RESOURCE_ARRAY(char, result_len + hash_len + 1); diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp index 61e7e8ed162..bcdbf37b5ec 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp @@ -308,9 +308,9 @@ jobjectArray readConfiguration0(JNIEnv *env, JVMCI_TRAPS) { JVMCIObjectArray vmFields = JVMCIENV->new_VMField_array(len, JVMCI_CHECK_NULL); for (int i = 0; i < len ; i++) { VMStructEntry vmField = JVMCIVMStructs::localHotSpotVMStructs[i]; - size_t name_buf_len = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 /* "::" */; - char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_len + 1); - sprintf(name_buf, "%s::%s", vmField.typeName, vmField.fieldName); + const size_t name_buf_size = strlen(vmField.typeName) + strlen(vmField.fieldName) + 2 + 1 /* "::" */; + char* name_buf = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, name_buf_size); + os::snprintf_checked(name_buf, name_buf_size, "%s::%s", vmField.typeName, vmField.fieldName); CSTRING_TO_JSTRING(name, name_buf); CSTRING_TO_JSTRING(type, vmField.typeString); JVMCIObject box; diff --git a/src/hotspot/share/prims/wbtestmethods/parserTests.cpp b/src/hotspot/share/prims/wbtestmethods/parserTests.cpp index cd5fee31dbf..b778b7cb4b8 100644 --- a/src/hotspot/share/prims/wbtestmethods/parserTests.cpp +++ b/src/hotspot/share/prims/wbtestmethods/parserTests.cpp @@ -174,7 +174,7 @@ WB_ENTRY(jobjectArray, WB_ParseCommandLine(JNIEnv* env, jobject o, jstring j_cmd if (arg) { arg->value_as_str(buf, sizeof(buf)); } else { - sprintf(buf, ""); + os::snprintf_checked(buf, sizeof(buf), ""); } oop parsedValue = java_lang_String::create_oop_from_str(buf, CHECK_NULL); returnvalue_array_ah->obj_at_put(i*2+1, parsedValue); diff --git a/src/hotspot/share/runtime/deoptimization.cpp b/src/hotspot/share/runtime/deoptimization.cpp index 61ad39dba3a..5de15069689 100644 --- a/src/hotspot/share/runtime/deoptimization.cpp +++ b/src/hotspot/share/runtime/deoptimization.cpp @@ -2580,7 +2580,7 @@ const char* Deoptimization::trap_reason_name(int reason) { if ((uint)reason < Reason_LIMIT) return _trap_reason_name[reason]; static char buf[20]; - sprintf(buf, "reason%d", reason); + os::snprintf_checked(buf, sizeof(buf), "reason%d", reason); return buf; } const char* Deoptimization::trap_action_name(int action) { @@ -2590,7 +2590,7 @@ const char* Deoptimization::trap_action_name(int action) { if ((uint)action < Action_LIMIT) return _trap_action_name[action]; static char buf[20]; - sprintf(buf, "action%d", action); + os::snprintf_checked(buf, sizeof(buf), "action%d", action); return buf; } @@ -2713,7 +2713,7 @@ void Deoptimization::print_statistics() { Bytecodes::Code bc = (Bytecodes::Code)(counter & LSB_MASK); if (bc_case == BC_CASE_LIMIT && (int)bc == 0) bc = Bytecodes::_illegal; - sprintf(name, "%s/%s/%s", + os::snprintf_checked(name, sizeof(name), "%s/%s/%s", trap_reason_name(reason), trap_action_name(action), Bytecodes::is_defined(bc)? Bytecodes::name(bc): "other"); diff --git a/src/hotspot/share/runtime/os.cpp b/src/hotspot/share/runtime/os.cpp index 26cd072e0f7..8968adeab9a 100644 --- a/src/hotspot/share/runtime/os.cpp +++ b/src/hotspot/share/runtime/os.cpp @@ -99,6 +99,16 @@ int os::snprintf(char* buf, size_t len, const char* fmt, ...) { return result; } +int os::snprintf_checked(char* buf, size_t len, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + int result = os::vsnprintf(buf, len, fmt, args); + va_end(args); + assert(result >= 0, "os::snprintf error"); + assert(static_cast(result) < len, "os::snprintf truncated"); + return result; +} + // Fill in buffer with current local time as an ISO-8601 string. // E.g., YYYY-MM-DDThh:mm:ss.mmm+zzzz. // Returns buffer, or NULL if it failed. @@ -1314,7 +1324,7 @@ char* os::format_boot_path(const char* format_string, FILE* os::fopen(const char* path, const char* mode) { char modified_mode[20]; assert(strlen(mode) + 1 < sizeof(modified_mode), "mode chars plus one extra must fit in buffer"); - sprintf(modified_mode, "%s" LINUX_ONLY("e") BSD_ONLY("e") WINDOWS_ONLY("N"), mode); + os::snprintf_checked(modified_mode, sizeof(modified_mode), "%s" LINUX_ONLY("e") BSD_ONLY("e") WINDOWS_ONLY("N"), mode); FILE* file = ::fopen(path, modified_mode); #if !(defined LINUX || defined BSD || defined _WINDOWS) diff --git a/src/hotspot/share/runtime/os.hpp b/src/hotspot/share/runtime/os.hpp index 7ccc9cf4c58..5459ff3b233 100644 --- a/src/hotspot/share/runtime/os.hpp +++ b/src/hotspot/share/runtime/os.hpp @@ -747,6 +747,10 @@ class os: AllStatic { static int vsnprintf(char* buf, size_t len, const char* fmt, va_list args) ATTRIBUTE_PRINTF(3, 0); static int snprintf(char* buf, size_t len, const char* fmt, ...) ATTRIBUTE_PRINTF(3, 4); + // Performs snprintf and asserts the result is non-negative (so there was not + // an encoding error) and that the output was not truncated. + static int snprintf_checked(char* buf, size_t len, const char* fmt, ...) ATTRIBUTE_PRINTF(3, 4); + // Get host name in buffer provided static bool get_host_name(char* buf, size_t buflen); diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index bc919d32e14..db6a4188996 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -84,7 +84,8 @@ PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v) const char* prefix = PerfDataManager::ns_to_string(ns); - _name = NEW_C_HEAP_ARRAY(char, strlen(name) + strlen(prefix) + 2, mtInternal); + const size_t _name_size = strlen(name) + strlen(prefix) + 2; + _name = NEW_C_HEAP_ARRAY(char, _name_size, mtInternal); assert(strlen(name) != 0, "invalid name"); if (ns == NULL_NS) { @@ -100,7 +101,7 @@ PerfData::PerfData(CounterNS ns, const char* name, Units u, Variability v) } } else { - sprintf(_name, "%s.%s", prefix, name); + os::snprintf_checked(_name, _name_size, "%s.%s", prefix, name); // set the F_Supported flag based on the given namespace. if (PerfDataManager::is_stable_supported(ns) || PerfDataManager::is_unstable_supported(ns)) { @@ -334,7 +335,7 @@ char* PerfDataManager::counter_name(const char* ns, const char* name) { size_t len = strlen(ns) + strlen(name) + 2; char* result = NEW_RESOURCE_ARRAY(char, len); - sprintf(result, "%s.%s", ns, name); + os::snprintf_checked(result, len, "%s.%s", ns, name); return result; } diff --git a/src/hotspot/share/utilities/debug.cpp b/src/hotspot/share/utilities/debug.cpp index 3fc8cb9acbc..696b1781311 100644 --- a/src/hotspot/share/utilities/debug.cpp +++ b/src/hotspot/share/utilities/debug.cpp @@ -446,7 +446,7 @@ extern "C" JNIEXPORT void disnm(intptr_t p) { extern "C" JNIEXPORT void printnm(intptr_t p) { char buffer[256]; - sprintf(buffer, "printnm: " INTPTR_FORMAT, p); + os::snprintf_checked(buffer, sizeof(buffer), "printnm: " INTPTR_FORMAT, p); Command c(buffer); CodeBlob* cb = CodeCache::find_blob((address) p); if (cb->is_nmethod()) { diff --git a/src/hotspot/share/utilities/utf8.cpp b/src/hotspot/share/utilities/utf8.cpp index 81ad02a9ba6..556e95fc662 100644 --- a/src/hotspot/share/utilities/utf8.cpp +++ b/src/hotspot/share/utilities/utf8.cpp @@ -27,7 +27,7 @@ #include "utilities/debug.hpp" #include "utilities/globalDefinitions.hpp" #include "utilities/utf8.hpp" - +#include "runtime/os.hpp" // Assume the utf8 string is in legal form and has been // checked in the class file parser/format checker. @@ -224,7 +224,7 @@ void UTF8::as_quoted_ascii(const char* utf8_str, int utf8_length, char* buf, int *p++ = (char)c; } else { if (p + 6 >= end) break; // string is truncated - sprintf(p, "\\u%04x", c); + os::snprintf_checked(p, 7, "\\u%04x", c); // counting terminating zero in p += 6; } } @@ -518,7 +518,7 @@ void UNICODE::as_quoted_ascii(const T* base, int length, char* buf, int buflen) *p++ = (char)c; } else { if (p + 6 >= end) break; // string is truncated - sprintf(p, "\\u%04x", c); + os::snprintf_checked(p, 7, "\\u%04x", c); p += 6; } } diff --git a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp index ed2de311c22..5f868f6e408 100644 --- a/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp +++ b/src/java.desktop/macosx/native/libjsound/PLATFORM_API_MacOSX_Ports.cpp @@ -635,7 +635,7 @@ void PORT_GetControls(void* id, INT32 portIndex, PortControlCreator* creator) { if (channelName == NULL) { return; } - sprintf(channelName, "Ch %d", ch); + snprintf(channelName, 16, "Ch %d", ch); } void* jControls[2]; From 8ea2a6777b68986df9d191f1bf983549d72cb3f8 Mon Sep 17 00:00:00 2001 From: Sangheon Kim Date: Fri, 9 Dec 2022 23:31:17 +0000 Subject: [PATCH 160/494] 8292265: Add old gen used field at G1HeapSummary JFR event Reviewed-by: tschatzl, ayang --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 9 +++++---- src/hotspot/share/gc/shared/gcHeapSummary.hpp | 8 +++++--- src/hotspot/share/gc/shared/gcTraceSend.cpp | 1 + src/hotspot/share/jfr/metadata/metadata.xml | 1 + 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index fa92c72ca46..0d651f7340e 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -2558,16 +2558,17 @@ bool G1CollectedHeap::print_location(outputStream* st, void* addr) const { G1HeapSummary G1CollectedHeap::create_g1_heap_summary() { - size_t eden_used_bytes = _eden.used_bytes(); - size_t survivor_used_bytes = _survivor.used_bytes(); + size_t eden_used_bytes = _monitoring_support->eden_space_used(); + size_t survivor_used_bytes = _monitoring_support->survivor_space_used(); + size_t old_gen_used_bytes = _monitoring_support->old_gen_used(); size_t heap_used = Heap_lock->owned_by_self() ? used() : used_unlocked(); size_t eden_capacity_bytes = (policy()->young_list_target_length() * HeapRegion::GrainBytes) - survivor_used_bytes; VirtualSpaceSummary heap_summary = create_heap_space_summary(); - return G1HeapSummary(heap_summary, heap_used, eden_used_bytes, - eden_capacity_bytes, survivor_used_bytes, num_regions()); + return G1HeapSummary(heap_summary, heap_used, eden_used_bytes, eden_capacity_bytes, + survivor_used_bytes, old_gen_used_bytes, num_regions()); } G1EvacSummary G1CollectedHeap::create_g1_evac_summary(G1EvacStats* stats) { diff --git a/src/hotspot/share/gc/shared/gcHeapSummary.hpp b/src/hotspot/share/gc/shared/gcHeapSummary.hpp index c0ed793fb67..6f72ec51b60 100644 --- a/src/hotspot/share/gc/shared/gcHeapSummary.hpp +++ b/src/hotspot/share/gc/shared/gcHeapSummary.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2022, 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,13 +117,15 @@ class G1HeapSummary : public GCHeapSummary { size_t _edenUsed; size_t _edenCapacity; size_t _survivorUsed; + size_t _oldGenUsed; uint _numberOfRegions; public: - G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, uint numberOfRegions) : - GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _numberOfRegions(numberOfRegions) { } + G1HeapSummary(VirtualSpaceSummary& heap_space, size_t heap_used, size_t edenUsed, size_t edenCapacity, size_t survivorUsed, size_t oldGenUsed, uint numberOfRegions) : + GCHeapSummary(heap_space, heap_used), _edenUsed(edenUsed), _edenCapacity(edenCapacity), _survivorUsed(survivorUsed), _oldGenUsed(oldGenUsed), _numberOfRegions(numberOfRegions) { } const size_t edenUsed() const { return _edenUsed; } const size_t edenCapacity() const { return _edenCapacity; } const size_t survivorUsed() const { return _survivorUsed; } + const size_t oldGenUsed() const { return _oldGenUsed; } const uint numberOfRegions() const { return _numberOfRegions; } virtual void accept(GCHeapSummaryVisitor* visitor) const { diff --git a/src/hotspot/share/gc/shared/gcTraceSend.cpp b/src/hotspot/share/gc/shared/gcTraceSend.cpp index 1cbf1f6fdb0..d7117ffbb40 100644 --- a/src/hotspot/share/gc/shared/gcTraceSend.cpp +++ b/src/hotspot/share/gc/shared/gcTraceSend.cpp @@ -244,6 +244,7 @@ class GCHeapSummaryEventSender : public GCHeapSummaryVisitor { e.set_edenUsedSize(g1_heap_summary->edenUsed()); e.set_edenTotalSize(g1_heap_summary->edenCapacity()); e.set_survivorUsedSize(g1_heap_summary->survivorUsed()); + e.set_oldGenUsedSize(g1_heap_summary->oldGenUsed()); e.set_numberOfRegions(g1_heap_summary->numberOfRegions()); e.commit(); } diff --git a/src/hotspot/share/jfr/metadata/metadata.xml b/src/hotspot/share/jfr/metadata/metadata.xml index 017c33a0857..841ddca0de9 100644 --- a/src/hotspot/share/jfr/metadata/metadata.xml +++ b/src/hotspot/share/jfr/metadata/metadata.xml @@ -329,6 +329,7 @@ + From a37de62d9ddadf1490ee59bd03224e8cea70a75b Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Sun, 11 Dec 2022 02:58:59 +0000 Subject: [PATCH 161/494] 8298126: Print statistics for objects in CDS archive heap Reviewed-by: ccheung --- src/hotspot/share/cds/heapShared.cpp | 55 ++++++++++++++++++++++++++++ src/hotspot/share/cds/heapShared.hpp | 9 +++++ 2 files changed, 64 insertions(+) diff --git a/src/hotspot/share/cds/heapShared.cpp b/src/hotspot/share/cds/heapShared.cpp index 6a37a50f127..9da6f85c766 100644 --- a/src/hotspot/share/cds/heapShared.cpp +++ b/src/hotspot/share/cds/heapShared.cpp @@ -84,6 +84,11 @@ bool HeapShared::_disable_writing = false; DumpedInternedStrings *HeapShared::_dumped_interned_strings = NULL; GrowableArrayCHeap* HeapShared::_native_pointers = NULL; +size_t HeapShared::_alloc_count[HeapShared::ALLOC_STAT_SLOTS]; +size_t HeapShared::_alloc_size[HeapShared::ALLOC_STAT_SLOTS]; +size_t HeapShared::_total_obj_count; +size_t HeapShared::_total_obj_size; + #ifndef PRODUCT #define ARCHIVE_TEST_FIELD_NAME "archivedObjects" static Array* _archived_ArchiveHeapTestClass = NULL; @@ -301,6 +306,7 @@ oop HeapShared::archive_object(oop obj) { oop archived_oop = cast_to_oop(G1CollectedHeap::heap()->archive_mem_allocate(len)); if (archived_oop != NULL) { + count_allocation(len); Copy::aligned_disjoint_words(cast_from_oop(obj), cast_from_oop(archived_oop), len); // Reinitialize markword to remove age/marking/locking/etc. // @@ -586,6 +592,7 @@ void HeapShared::copy_roots() { roots()->obj_at_put(i, _pending_roots->at(i)); } log_info(cds)("archived obj roots[%d] = " SIZE_FORMAT " words, klass = %p, obj = %p", length, size, k, mem); + count_allocation(roots()->size()); } // @@ -831,6 +838,9 @@ void HeapShared::write_subgraph_info_table() { _archived_ArchiveHeapTestClass = array; } #endif + if (log_is_enabled(Info, cds, heap)) { + print_stats(); + } } void HeapShared::serialize_root(SerializeClosure* soc) { @@ -1858,4 +1868,49 @@ ResourceBitMap HeapShared::calculate_ptrmap(MemRegion region) { } } +void HeapShared::count_allocation(size_t size) { + _total_obj_count ++; + _total_obj_size += size; + for (int i = 0; i < ALLOC_STAT_SLOTS; i++) { + if (size <= (size_t(1) << i)) { + _alloc_count[i] ++; + _alloc_size[i] += size; + return; + } + } +} + +static double avg_size(size_t size, size_t count) { + double avg = 0; + if (count > 0) { + avg = double(size * HeapWordSize) / double(count); + } + return avg; +} + +void HeapShared::print_stats() { + size_t huge_count = _total_obj_count; + size_t huge_size = _total_obj_size; + + for (int i = 0; i < ALLOC_STAT_SLOTS; i++) { + size_t byte_size_limit = (size_t(1) << i) * HeapWordSize; + size_t count = _alloc_count[i]; + size_t size = _alloc_size[i]; + log_info(cds, heap)(SIZE_FORMAT_W(8) " objects are <= " SIZE_FORMAT_W(-6) + " bytes (total " SIZE_FORMAT_W(8) " bytes, avg %8.1f bytes)", + count, byte_size_limit, size * HeapWordSize, avg_size(size, count)); + huge_count -= count; + huge_size -= size; + } + + log_info(cds, heap)(SIZE_FORMAT_W(8) " huge objects (total " SIZE_FORMAT_W(8) " bytes" + ", avg %8.1f bytes)", + huge_count, huge_size * HeapWordSize, + avg_size(huge_size, huge_count)); + log_info(cds, heap)(SIZE_FORMAT_W(8) " total objects (total " SIZE_FORMAT_W(8) " bytes" + ", avg %8.1f bytes)", + _total_obj_count, _total_obj_size * HeapWordSize, + avg_size(_total_obj_size, _total_obj_count)); +} + #endif // INCLUDE_CDS_JAVA_HEAP diff --git a/src/hotspot/share/cds/heapShared.hpp b/src/hotspot/share/cds/heapShared.hpp index 9990ab825b3..067897bd821 100644 --- a/src/hotspot/share/cds/heapShared.hpp +++ b/src/hotspot/share/cds/heapShared.hpp @@ -162,6 +162,15 @@ class HeapShared: AllStatic { static DumpedInternedStrings *_dumped_interned_strings; static GrowableArrayCHeap* _native_pointers; + // statistics + constexpr static int ALLOC_STAT_SLOTS = 16; + static size_t _alloc_count[ALLOC_STAT_SLOTS]; + static size_t _alloc_size[ALLOC_STAT_SLOTS]; + static size_t _total_obj_count; + static size_t _total_obj_size; // in HeapWords + + static void count_allocation(size_t size); + static void print_stats(); public: static unsigned oop_hash(oop const& p); static unsigned string_oop_hash(oop const& string) { From d624debe23f60d778d7be43f28d06e9454057217 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Sun, 11 Dec 2022 13:50:39 +0000 Subject: [PATCH 162/494] 8298459: Fix msys2 linking and handling out of tree build directory for source zip creation Reviewed-by: erikj --- make/ZipSource.gmk | 7 ++++--- make/common/MakeBase.gmk | 27 +++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/make/ZipSource.gmk b/make/ZipSource.gmk index 49d13433372..341af7e9847 100644 --- a/make/ZipSource.gmk +++ b/make/ZipSource.gmk @@ -1,5 +1,5 @@ # -# Copyright (c) 2014, 2020, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2022, 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 @@ include JavaCompilation.gmk include Modules.gmk SRC_ZIP_WORK_DIR := $(SUPPORT_OUTPUTDIR)/src +$(if $(filter $(TOPDIR)/%, $(SUPPORT_OUTPUTDIR)), $(eval SRC_ZIP_BASE := $(TOPDIR)), $(eval SRC_ZIP_BASE := $(SUPPORT_OUTPUTDIR))) # Hook to include the corresponding custom file, if present. $(eval $(call IncludeCustomExtension, ZipSource.gmk)) @@ -45,10 +46,10 @@ ALL_MODULES := $(FindAllModules) # again to create src.zip. $(foreach m, $(ALL_MODULES), \ $(foreach d, $(call FindModuleSrcDirs, $m), \ - $(eval $d_TARGET := $(SRC_ZIP_WORK_DIR)/$(patsubst $(TOPDIR)/%,%,$d)/$m) \ + $(eval $d_TARGET := $(SRC_ZIP_WORK_DIR)/$(patsubst $(TOPDIR)/%,%,$(patsubst $(SUPPORT_OUTPUTDIR)/%,%,$d))/$m) \ $(if $(SRC_GENERATED), , \ $(eval $$($d_TARGET): $d ; \ - $$(if $(filter $(TOPDIR)/%, $d), $$(link-file-relative), $$(link-file-absolute)) \ + $$(if $(filter $(SRC_ZIP_BASE)/%, $d), $$(link-file-relative), $$(link-file-absolute)) \ ) \ ) \ $(eval SRC_ZIP_SRCS += $$($d_TARGET)) \ diff --git a/make/common/MakeBase.gmk b/make/common/MakeBase.gmk index 8743f8a7619..252d9dd50da 100644 --- a/make/common/MakeBase.gmk +++ b/make/common/MakeBase.gmk @@ -306,17 +306,36 @@ endef # There are two versions, either creating a relative or an absolute link. Be # careful when using this on Windows since the symlink created is only valid in # the unix emulation environment. -define link-file-relative +# In msys2 we use mklink /J because its ln would perform a deep copy of the target. +# This inhibits performance and can lead to issues with long paths. With mklink /J +# relative linking does not work, so we handle the link as absolute path. +ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2) + define link-file-relative + $(call MakeTargetDir) + $(RM) '$(call DecodeSpace, $@)' + cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))" + endef +else + define link-file-relative $(call MakeTargetDir) $(RM) '$(call DecodeSpace, $@)' $(LN) -s '$(call DecodeSpace, $(call RelativePath, $<, $(@D)))' '$(call DecodeSpace, $@)' -endef + endef +endif -define link-file-absolute +ifeq ($(OPENJDK_BUILD_OS_ENV), windows.msys2) + define link-file-absolute + $(call MakeTargetDir) + $(RM) '$(call DecodeSpace, $@)' + cmd //c "mklink /J $(call FixPath, $(call DecodeSpace, $@)) $(call FixPath, $(call DecodeSpace, $<))" + endef +else + define link-file-absolute $(call MakeTargetDir) $(RM) '$(call DecodeSpace, $@)' $(LN) -s '$(call DecodeSpace, $<)' '$(call DecodeSpace, $@)' -endef + endef +endif ################################################################################ From d646e32b7a0f8e4a66f06e15e289d4ed70b8250e Mon Sep 17 00:00:00 2001 From: Andrey Turbanov Date: Mon, 12 Dec 2022 07:36:34 +0000 Subject: [PATCH 163/494] 8298090: Use String.join() instead of manual loop in DescriptorSupport.toString Reviewed-by: stsypanov, sspitsyn, lmesnik --- .../management/modelmbean/DescriptorSupport.java | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java index f74b34edcdd..00aa6ab7eb7 100644 --- a/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java +++ b/src/java.management/share/classes/javax/management/modelmbean/DescriptorSupport.java @@ -1234,14 +1234,13 @@ public synchronized String toString() { MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); } - String respStr = ""; String[] fields = getFields(); if ((fields == null) || (fields.length == 0)) { if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { MODELMBEAN_LOGGER.log(Level.TRACE, "Empty Descriptor"); } - return respStr; + return ""; } if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { @@ -1249,13 +1248,7 @@ public synchronized String toString() { "Printing " + fields.length + " fields"); } - for (int i=0; i < fields.length; i++) { - if (i == (fields.length - 1)) { - respStr = respStr.concat(fields[i]); - } else { - respStr = respStr.concat(fields[i] + ", "); - } - } + String respStr = String.join(", ", fields); if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { MODELMBEAN_LOGGER.log(Level.TRACE, "Exit returning " + respStr); From 8e5c3319d0c494eb60aa043f3daf3566d78a9f7b Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 12 Dec 2022 11:17:22 +0000 Subject: [PATCH 164/494] 8298471: Parallel: Don't keep alive nmethods in Young GC Reviewed-by: stefank, iwalulya --- src/hotspot/share/gc/parallel/psScavenge.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/gc/parallel/psScavenge.cpp b/src/hotspot/share/gc/parallel/psScavenge.cpp index 428e09f1bdc..808fa4a74dd 100644 --- a/src/hotspot/share/gc/parallel/psScavenge.cpp +++ b/src/hotspot/share/gc/parallel/psScavenge.cpp @@ -100,7 +100,7 @@ static void scavenge_roots_work(ParallelRootType::Value root_type, uint worker_i case ParallelRootType::code_cache: { - MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations, true /* keepalive nmethods */); + MarkingCodeBlobClosure code_closure(&roots_to_old_closure, CodeBlobToOopClosure::FixRelocations, false /* keepalive nmethods */); ScavengableNMethods::nmethods_do(&code_closure); } break; @@ -270,7 +270,7 @@ class PSThreadRootsTaskClosure : public ThreadClosure { PSPromotionManager* pm = PSPromotionManager::gc_thread_promotion_manager(_worker_id); PSScavengeRootsClosure roots_closure(pm); - MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations, true /* keepalive nmethods */); + MarkingCodeBlobClosure roots_in_blobs(&roots_closure, CodeBlobToOopClosure::FixRelocations, false /* keepalive nmethods */); thread->oops_do(&roots_closure, &roots_in_blobs); From 6c23b4fd0d7883bdcdf20438c21fe226c8de19f5 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Mon, 12 Dec 2022 11:18:33 +0000 Subject: [PATCH 165/494] 8298480: Remove unused KlassRemSet Reviewed-by: stefank --- src/hotspot/share/gc/shared/genOopClosures.hpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/hotspot/share/gc/shared/genOopClosures.hpp b/src/hotspot/share/gc/shared/genOopClosures.hpp index 05601199118..4ba6e82aa30 100644 --- a/src/hotspot/share/gc/shared/genOopClosures.hpp +++ b/src/hotspot/share/gc/shared/genOopClosures.hpp @@ -32,7 +32,6 @@ class Generation; class CardTableRS; class CardTableBarrierSet; class DefNewGeneration; -class KlassRemSet; class Method; class nmethod; From fabda246960cfdfff13c5a87de53d97169248172 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Mon, 12 Dec 2022 12:11:02 +0000 Subject: [PATCH 166/494] 8296389: C2: PhaseCFG::convert_NeverBranch_to_Goto must handle both orders of successors Reviewed-by: thartmann, chagedorn --- src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp | 2 +- .../shenandoah/c2/shenandoahBarrierSetC2.cpp | 2 +- .../gc/shenandoah/c2/shenandoahSupport.cpp | 12 +-- src/hotspot/share/opto/block.cpp | 12 +-- src/hotspot/share/opto/cfgnode.hpp | 5 +- src/hotspot/share/opto/loopPredicate.cpp | 2 +- src/hotspot/share/opto/loopnode.cpp | 4 +- src/hotspot/share/opto/loopopts.cpp | 8 +- src/hotspot/share/opto/node.hpp | 1 + .../TestPhaseCFGNeverBranchToGoto.jasm | 71 +++++++++++++++ .../TestPhaseCFGNeverBranchToGotoMain.java | 88 +++++++++++++++++++ 11 files changed, 186 insertions(+), 21 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGoto.jasm create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGotoMain.java diff --git a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp index 753644519c5..d08acc137c9 100644 --- a/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp +++ b/src/hotspot/share/gc/g1/c2/g1BarrierSetC2.cpp @@ -1009,7 +1009,7 @@ void G1BarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase phase) co if (if_ctrl != load_ctrl) { // Skip possible CProj->NeverBranch in infinite loops if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) - && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { + && if_ctrl->in(0)->is_NeverBranch()) { if_ctrl = if_ctrl->in(0)->in(0); } } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp index 950e64dd688..c561389307e 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahBarrierSetC2.cpp @@ -1028,7 +1028,7 @@ void ShenandoahBarrierSetC2::verify_gc_barriers(Compile* compile, CompilePhase p if (if_ctrl != load_ctrl) { // Skip possible CProj->NeverBranch in infinite loops if ((if_ctrl->is_Proj() && if_ctrl->Opcode() == Op_CProj) - && (if_ctrl->in(0)->is_MultiBranch() && if_ctrl->in(0)->Opcode() == Op_NeverBranch)) { + && if_ctrl->in(0)->is_NeverBranch()) { if_ctrl = if_ctrl->in(0)->in(0); } } diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index a1283726232..31c480a488a 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -757,7 +757,7 @@ Node* ShenandoahBarrierC2Support::no_branches(Node* c, Node* dom, bool allow_one return NodeSentinel; // unsupported } else if (c->Opcode() == Op_CatchProj) { return NodeSentinel; // unsupported - } else if (c->Opcode() == Op_CProj && next->Opcode() == Op_NeverBranch) { + } else if (c->Opcode() == Op_CProj && next->is_NeverBranch()) { return NodeSentinel; // unsupported } else { assert(next->unique_ctrl_out() == c, "unsupported branch pattern"); @@ -2002,7 +2002,7 @@ Node* ShenandoahIUBarrierNode::Identity(PhaseGVN* phase) { static bool has_never_branch(Node* root) { for (uint i = 1; i < root->req(); i++) { Node* in = root->in(i); - if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->Opcode() == Op_NeverBranch) { + if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->isNeverBranch()) { return true; } } @@ -2033,20 +2033,20 @@ void MemoryGraphFixer::collect_memory_nodes() { if (in->in(0)->is_Region()) { Node* r = in->in(0); for (uint j = 1; j < r->req(); j++) { - assert(r->in(j)->Opcode() != Op_NeverBranch, ""); + assert(!r->in(j)->is_NeverBranch(), ""); } } else { Node* proj = in->in(0); assert(proj->is_Proj(), ""); Node* in = proj->in(0); - assert(in->is_CallStaticJava() || in->Opcode() == Op_NeverBranch || in->Opcode() == Op_Catch || proj->is_IfProj(), ""); + assert(in->is_CallStaticJava() || in->is_NeverBranch() || in->Opcode() == Op_Catch || proj->is_IfProj(), ""); if (in->is_CallStaticJava()) { mem = in->in(TypeFunc::Memory); } else if (in->Opcode() == Op_Catch) { Node* call = in->in(0)->in(0); assert(call->is_Call(), ""); mem = call->in(TypeFunc::Memory); - } else if (in->Opcode() == Op_NeverBranch) { + } else if (in->is_NeverBranch()) { mem = collect_memory_for_infinite_loop(in); } } @@ -2518,7 +2518,7 @@ void MemoryGraphFixer::fix_mem(Node* ctrl, Node* new_ctrl, Node* mem, Node* mem_ } } } else if (!mem_is_valid(m, u) && - !(u->Opcode() == Op_CProj && u->in(0)->Opcode() == Op_NeverBranch && u->as_Proj()->_con == 1)) { + !(u->Opcode() == Op_CProj && u->in(0)->is_NeverBranch() && u->as_Proj()->_con == 1)) { uses.push(u); } } diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index df2a80b3f7e..57bdbd165a4 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -620,10 +620,13 @@ static bool no_flip_branch(Block *b) { // fake exit path to infinite loops. At this late stage they need to turn // into Goto's so that when you enter the infinite loop you indeed hang. void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) { - // Find true target int end_idx = b->end_idx(); - int idx = b->get_node(end_idx+1)->as_Proj()->_con; - Block *succ = b->_succs[idx]; + NeverBranchNode* never_branch = b->get_node(end_idx)->as_NeverBranch(); + Block* succ = get_block_for_node(never_branch->proj_out(0)->unique_ctrl_out_or_null()); + Block* dead = get_block_for_node(never_branch->proj_out(1)->unique_ctrl_out_or_null()); + assert(succ == b->_succs[0] || succ == b->_succs[1], "succ is a successor"); + assert(dead == b->_succs[0] || dead == b->_succs[1], "dead is a successor"); + Node* gto = _goto->clone(); // get a new goto node gto->set_req(0, b->head()); Node *bp = b->get_node(end_idx); @@ -642,7 +645,6 @@ void PhaseCFG::convert_NeverBranch_to_Goto(Block *b) { } } // Kill alternate exit path - Block* dead = b->_succs[1 - idx]; for (j = 1; j < dead->num_preds(); j++) { if (dead->pred(j)->in(0) == bp) { break; @@ -740,7 +742,7 @@ void PhaseCFG::remove_empty_blocks() { // to give a fake exit path to infinite loops. At this late stage they // need to turn into Goto's so that when you enter the infinite loop you // indeed hang. - if (block->get_node(block->end_idx())->Opcode() == Op_NeverBranch) { + if (block->get_node(block->end_idx())->is_NeverBranch()) { convert_NeverBranch_to_Goto(block); } diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index ea6ec6aff43..a41a744d537 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -591,7 +591,10 @@ class CreateExNode : public TypeNode { // empty. class NeverBranchNode : public MultiBranchNode { public: - NeverBranchNode( Node *ctrl ) : MultiBranchNode(1) { init_req(0,ctrl); } + NeverBranchNode(Node* ctrl) : MultiBranchNode(1) { + init_req(0, ctrl); + init_class_id(Class_NeverBranch); + } virtual int Opcode() const; virtual bool pinned() const { return true; }; virtual const Type *bottom_type() const { return TypeTuple::IFBOTH; } diff --git a/src/hotspot/share/opto/loopPredicate.cpp b/src/hotspot/share/opto/loopPredicate.cpp index a7c6f858f41..ef691c31d95 100644 --- a/src/hotspot/share/opto/loopPredicate.cpp +++ b/src/hotspot/share/opto/loopPredicate.cpp @@ -1442,7 +1442,7 @@ bool PhaseIdealLoop::loop_predication_impl(IdealLoopTree *loop) { } LoopNode* head = loop->_head->as_Loop(); - if (head->unique_ctrl_out()->Opcode() == Op_NeverBranch) { + if (head->unique_ctrl_out()->is_NeverBranch()) { // do nothing for infinite loops return false; } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index f8250bf59b4..17112264706 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4208,9 +4208,9 @@ bool PhaseIdealLoop::only_has_infinite_loops() { if (n->is_Root()) { // Found root -> there was an exit! return false; - } else if (n->Opcode() == Op_NeverBranch) { + } else if (n->is_NeverBranch()) { // Only follow the loop-internal projection, not the NeverBranch exit - ProjNode* proj = n->as_Multi()->proj_out_or_null(0); + ProjNode* proj = n->as_NeverBranch()->proj_out_or_null(0); assert(proj != nullptr, "must find loop-internal projection of NeverBranch"); worklist.push(proj); } else { diff --git a/src/hotspot/share/opto/loopopts.cpp b/src/hotspot/share/opto/loopopts.cpp index 79d6531b627..fbe8bab01eb 100644 --- a/src/hotspot/share/opto/loopopts.cpp +++ b/src/hotspot/share/opto/loopopts.cpp @@ -792,8 +792,8 @@ static void enqueue_cfg_uses(Node* m, Unique_Node_List& wq) { for (DUIterator_Fast imax, i = m->fast_outs(imax); i < imax; i++) { Node* u = m->fast_out(i); if (u->is_CFG()) { - if (u->Opcode() == Op_NeverBranch) { - u = ((NeverBranchNode*)u)->proj_out(0); + if (u->is_NeverBranch()) { + u = u->as_NeverBranch()->proj_out(0); enqueue_cfg_uses(u, wq); } else { wq.push(u); @@ -976,7 +976,7 @@ void PhaseIdealLoop::try_move_store_after_loop(Node* n) { #endif lca = place_outside_loop(lca, n_loop); assert(!n_loop->is_member(get_loop(lca)), "control must not be back in the loop"); - assert(get_loop(lca)->_nest < n_loop->_nest || lca->in(0)->Opcode() == Op_NeverBranch, "must not be moved into inner loop"); + assert(get_loop(lca)->_nest < n_loop->_nest || lca->in(0)->is_NeverBranch(), "must not be moved into inner loop"); // Move store out of the loop _igvn.replace_node(hook, n->in(MemNode::Memory)); @@ -1181,7 +1181,7 @@ Node* PhaseIdealLoop::place_outside_loop(Node* useblock, IdealLoopTree* loop) co Node* dom = idom(useblock); if (loop->is_member(get_loop(dom)) || // NeverBranch nodes are not assigned to the loop when constructed - (dom->Opcode() == Op_NeverBranch && loop->is_member(get_loop(dom->in(0))))) { + (dom->is_NeverBranch() && loop->is_member(get_loop(dom->in(0))))) { break; } useblock = dom; diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index b634dc78502..29b57d674f5 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -922,6 +922,7 @@ class Node { DEFINE_CLASS_QUERY(Mul) DEFINE_CLASS_QUERY(Multi) DEFINE_CLASS_QUERY(MultiBranch) + DEFINE_CLASS_QUERY(NeverBranch) DEFINE_CLASS_QUERY(Opaque1) DEFINE_CLASS_QUERY(OuterStripMinedLoop) DEFINE_CLASS_QUERY(OuterStripMinedLoopEnd) diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGoto.jasm b/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGoto.jasm new file mode 100644 index 00000000000..ba3e70e5d26 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGoto.jasm @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2022, 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. + */ + + +super public class TestPhaseCFGNeverBranchToGoto +{ + public Method "":"()V" + stack 2 locals 1 + { + aload_0; + invokespecial Method java/lang/Object."":"()V"; + return; + } + static Method test:"(III)V" + stack 200 locals 200 + { + iload 2; + ifeq LEND; // at runtime avoid the infinite-loop + + iload 0; + ifeq L20; + goto L10; + L10: + goto L11; + L11: + iinc 0, 1; + iload 1; + ifge L10; + goto L11; + L20: + iload 1; + ifle L21; + goto L10; + L21: + iconst_m1; // eventually false + ifge L11; + goto L20; + + LEND: + return; + } + public static Method main:"([Ljava/lang/String;)V" + stack 100 locals 100 + { + iconst_0; + iconst_m1; + iconst_0; + invokestatic Method test:"(III)V"; + return; + } +} diff --git a/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGotoMain.java b/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGotoMain.java new file mode 100644 index 00000000000..b7f346e312d --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestPhaseCFGNeverBranchToGotoMain.java @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022, 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 8296389 + * @summary Peeling of Irreducible loop can lead to NeverBranch being visited from either side + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:PerMethodTrapLimit=0 + * -XX:CompileCommand=compileonly,TestPhaseCFGNeverBranchToGotoMain::test + * TestPhaseCFGNeverBranchToGotoMain + */ + +/* + * @test + * @bug 8296389 + * @compile TestPhaseCFGNeverBranchToGoto.jasm + * @summary Peeling of Irreducible loop can lead to NeverBranch being visited from either side + * @run main/othervm -Xcomp -XX:-TieredCompilation -XX:PerMethodTrapLimit=0 + * -XX:CompileCommand=compileonly,TestPhaseCFGNeverBranchToGoto::test + * TestPhaseCFGNeverBranchToGoto + */ + + +public class TestPhaseCFGNeverBranchToGotoMain { + public static void main (String[] args) { + test(false, false); + } + + public static void test(boolean flag1, boolean flag2) { + if (flag1) { // runtime check, avoid infinite loop + int a = 77; + int b = 0; + do { // empty loop + a--; + b++; + } while (a > 0); + // a == 0, b == 77 - after first loop-opts phase + int p = 0; + for (int i = 0; i < 4; i++) { + if ((i % 2) == 0) { + p = 1; + } + } + // p == 1 - after second loop-opts phase (via unrolling) + // in first loop-opts phase we have 2x unrolling, 4x after second + int x = 1; + if (flag2) { + x = 3; + } // have region here, so that NeverBranch does not get removed + do { // infinite loop + do { + // NeverBranch inserted here, during loop-opts 1 + x *= 2; + if (p == 0) { // reason for peeling in loop-opts 1 + // after we know that p == 1, we lose this exit + break; + } + // once we know that b == 77, we lose exit + } while (b == 77); + // after we lost both exits above, this loop gets cut off + int y = 5; + do { + y *= 3; + } while (b == 77); + } while (true); + } + } +} From 56c438bfc278307ec1f97dfba60253ae6b64df44 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 12 Dec 2022 13:33:24 +0000 Subject: [PATCH 167/494] 8297822: De-duplicate code in module jdk.sctp Reviewed-by: dfuchs, rriggs --- make/modules/jdk.sctp/Java.gmk | 7 + .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 137 ---------------- .../nio/ch/sctp/SctpServerChannelImpl.java | 102 ------------ .../sun/nio/ch/sctp/SctpChannelImpl.java | 150 ------------------ .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 137 ---------------- .../nio/ch/sctp/SctpServerChannelImpl.java | 102 ------------ .../sun/nio/ch/sctp/SctpChannelImpl.java | 94 ++++++----- .../sun/nio/ch/sctp/SctpMultiChannelImpl.java | 88 +++++----- .../nio/ch/sctp/SctpServerChannelImpl.java | 53 +++---- .../sun/nio/ch/sctp/UnsupportedUtil.java | 44 +++++ .../sun/nio/ch/sctp/SctpChannelImpl.java | 150 ------------------ 11 files changed, 163 insertions(+), 901 deletions(-) delete mode 100644 src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java delete mode 100644 src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java delete mode 100644 src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpChannelImpl.java delete mode 100644 src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java delete mode 100644 src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java rename src/jdk.sctp/{aix => share}/classes/sun/nio/ch/sctp/SctpChannelImpl.java (52%) rename src/jdk.sctp/{windows => share}/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java (54%) rename src/jdk.sctp/{windows => share}/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java (64%) create mode 100644 src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java delete mode 100644 src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java diff --git a/make/modules/jdk.sctp/Java.gmk b/make/modules/jdk.sctp/Java.gmk index 05e27e1eaf8..8e2a7d6be81 100644 --- a/make/modules/jdk.sctp/Java.gmk +++ b/make/modules/jdk.sctp/Java.gmk @@ -44,3 +44,10 @@ endif ifeq ($(call isTargetOs, aix), true) EXCLUDE_FILES += $(SCTP_IMPL_CLASSES) endif + +ifeq ($(call isTargetOsType, unix), true) + ifeq ($(call isTargetOs, macos aix), false) + # This class is not needed on "unix" because SCTP in Java is supported for that platform + EXCLUDE_FILES += $(TOPDIR)/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java + endif +endif diff --git a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java deleted file mode 100644 index c2c1d968307..00000000000 --- a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2009, 2012, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.Association; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.MessageInfo; -import com.sun.nio.sctp.NotificationHandler; -import com.sun.nio.sctp.SctpMultiChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpMultiChannelImpl extends SctpMultiChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpMultiChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public Set associations() { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getRemoteAddresses - (Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel shutdown(Association association) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name, - Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel setOption(SctpSocketOption name, - T value, Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - public MessageInfo receive(ByteBuffer buffer, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public int send(ByteBuffer buffer, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel branch(Association association) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} diff --git a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java deleted file mode 100644 index 1e224afd13f..00000000000 --- a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2009, 2012, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.SctpServerChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpServerChannelImpl extends SctpServerChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpServerChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel accept() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel setOption(SctpSocketOption name, - T value) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} diff --git a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpChannelImpl.java deleted file mode 100644 index f804bb894f3..00000000000 --- a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2009, 2013, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.Association; -import com.sun.nio.sctp.MessageInfo; -import com.sun.nio.sctp.NotificationHandler; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpChannelImpl extends SctpChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public Association association() { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel bind(SocketAddress local) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean connect(SocketAddress remote) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean connect(SocketAddress remote, int maxOutStreams, - int maxInStreams) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean isConnectionPending() { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean finishConnect() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getRemoteAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel shutdown() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel setOption(SctpSocketOption name, T value) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - public MessageInfo receive(ByteBuffer dst, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public int send(ByteBuffer src, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} diff --git a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java deleted file mode 100644 index 37e9f768ecf..00000000000 --- a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ /dev/null @@ -1,137 +0,0 @@ -/* - * Copyright (c) 2009, 2013, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.Association; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.MessageInfo; -import com.sun.nio.sctp.NotificationHandler; -import com.sun.nio.sctp.SctpMultiChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpMultiChannelImpl extends SctpMultiChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpMultiChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public Set associations() { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getRemoteAddresses - (Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel shutdown(Association association) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name, - Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpMultiChannel setOption(SctpSocketOption name, - T value, Association association) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - public MessageInfo receive(ByteBuffer buffer, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public int send(ByteBuffer buffer, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel branch(Association association) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} diff --git a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java deleted file mode 100644 index 01ca7f0e643..00000000000 --- a/src/jdk.sctp/macosx/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2009, 2013, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.SctpServerChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpServerChannelImpl extends SctpServerChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpServerChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel accept() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpServerChannel setOption(SctpSocketOption name, - T value) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} diff --git a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpChannelImpl.java similarity index 52% rename from src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpChannelImpl.java rename to src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpChannelImpl.java index 8a147203402..1d6679376ee 100644 --- a/src/jdk.sctp/aix/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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,127 +24,123 @@ */ package sun.nio.ch.sctp; -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; import com.sun.nio.sctp.Association; import com.sun.nio.sctp.MessageInfo; import com.sun.nio.sctp.NotificationHandler; import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpSocketOption; +import java.io.IOException; +import java.net.InetAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + /** * Unimplemented. */ -public class SctpChannelImpl extends SctpChannel -{ - private static final String message = "SCTP not supported on this platform"; +public class SctpChannelImpl + extends SctpChannel { public SctpChannelImpl(SelectorProvider provider) { super(provider); - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public Association association() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpChannel bind(SocketAddress local) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpChannel bind(SocketAddress local) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpChannel bindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpChannel unbindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public boolean connect(SocketAddress remote) throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public boolean connect(SocketAddress remote, int maxOutStreams, - int maxInStreams) throws IOException { - throw new UnsupportedOperationException(message); + public boolean connect(SocketAddress remote, + int maxOutStreams, + int maxInStreams) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public boolean isConnectionPending() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public boolean finishConnect() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); + public Set getAllLocalAddresses() throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public Set getRemoteAddresses() - throws IOException { - throw new UnsupportedOperationException(message); + public Set getRemoteAddresses() throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpChannel shutdown() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public T getOption(SctpSocketOption name) - throws IOException { - throw new UnsupportedOperationException(message); + public T getOption(SctpSocketOption name) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpChannel setOption(SctpSocketOption name, T value) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpChannel setOption(SctpSocketOption name, + T value) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public Set> supportedOptions() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public MessageInfo receive(ByteBuffer dst, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); + public MessageInfo receive(ByteBuffer dst, + T attachment, + NotificationHandler handler) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public int send(ByteBuffer src, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); + public int send(ByteBuffer src, + MessageInfo messageInfo) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } } diff --git a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java similarity index 54% rename from src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java rename to src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java index c2c1d968307..1be65b7844d 100644 --- a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpMultiChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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,114 +24,110 @@ */ package sun.nio.ch.sctp; -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; import com.sun.nio.sctp.Association; -import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.MessageInfo; import com.sun.nio.sctp.NotificationHandler; +import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpMultiChannel; import com.sun.nio.sctp.SctpSocketOption; +import java.io.IOException; +import java.net.InetAddress; +import java.net.SocketAddress; +import java.nio.ByteBuffer; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + /** * Unimplemented. */ -public class SctpMultiChannelImpl extends SctpMultiChannel -{ - private static final String message = "SCTP not supported on this platform"; +public class SctpMultiChannelImpl + extends SctpMultiChannel { public SctpMultiChannelImpl(SelectorProvider provider) { super(provider); - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public Set associations() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpMultiChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); + int backlog) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpMultiChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpMultiChannel bindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpMultiChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpMultiChannel unbindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); + public Set getAllLocalAddresses() throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public Set getRemoteAddresses - (Association association) throws IOException { - throw new UnsupportedOperationException(message); + public Set getRemoteAddresses(Association association) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpMultiChannel shutdown(Association association) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpMultiChannel shutdown(Association association) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public T getOption(SctpSocketOption name, - Association association) throws IOException { - throw new UnsupportedOperationException(message); + Association association) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpMultiChannel setOption(SctpSocketOption name, - T value, Association association) throws IOException { - throw new UnsupportedOperationException(message); + T value, + Association association) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public Set> supportedOptions() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override - public MessageInfo receive(ByteBuffer buffer, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); + public MessageInfo receive(ByteBuffer buffer, + T attachment, + NotificationHandler handler) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public int send(ByteBuffer buffer, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); + public int send(ByteBuffer buffer, + MessageInfo messageInfo) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpChannel branch(Association association) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpChannel branch(Association association) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } } diff --git a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java similarity index 64% rename from src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java rename to src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java index 1e224afd13f..cd7cb33844a 100644 --- a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/SctpServerChannelImpl.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2009, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2009, 2022, 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,79 +24,76 @@ */ package sun.nio.ch.sctp; -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.channels.spi.SelectorProvider; import com.sun.nio.sctp.SctpChannel; import com.sun.nio.sctp.SctpServerChannel; import com.sun.nio.sctp.SctpSocketOption; +import java.io.IOException; +import java.net.InetAddress; +import java.net.SocketAddress; +import java.nio.channels.spi.SelectorProvider; +import java.util.Set; + /** * Unimplemented. */ -public class SctpServerChannelImpl extends SctpServerChannel -{ - private static final String message = "SCTP not supported on this platform"; +public class SctpServerChannelImpl + extends SctpServerChannel { public SctpServerChannelImpl(SelectorProvider provider) { super(provider); - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpChannel accept() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpServerChannel bind(SocketAddress local, - int backlog) throws IOException { - throw new UnsupportedOperationException(message); + int backlog) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpServerChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpServerChannel bindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public SctpServerChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); + public SctpServerChannel unbindAddress(InetAddress address) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); + public Set getAllLocalAddresses() throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public T getOption(SctpSocketOption name) throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public SctpServerChannel setOption(SctpSocketOption name, - T value) throws IOException { - throw new UnsupportedOperationException(message); + T value) throws IOException { + throw UnsupportedUtil.sctpUnsupported(); } @Override public Set> supportedOptions() { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } @Override public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); + throw UnsupportedUtil.sctpUnsupported(); } } diff --git a/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java new file mode 100644 index 00000000000..7edaee33ae5 --- /dev/null +++ b/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2022, 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. + */ + +package sun.nio.ch.sctp; + +/** + * Utility class used by implementations on platforms not supporting SCTP. + *

    + * This class is not present on the "unix" platform because unix can support SCTP. + */ +public final class UnsupportedUtil { + + private static final String MESSAGE = "SCTP not supported on this platform"; + + // Suppresses default constructor, ensuring non-instantiability. + private UnsupportedUtil() {} + + static UnsupportedOperationException sctpUnsupported() { + return new UnsupportedOperationException(MESSAGE); + } + +} diff --git a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java b/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java deleted file mode 100644 index 8a147203402..00000000000 --- a/src/jdk.sctp/windows/classes/sun/nio/ch/sctp/SctpChannelImpl.java +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2009, 2012, 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. - */ -package sun.nio.ch.sctp; - -import java.net.SocketAddress; -import java.net.InetAddress; -import java.io.IOException; -import java.util.Set; -import java.nio.ByteBuffer; -import java.nio.channels.spi.SelectorProvider; -import com.sun.nio.sctp.Association; -import com.sun.nio.sctp.MessageInfo; -import com.sun.nio.sctp.NotificationHandler; -import com.sun.nio.sctp.SctpChannel; -import com.sun.nio.sctp.SctpSocketOption; - -/** - * Unimplemented. - */ -public class SctpChannelImpl extends SctpChannel -{ - private static final String message = "SCTP not supported on this platform"; - - public SctpChannelImpl(SelectorProvider provider) { - super(provider); - throw new UnsupportedOperationException(message); - } - - @Override - public Association association() { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel bind(SocketAddress local) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel bindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel unbindAddress(InetAddress address) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean connect(SocketAddress remote) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean connect(SocketAddress remote, int maxOutStreams, - int maxInStreams) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean isConnectionPending() { - throw new UnsupportedOperationException(message); - } - - @Override - public boolean finishConnect() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getAllLocalAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set getRemoteAddresses() - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel shutdown() throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public T getOption(SctpSocketOption name) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public SctpChannel setOption(SctpSocketOption name, T value) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public Set> supportedOptions() { - throw new UnsupportedOperationException(message); - } - - @Override - public MessageInfo receive(ByteBuffer dst, T attachment, - NotificationHandler handler) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public int send(ByteBuffer src, MessageInfo messageInfo) - throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - protected void implConfigureBlocking(boolean block) throws IOException { - throw new UnsupportedOperationException(message); - } - - @Override - public void implCloseSelectableChannel() throws IOException { - throw new UnsupportedOperationException(message); - } -} From cf93933e21d146fe296b1e4b8e2ef06b699175d6 Mon Sep 17 00:00:00 2001 From: Severin Gehwolf Date: Mon, 12 Dec 2022 15:49:31 +0000 Subject: [PATCH 168/494] 8298271: java/security/SignedJar/spi-calendar-provider/TestSPISigned.java failing on Windows Reviewed-by: mullan --- test/jdk/ProblemList.txt | 2 -- .../SignedJar/spi-calendar-provider/TestSPISigned.java | 3 ++- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index d94e0b77c0b..4e00b2c1482 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -618,8 +618,6 @@ sun/security/pkcs11/rsa/TestKeyPairGenerator.java 8295343 linux-al sun/security/pkcs11/rsa/TestKeyFactory.java 8295343 linux-all sun/security/pkcs11/KeyStore/Basic.java 8295343 linux-all -java/security/SignedJar/spi-calendar-provider/TestSPISigned.java 8298271 windows-all - ############################################################################ # jdk_sound diff --git a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java index e7cf5146252..69fe8effe70 100644 --- a/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java +++ b/test/jdk/java/security/SignedJar/spi-calendar-provider/TestSPISigned.java @@ -33,6 +33,7 @@ import java.nio.file.Paths; import java.nio.file.Path; import java.nio.file.Files; +import java.io.File; import static java.util.Calendar.WEDNESDAY; /* @@ -95,7 +96,7 @@ public static void main(String[] args) throws Throwable { testRun.add("-Djava.locale.providers=SPI"); testRun.add("-cp"); String classPath = System.getProperty("java.class.path"); - classPath = classPath + ":" + SIGNED_JAR.toAbsolutePath().toString(); + classPath = classPath + File.pathSeparator + SIGNED_JAR.toAbsolutePath().toString(); testRun.add(classPath); testRun.add(TestSPISigned.class.getSimpleName()); testRun.add("run-test"); From 81f57d568fc687a484f96a8638fa4cdd29374f0e Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 12 Dec 2022 17:06:34 +0000 Subject: [PATCH 169/494] 8298567: Make field in RandomAccessFile final Reviewed-by: rriggs, chegar --- .../classes/java/io/RandomAccessFile.java | 54 +++++++++---------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/src/java.base/share/classes/java/io/RandomAccessFile.java b/src/java.base/share/classes/java/io/RandomAccessFile.java index 6a22ad271ba..ffe6e6f3c14 100644 --- a/src/java.base/share/classes/java/io/RandomAccessFile.java +++ b/src/java.base/share/classes/java/io/RandomAccessFile.java @@ -26,6 +26,7 @@ package java.io; import java.nio.channels.FileChannel; +import java.util.Objects; import jdk.internal.access.JavaIORandomAccessFileAccess; import jdk.internal.access.SharedSecrets; @@ -61,9 +62,15 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { - private FileDescriptor fd; - private volatile FileChannel channel; - private boolean rw; + private static final int O_RDONLY = 1; + private static final int O_RDWR = 2; + private static final int O_SYNC = 4; + private static final int O_DSYNC = 8; + private static final int O_TEMPORARY = 16; + + private final FileDescriptor fd; + + private final boolean rw; /** * The path of the referenced file @@ -73,14 +80,9 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { private final Object closeLock = new Object(); + private volatile FileChannel channel; private volatile boolean closed; - private static final int O_RDONLY = 1; - private static final int O_RDWR = 2; - private static final int O_SYNC = 4; - private static final int O_DSYNC = 8; - private static final int O_TEMPORARY = 16; - /** * Creates a random access file stream to read from, and optionally * to write to, a file with the specified name. A new @@ -113,7 +115,7 @@ public class RandomAccessFile implements DataOutput, DataInput, Closeable { * existing, writable regular file and a new regular file of * that name cannot be created, or if some other error occurs * while opening or creating the file - * @throws SecurityException if a security manager exists and its + * @throws SecurityException if a security manager exists and its * {@code checkRead} method denies read access to the file * or the mode is {@code "rw"} and the security manager's * {@code checkWrite} method denies write access to the file @@ -219,6 +221,8 @@ private RandomAccessFile(File file, String mode, boolean openAndDelete) { String name = (file != null ? file.getPath() : null); int imode = -1; + + boolean rw = false; if (mode.equals("r")) imode = O_RDONLY; else if (mode.startsWith("rw")) { @@ -233,6 +237,8 @@ else if (mode.equals("rwd")) imode = -1; } } + this.rw = rw; + if (openAndDelete) imode |= O_TEMPORARY; if (imode < 0) @@ -270,10 +276,7 @@ else if (mode.equals("rwd")) * @see java.io.FileDescriptor */ public final FileDescriptor getFD() throws IOException { - if (fd != null) { - return fd; - } - throw new IOException(); + return fd; } /** @@ -1008,20 +1011,15 @@ public final String readLine() throws IOException { while (!eol) { switch (c = read()) { - case -1: - case '\n': - eol = true; - break; - case '\r': - eol = true; - long cur = getFilePointer(); - if ((read()) != '\n') { - seek(cur); + case -1, '\n' -> eol = true; + case '\r' -> { + eol = true; + long cur = getFilePointer(); + if ((read()) != '\n') { + seek(cur); + } } - break; - default: - input.append((char)c); - break; + default -> input.append((char) c); } } @@ -1245,7 +1243,7 @@ public final void writeUTF(String str) throws IOException { SharedSecrets.setJavaIORandomAccessFileAccess(new JavaIORandomAccessFileAccess() { // This is for j.u.z.ZipFile.OPEN_DELETE. The O_TEMPORARY flag - // is only implemented/supported on windows. + // is only implemented/supported on Windows. public RandomAccessFile openAndDelete(File file, String mode) throws IOException { From 9ff85f65774c0a81ed10500d3591cd79b440aed0 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 12 Dec 2022 17:22:17 +0000 Subject: [PATCH 170/494] 8298589: java/net/SctpSanity.java fail with NoClassDefFoundError: sun/nio/ch/sctp/UnsupportedUtil Reviewed-by: alanb --- make/modules/jdk.sctp/Java.gmk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/make/modules/jdk.sctp/Java.gmk b/make/modules/jdk.sctp/Java.gmk index 8e2a7d6be81..10793d45c84 100644 --- a/make/modules/jdk.sctp/Java.gmk +++ b/make/modules/jdk.sctp/Java.gmk @@ -46,7 +46,7 @@ ifeq ($(call isTargetOs, aix), true) endif ifeq ($(call isTargetOsType, unix), true) - ifeq ($(call isTargetOs, macos aix), false) + ifeq ($(call isTargetOs, macosx aix), false) # This class is not needed on "unix" because SCTP in Java is supported for that platform EXCLUDE_FILES += $(TOPDIR)/src/jdk.sctp/share/classes/sun/nio/ch/sctp/UnsupportedUtil.java endif From 0267aa528b83be9914fee4bea8f548b8404b31f8 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Mon, 12 Dec 2022 17:59:25 +0000 Subject: [PATCH 171/494] 8297288: Example code in Scanner class Reviewed-by: lancea, bpb, alanb --- .../share/classes/java/util/Scanner.java | 28 +++++++++++-------- 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/src/java.base/share/classes/java/util/Scanner.java b/src/java.base/share/classes/java/util/Scanner.java index 9e544880ae2..f270a46cc49 100644 --- a/src/java.base/share/classes/java/util/Scanner.java +++ b/src/java.base/share/classes/java/util/Scanner.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ -51,24 +51,28 @@ * various {@code next} methods. * *

    For example, this code allows a user to read a number from - * {@code System.in}: - *

    {@code
    - *     Scanner sc = new Scanner(System.in);
    - *     int i = sc.nextInt();
    - * }
    + * the console. + * {@snippet : + * var con = System.console(); + * if (con != null) { + * // @link substring="reader()" target="java.io.Console#reader()" : + * Scanner sc = new Scanner(con.reader()); + * int i = sc.nextInt(); + * } + * } * *

    As another example, this code allows {@code long} types to be * assigned from entries in a file {@code myNumbers}: - *

    {@code
    + * {@snippet :
      *      Scanner sc = new Scanner(new File("myNumbers"));
      *      while (sc.hasNextLong()) {
      *          long aLong = sc.nextLong();
      *      }
    - * }
    + * } * *

    The scanner can also use delimiters other than whitespace. This * example reads several items in from a string: - *

    {@code
    + * {@snippet :
      *     String input = "1 fish 2 fish red fish blue fish";
      *     Scanner s = new Scanner(input).useDelimiter("\\s*fish\\s*");
      *     System.out.println(s.nextInt());
    @@ -76,7 +80,7 @@
      *     System.out.println(s.next());
      *     System.out.println(s.next());
      *     s.close();
    - * }
    + * } *

    * prints the following output: *

    {@code
    @@ -88,7 +92,7 @@
      *
      * 

    The same output can be generated with this code, which uses a regular * expression to parse all four tokens at once: - *

    {@code
    + * {@snippet :
      *     String input = "1 fish 2 fish red fish blue fish";
      *     Scanner s = new Scanner(input);
      *     s.findInLine("(\\d+) fish (\\d+) fish (\\w+) fish (\\w+)");
    @@ -96,7 +100,7 @@
      *     for (int i=1; i<=result.groupCount(); i++)
      *         System.out.println(result.group(i));
      *     s.close();
    - * }
    + * } * *

    The default whitespace delimiter used * by a scanner is as recognized by {@link Character#isWhitespace(char) From 781a2e0b2d7d0f36387837de6f50ff087502d317 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Mon, 12 Dec 2022 18:29:58 +0000 Subject: [PATCH 172/494] 8298343: "Could not confirm if TargetJDK is hardened." warning for SA tests on macosx-aarch64-debug Reviewed-by: amenkov, kevinw --- test/lib/jdk/test/lib/Platform.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/test/lib/jdk/test/lib/Platform.java b/test/lib/jdk/test/lib/Platform.java index 784f018435e..647c62834aa 100644 --- a/test/lib/jdk/test/lib/Platform.java +++ b/test/lib/jdk/test/lib/Platform.java @@ -293,6 +293,10 @@ public static boolean isHardenedOSX() throws IOException { isHardened = true; System.out.println("Target JDK is hardened. Some tests may be skipped."); } else if (line.indexOf("flags=0x20002(adhoc,linker-signed)") != -1 ) { + hardenedStatusConfirmed = true; + isHardened = false; + System.out.println("Target JDK is adhoc linker-signed, but not hardened."); + } else if (line.indexOf("flags=0x2(adhoc)") != -1 ) { hardenedStatusConfirmed = true; isHardened = false; System.out.println("Target JDK is adhoc signed, but not hardened."); From c7aca73177339f931f7dfb6627365548a32874f7 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Mon, 12 Dec 2022 19:36:55 +0000 Subject: [PATCH 173/494] 8295857: Clarify that cleanup code can be skipped when the JVM terminates (e.g. when calling halt()) Reviewed-by: lancea, bpb, naoto, dholmes, smarks --- .../share/classes/java/lang/Runtime.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index fd35265c0cc..ffef8160c25 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -89,10 +89,14 @@ * shutdown sequence. * *

    When the JVM terminates, all threads are immediately prevented from executing any further - * Java code. This includes shutdown hooks as well as daemon and non-daemon threads. The - * threads' current methods do not complete normally or abruptly; no {@code finally} clause - * of any method is executed, nor is any {@linkplain Thread.UncaughtExceptionHandler - * uncaught exception handler}. + * Java code. This includes shutdown hooks as well as daemon and non-daemon threads. + * This means, for example, that: + *

      + *
    • threads' current methods do not complete normally or abruptly;
    • + *
    • {@code finally} clauses are not executed;
    • + *
    • {@linkplain Thread.UncaughtExceptionHandler uncaught exception handlers} are not run; and
    • + *
    • resources opened with try-with-resources are not {@linkplain AutoCloseable closed};
    • + *
    * * @implNote * Native code typically uses the @@ -278,7 +282,8 @@ public boolean removeShutdownHook(Thread hook) { * @apiNote * This method should be used with extreme caution. Using it may circumvent or disrupt * any cleanup actions intended to be performed by shutdown hooks, possibly leading to - * data corruption. + * data corruption. See the termination section above + * for other possible consequences of halting the Java Virtual Machine. * * @param status * Termination status. By convention, a nonzero status code From c3bc4fcb3d0a8bd2eb308fae90a4cb865b216cb8 Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Mon, 12 Dec 2022 21:51:59 +0000 Subject: [PATCH 174/494] 8297505: Declare fields in some sun.security.pkcs11 classes as final Reviewed-by: valeriep --- .../classes/sun/security/pkcs11/Config.java | 2 +- .../sun/security/pkcs11/P11AEADCipher.java | 4 ++-- .../classes/sun/security/pkcs11/P11Key.java | 2 +- .../sun/security/pkcs11/P11KeyWrapCipher.java | 2 +- .../sun/security/pkcs11/P11RSACipher.java | 8 ++++---- .../P11TlsRsaPremasterSecretGenerator.java | 2 +- .../classes/sun/security/pkcs11/P11Util.java | 2 +- .../classes/sun/security/pkcs11/Session.java | 16 ++++++++-------- .../sun/security/pkcs11/SessionManager.java | 10 +++++----- .../share/classes/sun/security/pkcs11/Token.java | 2 +- 10 files changed, 25 insertions(+), 25 deletions(-) diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java index 70e69d9b877..3a1bb807263 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Config.java @@ -88,7 +88,7 @@ public List run() { private static final boolean DEBUG = false; // file name containing this configuration - private String filename; + private final String filename; // Reader and StringTokenizer used during parsing private Reader reader; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java index 7a91d17e74c..d8477217947 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11AEADCipher.java @@ -110,9 +110,9 @@ private enum Transformation { private SecureRandom random = JCAUtil.getSecureRandom(); // dataBuffer is cleared upon doFinal calls - private ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); // aadBuffer is cleared upon successful init calls - private ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream aadBuffer = new ByteArrayOutputStream(); private boolean updateCalled = false; private boolean requireReinit = false; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java index af6fbeba48a..bd2d6e81311 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Key.java @@ -1321,7 +1321,7 @@ final class NativeKeyHolder { private long keyID; // phantom reference notification clean up for session keys - private SessionKeyRef ref; + private final SessionKeyRef ref; private int refCount; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java index cdd01d6f5fc..75b28d3eaab 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11KeyWrapCipher.java @@ -117,7 +117,7 @@ private enum KeyWrapType { private SecureRandom random = JCAUtil.getSecureRandom(); // dataBuffer for storing enc/dec data; cleared upon doFinal calls - private ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); + private final ByteArrayOutputStream dataBuffer = new ByteArrayOutputStream(); P11KeyWrapCipher(Token token, String algorithm, long mechanism) throws PKCS11Exception, NoSuchAlgorithmException { diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java index f2c791cb3ef..626f3c3c008 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11RSACipher.java @@ -625,7 +625,7 @@ final class ConstructKeys { * * @return a public key constructed from the encodedKey. */ - private static final PublicKey constructPublicKey(byte[] encodedKey, + private static PublicKey constructPublicKey(byte[] encodedKey, String encodedKeyAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException { try { @@ -652,7 +652,7 @@ private static final PublicKey constructPublicKey(byte[] encodedKey, * * @return a private key constructed from the encodedKey. */ - private static final PrivateKey constructPrivateKey(byte[] encodedKey, + private static PrivateKey constructPrivateKey(byte[] encodedKey, String encodedKeyAlgorithm) throws InvalidKeyException, NoSuchAlgorithmException { try { @@ -679,12 +679,12 @@ private static final PrivateKey constructPrivateKey(byte[] encodedKey, * * @return a secret key constructed from the encodedKey. */ - private static final SecretKey constructSecretKey(byte[] encodedKey, + private static SecretKey constructSecretKey(byte[] encodedKey, String encodedKeyAlgorithm) { return new SecretKeySpec(encodedKey, encodedKeyAlgorithm); } - static final Key constructKey(byte[] encoding, String keyAlgorithm, + static Key constructKey(byte[] encoding, String keyAlgorithm, int keyType) throws InvalidKeyException, NoSuchAlgorithmException { return switch (keyType) { case Cipher.SECRET_KEY -> constructSecretKey(encoding, keyAlgorithm); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java index 981a3761933..0442c36594d 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11TlsRsaPremasterSecretGenerator.java @@ -55,7 +55,7 @@ final class P11TlsRsaPremasterSecretGenerator extends KeyGeneratorSpi { private final String algorithm; // mechanism id - private long mechanism; + private final long mechanism; @SuppressWarnings("deprecation") private TlsRsaPremasterSecretParameterSpec spec; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java index 67dd2dc33dd..5a3229653de 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/P11Util.java @@ -43,7 +43,7 @@ public final class P11Util { // A cleaner, shared within this module. public static final Cleaner cleaner = Cleaner.create(); - private static Object LOCK = new Object(); + private static final Object LOCK = new Object(); private static volatile Provider sun, sunRsaSign, sunJce; diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Session.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Session.java index 8035eac9a92..1ce66803639 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Session.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Session.java @@ -135,7 +135,7 @@ private void close(boolean checkObjCtr) { static boolean drainRefQueue() { boolean found = false; SessionRef next; - while ((next = (SessionRef) SessionRef.refQueue.poll())!= null) { + while ((next = (SessionRef) SessionRef.REF_QUEUE.poll())!= null) { found = true; next.dispose(); } @@ -150,24 +150,24 @@ static boolean drainRefQueue() { final class SessionRef extends PhantomReference implements Comparable { - static ReferenceQueue refQueue = new ReferenceQueue<>(); + static final ReferenceQueue REF_QUEUE = new ReferenceQueue<>(); - private static Set refList = + private static final Set REF_LIST = Collections.synchronizedSortedSet(new TreeSet<>()); // handle to the native session - private long id; - private Token token; + private final long id; + private final Token token; SessionRef(Session session, long id, Token token) { - super(session, refQueue); + super(session, REF_QUEUE); this.id = id; this.token = token; - refList.add(this); + REF_LIST.add(this); } void dispose() { - refList.remove(this); + REF_LIST.remove(this); try { if (token.isPresent(id)) { token.p11.C_CloseSession(id); diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SessionManager.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SessionManager.java index a9f81c0bdf6..49d95884e76 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SessionManager.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/SessionManager.java @@ -78,7 +78,7 @@ final class SessionManager { private final int maxSessions; // total number of active sessions - private AtomicInteger activeSessions = new AtomicInteger(); + private final AtomicInteger activeSessions = new AtomicInteger(); // pool of available object sessions private final Pool objSessions; @@ -88,7 +88,7 @@ final class SessionManager { // maximum number of active sessions during this invocation, for debugging private int maxActiveSessions; - private Object maxActiveSessionsLock; + private final Object maxActiveSessionsLock; // flags to use in the C_OpenSession() call private final long openSessionFlags; @@ -112,9 +112,9 @@ final class SessionManager { this.token = token; this.objSessions = new Pool(this, true); this.opSessions = new Pool(this, false); - if (debug != null) { - maxActiveSessionsLock = new Object(); - } + this.maxActiveSessionsLock = (debug != null) + ? new Object() + : null; } // returns whether only a fairly low number of sessions are diff --git a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java index 6ffee7ea2a0..3378409ca1c 100644 --- a/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java +++ b/src/jdk.crypto.cryptoki/share/classes/sun/security/pkcs11/Token.java @@ -46,7 +46,7 @@ * @author Andreas Sterbenz * @since 1.5 */ -class Token implements Serializable { +final class Token implements Serializable { // need to be serializable to allow SecureRandom to be serialized @Serial From be69930d9d72fe5b1c2b642943cc7d4347979ca6 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Mon, 12 Dec 2022 22:20:16 +0000 Subject: [PATCH 175/494] 8288287: Remove expired flags in JDK 21 Reviewed-by: kvn, rehn --- src/hotspot/share/runtime/arguments.cpp | 7 ------- src/java.base/share/man/java.1 | 18 +++++++++++++----- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index a9ca3e424af..5806750fbe1 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -548,13 +548,6 @@ static SpecialFlag const special_jvm_flags[] = { // -------------- Obsolete Flags - sorted by expired_in -------------- - { "ExtendedDTraceProbes", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "UseContainerCpuShares", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "PreferContainerQuotaForCPUCount", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "AliasLevel", JDK_Version::jdk(19), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "UseCodeAging", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "PrintSharedDictionary", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::jdk(21) }, - { "G1ConcRefinementGreenZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::undefined() }, { "G1ConcRefinementYellowZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::undefined() }, { "G1ConcRefinementRedZone", JDK_Version::undefined(), JDK_Version::jdk(20), JDK_Version::undefined() }, diff --git a/src/java.base/share/man/java.1 b/src/java.base/share/man/java.1 index 82ddd5143dc..680ec9a1613 100644 --- a/src/java.base/share/man/java.1 +++ b/src/java.base/share/man/java.1 @@ -36,7 +36,7 @@ . ftr VB CB . ftr VBI CBI .\} -.TH "JAVA" "1" "2023" "JDK 20-ea" "JDK Commands" +.TH "JAVA" "1" "2023" "JDK 21-ea" "JDK Commands" .hy .SH NAME .PP @@ -187,7 +187,7 @@ with new values added and old values removed. You\[aq]ll get an error message if you use a value of \f[I]N\f[R] that is no longer supported. The supported values of \f[I]N\f[R] are the current Java SE release -(\f[V]20\f[R]) and a limited number of previous releases, detailed in +(\f[V]21\f[R]) and a limited number of previous releases, detailed in the command-line help for \f[V]javac\f[R], under the \f[V]--source\f[R] and \f[V]--release\f[R] options. .RE @@ -3789,6 +3789,14 @@ Controlled \f[I]relaxed strong encapsulation\f[R], as defined in This option was deprecated in JDK 16 by \f[B]JEP 396\f[R] [https://openjdk.org/jeps/396] and made obsolete in JDK 17 by \f[B]JEP 403\f[R] [https://openjdk.org/jeps/403]. +.SH REMOVED JAVA OPTIONS +.PP +These \f[V]java\f[R] options have been removed in JDK 21 and using them +results in an error of: +.RS +.PP +\f[V]Unrecognized VM option\f[R] \f[I]option-name\f[R] +.RE .TP \f[V]-XX:+ExtendedDTraceProbes\f[R] \f[B]Linux and macOS:\f[R] Enables additional \f[V]dtrace\f[R] tool @@ -3798,13 +3806,13 @@ standard probes. Use the combination of these flags instead: \f[V]-XX:+DTraceMethodProbes\f[R], \f[V]-XX:+DTraceAllocProbes\f[R], \f[V]-XX:+DTraceMonitorProbes\f[R]. -.SH REMOVED JAVA OPTIONS -.PP -No documented java options have been removed in JDK 20. .PP For the lists and descriptions of options removed in previous releases see the \f[I]Removed Java Options\f[R] section in: .IP \[bu] 2 +\f[B]The \f[VB]java\f[B] Command, Release 20\f[R] +[https://docs.oracle.com/en/java/javase/20/docs/specs/man/java.html] +.IP \[bu] 2 \f[B]The \f[VB]java\f[B] Command, Release 19\f[R] [https://docs.oracle.com/en/java/javase/19/docs/specs/man/java.html] .IP \[bu] 2 From 8962c723a8ae62a8638e9e0a89c20001aea1549a Mon Sep 17 00:00:00 2001 From: Alexander Matveev Date: Mon, 12 Dec 2022 22:51:02 +0000 Subject: [PATCH 176/494] 8298488: [macos13] tools/jpackage tests failing with "Exit code: 137" on macOS Reviewed-by: asemenyuk --- .../classes/jdk/jpackage/internal/MacAppImageBuilder.java | 2 +- test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java | 4 ---- test/jdk/tools/jpackage/share/AppContentTest.java | 2 +- 3 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java index 543bbe29875..0e35d7f4fcc 100644 --- a/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java +++ b/src/jdk.jpackage/macosx/classes/jdk/jpackage/internal/MacAppImageBuilder.java @@ -401,7 +401,7 @@ private void doSigning(Map params) ENTITLEMENTS.fetchFrom(params)); } restoreKeychainList(params); - } else if (Platform.isArmMac()) { + } else if (Platform.isMac()) { signAppBundle(params, root, "-", null, null); } else { // Calling signAppBundle() without signingIdentity will result in 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 60492b2529f..9e4d2f86c00 100644 --- a/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java +++ b/test/jdk/tools/jpackage/helpers/jdk/jpackage/test/TKit.java @@ -180,10 +180,6 @@ public static boolean isOSX() { return (OS.contains("mac")); } - public static boolean isArmMac() { - return (isOSX() && "aarch64".equals(System.getProperty("os.arch"))); - } - public static boolean isLinux() { return ((OS.contains("nix") || OS.contains("nux"))); } diff --git a/test/jdk/tools/jpackage/share/AppContentTest.java b/test/jdk/tools/jpackage/share/AppContentTest.java index a493bc39127..666fafb7168 100644 --- a/test/jdk/tools/jpackage/share/AppContentTest.java +++ b/test/jdk/tools/jpackage/share/AppContentTest.java @@ -101,7 +101,7 @@ public void test() throws Exception { }) // On macOS aarch64 we always signing app image and signing will fail, since // test produces invalid app bundle. - .setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isArmMac() ? 1 : 0) + .setExpectedExitCode(testPathArgs.contains(TEST_BAD) || TKit.isOSX() ? 1 : 0) .run(); } } From 829cbc2cb16cfe4ad23df934768cb820e79511d8 Mon Sep 17 00:00:00 2001 From: David Holmes Date: Tue, 13 Dec 2022 00:04:38 +0000 Subject: [PATCH 177/494] 8292674: ReportJNIFatalError should print all java frames Reviewed-by: pchilanomate --- src/hotspot/share/prims/jni.cpp | 2 +- src/hotspot/share/prims/jniCheck.cpp | 4 +- src/hotspot/share/prims/jniCheck.hpp | 4 +- src/hotspot/share/runtime/javaThread.cpp | 52 +++++++++++++++++++ src/hotspot/share/runtime/javaThread.hpp | 6 +++ ...estPrimitiveArrayCriticalWithBadParam.java | 42 ++++++++++----- 6 files changed, 93 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/prims/jni.cpp b/src/hotspot/share/prims/jni.cpp index c17dde92c6d..814ecdfbf6f 100644 --- a/src/hotspot/share/prims/jni.cpp +++ b/src/hotspot/share/prims/jni.cpp @@ -626,7 +626,7 @@ JNI_ENTRY(void, jni_FatalError(JNIEnv *env, const char *msg)) HOTSPOT_JNI_FATALERROR_ENTRY(env, (char *) msg); tty->print_cr("FATAL ERROR in native method: %s", msg); - thread->print_stack(); + thread->print_jni_stack(); os::abort(); // Dump core and abort JNI_END diff --git a/src/hotspot/share/prims/jniCheck.cpp b/src/hotspot/share/prims/jniCheck.cpp index 6fbd44b5bcc..70187f78185 100644 --- a/src/hotspot/share/prims/jniCheck.cpp +++ b/src/hotspot/share/prims/jniCheck.cpp @@ -142,7 +142,7 @@ static const char * fatal_non_utf8_class_name2 = "\""; // When in VM state: static void ReportJNIWarning(JavaThread* thr, const char *msg) { tty->print_cr("WARNING in native method: %s", msg); - thr->print_stack(); + thr->print_jni_stack(); } // When in NATIVE state: @@ -193,7 +193,7 @@ check_pending_exception(JavaThread* thr) { IN_VM( tty->print_cr("WARNING in native method: JNI call made without checking exceptions when required to from %s", thr->get_pending_jni_exception_check()); - thr->print_stack(); + thr->print_jni_stack(); ) thr->clear_pending_jni_exception_check(); // Just complain once } diff --git a/src/hotspot/share/prims/jniCheck.hpp b/src/hotspot/share/prims/jniCheck.hpp index 6f3ee18d6b0..a41c79441d6 100644 --- a/src/hotspot/share/prims/jniCheck.hpp +++ b/src/hotspot/share/prims/jniCheck.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2022, 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 @@ extern "C" { // When in VM state: static inline void ReportJNIFatalError(JavaThread* thr, const char *msg) { tty->print_cr("FATAL ERROR in native method: %s", msg); - thr->print_stack(); + thr->print_jni_stack(); os::abort(true); } } diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index 20bba7d4848..f51aa24774d 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1673,6 +1673,16 @@ oop JavaThread::current_park_blocker() { return NULL; } +// Print stack trace for checked JNI warnings and JNI fatal errors. +// This is the external format from above, but selecting the platform +// or vthread as applicable. +void JavaThread::print_jni_stack() { + if (is_vthread_mounted()) { + print_vthread_stack_on(tty); + } else { + print_stack_on(tty); + } +} void JavaThread::print_stack_on(outputStream* st) { if (!has_last_Java_frame()) return; @@ -1706,6 +1716,48 @@ void JavaThread::print_stack_on(outputStream* st) { } } +void JavaThread::print_vthread_stack_on(outputStream* st) { + assert(is_vthread_mounted(), "Caller should have checked this"); + assert(has_last_Java_frame(), "must be"); + + Thread* current_thread = Thread::current(); + ResourceMark rm(current_thread); + HandleMark hm(current_thread); + + RegisterMap reg_map(this, + RegisterMap::UpdateMap::include, + RegisterMap::ProcessFrames::include, + RegisterMap::WalkContinuation::include); + ContinuationEntry* cont_entry = last_continuation(); + vframe* start_vf = last_java_vframe(®_map); + int count = 0; + for (vframe* f = start_vf; f != NULL; f = f->sender()) { + // Watch for end of vthread stack + if (Continuation::is_continuation_enterSpecial(f->fr())) { + assert(cont_entry == Continuation::get_continuation_entry_for_entry_frame(this, f->fr()), ""); + if (cont_entry->is_virtual_thread()) { + break; + } + cont_entry = cont_entry->parent(); + } + if (f->is_java_frame()) { + javaVFrame* jvf = javaVFrame::cast(f); + java_lang_Throwable::print_stack_element(st, jvf->method(), jvf->bci()); + + // Print out lock information + if (JavaMonitorsInStackTrace) { + jvf->print_lock_info_on(st, count); + } + } else { + // Ignore non-Java frames + } + + // Bail-out case for too deep stacks if MaxJavaStackTraceDepth > 0 + count++; + if (MaxJavaStackTraceDepth > 0 && MaxJavaStackTraceDepth == count) return; + } +} + #if INCLUDE_JVMTI // Rebind JVMTI thread state from carrier to virtual or from virtual to carrier. JvmtiThreadState* JavaThread::rebind_to_jvmti_thread_state_of(oop thread_oop) { diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 750903d44be..ed61a36ebf2 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -940,6 +940,12 @@ class JavaThread: public Thread { // Print stack trace in external format void print_stack_on(outputStream* st); void print_stack() { print_stack_on(tty); } + void print_vthread_stack_on(outputStream* st); + + // Print stack trace for checked JNI warnings and JNI fatal errors. + // This is the external format from above, but selecting the platform + // or vthread as applicable. + void print_jni_stack(); // Print stack traces in various internal formats void trace_stack() PRODUCT_RETURN; diff --git a/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java b/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java index c64b21c7d1b..36c48a7fd19 100644 --- a/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java +++ b/test/hotspot/jtreg/runtime/jni/checked/TestPrimitiveArrayCriticalWithBadParam.java @@ -1,5 +1,6 @@ /* * Copyright (c) 2021, Red Hat, Inc. All rights reserved. + * Copyright (c) 2022, 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,9 +25,11 @@ /** * @test TestPrimitiveArrayCriticalWithBadParam - * @bug 8269697 + * @bug 8269697 8292674 * @summary -Xcheck:jni should catch wrong parameter passed to GetPrimitiveArrayCritical + * @comment Tests reporting with regular thread and virtual thread. * @library /test/lib + * @enablePreview * @run main/native TestPrimitiveArrayCriticalWithBadParam */ import java.util.List; @@ -47,39 +50,54 @@ public class TestPrimitiveArrayCriticalWithBadParam { public static void main(String[] args) { if (args.length > 0) { - test(); + test(args[0]); } else { - runTest(); + runTest(false); + runTest(true); } } - private static void runTest() { + private static void runTest(boolean useVThread) { List pbArgs = new ArrayList<>(); pbArgs.add("-XX:-CreateCoredumpOnCrash"); pbArgs.add("-Xcheck:jni"); + pbArgs.add("--enable-preview"); pbArgs.add("-Djava.library.path=" + Utils.TEST_NATIVE_PATH); pbArgs.add(TestPrimitiveArrayCriticalWithBadParam.class.getName()); - pbArgs.add("test"); + pbArgs.add(useVThread ? "vtest" : "test"); try { ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(pbArgs.toArray(new String[0])); OutputAnalyzer analyzer = new OutputAnalyzer(pb.start()); // -Xcheck:jni should warn the bad parameter analyzer.shouldContain("FATAL ERROR in native method: Primitive type array expected but not received for JNI array operation"); + analyzer.shouldContain("TestPrimitiveArrayCriticalWithBadParam.pin"); analyzer.shouldNotHaveExitValue(0); } catch (IOException e) { throw new RuntimeException(e); } } - private static void test() { - Object[] objs = new Object[10]; - for (int i = 0; i < objs.length; i++) { - objs[i] = new MyClass(); + private static void test(String mode) { + Runnable r = () -> { + Object[] objs = new Object[10]; + for (int i = 0; i < objs.length; i++) { + objs[i] = new MyClass(); + } + pin(objs); + System.out.println("Object array pinned"); + unpin(objs); + }; + if (mode.equals("vtest")) { + Thread t = Thread.ofVirtual().start(r); + try { + t.join(); + } catch (InterruptedException ex) { + throw new Error("unexpected", ex); + } + } else { + r.run(); } - pin(objs); - System.out.println("Object array pinned"); - unpin(objs); } public static class MyClass { public Object ref = new Object(); From d4531903007dbe8dcdd163e423d23e8cefba61c8 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Dec 2022 00:49:16 +0000 Subject: [PATCH 178/494] 8296955: Kitchensink.java failed with "double free or corruption (!prev): " Reviewed-by: kbarrett, eosterlund, sspitsyn, dcubed --- src/hotspot/share/oops/instanceKlass.cpp | 50 ++++++++------------ src/hotspot/share/oops/method.cpp | 58 ++++++++---------------- src/hotspot/share/oops/method.hpp | 6 +-- 3 files changed, 39 insertions(+), 75 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d7a4c653726..7432a607d3b 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -2148,15 +2148,8 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { // the cache can't grow so we can just get the current values get_jmethod_id_length_value(jmeths, idnum, &length, &id); } else { - // cache can grow so we have to be more careful - if (Threads::number_of_threads() == 0 || - SafepointSynchronize::is_at_safepoint()) { - // we're single threaded or at a safepoint - no locking needed - get_jmethod_id_length_value(jmeths, idnum, &length, &id); - } else { - MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - get_jmethod_id_length_value(jmeths, idnum, &length, &id); - } + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + get_jmethod_id_length_value(jmeths, idnum, &length, &id); } } // implied else: @@ -2166,8 +2159,8 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { length <= idnum || // cache is too short id == NULL) { // cache doesn't contain entry - // This function can be called by the VMThread so we have to do all - // things that might block on a safepoint before grabbing the lock. + // This function can be called by the VMThread or GC worker threads so we + // have to do all things that might block on a safepoint before grabbing the lock. // Otherwise, we can deadlock with the VMThread or have a cache // consistency issue. These vars keep track of what we might have // to free after the lock is dropped. @@ -2186,25 +2179,20 @@ jmethodID InstanceKlass::get_jmethod_id(const methodHandle& method_h) { } // allocate a new jmethodID that might be used - jmethodID new_id = NULL; - if (method_h->is_old() && !method_h->is_obsolete()) { - // The method passed in is old (but not obsolete), we need to use the current version - Method* current_method = method_with_idnum((int)idnum); - assert(current_method != NULL, "old and but not obsolete, so should exist"); - new_id = Method::make_jmethod_id(class_loader_data(), current_method); - } else { - // It is the current version of the method or an obsolete method, - // use the version passed in - new_id = Method::make_jmethod_id(class_loader_data(), method_h()); - } - - if (Threads::number_of_threads() == 0 || - SafepointSynchronize::is_at_safepoint()) { - // we're single threaded or at a safepoint - no locking needed - id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths, - &to_dealloc_id, &to_dealloc_jmeths); - } else { + { MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + jmethodID new_id = NULL; + if (method_h->is_old() && !method_h->is_obsolete()) { + // The method passed in is old (but not obsolete), we need to use the current version + Method* current_method = method_with_idnum((int)idnum); + assert(current_method != NULL, "old and but not obsolete, so should exist"); + new_id = Method::make_jmethod_id(class_loader_data(), current_method); + } else { + // It is the current version of the method or an obsolete method, + // use the version passed in + new_id = Method::make_jmethod_id(class_loader_data(), method_h()); + } + id = get_jmethod_id_fetch_or_update(idnum, new_id, new_jmeths, &to_dealloc_id, &to_dealloc_jmeths); } @@ -2254,9 +2242,7 @@ jmethodID InstanceKlass::get_jmethod_id_fetch_or_update( assert(new_id != NULL, "sanity check"); assert(to_dealloc_id_p != NULL, "sanity check"); assert(to_dealloc_jmeths_p != NULL, "sanity check"); - assert(Threads::number_of_threads() == 0 || - SafepointSynchronize::is_at_safepoint() || - JmethodIdCreation_lock->owned_by_self(), "sanity check"); + assert(JmethodIdCreation_lock->owned_by_self(), "sanity check"); // reacquire the cache - we are locked, single threaded or at a safepoint jmethodID* jmeths = methods_jmethod_ids_acquire(); diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index 39ba8f395bb..c8b9409ddaa 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -2165,50 +2165,29 @@ JNIMethodBlockNode::JNIMethodBlockNode(int num_methods) : _top(0), _next(NULL) { } } -void Method::ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity) { - ClassLoaderData* cld = loader_data; - if (!SafepointSynchronize::is_at_safepoint()) { - // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock - // protects as well. - MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - if (cld->jmethod_ids() == NULL) { - cld->set_jmethod_ids(new JNIMethodBlock(capacity)); - } else { - cld->jmethod_ids()->ensure_methods(capacity); - } +void Method::ensure_jmethod_ids(ClassLoaderData* cld, int capacity) { + // Have to add jmethod_ids() to class loader data thread-safely. + // Also have to add the method to the list safely, which the lock + // protects as well. + MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); + if (cld->jmethod_ids() == NULL) { + cld->set_jmethod_ids(new JNIMethodBlock(capacity)); } else { - // At safepoint, we are single threaded and can set this. - if (cld->jmethod_ids() == NULL) { - cld->set_jmethod_ids(new JNIMethodBlock(capacity)); - } else { - cld->jmethod_ids()->ensure_methods(capacity); - } + cld->jmethod_ids()->ensure_methods(capacity); } } // Add a method id to the jmethod_ids -jmethodID Method::make_jmethod_id(ClassLoaderData* loader_data, Method* m) { - ClassLoaderData* cld = loader_data; - - if (!SafepointSynchronize::is_at_safepoint()) { - // Have to add jmethod_ids() to class loader data thread-safely. - // Also have to add the method to the list safely, which the lock - // protects as well. - MutexLocker ml(JmethodIdCreation_lock, Mutex::_no_safepoint_check_flag); - if (cld->jmethod_ids() == NULL) { - cld->set_jmethod_ids(new JNIMethodBlock()); - } - // jmethodID is a pointer to Method* - return (jmethodID)cld->jmethod_ids()->add_method(m); - } else { - // At safepoint, we are single threaded and can set this. - if (cld->jmethod_ids() == NULL) { - cld->set_jmethod_ids(new JNIMethodBlock()); - } - // jmethodID is a pointer to Method* - return (jmethodID)cld->jmethod_ids()->add_method(m); +jmethodID Method::make_jmethod_id(ClassLoaderData* cld, Method* m) { + // Have to add jmethod_ids() to class loader data thread-safely. + // Also have to add the method to the list safely, which the lock + // protects as well. + assert(JmethodIdCreation_lock->owned_by_self(), "sanity check"); + if (cld->jmethod_ids() == NULL) { + cld->set_jmethod_ids(new JNIMethodBlock()); } + // jmethodID is a pointer to Method* + return (jmethodID)cld->jmethod_ids()->add_method(m); } jmethodID Method::jmethod_id() { @@ -2218,8 +2197,7 @@ jmethodID Method::jmethod_id() { // Mark a jmethodID as free. This is called when there is a data race in // InstanceKlass while creating the jmethodID cache. -void Method::destroy_jmethod_id(ClassLoaderData* loader_data, jmethodID m) { - ClassLoaderData* cld = loader_data; +void Method::destroy_jmethod_id(ClassLoaderData* cld, jmethodID m) { Method** ptr = (Method**)m; assert(cld->jmethod_ids() != NULL, "should have method handles"); cld->jmethod_ids()->destroy_method(ptr); diff --git a/src/hotspot/share/oops/method.hpp b/src/hotspot/share/oops/method.hpp index 1fc28c86df3..4a5df8134cc 100644 --- a/src/hotspot/share/oops/method.hpp +++ b/src/hotspot/share/oops/method.hpp @@ -774,13 +774,13 @@ class Method : public Metadata { // however, can be GC'ed away if the class is unloaded or if the method is // made obsolete or deleted -- in these cases, the jmethodID // refers to NULL (as is the case for any weak reference). - static jmethodID make_jmethod_id(ClassLoaderData* loader_data, Method* mh); - static void destroy_jmethod_id(ClassLoaderData* loader_data, jmethodID mid); + static jmethodID make_jmethod_id(ClassLoaderData* cld, Method* mh); + static void destroy_jmethod_id(ClassLoaderData* cld, jmethodID mid); // Ensure there is enough capacity in the internal tracking data // structures to hold the number of jmethodIDs you plan to generate. // This saves substantial time doing allocations. - static void ensure_jmethod_ids(ClassLoaderData* loader_data, int capacity); + static void ensure_jmethod_ids(ClassLoaderData* cld, int capacity); // Use resolve_jmethod_id() in situations where the caller is expected // to provide a valid jmethodID; the only sanity checks are in asserts; From 173778e2fee58e47d35197b78eb23f46154b5b2b Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Tue, 13 Dec 2022 00:57:02 +0000 Subject: [PATCH 179/494] 8298568: Fastdebug build fails after JDK-8296389 Reviewed-by: rkennke, kvn, haosun --- src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp index 31c480a488a..d443bb8aa33 100644 --- a/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp +++ b/src/hotspot/share/gc/shenandoah/c2/shenandoahSupport.cpp @@ -2002,7 +2002,7 @@ Node* ShenandoahIUBarrierNode::Identity(PhaseGVN* phase) { static bool has_never_branch(Node* root) { for (uint i = 1; i < root->req(); i++) { Node* in = root->in(i); - if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->isNeverBranch()) { + if (in != NULL && in->Opcode() == Op_Halt && in->in(0)->is_Proj() && in->in(0)->in(0)->is_NeverBranch()) { return true; } } From 3b1142a280d66b2f5f7b4afbc76e940fdc30b463 Mon Sep 17 00:00:00 2001 From: Prasanta Sadhukhan Date: Tue, 13 Dec 2022 10:21:57 +0000 Subject: [PATCH 180/494] 8298618: Typo in JPEGImageReader and JPEGImageWriter Reviewed-by: iris, jdv, abhiscxk --- .../classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java | 2 +- .../classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java index add90538ef1..e2b3b3537ac 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageReader.java @@ -1824,7 +1824,7 @@ private synchronized void clearThreadLock() { Thread currThread = Thread.currentThread(); if (theThread == null || theThread != currThread) { throw new IllegalStateException("Attempt to clear thread lock " + - " form wrong thread." + + " from wrong thread." + " Locked thread: " + theThread + "; current thread: " + currThread); } diff --git a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java index 58f2cd023c5..0d41c4d2961 100644 --- a/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java +++ b/src/java.desktop/share/classes/com/sun/imageio/plugins/jpeg/JPEGImageWriter.java @@ -1821,7 +1821,7 @@ private synchronized void setThreadLock() { private synchronized void clearThreadLock() { Thread currThread = Thread.currentThread(); if (theThread == null || theThread != currThread) { - throw new IllegalStateException("Attempt to clear thread lock form wrong thread. " + + throw new IllegalStateException("Attempt to clear thread lock from wrong thread. " + "Locked thread: " + theThread + "; current thread: " + currThread); } From dbcfe7bc335846cd154dd78822fb64b7970ff9d2 Mon Sep 17 00:00:00 2001 From: Yude Lin Date: Tue, 13 Dec 2022 10:26:05 +0000 Subject: [PATCH 181/494] 8298521: Rename members in G1MonitoringSupport Reviewed-by: ayang, tschatzl --- .../share/gc/g1/g1MonitoringSupport.cpp | 20 +++++++++---------- .../share/gc/g1/g1MonitoringSupport.hpp | 8 ++++---- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp index beef2738ac9..680e989c853 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.cpp @@ -88,13 +88,13 @@ class G1OldGenerationCounters : public G1GenerationCounters { G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : _g1h(g1h), - _incremental_memory_manager("G1 Young Generation", "end of minor GC"), + _young_gc_memory_manager("G1 Young Generation", "end of minor GC"), _full_gc_memory_manager("G1 Old Generation", "end of major GC"), _conc_gc_memory_manager("G1 Concurrent GC", "end of concurrent GC pause"), _eden_space_pool(NULL), _survivor_space_pool(NULL), _old_gen_pool(NULL), - _incremental_collection_counters(NULL), + _young_collection_counters(NULL), _full_collection_counters(NULL), _conc_collection_counters(NULL), _young_gen_counters(NULL), @@ -121,7 +121,7 @@ G1MonitoringSupport::G1MonitoringSupport(G1CollectedHeap* g1h) : // // name "collector.0". In a generational collector this would be the // young generation collection. - _incremental_collection_counters = + _young_collection_counters = new CollectorCounters("G1 young collection pauses", 0); // name "collector.1". In a generational collector this would be the // old generation collection. @@ -202,9 +202,9 @@ void G1MonitoringSupport::initialize_serviceability() { _conc_gc_memory_manager.add_pool(_old_gen_pool); - _incremental_memory_manager.add_pool(_eden_space_pool); - _incremental_memory_manager.add_pool(_survivor_space_pool); - _incremental_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); + _young_gc_memory_manager.add_pool(_eden_space_pool); + _young_gc_memory_manager.add_pool(_survivor_space_pool); + _young_gc_memory_manager.add_pool(_old_gen_pool, false /* always_affected_by_gc */); } MemoryUsage G1MonitoringSupport::memory_usage() { @@ -214,7 +214,7 @@ MemoryUsage G1MonitoringSupport::memory_usage() { GrowableArray G1MonitoringSupport::memory_managers() { GrowableArray memory_managers(3); - memory_managers.append(&_incremental_memory_manager); + memory_managers.append(&_young_gc_memory_manager); memory_managers.append(&_full_gc_memory_manager); memory_managers.append(&_conc_gc_memory_manager); return memory_managers; @@ -298,7 +298,7 @@ void G1MonitoringSupport::update_sizes() { if (UsePerfData) { _eden_space_counters->update_capacity(pad_capacity(_eden_space_committed)); _eden_space_counters->update_used(_eden_space_used); - // only the "to" survivor space is active, so we don't need to + // only the "to" survivor space is active, so we don't need to // update the counters for the "from" survivor space _to_space_counters->update_capacity(pad_capacity(_survivor_space_committed)); _to_space_counters->update_used(_survivor_space_used); @@ -367,8 +367,8 @@ G1MonitoringScope::~G1MonitoringScope() { G1YoungGCMonitoringScope::G1YoungGCMonitoringScope(G1MonitoringSupport* monitoring_support, bool all_memory_pools_affected) : G1MonitoringScope(monitoring_support, - monitoring_support->_incremental_collection_counters, - &monitoring_support->_incremental_memory_manager, + monitoring_support->_young_collection_counters, + &monitoring_support->_young_gc_memory_manager, all_memory_pools_affected) { } diff --git a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp index 024e6583144..bae4ade0e43 100644 --- a/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp +++ b/src/hotspot/share/gc/g1/g1MonitoringSupport.hpp @@ -128,7 +128,7 @@ class G1MonitoringSupport : public CHeapObj { G1CollectedHeap* _g1h; // java.lang.management MemoryManager and MemoryPool support - GCMemoryManager _incremental_memory_manager; + GCMemoryManager _young_gc_memory_manager; GCMemoryManager _full_gc_memory_manager; GCMemoryManager _conc_gc_memory_manager; @@ -137,11 +137,11 @@ class G1MonitoringSupport : public CHeapObj { MemoryPool* _old_gen_pool; // jstat performance counters - // incremental collections both young and mixed - CollectorCounters* _incremental_collection_counters; + // young stop-the-world collections (including mixed) + CollectorCounters* _young_collection_counters; // full stop-the-world collections CollectorCounters* _full_collection_counters; - // stop-the-world phases in G1 + // stop-the-world phases in G1 concurrent collection CollectorCounters* _conc_collection_counters; // young collection set counters. The _eden_counters, // _from_counters, and _to_counters are associated with From 04b8d0cf5c964e16c583b66d9ab43a8c9a85fd72 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Tue, 13 Dec 2022 13:02:23 +0000 Subject: [PATCH 182/494] 8298084: Memory leak in Method::build_profiling_method_data Co-authored-by: Justin King Reviewed-by: kbarrett, eosterlund, dholmes, jcking, thartmann --- src/hotspot/share/memory/metadataFactory.hpp | 14 +++++++++++--- src/hotspot/share/oops/instanceKlass.cpp | 18 ++++++++++-------- src/hotspot/share/oops/instanceKlass.hpp | 2 +- src/hotspot/share/oops/method.cpp | 7 +++---- src/hotspot/share/oops/methodData.cpp | 10 ++++++++++ src/hotspot/share/oops/methodData.hpp | 5 +++-- 6 files changed, 38 insertions(+), 18 deletions(-) diff --git a/src/hotspot/share/memory/metadataFactory.hpp b/src/hotspot/share/memory/metadataFactory.hpp index 45237efd678..4f9f7490e11 100644 --- a/src/hotspot/share/memory/metadataFactory.hpp +++ b/src/hotspot/share/memory/metadataFactory.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2010, 2022, 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,6 +30,7 @@ #include "oops/array.inline.hpp" #include "utilities/exceptions.hpp" #include "utilities/globalDefinitions.hpp" +#include class MetadataFactory : AllStatic { public: @@ -61,14 +62,21 @@ class MetadataFactory : AllStatic { // Deallocation method for metadata template - static void free_metadata(ClassLoaderData* loader_data, T md) { + static void free_metadata(ClassLoaderData* loader_data, T* md) { if (md != NULL) { assert(loader_data != NULL, "shouldn't pass null"); int size = md->size(); - // Call metadata's deallocate function which will call deallocate fields + // Call metadata's deallocate function which will deallocate fields and release_C_heap_structures assert(!md->on_stack(), "can't deallocate things on stack"); assert(!md->is_shared(), "cannot deallocate if in shared spaces"); md->deallocate_contents(loader_data); + // Call the destructor. This is currently used for MethodData which has a member + // that needs to be destructed to release resources. Most Metadata derived classes have noop + // destructors and/or cleanup using deallocate_contents. + // T is a potentially const or volatile qualified pointer. Remove any const + // or volatile so we can call the destructor of the type T points to. + using U = std::remove_cv_t; + md->~U(); loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass()); } } diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index 7432a607d3b..dade330a248 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -595,10 +595,10 @@ void InstanceKlass::deallocate_contents(ClassLoaderData* loader_data) { // Release C heap allocated data that this points to, which includes // reference counting symbol names. - // Can't release the constant pool here because the constant pool can be - // deallocated separately from the InstanceKlass for default methods and - // redefine classes. - release_C_heap_structures(/* release_constant_pool */ false); + // Can't release the constant pool or MethodData C heap data here because the constant + // pool can be deallocated separately from the InstanceKlass for default methods and + // redefine classes. MethodData can also be released separately. + release_C_heap_structures(/* release_sub_metadata */ false); deallocate_methods(loader_data, methods()); set_methods(NULL); @@ -2650,13 +2650,15 @@ static void method_release_C_heap_structures(Method* m) { m->release_C_heap_structures(); } -// Called also by InstanceKlass::deallocate_contents, with false for release_constant_pool. -void InstanceKlass::release_C_heap_structures(bool release_constant_pool) { +// Called also by InstanceKlass::deallocate_contents, with false for release_sub_metadata. +void InstanceKlass::release_C_heap_structures(bool release_sub_metadata) { // Clean up C heap Klass::release_C_heap_structures(); // Deallocate and call destructors for MDO mutexes - methods_do(method_release_C_heap_structures); + if (release_sub_metadata) { + methods_do(method_release_C_heap_structures); + } // Destroy the init_monitor delete _init_monitor; @@ -2696,7 +2698,7 @@ void InstanceKlass::release_C_heap_structures(bool release_constant_pool) { FREE_C_HEAP_ARRAY(char, _source_debug_extension); - if (release_constant_pool) { + if (release_sub_metadata) { constants()->release_C_heap_structures(); } } diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 9911176b71d..56545831f48 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -1012,7 +1012,7 @@ class InstanceKlass: public Klass { // callbacks for actions during class unloading static void unload_class(InstanceKlass* ik); - virtual void release_C_heap_structures(bool release_constant_pool = true); + virtual void release_C_heap_structures(bool release_sub_metadata = true); // Naming const char* signature_name() const; diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index c8b9409ddaa..b5355a156bb 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -141,10 +141,9 @@ void Method::deallocate_contents(ClassLoaderData* loader_data) { void Method::release_C_heap_structures() { if (method_data()) { -#if INCLUDE_JVMCI - FailedSpeculation::free_failed_speculations(method_data()->get_failed_speculations_address()); -#endif - // Destroy MethodData + method_data()->release_C_heap_structures(); + + // Destroy MethodData embedded lock method_data()->~MethodData(); } } diff --git a/src/hotspot/share/oops/methodData.cpp b/src/hotspot/share/oops/methodData.cpp index c8fb31123ca..c8b12329b92 100644 --- a/src/hotspot/share/oops/methodData.cpp +++ b/src/hotspot/share/oops/methodData.cpp @@ -1821,3 +1821,13 @@ void MethodData::clean_weak_method_links() { clean_extra_data(&cl); verify_extra_data_clean(&cl); } + +void MethodData::deallocate_contents(ClassLoaderData* loader_data) { + release_C_heap_structures(); +} + +void MethodData::release_C_heap_structures() { +#if INCLUDE_JVMCI + FailedSpeculation::free_failed_speculations(get_failed_speculations_address()); +#endif +} diff --git a/src/hotspot/share/oops/methodData.hpp b/src/hotspot/share/oops/methodData.hpp index 9dcff2b7ed9..508278e6d74 100644 --- a/src/hotspot/share/oops/methodData.hpp +++ b/src/hotspot/share/oops/methodData.hpp @@ -2449,8 +2449,9 @@ class MethodData : public Metadata { virtual void metaspace_pointers_do(MetaspaceClosure* iter); virtual MetaspaceObj::Type type() const { return MethodDataType; } - // Deallocation support - no metaspace pointer fields to deallocate - void deallocate_contents(ClassLoaderData* loader_data) {} + // Deallocation support + void deallocate_contents(ClassLoaderData* loader_data); + void release_C_heap_structures(); // GC support void set_size(int object_size_in_bytes) { _size = object_size_in_bytes; } From c612f93e5a63cc94da6634c3cf361eb87582f129 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 13 Dec 2022 13:37:33 +0000 Subject: [PATCH 183/494] 8298576: Serial: Move some MarkSweep method definitions to cpp Reviewed-by: stefank, tschatzl --- src/hotspot/share/gc/serial/markSweep.cpp | 48 +++++++++++++++++-- .../share/gc/serial/markSweep.inline.hpp | 41 ---------------- 2 files changed, 44 insertions(+), 45 deletions(-) diff --git a/src/hotspot/share/gc/serial/markSweep.cpp b/src/hotspot/share/gc/serial/markSweep.cpp index 717d931b929..f175c159910 100644 --- a/src/hotspot/share/gc/serial/markSweep.cpp +++ b/src/hotspot/share/gc/serial/markSweep.cpp @@ -65,7 +65,7 @@ MarkAndPushClosure MarkSweep::mark_and_push_closure(ClassLoaderData::_claim_stw_ CLDToOopClosure MarkSweep::follow_cld_closure(&mark_and_push_closure, ClassLoaderData::_claim_stw_fullgc_mark); CLDToOopClosure MarkSweep::adjust_cld_closure(&adjust_pointer_closure, ClassLoaderData::_claim_stw_fullgc_adjust); -template inline void MarkSweep::KeepAliveClosure::do_oop_work(T* p) { +template void MarkSweep::KeepAliveClosure::do_oop_work(T* p) { mark_and_push(p); } @@ -75,7 +75,7 @@ void MarkSweep::push_objarray(oop obj, size_t index) { _objarray_stack.push(task); } -inline void MarkSweep::follow_array(objArrayOop array) { +void MarkSweep::follow_array(objArrayOop array) { MarkSweep::follow_klass(array->klass()); // Don't push empty arrays to avoid unnecessary work. if (array->length() > 0) { @@ -83,7 +83,7 @@ inline void MarkSweep::follow_array(objArrayOop array) { } } -inline void MarkSweep::follow_object(oop obj) { +void MarkSweep::follow_object(oop obj) { assert(obj->is_gc_marked(), "should be marked"); if (obj->is_objArray()) { // Handle object arrays explicitly to allow them to @@ -128,7 +128,7 @@ MarkSweep::FollowStackClosure MarkSweep::follow_stack_closure; void MarkSweep::FollowStackClosure::do_void() { follow_stack(); } -template inline void MarkSweep::follow_root(T* p) { +template void MarkSweep::follow_root(T* p) { assert(!Universe::heap()->is_in(p), "roots shouldn't be things within the heap"); T heap_oop = RawAccess<>::oop_load(p); @@ -173,6 +173,46 @@ void MarkSweep::set_ref_processor(ReferenceProcessor* rp) { mark_and_push_closure.set_ref_discoverer(_ref_processor); } +void MarkSweep::mark_object(oop obj) { + if (StringDedup::is_enabled() && + java_lang_String::is_instance(obj) && + SerialStringDedup::is_candidate_from_mark(obj)) { + _string_dedup_requests->add(obj); + } + + // some marks may contain information we need to preserve so we store them away + // and overwrite the mark. We'll restore it at the end of markSweep. + markWord mark = obj->mark(); + obj->set_mark(markWord::prototype().set_marked()); + + ContinuationGCSupport::transform_stack_chunk(obj); + + if (obj->mark_must_be_preserved(mark)) { + preserve_mark(obj, mark); + } +} + +template void MarkSweep::mark_and_push(T* p) { + T heap_oop = RawAccess<>::oop_load(p); + if (!CompressedOops::is_null(heap_oop)) { + oop obj = CompressedOops::decode_not_null(heap_oop); + if (!obj->mark().is_marked()) { + mark_object(obj); + _marking_stack.push(obj); + } + } +} + +void MarkSweep::follow_klass(Klass* klass) { + oop op = klass->class_loader_data()->holder_no_keepalive(); + MarkSweep::mark_and_push(&op); +} + +template +void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); } +void MarkAndPushClosure::do_oop( oop* p) { do_oop_work(p); } +void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } + AdjustPointerClosure MarkSweep::adjust_pointer_closure; void MarkSweep::adjust_marks() { diff --git a/src/hotspot/share/gc/serial/markSweep.inline.hpp b/src/hotspot/share/gc/serial/markSweep.inline.hpp index 0f4a12af0f9..97283e98746 100644 --- a/src/hotspot/share/gc/serial/markSweep.inline.hpp +++ b/src/hotspot/share/gc/serial/markSweep.inline.hpp @@ -39,46 +39,6 @@ #include "utilities/align.hpp" #include "utilities/stack.inline.hpp" -inline void MarkSweep::mark_object(oop obj) { - if (StringDedup::is_enabled() && - java_lang_String::is_instance(obj) && - SerialStringDedup::is_candidate_from_mark(obj)) { - _string_dedup_requests->add(obj); - } - - // some marks may contain information we need to preserve so we store them away - // and overwrite the mark. We'll restore it at the end of markSweep. - markWord mark = obj->mark(); - obj->set_mark(markWord::prototype().set_marked()); - - ContinuationGCSupport::transform_stack_chunk(obj); - - if (obj->mark_must_be_preserved(mark)) { - preserve_mark(obj, mark); - } -} - -template inline void MarkSweep::mark_and_push(T* p) { - T heap_oop = RawAccess<>::oop_load(p); - if (!CompressedOops::is_null(heap_oop)) { - oop obj = CompressedOops::decode_not_null(heap_oop); - if (!obj->mark().is_marked()) { - mark_object(obj); - _marking_stack.push(obj); - } - } -} - -inline void MarkSweep::follow_klass(Klass* klass) { - oop op = klass->class_loader_data()->holder_no_keepalive(); - MarkSweep::mark_and_push(&op); -} - -template -inline void MarkAndPushClosure::do_oop_work(T* p) { MarkSweep::mark_and_push(p); } -inline void MarkAndPushClosure::do_oop( oop* p) { do_oop_work(p); } -inline void MarkAndPushClosure::do_oop(narrowOop* p) { do_oop_work(p); } - template inline void MarkSweep::adjust_pointer(T* p) { T heap_oop = RawAccess<>::oop_load(p); if (!CompressedOops::is_null(heap_oop)) { @@ -98,7 +58,6 @@ void AdjustPointerClosure::do_oop_work(T* p) { MarkSweep::adjust_point inline void AdjustPointerClosure::do_oop(oop* p) { do_oop_work(p); } inline void AdjustPointerClosure::do_oop(narrowOop* p) { do_oop_work(p); } - inline size_t MarkSweep::adjust_pointers(oop obj) { return obj->oop_iterate_size(&MarkSweep::adjust_pointer_closure); } From 216775ff22e98dadac9ecd9d2cd756d136fd3bd0 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 13 Dec 2022 14:28:40 +0000 Subject: [PATCH 184/494] 8298144: Remove Space::new_dcto_cl Reviewed-by: stefank, tschatzl --- src/hotspot/share/gc/shared/cardTableRS.cpp | 4 ++-- src/hotspot/share/gc/shared/cardTableRS.hpp | 6 +++--- src/hotspot/share/gc/shared/space.cpp | 6 ------ src/hotspot/share/gc/shared/space.hpp | 11 +---------- 4 files changed, 6 insertions(+), 21 deletions(-) diff --git a/src/hotspot/share/gc/shared/cardTableRS.cpp b/src/hotspot/share/gc/shared/cardTableRS.cpp index bff99c179e0..00a4c93c960 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.cpp +++ b/src/hotspot/share/gc/shared/cardTableRS.cpp @@ -111,7 +111,7 @@ void ClearNoncleanCardWrapper::do_MemRegion(MemRegion mr) { } } -void CardTableRS::younger_refs_in_space_iterate(Space* sp, +void CardTableRS::younger_refs_in_space_iterate(ContiguousSpace* sp, HeapWord* gen_boundary, OopIterateClosure* cl) { verify_used_region_at_save_marks(sp); @@ -440,7 +440,7 @@ void CardTableRS::initialize() { CardTable::initialize(); } -void CardTableRS::non_clean_card_iterate(Space* sp, +void CardTableRS::non_clean_card_iterate(ContiguousSpace* sp, HeapWord* gen_boundary, MemRegion mr, OopIterateClosure* cl, diff --git a/src/hotspot/share/gc/shared/cardTableRS.hpp b/src/hotspot/share/gc/shared/cardTableRS.hpp index 4a7135c02b7..0e49d496b2d 100644 --- a/src/hotspot/share/gc/shared/cardTableRS.hpp +++ b/src/hotspot/share/gc/shared/cardTableRS.hpp @@ -29,10 +29,10 @@ #include "memory/memRegion.hpp" #include "oops/oop.hpp" +class ContiguousSpace; class DirtyCardToOopClosure; class Generation; class Space; - // This RemSet uses a card table both as shared data structure // for a mod ref barrier set and for the rem set information. @@ -47,7 +47,7 @@ class CardTableRS : public CardTable { public: CardTableRS(MemRegion whole_heap); - void younger_refs_in_space_iterate(Space* sp, HeapWord* gen_boundary, OopIterateClosure* cl); + void younger_refs_in_space_iterate(ContiguousSpace* sp, HeapWord* gen_boundary, OopIterateClosure* cl); virtual void verify_used_region_at_save_marks(Space* sp) const NOT_DEBUG_RETURN; @@ -70,7 +70,7 @@ class CardTableRS : public CardTable { // Iterate over the portion of the card-table which covers the given // region mr in the given space and apply cl to any dirty sub-regions // of mr. Clears the dirty cards as they are processed. - void non_clean_card_iterate(Space* sp, + void non_clean_card_iterate(ContiguousSpace* sp, HeapWord* gen_boundary, MemRegion mr, OopIterateClosure* cl, diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 84925eb499d..43f06dd0b90 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -161,12 +161,6 @@ void DirtyCardToOopClosure::do_MemRegion(MemRegion mr) { _min_done = bottom; } -DirtyCardToOopClosure* Space::new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, - HeapWord* boundary) { - return new DirtyCardToOopClosure(this, cl, precision, boundary); -} - HeapWord* ContiguousSpaceDCTOC::get_actual_top(HeapWord* top, HeapWord* top_obj) { if (top_obj != NULL && top_obj < (_sp->toContiguousSpace())->top()) { diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index 211dc51125c..b673f3acfd1 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -173,14 +173,6 @@ class Space: public CHeapObj { // included in the iteration. virtual void object_iterate(ObjectClosure* blk) = 0; - // Create and return a new dirty card to oop closure. Can be - // overridden to return the appropriate type of closure - // depending on the type of space in which the closure will - // operate. ResourceArea allocated. - virtual DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, - CardTable::PrecisionStyle precision, - HeapWord* boundary); - // If "p" is in the space, returns the address of the start of the // "block" that contains "p". We say "block" instead of "object" since // some heaps may not pack objects densely; a chunk may either be an @@ -474,10 +466,9 @@ class ContiguousSpace: public CompactibleSpace { set_top(compaction_top()); } - // Override. DirtyCardToOopClosure* new_dcto_cl(OopIterateClosure* cl, CardTable::PrecisionStyle precision, - HeapWord* boundary) override; + HeapWord* boundary); // Apply "blk->do_oop" to the addresses of all reference fields in objects // starting with the _saved_mark_word, which was noted during a generation's From 4081bba86900d03f195258ca88d51321d31d3678 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Tue, 13 Dec 2022 14:29:46 +0000 Subject: [PATCH 185/494] 8297960: G1: Move Root Region Scan Waiting outside collection in logs Reviewed-by: iwalulya, tschatzl --- src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp index 83a22a5e820..b799a12531b 100644 --- a/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp +++ b/src/hotspot/share/gc/g1/g1GCPhaseTimes.cpp @@ -412,8 +412,7 @@ double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { const double pre_concurrent_start_ms = average_time_ms(ResetMarkingState) + average_time_ms(NoteStartOfMark); - const double sum_ms = _root_region_scan_wait_time_ms + - _cur_prepare_tlab_time_ms + + const double sum_ms = _cur_prepare_tlab_time_ms + _cur_concatenate_dirty_card_logs_time_ms + _recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms + @@ -423,9 +422,6 @@ double G1GCPhaseTimes::print_pre_evacuate_collection_set() const { info_time("Pre Evacuate Collection Set", sum_ms); - if (_root_region_scan_wait_time_ms > 0.0) { - debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); - } debug_time("Prepare TLABs", _cur_prepare_tlab_time_ms); debug_time("Concatenate Dirty Card Logs", _cur_concatenate_dirty_card_logs_time_ms); debug_time("Choose Collection Set", (_recorded_young_cset_choice_time_ms + _recorded_non_young_cset_choice_time_ms)); @@ -557,6 +553,10 @@ void G1GCPhaseTimes::print_other(double accounted_ms) const { } void G1GCPhaseTimes::print(bool evacuation_failed) { + if (_root_region_scan_wait_time_ms > 0.0) { + debug_time("Root Region Scan Waiting", _root_region_scan_wait_time_ms); + } + // Check if some time has been recorded for verification and only then print // the message. We do not use Verify*GC here to print because VerifyGCType // further limits actual verification. @@ -565,10 +565,17 @@ void G1GCPhaseTimes::print(bool evacuation_failed) { } double accounted_ms = 0.0; + + accounted_ms += _root_region_scan_wait_time_ms; + accounted_ms += _cur_verify_before_time_ms; + accounted_ms += print_pre_evacuate_collection_set(); accounted_ms += print_evacuate_initial_collection_set(); accounted_ms += print_evacuate_optional_collection_set(); accounted_ms += print_post_evacuate_collection_set(evacuation_failed); + + accounted_ms += _cur_verify_after_time_ms; + print_other(accounted_ms); // See above comment on the _cur_verify_before_time_ms check. From 042b7062f19b313f31b228bd96d2a74cc1165ab9 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Tue, 13 Dec 2022 15:43:16 +0000 Subject: [PATCH 186/494] 8297235: ZGC: assert(regs[i] != regs[j]) failed: Multiple uses of register: rax Reviewed-by: eosterlund, ayang, rcastanedalo --- src/hotspot/cpu/x86/gc/z/z_x86_64.ad | 63 +++++++++++++------------- test/jdk/ProblemList-zgc.txt | 68 ---------------------------- 2 files changed, 31 insertions(+), 100 deletions(-) diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index f3e19b41733..44f3f221fae 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -35,7 +35,7 @@ source %{ static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, uint8_t barrier_data) { if (barrier_data == ZLoadBarrierElided) { - return; // Elided. + return; } ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); { @@ -60,6 +60,27 @@ static void z_load_barrier_cmpxchg(MacroAssembler& _masm, const MachNode* node, __ bind(*stub->continuation()); } +static void z_cmpxchg_common(MacroAssembler& _masm, const MachNode* node, Register mem_reg, Register newval, Register tmp) { + // Compare value (oldval) is in rax + const Address mem = Address(mem_reg, 0); + + if (node->barrier_data() != ZLoadBarrierElided) { + __ movptr(tmp, rax); + } + + __ lock(); + __ cmpxchgptr(newval, mem); + + if (node->barrier_data() != ZLoadBarrierElided) { + Label good; + z_load_barrier_cmpxchg(_masm, node, mem, rax, tmp, good); + __ movptr(rax, tmp); + __ lock(); + __ cmpxchgptr(newval, mem); + __ bind(good); + } +} + %} // Load Pointer @@ -81,7 +102,7 @@ instruct zLoadP(rRegP dst, memory mem, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ +instruct zCompareAndExchangeP(indirect mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ match(Set oldval (CompareAndExchangeP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); effect(KILL cr, TEMP tmp); @@ -90,26 +111,14 @@ instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP t "cmpxchgq $newval, $mem" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - - if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - } + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); %} ins_pipe(pipe_cmpxchg); %} -instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ +instruct zCompareAndSwapP(rRegI res, indirect mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ match(Set res (CompareAndSwapP mem (Binary oldval newval))); match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); @@ -121,20 +130,10 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags "movzbl $res, $res" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - __ cmpptr($tmp$$Register, $oldval$$Register); + __ cmpptr($tmp$$Register, rax); } __ setb(Assembler::equal, $res$$Register); __ movzbl($res$$Register, $res$$Register); @@ -143,7 +142,7 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags ins_pipe(pipe_cmpxchg); %} -instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ +instruct zXChgP(indirect mem, rRegP newval, rFlagsReg cr) %{ match(Set newval (GetAndSetP mem newval)); predicate(UseZGC && n->as_LoadStore()->barrier_data() != 0); effect(KILL cr); @@ -151,7 +150,7 @@ instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ format %{ "xchgq $newval, $mem" %} ins_encode %{ - __ xchgptr($newval$$Register, $mem$$Address); + __ xchgptr($newval$$Register, Address($mem$$Register, 0)); z_load_barrier(_masm, this, Address(noreg, 0), $newval$$Register, noreg /* tmp */, barrier_data()); %} diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index f4b2f9ae4e8..c3d4ecd4b9f 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -26,71 +26,3 @@ # List of quarantined tests for testing with ZGC. # ############################################################################# - -java/lang/StackWalker/AcrossThreads.java 8297235 generic-x64 -java/math/BigInteger/BigIntegerParallelMultiplyTest.java 8297235 generic-x64 -java/util/Arrays/SetAllTest.java 8297235 generic-x64 -java/util/Arrays/Sorting.java 8297235 generic-x64 -java/util/Arrays/largeMemory/ParallelPrefix.java 8297235 generic-x64 -java/util/BitSet/stream/BitSetStreamTest.java 8297235 generic-x64 -java/util/Collection/IteratorMicroBenchmark.java 8297235 generic-x64 -java/util/Collections/UnmodifiableMapEntrySet.java 8297235 generic-x64 -java/util/DoubleStreamSums/CompensatedSums.java 8297235 generic-x64 -java/util/Random/RandomTest.java 8297235 generic-x64 -java/util/Scanner/ScannerStreamTest.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNow.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAny.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAnyRace.java 8297235 generic-x64 -java/util/concurrent/forkjoin/Integrate.java 8297235 generic-x64 -java/util/concurrent/forkjoin/NQueensCS.java 8297235 generic-x64 -java/util/concurrent/tck/JSR166TestCase.java 8297235 generic-x64 -java/util/regex/PatternStreamTest.java 8297235 generic-x64 -java/util/stream/CustomFJPoolTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/DoubleNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/FlagOpTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/IntNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/LongNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/NodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/StreamReuseTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpStatefulTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/mapMultiOpTest.java 8297235 generic-x64 - -jdk/internal/vm/Continuation/Fuzz.java#default 8298058 generic-x64 From bf78f716bd3e58df24ff1e6f4a0104025379f821 Mon Sep 17 00:00:00 2001 From: Brent Christian Date: Tue, 13 Dec 2022 19:07:44 +0000 Subject: [PATCH 187/494] 8295857: Clarify that cleanup code can be skipped when the JVM terminates (e.g. when calling halt()) Reviewed-by: iris Backport-of: c7aca73177339f931f7dfb6627365548a32874f7 --- .../share/classes/java/lang/Runtime.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/java.base/share/classes/java/lang/Runtime.java b/src/java.base/share/classes/java/lang/Runtime.java index fd35265c0cc..ffef8160c25 100644 --- a/src/java.base/share/classes/java/lang/Runtime.java +++ b/src/java.base/share/classes/java/lang/Runtime.java @@ -89,10 +89,14 @@ * shutdown sequence. * *

    When the JVM terminates, all threads are immediately prevented from executing any further - * Java code. This includes shutdown hooks as well as daemon and non-daemon threads. The - * threads' current methods do not complete normally or abruptly; no {@code finally} clause - * of any method is executed, nor is any {@linkplain Thread.UncaughtExceptionHandler - * uncaught exception handler}. + * Java code. This includes shutdown hooks as well as daemon and non-daemon threads. + * This means, for example, that: + *

      + *
    • threads' current methods do not complete normally or abruptly;
    • + *
    • {@code finally} clauses are not executed;
    • + *
    • {@linkplain Thread.UncaughtExceptionHandler uncaught exception handlers} are not run; and
    • + *
    • resources opened with try-with-resources are not {@linkplain AutoCloseable closed};
    • + *
    * * @implNote * Native code typically uses the @@ -278,7 +282,8 @@ public boolean removeShutdownHook(Thread hook) { * @apiNote * This method should be used with extreme caution. Using it may circumvent or disrupt * any cleanup actions intended to be performed by shutdown hooks, possibly leading to - * data corruption. + * data corruption. See the termination section above + * for other possible consequences of halting the Java Virtual Machine. * * @param status * Termination status. By convention, a nonzero status code From 68022770dedb78f9e6d26c17d76ea6df2f17600b Mon Sep 17 00:00:00 2001 From: Ioi Lam Date: Tue, 13 Dec 2022 19:35:30 +0000 Subject: [PATCH 188/494] 8298524: Debug function to trace reachability of CDS archived heap objects Reviewed-by: ccheung --- src/hotspot/share/cds/cdsHeapVerifier.cpp | 44 +++++++++++++---------- src/hotspot/share/cds/cdsHeapVerifier.hpp | 4 ++- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/src/hotspot/share/cds/cdsHeapVerifier.cpp b/src/hotspot/share/cds/cdsHeapVerifier.cpp index 710c87069b0..c02caced364 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.cpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.cpp @@ -236,7 +236,7 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& ls.print("Value: "); orig_obj->print_on(&ls); ls.print_cr("--- trace begin ---"); - trace_to_root(orig_obj, NULL, &value); + trace_to_root(&ls, orig_obj, NULL, &value); ls.print_cr("--- trace end ---"); ls.cr(); _problems ++; @@ -248,54 +248,62 @@ inline bool CDSHeapVerifier::do_entry(oop& orig_obj, HeapShared::CachedOopInfo& class CDSHeapVerifier::TraceFields : public FieldClosure { oop _orig_obj; oop _orig_field; - LogStream* _ls; + outputStream* _st; public: - TraceFields(oop orig_obj, oop orig_field, LogStream* ls) - : _orig_obj(orig_obj), _orig_field(orig_field), _ls(ls) {} + TraceFields(oop orig_obj, oop orig_field, outputStream* st) + : _orig_obj(orig_obj), _orig_field(orig_field), _st(st) {} void do_field(fieldDescriptor* fd) { if (fd->field_type() == T_OBJECT || fd->field_type() == T_ARRAY) { oop obj_field = _orig_obj->obj_field(fd->offset()); if (obj_field == _orig_field) { - _ls->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset()); + _st->print("::%s (offset = %d)", fd->name()->as_C_string(), fd->offset()); } } } }; -// Hint: to exercise this function, uncomment out one of the ADD_EXCL lines above. -int CDSHeapVerifier::trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p) { +// Call this function (from gdb, etc) if you want to know why an object is archived. +void CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj) { + HeapShared::CachedOopInfo* info = HeapShared::archived_object_cache()->get(orig_obj); + if (info != NULL) { + trace_to_root(st, orig_obj, NULL, info); + } else { + st->print_cr("Not an archived object??"); + } +} + +int CDSHeapVerifier::trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* info) { int level = 0; - LogStream ls(Log(cds, heap)::warning()); - if (p->_referrer != NULL) { - HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(p->_referrer); + if (info->_referrer != NULL) { + HeapShared::CachedOopInfo* ref = HeapShared::archived_object_cache()->get(info->_referrer); assert(ref != NULL, "sanity"); - level = trace_to_root(p->_referrer, orig_obj, ref) + 1; + level = trace_to_root(st, info->_referrer, orig_obj, ref) + 1; } else if (java_lang_String::is_instance(orig_obj)) { - ls.print_cr("[%2d] (shared string table)", level++); + st->print_cr("[%2d] (shared string table)", level++); } Klass* k = orig_obj->klass(); ResourceMark rm; - ls.print("[%2d] ", level); - orig_obj->print_address_on(&ls); - ls.print(" %s", k->internal_name()); + st->print("[%2d] ", level); + orig_obj->print_address_on(st); + st->print(" %s", k->internal_name()); if (orig_field != NULL) { if (k->is_instance_klass()) { - TraceFields clo(orig_obj, orig_field, &ls);; + TraceFields clo(orig_obj, orig_field, st); InstanceKlass::cast(k)->do_nonstatic_fields(&clo); } else { assert(orig_obj->is_objArray(), "must be"); objArrayOop array = (objArrayOop)orig_obj; for (int i = 0; i < array->length(); i++) { if (array->obj_at(i) == orig_field) { - ls.print(" @[%d]", i); + st->print(" @[%d]", i); break; } } } } - ls.cr(); + st->cr(); return level; } diff --git a/src/hotspot/share/cds/cdsHeapVerifier.hpp b/src/hotspot/share/cds/cdsHeapVerifier.hpp index 6bc8c7ddd87..947308e24e8 100644 --- a/src/hotspot/share/cds/cdsHeapVerifier.hpp +++ b/src/hotspot/share/cds/cdsHeapVerifier.hpp @@ -69,7 +69,7 @@ class CDSHeapVerifier : public KlassClosure { } return NULL; } - int trace_to_root(oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); + static int trace_to_root(outputStream* st, oop orig_obj, oop orig_field, HeapShared::CachedOopInfo* p); CDSHeapVerifier(); ~CDSHeapVerifier(); @@ -83,6 +83,8 @@ class CDSHeapVerifier : public KlassClosure { inline bool do_entry(oop& orig_obj, HeapShared::CachedOopInfo& value); static void verify() NOT_DEBUG_RETURN; + + static void trace_to_root(outputStream* st, oop orig_obj); }; #endif // INCLUDE_CDS_JAVA_HEAP From a120764cc4636b3b0cd128d43de148bdc3f4513b Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 13 Dec 2022 19:49:16 +0000 Subject: [PATCH 189/494] 8298514: vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002/TestDescription.java fails with usage tracker Reviewed-by: cjplummer, sspitsyn --- .../threadDeathRequests/thrdeathreq002.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java index ac3ab653fa9..d725958ff65 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventRequestManager/threadDeathRequests/thrdeathreq002.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -266,7 +266,7 @@ private void testRun() for (int i = 0; ; i++) { vm.resume(); - breakpointForCommunication(); + breakpointForCommunication(debuggeeName); int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); From 220781fa56a9c8d3b64c5c6578ffd76b9edb795c Mon Sep 17 00:00:00 2001 From: Alex Menkov Date: Tue, 13 Dec 2022 19:50:09 +0000 Subject: [PATCH 190/494] 8298513: vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009/TestDescription.java fails with usage tracker Reviewed-by: cjplummer, sspitsyn, lmesnik --- .../nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java index 86a8e1faa5e..d7a1bbc7833 100644 --- a/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java +++ b/test/hotspot/jtreg/vmTestbase/nsk/jdi/EventSet/suspendPolicy/suspendpolicy009.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2001, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2001, 2022, 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 @@ -292,7 +292,7 @@ private void testRun() for (int i = 0; ; i++) { - breakpointForCommunication(); + breakpointForCommunication(debuggeeName); int instruction = ((IntegerValue) (debuggeeClass.getValue(debuggeeClass.fieldByName("instruction")))).value(); From c6f22b416072a9be5436f45e2f595ceea228f3bd Mon Sep 17 00:00:00 2001 From: Joe Darcy Date: Tue, 13 Dec 2022 20:48:13 +0000 Subject: [PATCH 191/494] 8297305: Clarify that javax.lang.model.util.Elements.overrides is irreflexive Reviewed-by: jjg --- .../share/classes/javax/lang/model/util/Elements.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java index f567c7f3b1b..c8849d6f612 100644 --- a/src/java.compiler/share/classes/javax/lang/model/util/Elements.java +++ b/src/java.compiler/share/classes/javax/lang/model/util/Elements.java @@ -622,6 +622,8 @@ default TypeElement getOutermostTypeElement(Element e) { * overrides another method. * When a non-abstract method overrides an abstract one, the * former is also said to implement the latter. + * As implied by JLS {@jls 8.4.8.1}, a method does not + * override itself. The overrides relation is irreflexive. * *

    In the simplest and most typical usage, the value of the * {@code type} parameter will simply be the class or interface From 61ab16f79a735a98b3c095daf1b541f4fc5413c0 Mon Sep 17 00:00:00 2001 From: Jonathan Gibbons Date: Tue, 13 Dec 2022 23:20:43 +0000 Subject: [PATCH 192/494] 8298700: Typo in DocTree comment Reviewed-by: darcy --- .../share/classes/com/sun/source/doctree/DocTree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java index 9d457a739da..7f81af9a507 100644 --- a/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java +++ b/src/jdk.compiler/share/classes/com/sun/source/doctree/DocTree.java @@ -227,7 +227,7 @@ enum Kind { SPEC("spec"), /** - * Used for instances of {@link EndElementTree} + * Used for instances of {@link StartElementTree} * representing the start of an HTML element. */ START_ELEMENT, From 51f0a1ce4b0d72cf7e82e01f7014274d8b7d1575 Mon Sep 17 00:00:00 2001 From: Christoph Langer Date: Wed, 14 Dec 2022 07:32:28 +0000 Subject: [PATCH 193/494] 8298527: Cygwin's uname -m returns different string than before Reviewed-by: erikj --- make/autoconf/build-aux/config.guess | 74 +++++++++++++--------------- 1 file changed, 34 insertions(+), 40 deletions(-) diff --git a/make/autoconf/build-aux/config.guess b/make/autoconf/build-aux/config.guess index b08072b556c..daf45ae414d 100644 --- a/make/autoconf/build-aux/config.guess +++ b/make/autoconf/build-aux/config.guess @@ -29,7 +29,40 @@ # and fix the broken property, if needed. DIR=`dirname $0` -OUT=`. $DIR/autoconf-config.guess` +OUT=`. $DIR/autoconf-config.guess 2> /dev/null` + +# Handle some cases that autoconf-config.guess is not capable of +if [ "x$OUT" = x ]; then + if [ `uname -s` = Linux ]; then + # Test and fix little endian MIPS. + if [ `uname -m` = mipsel ]; then + OUT=mipsel-unknown-linux-gnu + elif [ `uname -m` = mips64el ]; then + OUT=mips64el-unknown-linux-gnu + # Test and fix little endian PowerPC64. + elif [ `uname -m` = ppc64le ]; then + OUT=powerpc64le-unknown-linux-gnu + # Test and fix LoongArch64. + elif [ `uname -m` = loongarch64 ]; then + OUT=loongarch64-unknown-linux-gnu + # Test and fix RISC-V. + elif [ `uname -m` = riscv64 ]; then + OUT=riscv64-unknown-linux-gnu + fi + # Test and fix cygwin machine arch .x86_64 + elif [[ `uname -s` = CYGWIN* ]]; then + if [ `uname -m` = ".x86_64" ]; then + OUT=x86_64-unknown-cygwin + fi + fi + + if [ "x$OUT" = x ]; then + # Run autoconf-config.guess again to get the error message. + . $DIR/autoconf-config.guess > /dev/null + else + printf "guessed by custom config.guess... " >&2 + fi +fi # Detect C library. # Use '-gnu' suffix on systems that use glibc. @@ -81,45 +114,6 @@ if test $? = 0; then OUT=powerpc$KERNEL_BITMODE`echo $OUT | sed -e 's/[^-]*//'` fi -# Test and fix little endian PowerPC64. -# TODO: should be handled by autoconf-config.guess. -if [ "x$OUT" = x ]; then - if [ `uname -m` = ppc64le ]; then - if [ `uname -s` = Linux ]; then - OUT=powerpc64le-unknown-linux-gnu - fi - fi -fi - -# Test and fix little endian MIPS. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = mipsel ]; then - OUT=mipsel-unknown-linux-gnu - elif [ `uname -m` = mips64el ]; then - OUT=mips64el-unknown-linux-gnu - fi - fi -fi - -# Test and fix LoongArch64. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = loongarch64 ]; then - OUT=loongarch64-unknown-linux-gnu - fi - fi -fi - -# Test and fix RISC-V. -if [ "x$OUT" = x ]; then - if [ `uname -s` = Linux ]; then - if [ `uname -m` = riscv64 ]; then - OUT=riscv64-unknown-linux-gnu - fi - fi -fi - # Test and fix cpu on macos-aarch64, uname -p reports arm, buildsys expects aarch64 echo $OUT | grep arm-apple-darwin > /dev/null 2> /dev/null if test $? != 0; then From 27d4971182ab1cbe7e6bc40cd22c1c70661a3ab2 Mon Sep 17 00:00:00 2001 From: Roland Westrelin Date: Wed, 14 Dec 2022 10:03:36 +0000 Subject: [PATCH 194/494] 8298520: C2: assert(found_opaque == res) failed: wrong pattern Reviewed-by: thartmann, chagedorn --- src/hotspot/share/opto/loopnode.cpp | 21 +++++++++++++++++++-- src/hotspot/share/opto/loopnode.hpp | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index f8250bf59b4..4f7f2c44f1b 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -2547,7 +2547,8 @@ SafePointNode* CountedLoopNode::outer_safepoint() const { Node* CountedLoopNode::skip_predicates_from_entry(Node* ctrl) { while (ctrl != NULL && ctrl->is_Proj() && ctrl->in(0) != NULL && ctrl->in(0)->is_If() && - (ctrl->in(0)->as_If()->proj_out_or_null(1-ctrl->as_Proj()->_con) == NULL || + !is_zero_trip_guard_if(ctrl->in(0)->as_If()) && + (ctrl->in(0)->as_If()->proj_out_or_null(1-ctrl->as_Proj()->_con) == NULL || (ctrl->in(0)->as_If()->proj_out(1-ctrl->as_Proj()->_con)->outcnt() == 1 && ctrl->in(0)->as_If()->proj_out(1-ctrl->as_Proj()->_con)->unique_out()->Opcode() == Op_Halt))) { ctrl = ctrl->in(0)->in(0); @@ -2556,6 +2557,22 @@ Node* CountedLoopNode::skip_predicates_from_entry(Node* ctrl) { return ctrl; } +bool CountedLoopNode::is_zero_trip_guard_if(const IfNode* iff) { + if (iff->in(1) == NULL || !iff->in(1)->is_Bool()) { + return false; + } + if (iff->in(1)->in(1) == NULL || iff->in(1)->in(1)->Opcode() != Op_CmpI) { + return false; + } + if (iff->in(1)->in(1)->in(1) != NULL && iff->in(1)->in(1)->in(1)->Opcode() == Op_OpaqueZeroTripGuard) { + return true; + } + if (iff->in(1)->in(1)->in(2) != NULL && iff->in(1)->in(1)->in(2)->Opcode() == Op_OpaqueZeroTripGuard) { + return true; + } + return false; +} + Node* CountedLoopNode::skip_predicates() { Node* ctrl = in(LoopNode::EntryControl); if (is_main_loop()) { @@ -5459,7 +5476,7 @@ Node* CountedLoopNode::is_canonical_loop_entry() { return NULL; } Node* iffm = ctrl->in(0); - if (iffm == NULL || !iffm->is_If()) { + if (iffm == NULL || iffm->Opcode() != Op_If) { return NULL; } Node* bolzm = iffm->in(1); diff --git a/src/hotspot/share/opto/loopnode.hpp b/src/hotspot/share/opto/loopnode.hpp index defb1ad6cbb..aadcf42a592 100644 --- a/src/hotspot/share/opto/loopnode.hpp +++ b/src/hotspot/share/opto/loopnode.hpp @@ -355,6 +355,8 @@ class CountedLoopNode : public BaseCountedLoopNode { #ifndef PRODUCT virtual void dump_spec(outputStream *st) const; #endif + + static bool is_zero_trip_guard_if(const IfNode* iff); }; class LongCountedLoopNode : public BaseCountedLoopNode { From b754aa5e3f231aea8da5274c330dc55dd78b0f67 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 14 Dec 2022 11:04:49 +0000 Subject: [PATCH 195/494] 8298371: monitors_on_stack extracts unprocessed oops Reviewed-by: pchilanomate, rehn --- src/hotspot/share/runtime/continuationFreezeThaw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 645b6619cc8..ef4bacbbb98 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -1461,7 +1461,7 @@ static bool monitors_on_stack(JavaThread* thread) { ContinuationEntry* ce = thread->last_continuation(); RegisterMap map(thread, RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::skip, + RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); map.set_include_argument_oops(false); for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { From d32d6c028de4aed8d1f1ef70734d43f056a0ff34 Mon Sep 17 00:00:00 2001 From: Matthijs Bijman Date: Wed, 14 Dec 2022 11:30:34 +0000 Subject: [PATCH 196/494] 8297791: update _max_classes in node type system Reviewed-by: thartmann --- src/hotspot/share/opto/node.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/opto/node.hpp b/src/hotspot/share/opto/node.hpp index 29b57d674f5..221491f9795 100644 --- a/src/hotspot/share/opto/node.hpp +++ b/src/hotspot/share/opto/node.hpp @@ -763,7 +763,7 @@ class Node { DEFINE_CLASS_ID(Move, Node, 17) DEFINE_CLASS_ID(LShift, Node, 18) - _max_classes = ClassMask_Move + _max_classes = ClassMask_LShift }; #undef DEFINE_CLASS_ID From 9bcdfc428597e1465c8a014d816ef671420d22df Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Wed, 14 Dec 2022 11:36:04 +0000 Subject: [PATCH 197/494] 8298425: System.console().readLine() hangs in jshell Reviewed-by: naoto, alanb --- .../execution/JdiDefaultExecutionControl.java | 8 +++- test/langtools/jdk/jshell/ConsoleTest.java | 42 +++++++++++++++++++ 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 test/langtools/jdk/jshell/ConsoleTest.java diff --git a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java index c9590380064..0044c1b4be4 100644 --- a/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java +++ b/src/jdk.jshell/share/classes/jdk/jshell/execution/JdiDefaultExecutionControl.java @@ -48,6 +48,7 @@ import com.sun.jdi.ThreadReference; import com.sun.jdi.VMDisconnectedException; import com.sun.jdi.VirtualMachine; +import java.util.stream.Stream; import jdk.jshell.spi.ExecutionControl; import jdk.jshell.spi.ExecutionEnv; import static jdk.jshell.execution.Util.remoteInputOutput; @@ -96,10 +97,15 @@ static ExecutionControl create(ExecutionEnv env, String remoteAgent, // timeout on I/O-socket listener.setSoTimeout(timeout); int port = listener.getLocalPort(); + List augmentedremoteVMOptions = + Stream.concat(env.extraRemoteVMOptions().stream(), + //disable System.console(): + List.of("-Djdk.console=java.base").stream()) + .toList(); // Set-up the JDI connection JdiInitiator jdii = new JdiInitiator(port, - env.extraRemoteVMOptions(), remoteAgent, isLaunch, host, + augmentedremoteVMOptions, remoteAgent, isLaunch, host, timeout, Collections.emptyMap()); VirtualMachine vm = jdii.vm(); Process process = jdii.process(); diff --git a/test/langtools/jdk/jshell/ConsoleTest.java b/test/langtools/jdk/jshell/ConsoleTest.java new file mode 100644 index 00000000000..5d2d8602df7 --- /dev/null +++ b/test/langtools/jdk/jshell/ConsoleTest.java @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2022, 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 8298425 + * @summary Verify behavior of System.console() + * @build KullaTesting TestingInputStream + * @run testng ConsoleTest + */ + + +import org.testng.annotations.Test; + +public class ConsoleTest extends KullaTesting { + + @Test + public void testConsole1() { + assertEval("System.console()", "null"); + } + +} From ceca4fc9ec33808873a6e4f5d13619db455ce214 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 14 Dec 2022 12:45:17 +0000 Subject: [PATCH 198/494] 8298264: Merge OffsetTableContigSpace into TenuredSpace Reviewed-by: stefank, tschatzl --- .../share/gc/serial/vmStructs_serial.hpp | 8 ++--- src/hotspot/share/gc/shared/space.cpp | 20 +++++------ src/hotspot/share/gc/shared/space.hpp | 32 ++++++----------- src/hotspot/share/gc/shared/space.inline.hpp | 8 ++--- .../gc/shared/OffsetTableContigSpace.java | 35 ------------------- .../jvm/hotspot/gc/shared/TenuredSpace.java | 2 +- 6 files changed, 28 insertions(+), 77 deletions(-) delete mode 100644 src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java diff --git a/src/hotspot/share/gc/serial/vmStructs_serial.hpp b/src/hotspot/share/gc/serial/vmStructs_serial.hpp index 30bd21d40a4..2fb7404f3e8 100644 --- a/src/hotspot/share/gc/serial/vmStructs_serial.hpp +++ b/src/hotspot/share/gc/serial/vmStructs_serial.hpp @@ -59,15 +59,14 @@ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_threshold, HeapWord*) \ nonstatic_field(BlockOffsetArrayContigSpace, _next_offset_index, size_t) \ \ - nonstatic_field(OffsetTableContigSpace, _offsets, BlockOffsetArray) + nonstatic_field(TenuredSpace, _offsets, BlockOffsetArray) #define VM_TYPES_SERIALGC(declare_type, \ declare_toplevel_type, \ declare_integer_type) \ declare_type(SerialHeap, GenCollectedHeap) \ declare_type(TenuredGeneration, Generation) \ - declare_type(TenuredSpace, OffsetTableContigSpace) \ - declare_type(OffsetTableContigSpace, ContiguousSpace) \ + declare_type(TenuredSpace, ContiguousSpace) \ \ declare_type(DefNewGeneration, Generation) \ \ @@ -76,8 +75,7 @@ declare_toplevel_type(BlockOffsetTable) \ declare_type(BlockOffsetArray, BlockOffsetTable) \ declare_type(BlockOffsetArrayContigSpace, BlockOffsetArray) \ - declare_toplevel_type(BlockOffsetSharedArray*) \ - declare_toplevel_type(OffsetTableContigSpace*) + declare_toplevel_type(BlockOffsetSharedArray*) #define VM_INT_CONSTANTS_SERIALGC(declare_constant, \ declare_constant_with_value) diff --git a/src/hotspot/share/gc/shared/space.cpp b/src/hotspot/share/gc/shared/space.cpp index 43f06dd0b90..3a4f780ccad 100644 --- a/src/hotspot/share/gc/shared/space.cpp +++ b/src/hotspot/share/gc/shared/space.cpp @@ -284,17 +284,17 @@ bool ContiguousSpace::is_free_block(const HeapWord* p) const { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::clear(bool mangle_space) { +void TenuredSpace::clear(bool mangle_space) { ContiguousSpace::clear(mangle_space); _offsets.initialize_threshold(); } -void OffsetTableContigSpace::set_bottom(HeapWord* new_bottom) { +void TenuredSpace::set_bottom(HeapWord* new_bottom) { Space::set_bottom(new_bottom); _offsets.set_bottom(new_bottom); } -void OffsetTableContigSpace::set_end(HeapWord* new_end) { +void TenuredSpace::set_end(HeapWord* new_end) { // Space should not advertise an increase in size // until after the underlying offset table has been enlarged. _offsets.resize(pointer_delta(new_end, bottom())); @@ -590,7 +590,7 @@ void ContiguousSpace::print_on(outputStream* st) const { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::print_on(outputStream* st) const { +void TenuredSpace::print_on(outputStream* st) const { print_short_on(st); st->print_cr(" [" PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ", " PTR_FORMAT ")", @@ -733,18 +733,18 @@ HeapWord* ContiguousSpace::par_allocate(size_t size) { } #if INCLUDE_SERIALGC -void OffsetTableContigSpace::initialize_threshold() { +void TenuredSpace::initialize_threshold() { _offsets.initialize_threshold(); } -void OffsetTableContigSpace::alloc_block(HeapWord* start, HeapWord* end) { +void TenuredSpace::alloc_block(HeapWord* start, HeapWord* end) { _offsets.alloc_block(start, end); } -OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr) : +TenuredSpace::TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, + MemRegion mr) : _offsets(sharedOffsetArray, mr), - _par_alloc_lock(Mutex::safepoint, "OffsetTableContigSpaceParAlloc_lock", true) + _par_alloc_lock(Mutex::safepoint, "TenuredSpaceParAlloc_lock", true) { _offsets.set_contig_space(this); initialize(mr, SpaceDecorator::Clear, SpaceDecorator::Mangle); @@ -753,7 +753,7 @@ OffsetTableContigSpace::OffsetTableContigSpace(BlockOffsetSharedArray* sharedOff #define OBJ_SAMPLE_INTERVAL 0 #define BLOCK_SAMPLE_INTERVAL 100 -void OffsetTableContigSpace::verify() const { +void TenuredSpace::verify() const { HeapWord* p = bottom(); HeapWord* prev_p = NULL; int objs = 0; diff --git a/src/hotspot/share/gc/shared/space.hpp b/src/hotspot/share/gc/shared/space.hpp index b673f3acfd1..1fec23ddec1 100644 --- a/src/hotspot/share/gc/shared/space.hpp +++ b/src/hotspot/share/gc/shared/space.hpp @@ -550,22 +550,25 @@ class ContiguousSpaceDCTOC : public DirtyCardToOopClosure { {} }; -// A ContigSpace that Supports an efficient "block_start" operation via -// a BlockOffsetArray (whose BlockOffsetSharedArray may be shared with -// other spaces.) This is the abstract base class for old generation -// (tenured) spaces. #if INCLUDE_SERIALGC -class OffsetTableContigSpace: public ContiguousSpace { + +// Class TenuredSpace is used by TenuredGeneration; it supports an efficient +// "block_start" operation via a BlockOffsetArray (whose BlockOffsetSharedArray +// may be shared with other spaces.) + +class TenuredSpace: public ContiguousSpace { friend class VMStructs; protected: BlockOffsetArrayContigSpace _offsets; Mutex _par_alloc_lock; + // Mark sweep support + size_t allowed_dead_ratio() const override; public: // Constructor - OffsetTableContigSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr); + TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, + MemRegion mr); void set_bottom(HeapWord* value) override; void set_end(HeapWord* value) override; @@ -587,21 +590,6 @@ class OffsetTableContigSpace: public ContiguousSpace { // Debugging void verify() const override; }; - - -// Class TenuredSpace is used by TenuredGeneration - -class TenuredSpace: public OffsetTableContigSpace { - friend class VMStructs; - protected: - // Mark sweep support - size_t allowed_dead_ratio() const override; - public: - // Constructor - TenuredSpace(BlockOffsetSharedArray* sharedOffsetArray, - MemRegion mr) : - OffsetTableContigSpace(sharedOffsetArray, mr) {} -}; #endif //INCLUDE_SERIALGC #endif // SHARE_GC_SHARED_SPACE_HPP diff --git a/src/hotspot/share/gc/shared/space.inline.hpp b/src/hotspot/share/gc/shared/space.inline.hpp index 963b9a2d9cb..a2b3b67ed57 100644 --- a/src/hotspot/share/gc/shared/space.inline.hpp +++ b/src/hotspot/share/gc/shared/space.inline.hpp @@ -44,7 +44,7 @@ inline HeapWord* Space::block_start(const void* p) { } #if INCLUDE_SERIALGC -inline HeapWord* OffsetTableContigSpace::allocate(size_t size) { +inline HeapWord* TenuredSpace::allocate(size_t size) { HeapWord* res = ContiguousSpace::allocate(size); if (res != NULL) { _offsets.alloc_block(res, size); @@ -55,7 +55,7 @@ inline HeapWord* OffsetTableContigSpace::allocate(size_t size) { // Because of the requirement of keeping "_offsets" up to date with the // allocations, we sequentialize these with a lock. Therefore, best if // this is used for larger LAB allocations only. -inline HeapWord* OffsetTableContigSpace::par_allocate(size_t size) { +inline HeapWord* TenuredSpace::par_allocate(size_t size) { MutexLocker x(&_par_alloc_lock); // This ought to be just "allocate", because of the lock above, but that // ContiguousSpace::allocate asserts that either the allocating thread @@ -73,7 +73,7 @@ inline HeapWord* OffsetTableContigSpace::par_allocate(size_t size) { } inline HeapWord* -OffsetTableContigSpace::block_start_const(const void* p) const { +TenuredSpace::block_start_const(const void* p) const { return _offsets.block_start(p); } @@ -156,7 +156,7 @@ inline void CompactibleSpace::clear_empty_region(SpaceType* space) { // Reset space after compaction is complete space->reset_after_compaction(); // We do this clear, below, since it has overloaded meanings for some - // space subtypes. For example, OffsetTableContigSpace's that were + // space subtypes. For example, TenuredSpace's that were // compacted into will have had their offset table thresholds updated // continuously, but those that weren't need to have their thresholds // re-initialized. Also mangles unused area for debugging. diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java deleted file mode 100644 index 30564238287..00000000000 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/OffsetTableContigSpace.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (c) 2000, 2015, 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 sun.jvm.hotspot.gc.shared; - -import sun.jvm.hotspot.debugger.*; - -/** No additional functionality for now */ - -public class OffsetTableContigSpace extends ContiguousSpace { - public OffsetTableContigSpace(Address addr) { - super(addr); - } -} diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/TenuredSpace.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/TenuredSpace.java index 7a5b46ddff6..02d855822da 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/TenuredSpace.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/gc/shared/TenuredSpace.java @@ -28,7 +28,7 @@ /** No additional functionality for now */ -public class TenuredSpace extends OffsetTableContigSpace { +public class TenuredSpace extends ContiguousSpace { public TenuredSpace(Address addr) { super(addr); } From 9ee5037055a85a5d457a31392dc4ce1ca6c47768 Mon Sep 17 00:00:00 2001 From: Albert Mingkun Yang Date: Wed, 14 Dec 2022 12:46:15 +0000 Subject: [PATCH 199/494] 8298636: Fix return value in WB_CountAliveClasses and WB_GetSymbolRefcount Reviewed-by: dholmes --- src/hotspot/share/prims/whitebox.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/prims/whitebox.cpp b/src/hotspot/share/prims/whitebox.cpp index 6524718a959..edfeb047283 100644 --- a/src/hotspot/share/prims/whitebox.cpp +++ b/src/hotspot/share/prims/whitebox.cpp @@ -207,7 +207,9 @@ class WBIsKlassAliveClosure : public LockedClassesDo { WB_ENTRY(jint, WB_CountAliveClasses(JNIEnv* env, jobject target, jstring name)) oop h_name = JNIHandles::resolve(name); - if (h_name == NULL) return false; + if (h_name == NULL) { + return 0; + } Symbol* sym = java_lang_String::as_symbol(h_name); TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return @@ -220,7 +222,9 @@ WB_END WB_ENTRY(jint, WB_GetSymbolRefcount(JNIEnv* env, jobject unused, jstring name)) oop h_name = JNIHandles::resolve(name); - if (h_name == NULL) return false; + if (h_name == NULL) { + return 0; + } Symbol* sym = java_lang_String::as_symbol(h_name); TempNewSymbol tsym(sym); // Make sure to decrement reference count on sym on return return (jint)sym->refcount(); From 2e801e16ec40ce0e25d8679e21d7da347c52d7be Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 14 Dec 2022 12:47:08 +0000 Subject: [PATCH 200/494] 8298475: Remove JVM_ACC_PROMOTED_FLAGS Reviewed-by: sspitsyn, dcubed, dholmes --- .../share/classfile/classFileParser.cpp | 30 ++++++++----------- .../share/classfile/classFileParser.hpp | 5 ++-- src/hotspot/share/oops/instanceKlass.hpp | 3 ++ .../share/oops/instanceKlassMiscStatus.cpp | 10 +++++++ .../share/oops/instanceKlassMiscStatus.hpp | 6 ++-- src/hotspot/share/prims/jvmtiEnv.cpp | 2 +- .../share/prims/jvmtiRedefineClasses.cpp | 13 ++------ src/hotspot/share/runtime/vmStructs.cpp | 1 - src/hotspot/share/utilities/accessFlags.hpp | 9 ++---- .../jvm/hotspot/runtime/ClassConstants.java | 4 +-- 10 files changed, 41 insertions(+), 42 deletions(-) diff --git a/src/hotspot/share/classfile/classFileParser.cpp b/src/hotspot/share/classfile/classFileParser.cpp index e1837f3ca86..1d4b6501a6c 100644 --- a/src/hotspot/share/classfile/classFileParser.cpp +++ b/src/hotspot/share/classfile/classFileParser.cpp @@ -2260,18 +2260,16 @@ void ClassFileParser::copy_method_annotations(ConstMethod* cm, // Method* to save footprint, so we only know the size of the resulting Method* when the // entire method attribute is parsed. // -// The promoted_flags parameter is used to pass relevant access_flags -// from the method back up to the containing klass. These flag values -// are added to klass's access_flags. +// The has_localvariable_table parameter is used to pass up the value to InstanceKlass. Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, bool is_interface, const ConstantPool* cp, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, TRAPS) { assert(cfs != NULL, "invariant"); assert(cp != NULL, "invariant"); - assert(promoted_flags != NULL, "invariant"); + assert(has_localvariable_table != NULL, "invariant"); ResourceMark rm(THREAD); // Parse fixed parts: @@ -2820,7 +2818,7 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, // Copy class file LVT's/LVTT's into the HotSpot internal LVT. if (total_lvt_length > 0) { - promoted_flags->set_has_localvariable_table(); + *has_localvariable_table = true; copy_localvariable_table(m->constMethod(), lvt_cnt, localvariable_table_length, @@ -2876,18 +2874,15 @@ Method* ClassFileParser::parse_method(const ClassFileStream* const cfs, } -// The promoted_flags parameter is used to pass relevant access_flags -// from the methods back up to the containing klass. These flag values -// are added to klass's access_flags. // Side-effects: populates the _methods field in the parser void ClassFileParser::parse_methods(const ClassFileStream* const cfs, bool is_interface, - AccessFlags* promoted_flags, + bool* const has_localvariable_table, bool* has_final_method, bool* declares_nonstatic_concrete_methods, TRAPS) { assert(cfs != NULL, "invariant"); - assert(promoted_flags != NULL, "invariant"); + assert(has_localvariable_table != NULL, "invariant"); assert(has_final_method != NULL, "invariant"); assert(declares_nonstatic_concrete_methods != NULL, "invariant"); @@ -2907,7 +2902,7 @@ void ClassFileParser::parse_methods(const ClassFileStream* const cfs, Method* method = parse_method(cfs, is_interface, _cp, - promoted_flags, + has_localvariable_table, CHECK); if (method->is_final()) { @@ -5333,6 +5328,10 @@ void ClassFileParser::fill_instance_klass(InstanceKlass* ik, assert(NULL == _record_components, "invariant"); assert(NULL == _permitted_subclasses, "invariant"); + if (_has_localvariable_table) { + ik->set_has_localvariable_table(true); + } + if (_has_final_method) { ik->set_has_final_method(); } @@ -5596,6 +5595,7 @@ ClassFileParser::ClassFileParser(ClassFileStream* stream, _relax_verify(false), _has_nonstatic_concrete_methods(false), _declares_nonstatic_concrete_methods(false), + _has_localvariable_table(false), _has_final_method(false), _has_contended_fields(false), _has_finalizer(false), @@ -5901,19 +5901,15 @@ void ClassFileParser::parse_stream(const ClassFileStream* const stream, assert(_fields != NULL, "invariant"); // Methods - AccessFlags promoted_flags; parse_methods(stream, _access_flags.is_interface(), - &promoted_flags, + &_has_localvariable_table, &_has_final_method, &_declares_nonstatic_concrete_methods, CHECK); assert(_methods != NULL, "invariant"); - // promote flags from parse_methods() to the klass' flags - _access_flags.add_promoted_flags(promoted_flags.as_int()); - if (_declares_nonstatic_concrete_methods) { _has_nonstatic_concrete_methods = true; } diff --git a/src/hotspot/share/classfile/classFileParser.hpp b/src/hotspot/share/classfile/classFileParser.hpp index 3fe2414e93a..d8bb95b8a7a 100644 --- a/src/hotspot/share/classfile/classFileParser.hpp +++ b/src/hotspot/share/classfile/classFileParser.hpp @@ -187,6 +187,7 @@ class ClassFileParser { bool _has_nonstatic_concrete_methods; bool _declares_nonstatic_concrete_methods; + bool _has_localvariable_table; bool _has_final_method; bool _has_contended_fields; @@ -267,12 +268,12 @@ class ClassFileParser { Method* parse_method(const ClassFileStream* const cfs, bool is_interface, const ConstantPool* cp, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, TRAPS); void parse_methods(const ClassFileStream* const cfs, bool is_interface, - AccessFlags* const promoted_flags, + bool* const has_localvariable_table, bool* const has_final_method, bool* const declares_nonstatic_concrete_methods, TRAPS); diff --git a/src/hotspot/share/oops/instanceKlass.hpp b/src/hotspot/share/oops/instanceKlass.hpp index 56545831f48..e1fd188040b 100644 --- a/src/hotspot/share/oops/instanceKlass.hpp +++ b/src/hotspot/share/oops/instanceKlass.hpp @@ -336,6 +336,9 @@ class InstanceKlass: public Klass { bool has_nonstatic_fields() const { return _misc_status.has_nonstatic_fields(); } void set_has_nonstatic_fields(bool b) { _misc_status.set_has_nonstatic_fields(b); } + bool has_localvariable_table() const { return _misc_status.has_localvariable_table(); } + void set_has_localvariable_table(bool b) { _misc_status.set_has_localvariable_table(b); } + // field sizes int nonstatic_field_size() const { return _nonstatic_field_size; } void set_nonstatic_field_size(int size) { _nonstatic_field_size = size; } diff --git a/src/hotspot/share/oops/instanceKlassMiscStatus.cpp b/src/hotspot/share/oops/instanceKlassMiscStatus.cpp index 32144ea8fb8..98e97fa66f1 100644 --- a/src/hotspot/share/oops/instanceKlassMiscStatus.cpp +++ b/src/hotspot/share/oops/instanceKlassMiscStatus.cpp @@ -26,6 +26,7 @@ #include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "oops/instanceKlassMiscStatus.hpp" +#include "runtime/safepoint.hpp" #include "utilities/macros.hpp" #if INCLUDE_CDS @@ -57,4 +58,13 @@ void InstanceKlassMiscStatus::assign_class_loader_type(const ClassLoaderData* cl set_shared_class_loader_type(ClassLoader::APP_LOADER); } } + +#ifdef ASSERT +void InstanceKlassMiscStatus::assert_is_safe(bool set) { + // Setting a flag is safe if it's set once or at a safepoint. RedefineClasses can set or + // reset flags at a safepoint. + assert(!set || SafepointSynchronize::is_at_safepoint(), "set once or at safepoint"); +} +#endif // ASSERT + #endif // INCLUDE_CDS diff --git a/src/hotspot/share/oops/instanceKlassMiscStatus.hpp b/src/hotspot/share/oops/instanceKlassMiscStatus.hpp index 3bbe4d52b86..2368d85d858 100644 --- a/src/hotspot/share/oops/instanceKlassMiscStatus.hpp +++ b/src/hotspot/share/oops/instanceKlassMiscStatus.hpp @@ -45,7 +45,8 @@ class InstanceKlassMiscStatus { flag(is_shared_boot_class , 1 << 10) /* defining class loader is boot class loader */ \ flag(is_shared_platform_class , 1 << 11) /* defining class loader is platform class loader */ \ flag(is_shared_app_class , 1 << 12) /* defining class loader is app class loader */ \ - flag(has_contended_annotations , 1 << 13) /* has @Contended annotation */ + flag(has_contended_annotations , 1 << 13) /* has @Contended annotation */ \ + flag(has_localvariable_table , 1 << 14) /* has localvariable information */ #define IK_FLAGS_ENUM_NAME(name, value) _misc_##name = value, enum { @@ -72,7 +73,7 @@ class InstanceKlassMiscStatus { #define IK_FLAGS_SET(name, ignore) \ void set_##name(bool b) { \ - assert(!name(), "set once"); \ + assert_is_safe(name()); \ if (b) _flags |= _misc_##name; \ } IK_FLAGS_DO(IK_FLAGS_SET) @@ -85,6 +86,7 @@ class InstanceKlassMiscStatus { void set_shared_class_loader_type(s2 loader_type); void assign_class_loader_type(const ClassLoaderData* cld); + void assert_is_safe(bool set) NOT_DEBUG_RETURN; }; #endif // SHARE_OOPS_INSTANCEKLASSMISCSTATUS_HPP diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index 468272aaf6f..c3f48424e1f 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -3522,7 +3522,7 @@ JvmtiEnv::GetLocalVariableTable(Method* method, jint* entry_count_ptr, jvmtiLoca // does the klass have any local variable information? InstanceKlass* ik = method->method_holder(); - if (!ik->access_flags().has_localvariable_table()) { + if (!ik->has_localvariable_table()) { return (JVMTI_ERROR_ABSENT_INFORMATION); } diff --git a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp index 9cea6247112..52ae972a588 100644 --- a/src/hotspot/share/prims/jvmtiRedefineClasses.cpp +++ b/src/hotspot/share/prims/jvmtiRedefineClasses.cpp @@ -4371,16 +4371,9 @@ void VM_RedefineClasses::redefine_single_class(Thread* current, jclass the_jclas (int)strlen(scratch_class->source_debug_extension())); // Use of javac -g could be different in the old and the new - if (scratch_class->access_flags().has_localvariable_table() != - the_class->access_flags().has_localvariable_table()) { - - AccessFlags flags = the_class->access_flags(); - if (scratch_class->access_flags().has_localvariable_table()) { - flags.set_has_localvariable_table(); - } else { - flags.clear_has_localvariable_table(); - } - the_class->set_access_flags(flags); + if (scratch_class->has_localvariable_table() != + the_class->has_localvariable_table()) { + the_class->set_has_localvariable_table(scratch_class->has_localvariable_table()); } swap_annotations(the_class, scratch_class); diff --git a/src/hotspot/share/runtime/vmStructs.cpp b/src/hotspot/share/runtime/vmStructs.cpp index ebf187a03ce..27eea4622ff 100644 --- a/src/hotspot/share/runtime/vmStructs.cpp +++ b/src/hotspot/share/runtime/vmStructs.cpp @@ -2098,7 +2098,6 @@ declare_constant(JVM_ACC_HAS_FINALIZER) \ declare_constant(JVM_ACC_IS_CLONEABLE_FAST) \ declare_constant(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) \ - declare_constant(JVM_ACC_PROMOTED_FLAGS) \ declare_constant(JVM_ACC_FIELD_ACCESS_WATCHED) \ declare_constant(JVM_ACC_FIELD_MODIFICATION_WATCHED) \ declare_constant(JVM_ACC_FIELD_INTERNAL) \ diff --git a/src/hotspot/share/utilities/accessFlags.hpp b/src/hotspot/share/utilities/accessFlags.hpp index 71c9c286f8f..b7814b0d96c 100644 --- a/src/hotspot/share/utilities/accessFlags.hpp +++ b/src/hotspot/share/utilities/accessFlags.hpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -72,11 +72,9 @@ enum { JVM_ACC_IS_BEING_REDEFINED = 0x00100000, // True if the klass is being redefined. JVM_ACC_HAS_RESOLVED_METHODS = 0x00200000, // True if the klass has resolved methods - // Klass* and Method* flags + // Method* flags JVM_ACC_HAS_LOCAL_VARIABLE_TABLE= 0x00400000, - JVM_ACC_PROMOTED_FLAGS = 0x00400000, // flags promoted from methods to the holding klass - // field flags // Note: these flags must be defined in the low order 16 bits because // InstanceKlass only stores a ushort worth of information from the @@ -156,7 +154,7 @@ class AccessFlags { bool is_hidden_class () const { return (_flags & JVM_ACC_IS_HIDDEN_CLASS ) != 0; } bool is_value_based_class () const { return (_flags & JVM_ACC_IS_VALUE_BASED_CLASS ) != 0; } - // Klass* and Method* flags + // Method* flags bool has_localvariable_table () const { return (_flags & JVM_ACC_HAS_LOCAL_VARIABLE_TABLE) != 0; } void set_has_localvariable_table() { atomic_set_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); } void clear_has_localvariable_table() { atomic_clear_bits(JVM_ACC_HAS_LOCAL_VARIABLE_TABLE); } @@ -184,7 +182,6 @@ class AccessFlags { jint get_flags () const { return (_flags & JVM_ACC_WRITTEN_FLAGS); } // Initialization - void add_promoted_flags(jint flags) { _flags |= (flags & JVM_ACC_PROMOTED_FLAGS); } void set_field_flags(jint flags) { assert((flags & JVM_ACC_FIELD_FLAGS) == flags, "only recognized flags"); _flags = (flags & JVM_ACC_FIELD_FLAGS); diff --git a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java index 0366bc049f0..f3224be7f78 100644 --- a/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java +++ b/src/jdk.hotspot.agent/share/classes/sun/jvm/hotspot/runtime/ClassConstants.java @@ -134,10 +134,8 @@ public interface ClassConstants // True if klass supports the Clonable interface public static final long JVM_ACC_IS_CLONEABLE = 0x80000000; - // Klass* and Method* flags + // Method* flags public static final long JVM_ACC_HAS_LOCAL_VARIABLE_TABLE = 0x00200000; - // flags promoted from methods to the holding klass - public static final long JVM_ACC_PROMOTED_FLAGS = 0x00200000; // field flags // Note: these flags must be defined in the low order 16 bits because From 0bbc4181cdbccfc3a542f306ce1902cc2e9f36cb Mon Sep 17 00:00:00 2001 From: Andrew Haley Date: Wed, 14 Dec 2022 13:32:21 +0000 Subject: [PATCH 201/494] 8294902: Undefined Behavior in C2 regalloc with null references Reviewed-by: kvn, vlivanov --- src/hotspot/share/memory/arena.cpp | 1 + src/hotspot/share/opto/bytecodeInfo.cpp | 6 +-- src/hotspot/share/opto/chaitin.hpp | 4 +- src/hotspot/share/opto/postaloc.cpp | 49 ++++++++++--------- src/hotspot/share/runtime/vmStructs.hpp | 15 ++++-- .../share/utilities/globalDefinitions.hpp | 5 ++ .../share/utilities/globalDefinitions_gcc.hpp | 19 +++++-- 7 files changed, 63 insertions(+), 36 deletions(-) diff --git a/src/hotspot/share/memory/arena.cpp b/src/hotspot/share/memory/arena.cpp index 050d129351f..8ae29c1d627 100644 --- a/src/hotspot/share/memory/arena.cpp +++ b/src/hotspot/share/memory/arena.cpp @@ -369,6 +369,7 @@ void *Arena::Arealloc(void* old_ptr, size_t old_size, size_t new_size, AllocFail // Determine if pointer belongs to this Arena or not. bool Arena::contains( const void *ptr ) const { + if (_chunk == NULL) return false; if( (void*)_chunk->bottom() <= ptr && ptr < (void*)_hwm ) return true; // Check for in this chunk for (Chunk *c = _first; c; c = c->next()) { diff --git a/src/hotspot/share/opto/bytecodeInfo.cpp b/src/hotspot/share/opto/bytecodeInfo.cpp index 9c1de4ea3c4..1191913bfb9 100644 --- a/src/hotspot/share/opto/bytecodeInfo.cpp +++ b/src/hotspot/share/opto/bytecodeInfo.cpp @@ -44,7 +44,7 @@ InlineTree::InlineTree(Compile* c, JVMState* caller_jvms, int caller_bci, int max_inline_level) : C(c), - _caller_jvms(caller_jvms), + _caller_jvms(NULL), _method(callee), _late_inline(false), _caller_tree((InlineTree*) caller_tree), @@ -57,13 +57,13 @@ InlineTree::InlineTree(Compile* c, _count_inlines = 0; _forced_inline = false; #endif - if (_caller_jvms != NULL) { + if (caller_jvms != NULL) { // Keep a private copy of the caller_jvms: _caller_jvms = new (C) JVMState(caller_jvms->method(), caller_tree->caller_jvms()); _caller_jvms->set_bci(caller_jvms->bci()); assert(!caller_jvms->should_reexecute(), "there should be no reexecute bytecode with inlining"); + assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); } - assert(_caller_jvms->same_calls_as(caller_jvms), "consistent JVMS"); assert((caller_tree == NULL ? 0 : caller_tree->stack_depth() + 1) == stack_depth(), "correct (redundant) depth parameter"); assert(caller_bci == this->caller_bci(), "correct (redundant) bci parameter"); // Update hierarchical counts, count_inline_bcs() and count_inlines() diff --git a/src/hotspot/share/opto/chaitin.hpp b/src/hotspot/share/opto/chaitin.hpp index 3134dbdb9c7..240b638bde3 100644 --- a/src/hotspot/share/opto/chaitin.hpp +++ b/src/hotspot/share/opto/chaitin.hpp @@ -731,8 +731,8 @@ class PhaseChaitin : public PhaseRegAlloc { int yank_if_dead_recurse(Node *old, Node *orig_old, Block *current_block, Node_List *value, Node_List *regnd); int yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ); - int elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs ); - int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd ); + int elide_copy( Node *n, int k, Block *current_block, Node_List *value, Node_List *regnd, bool can_change_regs ); + int use_prior_register( Node *copy, uint idx, Node *def, Block *current_block, Node_List *value, Node_List *regnd ); bool may_be_copy_of_callee( Node *def ) const; // If nreg already contains the same constant as val then eliminate it diff --git a/src/hotspot/share/opto/postaloc.cpp b/src/hotspot/share/opto/postaloc.cpp index 96c30a122bb..579d4cdec4d 100644 --- a/src/hotspot/share/opto/postaloc.cpp +++ b/src/hotspot/share/opto/postaloc.cpp @@ -30,7 +30,7 @@ // See if this register (or pairs, or vector) already contains the value. static bool register_contains_value(Node* val, OptoReg::Name reg, int n_regs, - Node_List& value) { + const Node_List &value) { for (int i = 0; i < n_regs; i++) { OptoReg::Name nreg = OptoReg::add(reg,-i); if (value[nreg] != val) @@ -77,7 +77,7 @@ bool PhaseChaitin::may_be_copy_of_callee( Node *def ) const { //------------------------------yank----------------------------------- // Helper function for yank_if_dead -int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_List *regnd ) { +int PhaseChaitin::yank(Node *old, Block *current_block, Node_List *value, Node_List *regnd) { int blk_adjust=0; Block *oldb = _cfg.get_block_for_node(old); oldb->find_remove(old); @@ -87,9 +87,10 @@ int PhaseChaitin::yank( Node *old, Block *current_block, Node_List *value, Node_ } _cfg.unmap_node_from_block(old); OptoReg::Name old_reg = lrgs(_lrg_map.live_range_id(old)).reg(); - if( regnd && (*regnd)[old_reg]==old ) { // Instruction is currently available? - value->map(old_reg,NULL); // Yank from value/regnd maps - regnd->map(old_reg,NULL); // This register's value is now unknown + assert(value != NULL || regnd == NULL, "sanity"); + if (value != NULL && regnd != NULL && regnd->at(old_reg) == old) { // Instruction is currently available? + value->map(old_reg, NULL); // Yank from value/regnd maps + regnd->map(old_reg, NULL); // This register's value is now unknown } return blk_adjust; } @@ -161,7 +162,7 @@ int PhaseChaitin::yank_if_dead_recurse(Node *old, Node *orig_old, Block *current // Use the prior value instead of the current value, in an effort to make // the current value go dead. Return block iterator adjustment, in case // we yank some instructions from this block. -int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *current_block, Node_List &value, Node_List ®nd ) { +int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *current_block, Node_List *value, Node_List *regnd ) { // No effect? if( def == n->in(idx) ) return 0; // Def is currently dead and can be removed? Do not resurrect @@ -207,7 +208,7 @@ int PhaseChaitin::use_prior_register( Node *n, uint idx, Node *def, Block *curre _post_alloc++; // Is old def now dead? We successfully yanked a copy? - return yank_if_dead(old,current_block,&value,®nd); + return yank_if_dead(old,current_block,value,regnd); } @@ -229,7 +230,7 @@ Node *PhaseChaitin::skip_copies( Node *c ) { //------------------------------elide_copy------------------------------------- // Remove (bypass) copies along Node n, edge k. -int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &value, Node_List ®nd, bool can_change_regs ) { +int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List *value, Node_List *regnd, bool can_change_regs ) { int blk_adjust = 0; uint nk_idx = _lrg_map.live_range_id(n->in(k)); @@ -253,11 +254,14 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v // Phis and 2-address instructions cannot change registers so easily - their // outputs must match their input. - if( !can_change_regs ) + if (!can_change_regs) { return blk_adjust; // Only check stupid copies! - + } // Loop backedges won't have a value-mapping yet - if( &value == NULL ) return blk_adjust; + assert(regnd != NULL || value == NULL, "sanity"); + if (value == NULL || regnd == NULL) { + return blk_adjust; + } // Skip through all copies to the _value_ being used. Do not change from // int to pointer. This attempts to jump through a chain of copies, where @@ -273,10 +277,11 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v // See if it happens to already be in the correct register! // (either Phi's direct register, or the common case of the name // never-clobbered original-def register) - if (register_contains_value(val, val_reg, n_regs, value)) { - blk_adjust += use_prior_register(n,k,regnd[val_reg],current_block,value,regnd); - if( n->in(k) == regnd[val_reg] ) // Success! Quit trying - return blk_adjust; + if (register_contains_value(val, val_reg, n_regs, *value)) { + blk_adjust += use_prior_register(n,k,regnd->at(val_reg),current_block,value,regnd); + if (n->in(k) == regnd->at(val_reg)) { + return blk_adjust; // Success! Quit trying + } } // See if we can skip the copy by changing registers. Don't change from @@ -304,7 +309,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v if (ignore_self) continue; } - Node *vv = value[reg]; + Node *vv = value->at(reg); // For scalable register, number of registers may be inconsistent between // "val_reg" and "reg". For example, when "val" resides in register // but "reg" is located in stack. @@ -325,7 +330,7 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v last = (n_regs-1); // Looking for the last part of a set } if ((reg&last) != last) continue; // Wrong part of a set - if (!register_contains_value(vv, reg, n_regs, value)) continue; // Different value + if (!register_contains_value(vv, reg, n_regs, *value)) continue; // Different value } if( vv == val || // Got a direct hit? (t && vv && vv->bottom_type() == t && vv->is_Mach() && @@ -333,9 +338,9 @@ int PhaseChaitin::elide_copy( Node *n, int k, Block *current_block, Node_List &v assert( !n->is_Phi(), "cannot change registers at a Phi so easily" ); if( OptoReg::is_stack(nk_reg) || // CISC-loading from stack OR OptoReg::is_reg(reg) || // turning into a register use OR - regnd[reg]->outcnt()==1 ) { // last use of a spill-load turns into a CISC use - blk_adjust += use_prior_register(n,k,regnd[reg],current_block,value,regnd); - if( n->in(k) == regnd[reg] ) // Success! Quit trying + regnd->at(reg)->outcnt()==1 ) { // last use of a spill-load turns into a CISC use + blk_adjust += use_prior_register(n,k,regnd->at(reg),current_block,value,regnd); + if( n->in(k) == regnd->at(reg) ) // Success! Quit trying return blk_adjust; } // End of if not degrading to a stack } // End of if found value in another register @@ -535,7 +540,7 @@ void PhaseChaitin::post_allocate_copy_removal() { Block* pb = _cfg.get_block_for_node(block->pred(j)); // Remove copies along phi edges for (uint k = 1; k < phi_dex; k++) { - elide_copy(block->get_node(k), j, block, *blk2value[pb->_pre_order], *blk2regnd[pb->_pre_order], false); + elide_copy(block->get_node(k), j, block, blk2value[pb->_pre_order], blk2regnd[pb->_pre_order], false); } if (blk2value[pb->_pre_order]) { // Have a mapping on this edge? // See if this predecessor's mappings have been used by everybody @@ -691,7 +696,7 @@ void PhaseChaitin::post_allocate_copy_removal() { // Remove copies along input edges for (k = 1; k < n->req(); k++) { - j -= elide_copy(n, k, block, value, regnd, two_adr != k); + j -= elide_copy(n, k, block, &value, ®nd, two_adr != k); } // Unallocated Nodes define no registers diff --git a/src/hotspot/share/runtime/vmStructs.hpp b/src/hotspot/share/runtime/vmStructs.hpp index 5e9db68bd70..7b0425b17c9 100644 --- a/src/hotspot/share/runtime/vmStructs.hpp +++ b/src/hotspot/share/runtime/vmStructs.hpp @@ -188,13 +188,18 @@ class VMStructs { #ifdef ASSERT // This macro checks the type of a VMStructEntry by comparing pointer types -#define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ - {typeName *dummyObj = NULL; type* dummy = &dummyObj->fieldName; \ - assert(offset_of(typeName, fieldName) < sizeof(typeName), "Illegal nonstatic struct entry, field offset too large"); } +#define CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) { \ + static_assert( \ + std::is_convertible< \ + std::add_pointer_t().fieldName)>, \ + std::add_pointer_t>::value, \ + "type mismatch for " XSTR(fieldName) " member of " XSTR(typeName)); \ + assert(offset_of(typeName, fieldName) < sizeof(typeName), "..."); \ +} // This macro checks the type of a volatile VMStructEntry by comparing pointer types -#define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ - {typedef type dummyvtype; typeName *dummyObj = NULL; volatile dummyvtype* dummy = &dummyObj->fieldName; } +#define CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ + CHECK_NONSTATIC_VM_STRUCT_ENTRY(typeName, fieldName, std::add_volatile_t) // This macro checks the type of a static VMStructEntry by comparing pointer types #define CHECK_STATIC_VM_STRUCT_ENTRY(typeName, fieldName, type) \ diff --git a/src/hotspot/share/utilities/globalDefinitions.hpp b/src/hotspot/share/utilities/globalDefinitions.hpp index 3771ac0f277..5c6281eed42 100644 --- a/src/hotspot/share/utilities/globalDefinitions.hpp +++ b/src/hotspot/share/utilities/globalDefinitions.hpp @@ -35,6 +35,7 @@ #include COMPILER_HEADER(utilities/globalDefinitions) #include +#include class oopDesc; @@ -1287,4 +1288,8 @@ template bool primitive_equals(const K& k0, const K& k1) { // Allow use of C++ thread_local when approved - see JDK-8282469. #define APPROVED_CPP_THREAD_LOCAL thread_local +// Converts any type T to a reference type. +template +std::add_rvalue_reference_t declval() noexcept; + #endif // SHARE_UTILITIES_GLOBALDEFINITIONS_HPP diff --git a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp index 4aed8605182..9ccf8fa2008 100644 --- a/src/hotspot/share/utilities/globalDefinitions_gcc.hpp +++ b/src/hotspot/share/utilities/globalDefinitions_gcc.hpp @@ -139,10 +139,21 @@ inline int g_isfinite(jdouble f) { return isfinite(f); } #endif // _LP64 // gcc warns about applying offsetof() to non-POD object or calculating -// offset directly when base address is NULL. Use 16 to get around the -// warning. The -Wno-invalid-offsetof option could be used to suppress -// this warning, but we instead just avoid the use of offsetof(). -#define offset_of(klass,field) (size_t)((intx)&(((klass*)16)->field) - 16) +// offset directly when base address is NULL. The -Wno-invalid-offsetof +// option could be used to suppress this warning, but we instead just +// avoid the use of offsetof(). +// +// FIXME: This macro is complex and rather arcane. Perhaps we should +// use offsetof() instead, with the invalid-offsetof warning +// temporarily disabled. +#define offset_of(klass,field) \ +[]() { \ + char space[sizeof (klass)] ATTRIBUTE_ALIGNED(16); \ + klass* dummyObj = (klass*)space; \ + char* c = (char*)(void*)&dummyObj->field; \ + return (size_t)(c - space); \ +}() + #if defined(_LP64) && defined(__APPLE__) #define JLONG_FORMAT "%ld" From 279170147a10ec2da2242b4dcb3279c41c471000 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 14 Dec 2022 13:36:36 +0000 Subject: [PATCH 202/494] 8298296: gc/TestFullGCCount.java fails with "System.gc collections miscounted." Reviewed-by: tschatzl, ayang --- test/hotspot/jtreg/ProblemList.txt | 1 - test/hotspot/jtreg/gc/TestFullGCCount.java | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 1cd805f7450..66121e1dcb1 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -80,7 +80,6 @@ gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293,8298073 macosx-x64,macosx-aarch64 gc/stress/TestStressG1Humongous.java 8286554 windows-x64 -gc/TestFullGCCount.java 8298296 linux-x64 ############################################################################# diff --git a/test/hotspot/jtreg/gc/TestFullGCCount.java b/test/hotspot/jtreg/gc/TestFullGCCount.java index 4557fb95c7b..08f8125de83 100644 --- a/test/hotspot/jtreg/gc/TestFullGCCount.java +++ b/test/hotspot/jtreg/gc/TestFullGCCount.java @@ -29,6 +29,8 @@ * @summary JMM GC counters overcount in some cases * @comment Shenandoah has "ExplicitGCInvokesConcurrent" on by default * @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false) + * @comment G1 has separate counters for STW Full GC and concurrent GC. + * @requires !(vm.gc == "G1" & vm.opt.ExplicitGCInvokesConcurrent) * @requires vm.gc != "Z" * @modules java.management * @run main/othervm -Xlog:gc gc.TestFullGCCount From 0eeaf6b219758563712d951b3c6ff160ebeff52d Mon Sep 17 00:00:00 2001 From: Erik Gahlin Date: Wed, 14 Dec 2022 13:40:15 +0000 Subject: [PATCH 203/494] 8298649: JFR: RemoteRecordingStream support for checkpoint event sizes beyond u4 Reviewed-by: mgronlun --- .../share/classes/jdk/management/jfr/DiskRepository.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java index 10822fa5403..4b3fda3defd 100644 --- a/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java +++ b/src/jdk.management.jfr/share/classes/jdk/management/jfr/DiskRepository.java @@ -139,7 +139,7 @@ public State next() { private long typeId; private int typeIdshift; private int sizeShift; - private int payLoadSize; + private long payLoadSize; private int longValueshift; private int eventFieldSize; private int lastFlush; @@ -225,7 +225,7 @@ private void processNumericValueInEvent() { private void processEvent() { int left = currentByteArray.length - index; if (left >= payLoadSize) { - index += payLoadSize; + index = index + (int)payLoadSize; payLoadSize = 0; state = State.EVENT_SIZE; } else { @@ -261,7 +261,7 @@ private void processEventSize() throws IOException { eventFieldSize++; byte b = nextByte(false); - int v = (b & 0x7F); + long v = (b & 0x7F); payLoadSize += (v << sizeShift); if (b >= 0) { if (payLoadSize == 0) { From 581f9f2306835680cd6d5dbbe37f610fb4de4677 Mon Sep 17 00:00:00 2001 From: Axel Boldt-Christmas Date: Wed, 14 Dec 2022 14:10:24 +0000 Subject: [PATCH 204/494] 8297235: ZGC: assert(regs[i] != regs[j]) failed: Multiple uses of register: rax Reviewed-by: thartmann, rcastanedalo Backport-of: 042b7062f19b313f31b228bd96d2a74cc1165ab9 --- src/hotspot/cpu/x86/gc/z/z_x86_64.ad | 63 +++++++++++++------------- test/jdk/ProblemList-zgc.txt | 68 ---------------------------- 2 files changed, 31 insertions(+), 100 deletions(-) diff --git a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad index f3e19b41733..44f3f221fae 100644 --- a/src/hotspot/cpu/x86/gc/z/z_x86_64.ad +++ b/src/hotspot/cpu/x86/gc/z/z_x86_64.ad @@ -35,7 +35,7 @@ source %{ static void z_load_barrier(MacroAssembler& _masm, const MachNode* node, Address ref_addr, Register ref, Register tmp, uint8_t barrier_data) { if (barrier_data == ZLoadBarrierElided) { - return; // Elided. + return; } ZLoadBarrierStubC2* const stub = ZLoadBarrierStubC2::create(node, ref_addr, ref, tmp, barrier_data); { @@ -60,6 +60,27 @@ static void z_load_barrier_cmpxchg(MacroAssembler& _masm, const MachNode* node, __ bind(*stub->continuation()); } +static void z_cmpxchg_common(MacroAssembler& _masm, const MachNode* node, Register mem_reg, Register newval, Register tmp) { + // Compare value (oldval) is in rax + const Address mem = Address(mem_reg, 0); + + if (node->barrier_data() != ZLoadBarrierElided) { + __ movptr(tmp, rax); + } + + __ lock(); + __ cmpxchgptr(newval, mem); + + if (node->barrier_data() != ZLoadBarrierElided) { + Label good; + z_load_barrier_cmpxchg(_masm, node, mem, rax, tmp, good); + __ movptr(rax, tmp); + __ lock(); + __ cmpxchgptr(newval, mem); + __ bind(good); + } +} + %} // Load Pointer @@ -81,7 +102,7 @@ instruct zLoadP(rRegP dst, memory mem, rFlagsReg cr) ins_pipe(ialu_reg_mem); %} -instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ +instruct zCompareAndExchangeP(indirect mem, rax_RegP oldval, rRegP newval, rRegP tmp, rFlagsReg cr) %{ match(Set oldval (CompareAndExchangeP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); effect(KILL cr, TEMP tmp); @@ -90,26 +111,14 @@ instruct zCompareAndExchangeP(memory mem, rax_RegP oldval, rRegP newval, rRegP t "cmpxchgq $newval, $mem" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - - if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - } + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); %} ins_pipe(pipe_cmpxchg); %} -instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ +instruct zCompareAndSwapP(rRegI res, indirect mem, rRegP newval, rRegP tmp, rFlagsReg cr, rax_RegP oldval) %{ match(Set res (CompareAndSwapP mem (Binary oldval newval))); match(Set res (WeakCompareAndSwapP mem (Binary oldval newval))); predicate(UseZGC && n->as_LoadStore()->barrier_data() == ZLoadBarrierStrong); @@ -121,20 +130,10 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags "movzbl $res, $res" %} ins_encode %{ - if (barrier_data() != ZLoadBarrierElided) { // barrier could be elided by ZBarrierSetC2::analyze_dominating_barriers() - __ movptr($tmp$$Register, $oldval$$Register); - } - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - + precond($oldval$$Register == rax); + z_cmpxchg_common(_masm, this, $mem$$Register, $newval$$Register, $tmp$$Register); if (barrier_data() != ZLoadBarrierElided) { - Label good; - z_load_barrier_cmpxchg(_masm, this, $mem$$Address, $oldval$$Register, $tmp$$Register, good); - __ movptr($oldval$$Register, $tmp$$Register); - __ lock(); - __ cmpxchgptr($newval$$Register, $mem$$Address); - __ bind(good); - __ cmpptr($tmp$$Register, $oldval$$Register); + __ cmpptr($tmp$$Register, rax); } __ setb(Assembler::equal, $res$$Register); __ movzbl($res$$Register, $res$$Register); @@ -143,7 +142,7 @@ instruct zCompareAndSwapP(rRegI res, memory mem, rRegP newval, rRegP tmp, rFlags ins_pipe(pipe_cmpxchg); %} -instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ +instruct zXChgP(indirect mem, rRegP newval, rFlagsReg cr) %{ match(Set newval (GetAndSetP mem newval)); predicate(UseZGC && n->as_LoadStore()->barrier_data() != 0); effect(KILL cr); @@ -151,7 +150,7 @@ instruct zXChgP(memory mem, rRegP newval, rFlagsReg cr) %{ format %{ "xchgq $newval, $mem" %} ins_encode %{ - __ xchgptr($newval$$Register, $mem$$Address); + __ xchgptr($newval$$Register, Address($mem$$Register, 0)); z_load_barrier(_masm, this, Address(noreg, 0), $newval$$Register, noreg /* tmp */, barrier_data()); %} diff --git a/test/jdk/ProblemList-zgc.txt b/test/jdk/ProblemList-zgc.txt index f4b2f9ae4e8..c3d4ecd4b9f 100644 --- a/test/jdk/ProblemList-zgc.txt +++ b/test/jdk/ProblemList-zgc.txt @@ -26,71 +26,3 @@ # List of quarantined tests for testing with ZGC. # ############################################################################# - -java/lang/StackWalker/AcrossThreads.java 8297235 generic-x64 -java/math/BigInteger/BigIntegerParallelMultiplyTest.java 8297235 generic-x64 -java/util/Arrays/SetAllTest.java 8297235 generic-x64 -java/util/Arrays/Sorting.java 8297235 generic-x64 -java/util/Arrays/largeMemory/ParallelPrefix.java 8297235 generic-x64 -java/util/BitSet/stream/BitSetStreamTest.java 8297235 generic-x64 -java/util/Collection/IteratorMicroBenchmark.java 8297235 generic-x64 -java/util/Collections/UnmodifiableMapEntrySet.java 8297235 generic-x64 -java/util/DoubleStreamSums/CompensatedSums.java 8297235 generic-x64 -java/util/Random/RandomTest.java 8297235 generic-x64 -java/util/Scanner/ScannerStreamTest.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNow.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAny.java 8297235 generic-x64 -java/util/concurrent/forkjoin/AsyncShutdownNowInvokeAnyRace.java 8297235 generic-x64 -java/util/concurrent/forkjoin/Integrate.java 8297235 generic-x64 -java/util/concurrent/forkjoin/NQueensCS.java 8297235 generic-x64 -java/util/concurrent/tck/JSR166TestCase.java 8297235 generic-x64 -java/util/regex/PatternStreamTest.java 8297235 generic-x64 -java/util/stream/CustomFJPoolTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/DoubleNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/FlagOpTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/IntNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/LongNodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/NodeTest.java 8297235 generic-x64 -java/util/stream/boottest/java.base/java/util/stream/StreamReuseTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/SplittableRandomTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CollectAndSummaryStatisticsTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CollectorsTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ConcatOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/CountTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/DistinctOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/DoublePrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FilterOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FindAnyOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FindFirstOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/FlatMapOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ForEachOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/GroupByOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/InfiniteStreamWithLimitOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntPrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntReduceTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntSliceOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IntUniqOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/IterateTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/LongPrimitiveOpsTests.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MapOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MatchOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/MinMaxTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveAverageOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/PrimitiveSumTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/RangeTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceByOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ReduceTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SequentialOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SliceOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/SortedOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamBuilderTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamLinkTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/StreamSpliteratorTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/TeeOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ToArrayOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/ToListOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpStatefulTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/WhileOpTest.java 8297235 generic-x64 -java/util/stream/test/org/openjdk/tests/java/util/stream/mapMultiOpTest.java 8297235 generic-x64 - -jdk/internal/vm/Continuation/Fuzz.java#default 8298058 generic-x64 From ed8a2120ca1e9756c6ab5eeebfe24c15d549f04e Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Wed, 14 Dec 2022 14:34:24 +0000 Subject: [PATCH 205/494] 8298376: ZGC: thaws stackChunk with stale oops Reviewed-by: eosterlund, pchilanomate --- src/hotspot/share/oops/stackChunkOop.hpp | 2 ++ src/hotspot/share/oops/stackChunkOop.inline.hpp | 13 ++++++++++++- .../share/runtime/continuationJavaClasses.hpp | 3 ++- .../runtime/continuationJavaClasses.inline.hpp | 5 +++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/oops/stackChunkOop.hpp b/src/hotspot/share/oops/stackChunkOop.hpp index f6ce1ecc500..c1c0aee8f24 100644 --- a/src/hotspot/share/oops/stackChunkOop.hpp +++ b/src/hotspot/share/oops/stackChunkOop.hpp @@ -91,6 +91,8 @@ class stackChunkOopDesc : public instanceOopDesc { inline int max_thawing_size() const; inline void set_max_thawing_size(int value); + inline oop cont() const; + template inline oop cont() const; inline void set_cont(oop value); template diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index 5de21075666..41ce22a7c34 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -86,7 +86,18 @@ inline void stackChunkOopDesc::set_max_thawing_size(int value) { jdk_internal_vm_StackChunk::set_maxThawingSize(this, (jint)value); } -inline oop stackChunkOopDesc::cont() const { return jdk_internal_vm_StackChunk::cont(as_oop()); } +inline oop stackChunkOopDesc::cont() const { return UseCompressedOops ? cont() : cont(); /* jdk_internal_vm_StackChunk::cont(as_oop()); */ } +template +inline oop stackChunkOopDesc::cont() const { + // The state of the cont oop is used by ZCollectedHeap::requires_barriers, + // to determine the age of the stackChunkOopDesc. For that to work, it is + // only the GC that is allowed to perform a load barrier on the oop. + // This function is used by non-GC code and therfore create a stack-local + // copy on the oop and perform the load barrier on that copy instead. + oop obj = jdk_internal_vm_StackChunk::cont_raw

    (as_oop()); + obj = (oop)NativeAccess<>::oop_load(&obj); + return obj; +} inline void stackChunkOopDesc::set_cont(oop value) { jdk_internal_vm_StackChunk::set_cont(this, value); } template inline void stackChunkOopDesc::set_cont_raw(oop value) { jdk_internal_vm_StackChunk::set_cont_raw

    (this, value); } diff --git a/src/hotspot/share/runtime/continuationJavaClasses.hpp b/src/hotspot/share/runtime/continuationJavaClasses.hpp index 2186dbe3535..d8634161a4b 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.hpp @@ -124,7 +124,8 @@ class jdk_internal_vm_StackChunk: AllStatic { static inline void set_maxThawingSize(oop chunk, int value); // cont oop's processing is essential for the chunk's GC protocol - static inline oop cont(oop chunk); + template + static inline oop cont_raw(oop chunk); static inline void set_cont(oop chunk, oop value); template static inline void set_cont_raw(oop chunk, oop value); diff --git a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp index 1d0ff75225a..5bba4016033 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp @@ -81,8 +81,9 @@ inline void jdk_internal_vm_StackChunk::set_parent_access(oop chunk, oop value) chunk->obj_field_put_access(_parent_offset, value); } -inline oop jdk_internal_vm_StackChunk::cont(oop chunk) { - return chunk->obj_field(_cont_offset); +template +inline oop jdk_internal_vm_StackChunk::cont_raw(oop chunk) { + return (oop)RawAccess<>::oop_load(chunk->field_addr

    (_cont_offset)); } inline void jdk_internal_vm_StackChunk::set_cont(oop chunk, oop value) { From 0dce5b811d64ac17b9580d6a2d8eca1df70990a1 Mon Sep 17 00:00:00 2001 From: Daniel Fuchs Date: Wed, 14 Dec 2022 16:39:32 +0000 Subject: [PATCH 206/494] 8296610: java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java failed with "BindException: Address already in use: connect" Reviewed-by: michaelm --- .../HTTPSetAuthenticatorTest.java | 60 +++++++++---------- .../SetAuthenticator/HTTPTestClient.java | 30 ++++++++++ 2 files changed, 60 insertions(+), 30 deletions(-) diff --git a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java index 243c79d9644..6145f48523d 100644 --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPSetAuthenticatorTest.java @@ -191,25 +191,25 @@ public int run(HTTPTestServer server, // Now tries with explicitly setting the default authenticator: it should // be invoked again. // Uncomment the code below when 8169068 is available. -// System.out.println("\nClient: Explicitly setting the default authenticator: " -// + toString(Authenticator.getDefault())); -// HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault()); -// count = authOne.count.get(); -// if (count != expectedIncrement) { -// throw new AssertionError("Authenticator #1 called " + count(count) -// + " expected it to be called " + expected(expectedIncrement)); -// } -// count = authTwo.count.get(); -// if (count != expectedIncrement) { -// throw new AssertionError("Authenticator #2 called " + count(count) -// + " expected it to be called " + expected(expectedIncrement)); -// } -// count = AUTHENTICATOR.count.get(); -// if (count != defaultCount + 2 * expectedIncrement) { -// throw new AssertionError("Default Authenticator called " + count(count) -// + " expected it to be called " -// + expected(defaultCount + 2 * expectedIncrement)); -// } + System.out.println("\nClient: Explicitly setting the default authenticator: " + + toString(Authenticator.getDefault())); + HTTPTestClient.connect(protocol, server, mode, Authenticator.getDefault()); + count = authOne.count.get(); + if (count != expectedIncrement) { + throw new AssertionError("Authenticator #1 called " + count(count) + + " expected it to be called " + expected(expectedIncrement)); + } + count = authTwo.count.get(); + if (count != expectedIncrement) { + throw new AssertionError("Authenticator #2 called " + count(count) + + " expected it to be called " + expected(expectedIncrement)); + } + count = AUTHENTICATOR.count.get(); + if (count != defaultCount + 2 * expectedIncrement) { + throw new AssertionError("Default Authenticator called " + count(count) + + " expected it to be called " + + expected(defaultCount + 2 * expectedIncrement)); + } // Now tries to set an authenticator on a connected connection. URL url = url(protocol, server.getAddress(), "/"); @@ -238,16 +238,16 @@ public int run(HTTPTestServer server, + ise); } // Uncomment the code below when 8169068 is available. -// try { -// conn.setAuthenticator(Authenticator.getDefault()); -// throw new RuntimeException("Expected IllegalStateException" -// + " trying to set an authenticator after connect" -// + " not raised."); -// } catch (IllegalStateException ise) { -// System.out.println("Client: caught expected ISE" -// + " trying to set an authenticator after connect: " -// + ise); -// } + try { + conn.setAuthenticator(Authenticator.getDefault()); + throw new RuntimeException("Expected IllegalStateException" + + " trying to set an authenticator after connect" + + " not raised."); + } catch (IllegalStateException ise) { + System.out.println("Client: caught expected ISE" + + " trying to set an authenticator after connect: " + + ise); + } try { conn.setAuthenticator(null); throw new RuntimeException("Expected" @@ -279,7 +279,7 @@ public int run(HTTPTestServer server, // All good! // return the number of times the default authenticator is supposed // to have been called. - return scheme == HttpSchemeType.NONE ? 0 : 1 * EXPECTED_AUTH_CALLS_PER_TEST; + return scheme == HttpSchemeType.NONE ? 0 : 2 * EXPECTED_AUTH_CALLS_PER_TEST; } static String toString(Authenticator a) { diff --git a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java index 4d1f5c52a78..3f436ef6d02 100644 --- a/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java +++ b/test/jdk/java/net/HttpURLConnection/SetAuthenticator/HTTPTestClient.java @@ -23,10 +23,12 @@ import java.io.IOException; import java.net.Authenticator; +import java.net.BindException; import java.net.HttpURLConnection; import java.net.InetSocketAddress; import java.net.Proxy; import java.net.URL; +import java.time.Duration; import javax.net.ssl.HttpsURLConnection; /** @@ -35,11 +37,39 @@ */ public class HTTPTestClient extends HTTPTest { + public static final long DELAY_BEFORE_RETRY = 2500; // milliseconds + public static void connect(HttpProtocolType protocol, HTTPTestServer server, HttpAuthType authType, Authenticator auth) throws IOException { + try { + doConnect(protocol, server, authType, auth); + } catch (BindException ex) { + // sleep a bit then try again once + System.out.println("WARNING: Unexpected BindException: " + ex); + System.out.println("\tSleeping a bit and try again..."); + long start = System.nanoTime(); + System.gc(); + try { + Thread.sleep(DELAY_BEFORE_RETRY); + } catch (InterruptedException iex) { + // ignore + } + System.gc(); + System.out.println("\tRetrying after " + + Duration.ofNanos(System.nanoTime() - start).toMillis() + + " milliseconds"); + doConnect(protocol, server, authType, auth); + } + } + + public static void doConnect(HttpProtocolType protocol, + HTTPTestServer server, + HttpAuthType authType, + Authenticator auth) + throws IOException { InetSocketAddress address = server.getAddress(); final URL url = url(protocol, address, "/"); From c05dbac3cbd8de3822191bcb5c34832c997bc4a9 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Wed, 14 Dec 2022 16:51:41 +0000 Subject: [PATCH 207/494] 8193547: Regression automated test '/open/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java' fails Reviewed-by: serb --- test/jdk/ProblemList.txt | 1 - .../Toolkit/DesktopProperties/rfe4758438.java | 114 ++++++++++++------ .../Toolkit/DesktopProperties/rfe4758438.sh | 41 ++++--- 3 files changed, 103 insertions(+), 53 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 17bad35da71..113e11dd6ef 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -426,7 +426,6 @@ java/awt/SplashScreen/MultiResolutionSplash/unix/UnixMultiResolutionSplashTest.j java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java 7107528 linux-all,macosx-all java/awt/Mouse/MouseDragEvent/MouseDraggedTest.java 8080676 linux-all java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersInKeyEvent.java 8157147 linux-all,windows-all,macosx-all -java/awt/Toolkit/DesktopProperties/rfe4758438.java 8193547 linux-all java/awt/Toolkit/ToolkitPropertyTest/ToolkitPropertyTest_Enable.java 6847163 java/awt/xembed/server/RunTestXEmbed.java 7034201 linux-all java/awt/Modal/ModalFocusTransferTests/FocusTransferDialogsDocModalTest.java 8164473 linux-all diff --git a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java index aa69f8fa4b7..784dc0ff18b 100644 --- a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java +++ b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2022, 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,6 +30,7 @@ * @test * @key headful * @bug 4758438 + * @requires os.family == "linux" * @summary Testcase to check the implementation of RFE 4758438 * The RFE suggests that the GNOME desktop properties * should be made accessible through the @@ -43,12 +44,14 @@ public class rfe4758438 implements PropertyChangeListener { enum PROPS { drag_threshold( + "org.gnome.desktop.peripherals.mouse drag-threshold", "org.gnome.settings-daemon.peripherals.mouse drag-threshold", "/desktop/gnome/peripherals/mouse/drag_threshold", "gnome.Net/DndDragThreshold", "int", new String[]{"5", "6"}), double_click( + "org.gnome.desktop.peripherals.mouse double-click", "org.gnome.settings-daemon.peripherals.mouse double-click", "/desktop/gnome/peripherals/mouse/double_click", "gnome.Net/DoubleClickTime", @@ -56,31 +59,43 @@ enum PROPS { new String[]{"200","300"}), cursor_blink( "org.gnome.desktop.interface cursor-blink", + null, "/desktop/gnome/interface/cursor_blink", "gnome.Net/CursorBlink", "bool", new String[]{"true","false"}), cursor_blink_time( "org.gnome.desktop.interface cursor-blink-time", + null, "/desktop/gnome/interface/cursor_blink_time", "gnome.Net/CursorBlinkTime", "int", new String[]{"1000","1500"}), gtk_theme( "org.gnome.desktop.interface gtk-theme", + null, "/desktop/gnome/interface/gtk_theme", "gnome.Net/ThemeName", "string", new String[]{"Crux","Simple"}); public final String gsettings; + public final String gsettingsFallback; public final String gconftool; public final String java; public final String type; public final String[] values; - PROPS(String gsettings, String gconftool, String java, String type, String[] values){ + PROPS( + String gsettings, + String gsettingsFallback, + String gconftool, + String java, + String type, + String[] values + ){ this.gsettings = gsettings; + this.gsettingsFallback = gsettingsFallback; this.gconftool = gconftool; this.java = java; this.type = type; @@ -90,10 +105,10 @@ enum PROPS { static boolean useGsettings; static String tool; - Toolkit toolkit = Toolkit.getDefaultToolkit(); + final Toolkit toolkit = Toolkit.getDefaultToolkit(); String changedProperty; Object changedValue; - Object lock = new Object(); + final Object lock = new Object(); /** * Implementation of PropertyChangeListener method @@ -105,7 +120,7 @@ public void propertyChange(PropertyChangeEvent event) { synchronized(lock) { try { lock.notifyAll(); - } catch (Exception e) { + } catch (Exception ignored) { } } } @@ -132,6 +147,34 @@ void doTest() throws Exception { System.out.println("Test passed"); } + String prepareCommand(PROPS property, boolean useMain) { + //Create the command to execute + StringBuffer sb = new StringBuffer(tool); + if (useGsettings) { + sb.append(" set "); + sb.append( useMain + ? property.gsettings + : property.gsettingsFallback + ); + sb.append(" "); + } else { + sb.append(" --set --type="); + sb.append(property.type); + sb.append(" "); + sb.append(property.gconftool); + sb.append(" "); + } + return sb.toString(); + } + + int doTestCommand(String cmd) throws Exception { + //Initialize the variables and execute the command + changedProperty = ""; + changedValue = null; + + return executeCommand(cmd); + } + /** * Do the test for each property. Find the current value * of the property, set the property to a value not equal @@ -146,10 +189,10 @@ void doTest(PROPS property) throws Exception { //For boolean type values, getDesktopProperty method returns Integer objects if (property.type.equals("bool")) { - if (obj.equals(new Integer(1))) { - obj = new String("true"); + if (obj.equals(1)) { + obj = "true"; } else { - obj = new String("false"); + obj = "false"; } } Object value = property.values[0]; @@ -157,56 +200,53 @@ void doTest(PROPS property) throws Exception { value = property.values[1]; } - //Create the command to execute - StringBuffer sb = new StringBuffer(tool); - if (useGsettings) { - sb.append(" set "); - sb.append(property.gsettings); - sb.append(" "); - } else { - sb.append(" --set --type="); - sb.append(property.type); - sb.append(" "); - sb.append(property.gconftool); - sb.append(" "); - } - String tempCommand = sb.toString(); - sb.append(value.toString()); + String tempCommand = prepareCommand(property, true); - //Initialize the variables and execute the command - changedProperty = ""; - changedValue = null; - if (executeCommand(sb.toString()) != 0) - throw new RuntimeException("Could not execute the command"); + int retVal = doTestCommand(tempCommand + value); + + if (retVal != 0) { + if (useGsettings && property.gsettingsFallback != null) { + System.out.printf("Failed:\n\t%s\nTrying fallback:\n\t", tempCommand); + tempCommand = prepareCommand(property, false); + System.out.println(tempCommand); + + retVal = doTestCommand(tempCommand + value); + } + + if (retVal != 0) { + throw new RuntimeException("Could not execute the command"); + } + } synchronized(lock) { try { lock.wait(5000); - } catch (Exception e) { + } catch (Exception ignored) { } } + if (property.type.equals("bool")) { - if (changedValue.equals(new Integer(1))) { - changedValue = new String("true"); + if (changedValue.equals(1)) { + changedValue = "true"; } else { - changedValue = new String("false"); + changedValue = "false"; } } //Check if the event got triggered if (!changedProperty.equals(property.java)) { //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); throw new RuntimeException("PropertyChangedEvent did not occur for " + property.java); } else if (!changedValue.toString().equals(value.toString())) { //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); throw new RuntimeException("New value of the property is different from " + "the value supplied"); } //Reset the property - executeCommand(tempCommand + obj.toString()); + executeCommand(tempCommand + obj); } /** @@ -231,9 +271,9 @@ int executeCommand(String command) throws Exception { stderr.append((char) es.read()); if (stdout.length() > 0) - System.out.println(stdout.toString()); + System.out.println(stdout); if (stderr.length() > 0) - System.err.println(stderr.toString()); + System.err.println(stderr); return process.exitValue(); } } diff --git a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh index 6a55d727c7b..ce5628ac9d4 100644 --- a/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh +++ b/test/jdk/java/awt/Toolkit/DesktopProperties/rfe4758438.sh @@ -1,4 +1,4 @@ -# Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2014, 2022, 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,18 +28,20 @@ OS=`uname` case "$OS" in Linux* ) - GNOMESID=`pgrep gnome-session` + GNOMESID=`pgrep gnome-session | head -n1` + + printf "\n/* gnome-session environ\n" + cat "/proc/$GNOMESID/environ" | tr '\0' '\n' + printf "\n*/\n\n" + DBUS_SESSION_BUS_ADDRESS=`grep -z DBUS_SESSION_BUS_ADDRESS /proc/$GNOMESID/environ | cut -d= -f2-` export DBUS_SESSION_BUS_ADDRESS + DISPLAY=`grep -z DISPLAY /proc/$GNOMESID/environ | cut -d= -f2-` export DISPLAY - ;; - Sun* ) - GNOMESID=`pgrep gnome-session` - DBUS_SESSION_BUS_ADDRESS=`pargs -e $GNOMESID | grep DBUS_SESSION_BUS_ADDRESS | cut -d= -f2-` - export DBUS_SESSION_BUS_ADDRESS - DISPLAY=`pargs -e $GNOMESID | grep DISPLAY | cut -d= -f2-` - export DISPLAY + + XDG_CURRENT_DESKTOP=`grep -z XDG_CURRENT_DESKTOP /proc/$GNOMESID/environ | cut -d= -f2-` + export XDG_CURRENT_DESKTOP ;; * ) echo "This Feature is not to be tested on $OS" @@ -47,13 +49,18 @@ case "$OS" in ;; esac -if [ ${GNOME_DESKTOP_SESSION_ID:-nonset} = "nonset" ]; +printf "\n/* Test env:\n\n" +env +printf "\n*/\n\n" + +XDG_GNOME=$(echo $XDG_CURRENT_DESKTOP | grep -i gnome) + +if [ -z "$XDG_GNOME" ] \ + && [ ${GNOME_DESKTOP_SESSION_ID:-nonset} = "nonset" ] \ + && [ ${GNOME_SESSION_NAME:-nonset} = "nonset" ] then - if [ ${GNOME_SESSION_NAME:-nonset} = "nonset" ]; - then - echo "This test should run under Gnome" - exit 0 - fi + echo "This test should run under Gnome" + exit 0 fi SCHEMAS=`gsettings list-schemas | wc -l` @@ -70,7 +77,11 @@ fi cd ${TESTSRC} echo $PWD echo "${TESTJAVA}/bin/javac -d ${TESTCLASSES} rfe4758438.java" + +set -e ${TESTJAVA}/bin/javac -d ${TESTCLASSES} rfe4758438.java +set +e + cd ${TESTCLASSES} ${TESTJAVA}/bin/java -DuseGsettings=${USE_GSETTINGS} -Dtool=${TOOL} ${TESTVMOPTS} rfe4758438 From 736fcd49f7cd3aa6f226b2e088415eaf05f97ee8 Mon Sep 17 00:00:00 2001 From: Emanuel Peter Date: Wed, 14 Dec 2022 17:25:49 +0000 Subject: [PATCH 208/494] 8296318: use-def assert: special case undetected loops nested in infinite loops Reviewed-by: chagedorn, kvn --- src/hotspot/share/opto/block.cpp | 8 ++- src/hotspot/share/opto/cfgnode.cpp | 41 ++++++++++++ src/hotspot/share/opto/cfgnode.hpp | 4 ++ src/hotspot/share/opto/loopnode.cpp | 25 +------- .../TestUndetectedLoopInInfiniteLoop.java | 62 +++++++++++++++++++ 5 files changed, 115 insertions(+), 25 deletions(-) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestUndetectedLoopInInfiniteLoop.java diff --git a/src/hotspot/share/opto/block.cpp b/src/hotspot/share/opto/block.cpp index 57bdbd165a4..f729f93b03b 100644 --- a/src/hotspot/share/opto/block.cpp +++ b/src/hotspot/share/opto/block.cpp @@ -1375,7 +1375,13 @@ void PhaseCFG::verify() const { } } } - assert(is_loop || block->find_node(def) < j, "uses must follow definitions"); + // Uses must be before definition, except if: + // - We are in some kind of loop we already detected + // - We are in infinite loop, where Region may not have been turned into LoopNode + assert(block->find_node(def) < j || + is_loop || + (n->is_Phi() && block->head()->as_Region()->is_in_infinite_subgraph()), + "uses must follow definitions (except in loops)"); } } } diff --git a/src/hotspot/share/opto/cfgnode.cpp b/src/hotspot/share/opto/cfgnode.cpp index 8afc4d5d844..b829523ca9b 100644 --- a/src/hotspot/share/opto/cfgnode.cpp +++ b/src/hotspot/share/opto/cfgnode.cpp @@ -394,6 +394,47 @@ bool RegionNode::is_unreachable_from_root(const PhaseGVN* phase) const { return true; // The Region node is unreachable - it is dead. } +#ifdef ASSERT +// Is this region in an infinite subgraph? +// (no path to root except through false NeverBranch exit) +bool RegionNode::is_in_infinite_subgraph() { + ResourceMark rm; + Unique_Node_List worklist; + worklist.push(this); + return RegionNode::are_all_nodes_in_infinite_subgraph(worklist); +} + +// Are all nodes in worklist in infinite subgraph? +// (no path to root except through false NeverBranch exit) +// worklist is directly used for the traversal +bool RegionNode::are_all_nodes_in_infinite_subgraph(Unique_Node_List& worklist) { + // BFS traversal down the CFG, except through NeverBranch exits + for (uint i = 0; i < worklist.size(); ++i) { + Node* n = worklist.at(i); + assert(n->is_CFG(), "only traverse CFG"); + if (n->is_Root()) { + // Found root -> there was an exit! + return false; + } else if (n->is_NeverBranch()) { + // Only follow the loop-internal projection, not the NeverBranch exit + ProjNode* proj = n->as_NeverBranch()->proj_out_or_null(0); + assert(proj != nullptr, "must find loop-internal projection of NeverBranch"); + worklist.push(proj); + } else { + // Traverse all CFG outputs + for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { + Node* use = n->fast_out(i); + if (use->is_CFG()) { + worklist.push(use); + } + } + } + } + // No exit found for any loop -> all are infinite + return true; +} +#endif //ASSERT + bool RegionNode::try_clean_mem_phi(PhaseGVN *phase) { // Incremental inlining + PhaseStringOpts sometimes produce: // diff --git a/src/hotspot/share/opto/cfgnode.hpp b/src/hotspot/share/opto/cfgnode.hpp index a41a744d537..e9d4219cf8b 100644 --- a/src/hotspot/share/opto/cfgnode.hpp +++ b/src/hotspot/share/opto/cfgnode.hpp @@ -91,6 +91,10 @@ class RegionNode : public Node { PhiNode* has_unique_phi() const; // returns the unique phi user, or NULL // Is this region node unreachable from root? bool is_unreachable_region(const PhaseGVN* phase); +#ifdef ASSERT + bool is_in_infinite_subgraph(); + static bool are_all_nodes_in_infinite_subgraph(Unique_Node_List& worklist); +#endif //ASSERT virtual int Opcode() const; virtual uint size_of() const { return sizeof(*this); } virtual bool pinned() const { return (const Node*)in(0) == this; } diff --git a/src/hotspot/share/opto/loopnode.cpp b/src/hotspot/share/opto/loopnode.cpp index 17112264706..a06773435b6 100644 --- a/src/hotspot/share/opto/loopnode.cpp +++ b/src/hotspot/share/opto/loopnode.cpp @@ -4201,30 +4201,7 @@ bool PhaseIdealLoop::only_has_infinite_loops() { assert(head->is_Region(), ""); worklist.push(head); } - // BFS traversal down the CFG, except through NeverBranch exits - for (uint i = 0; i < worklist.size(); ++i) { - Node* n = worklist.at(i); - assert(n->is_CFG(), "only traverse CFG"); - if (n->is_Root()) { - // Found root -> there was an exit! - return false; - } else if (n->is_NeverBranch()) { - // Only follow the loop-internal projection, not the NeverBranch exit - ProjNode* proj = n->as_NeverBranch()->proj_out_or_null(0); - assert(proj != nullptr, "must find loop-internal projection of NeverBranch"); - worklist.push(proj); - } else { - // Traverse all CFG outputs - for (DUIterator_Fast imax, i = n->fast_outs(imax); i < imax; i++) { - Node* use = n->fast_out(i); - if (use->is_CFG()) { - worklist.push(use); - } - } - } - } - // No exit found for any loop -> all are infinite - return true; + return RegionNode::are_all_nodes_in_infinite_subgraph(worklist); } #endif diff --git a/test/hotspot/jtreg/compiler/loopopts/TestUndetectedLoopInInfiniteLoop.java b/test/hotspot/jtreg/compiler/loopopts/TestUndetectedLoopInInfiniteLoop.java new file mode 100644 index 00000000000..868a9f27d56 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestUndetectedLoopInInfiniteLoop.java @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2022, 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 8296318 + * @summary Loops inside infinite loops may not be detected, thus a region may still + * be the loop head, even if it is not a LoopNode. + * @run main/othervm -Xcomp -XX:-TieredCompilation + * -XX:CompileCommand=compileonly,TestUndetectedLoopInInfiniteLoop::test* + * -XX:PerMethodTrapLimit=0 + * TestUndetectedLoopInInfiniteLoop + */ + + +public class TestUndetectedLoopInInfiniteLoop { + public static void main (String[] args) { + test(true, false); + } + public static void test(boolean flag, boolean flag2) { + int x = 0; + if (flag2) { // runtime check, avoid infinite loop + while (true) { // infinite loop (no exit) + if (flag) { + x++; + } + do { // inner loop + // assert for this block + // Region + // Phi -> SubI -> XorI ---> Phi + x = (x - 1) ^ 1; + // Problem: this looks like a loop, but we have no LoopNode + // We have no LoopNode, because this is all in an infinite + // loop, and during PhaseIdealLoop::build_loop_tree we do not + // attach the loops of an infinite loop to the loop tree, + // and hence we do not get to call beautify_loop on these loops + // which would have turned the Region into a LoopNode. + } while (x < 0); + } + } + } +} From 7241e358bfbb004897b84da3c154d7bdd96cb560 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 14 Dec 2022 17:53:11 +0000 Subject: [PATCH 209/494] 8298692: Fix typos in test/jdk/com/sun/jdi files Reviewed-by: amenkov, sspitsyn --- test/jdk/com/sun/jdi/ArgumentValuesTest.java | 2 +- test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java | 2 +- test/jdk/com/sun/jdi/lib/jdb/Jdb.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/com/sun/jdi/ArgumentValuesTest.java b/test/jdk/com/sun/jdi/ArgumentValuesTest.java index bcce51bc562..5bae42c4e28 100644 --- a/test/jdk/com/sun/jdi/ArgumentValuesTest.java +++ b/test/jdk/com/sun/jdi/ArgumentValuesTest.java @@ -227,7 +227,7 @@ protected void runTests() } } - // a method with with one generic param + // a method with one generic param { System.out.println("----- Testing generic args"); bpe = resumeTo("ArgumentValuesTarg", GENERIC_ARGS_LINE_1); diff --git a/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java b/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java index a726e19192f..5a6ca80573d 100644 --- a/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java +++ b/test/jdk/com/sun/jdi/connect/spi/GeneratedConnectors.java @@ -25,7 +25,7 @@ * @bug 4287596 * @summary Unit test for "Pluggable Connectors and Transports" feature. * - * When a transport service is deployed the virtual machine machine + * When a transport service is deployed the virtual machine * is required to create an AttachingConnector and ListeningConnector * to encapsulate the transport. This tests that the connectors are * created and that they have an "address" argument. diff --git a/test/jdk/com/sun/jdi/lib/jdb/Jdb.java b/test/jdk/com/sun/jdi/lib/jdb/Jdb.java index 0c7c84c521f..73ab885dbf9 100644 --- a/test/jdk/com/sun/jdi/lib/jdb/Jdb.java +++ b/test/jdk/com/sun/jdi/lib/jdb/Jdb.java @@ -152,7 +152,7 @@ public void shutdown() { # # 5) ^main[89] > @ # - # i.e., the > prompt comes out AFTER the prompt we we need to wait for. + # i.e., the > prompt comes out AFTER the prompt we need to wait for. */ // compile regexp once private final static String promptPattern = "?\\[[1-9][0-9]*\\] [ >]*$"; From 8ff2928a04aeec8c09ff4a1ec4e83d4c9010950e Mon Sep 17 00:00:00 2001 From: Thomas Schatzl Date: Wed, 14 Dec 2022 17:55:15 +0000 Subject: [PATCH 210/494] 8297639: Remove preventive GCs in G1 Reviewed-by: ayang, iwalulya --- src/hotspot/share/gc/g1/g1AllocRegion.hpp | 9 +- src/hotspot/share/gc/g1/g1Allocator.cpp | 4 +- src/hotspot/share/gc/g1/g1Allocator.hpp | 4 - .../share/gc/g1/g1Allocator.inline.hpp | 10 --- src/hotspot/share/gc/g1/g1CollectedHeap.cpp | 56 ++++-------- src/hotspot/share/gc/g1/g1CollectionSet.cpp | 4 - src/hotspot/share/gc/g1/g1CollectionSet.hpp | 1 - src/hotspot/share/gc/g1/g1Policy.cpp | 87 ------------------- src/hotspot/share/gc/g1/g1Policy.hpp | 10 --- src/hotspot/share/gc/g1/g1VMOperations.cpp | 7 +- src/hotspot/share/gc/g1/g1VMOperations.hpp | 3 - src/hotspot/share/gc/shared/gcCause.cpp | 3 - src/hotspot/share/gc/shared/gcCause.hpp | 1 - .../jtreg/gc/g1/TestEvacuationFailure.java | 1 - .../jtreg/gc/g1/TestGCLogMessages.java | 2 - .../hotspot/jtreg/gc/g1/TestVerifyGCType.java | 3 +- 16 files changed, 26 insertions(+), 179 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1AllocRegion.hpp b/src/hotspot/share/gc/g1/g1AllocRegion.hpp index 4abf3530533..a609472a5c9 100644 --- a/src/hotspot/share/gc/g1/g1AllocRegion.hpp +++ b/src/hotspot/share/gc/g1/g1AllocRegion.hpp @@ -88,6 +88,10 @@ class G1AllocRegion : public CHeapObj { // to allocate a new region even if the max has been reached. HeapWord* new_alloc_region_and_allocate(size_t word_size, bool force); + // Perform an allocation out of a new allocation region, retiring the current one. + inline HeapWord* attempt_allocation_using_new_region(size_t min_word_size, + size_t desired_word_size, + size_t* actual_word_size); protected: // The memory node index this allocation region belongs to. uint _node_index; @@ -172,11 +176,6 @@ class G1AllocRegion : public CHeapObj { size_t desired_word_size, size_t* actual_word_size); - // Perform an allocation out of a new allocation region, retiring the current one. - inline HeapWord* attempt_allocation_using_new_region(size_t min_word_size, - size_t desired_word_size, - size_t* actual_word_size); - // Should be called to allocate a new region even if the max of this // type of regions has been reached. Should only be called if other // allocation attempts have failed and we are not holding a valid diff --git a/src/hotspot/share/gc/g1/g1Allocator.cpp b/src/hotspot/share/gc/g1/g1Allocator.cpp index 4de83eb6d4c..6eab853381b 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.cpp +++ b/src/hotspot/share/gc/g1/g1Allocator.cpp @@ -254,8 +254,8 @@ HeapWord* G1Allocator::survivor_attempt_allocation(size_t min_word_size, // the memory may have been used up as the threads waited to acquire the lock. if (!survivor_is_full()) { result = survivor_gc_alloc_region(node_index)->attempt_allocation_locked(min_word_size, - desired_word_size, - actual_word_size); + desired_word_size, + actual_word_size); if (result == NULL) { set_survivor_full(); } diff --git a/src/hotspot/share/gc/g1/g1Allocator.hpp b/src/hotspot/share/gc/g1/g1Allocator.hpp index bc97de7fc15..9dd5fcdebe6 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.hpp @@ -117,10 +117,6 @@ class G1Allocator : public CHeapObj { size_t desired_word_size, size_t* actual_word_size); - // Attempt allocation, retiring the current region and allocating a new one. It is - // assumed that attempt_allocation() has been tried and failed already first. - inline HeapWord* attempt_allocation_using_new_region(size_t word_size); - // This is to be called when holding an appropriate lock. It first tries in the // current allocation region, and then attempts an allocation using a new region. inline HeapWord* attempt_allocation_locked(size_t word_size); diff --git a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp index 0237e002140..aa10347ad4e 100644 --- a/src/hotspot/share/gc/g1/g1Allocator.inline.hpp +++ b/src/hotspot/share/gc/g1/g1Allocator.inline.hpp @@ -62,16 +62,6 @@ inline HeapWord* G1Allocator::attempt_allocation(size_t min_word_size, return mutator_alloc_region(node_index)->attempt_allocation(min_word_size, desired_word_size, actual_word_size); } -inline HeapWord* G1Allocator::attempt_allocation_using_new_region(size_t word_size) { - uint node_index = current_node_index(); - size_t temp; - HeapWord* result = mutator_alloc_region(node_index)->attempt_allocation_using_new_region(word_size, word_size, &temp); - assert(result != NULL || mutator_alloc_region(node_index)->get() == NULL, - "Must not have a mutator alloc region if there is no memory, but is " PTR_FORMAT, - p2i(mutator_alloc_region(node_index)->get())); - return result; -} - inline HeapWord* G1Allocator::attempt_allocation_locked(size_t word_size) { uint node_index = current_node_index(); HeapWord* result = mutator_alloc_region(node_index)->attempt_allocation_locked(word_size); diff --git a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp index 0d651f7340e..35e92173888 100644 --- a/src/hotspot/share/gc/g1/g1CollectedHeap.cpp +++ b/src/hotspot/share/gc/g1/g1CollectedHeap.cpp @@ -398,7 +398,6 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { HeapWord* result = NULL; for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; - bool preventive_collection_required = false; uint gc_count_before; { @@ -406,32 +405,21 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { // Now that we have the lock, we first retry the allocation in case another // thread changed the region while we were waiting to acquire the lock. - size_t actual_size; - result = _allocator->attempt_allocation(word_size, word_size, &actual_size); + result = _allocator->attempt_allocation_locked(word_size); if (result != NULL) { return result; } - preventive_collection_required = policy()->preventive_collection_required(1); - if (!preventive_collection_required) { - // We've already attempted a lock-free allocation above, so we don't want to - // do it again. Let's jump straight to replacing the active region. - result = _allocator->attempt_allocation_using_new_region(word_size); + // If the GCLocker is active and we are bound for a GC, try expanding young gen. + // This is different to when only GCLocker::needs_gc() is set: try to avoid + // waiting because the GCLocker is active to not wait too long. + if (GCLocker::is_active_and_needs_gc() && policy()->can_expand_young_list()) { + // No need for an ergo message here, can_expand_young_list() does this when + // it returns true. + result = _allocator->attempt_allocation_force(word_size); if (result != NULL) { return result; } - - // If the GCLocker is active and we are bound for a GC, try expanding young gen. - // This is different to when only GCLocker::needs_gc() is set: try to avoid - // waiting because the GCLocker is active to not wait too long. - if (GCLocker::is_active_and_needs_gc() && policy()->can_expand_young_list()) { - // No need for an ergo message here, can_expand_young_list() does this when - // it returns true. - result = _allocator->attempt_allocation_force(word_size); - if (result != NULL) { - return result; - } - } } // Only try a GC if the GCLocker does not signal the need for a GC. Wait until @@ -443,10 +431,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_slow(size_t word_size) { } if (should_try_gc) { - GCCause::Cause gc_cause = preventive_collection_required ? GCCause::_g1_preventive_collection - : GCCause::_g1_inc_collection_pause; bool succeeded; - result = do_collection_pause(word_size, gc_count_before, &succeeded, gc_cause); + result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_inc_collection_pause); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, @@ -860,7 +846,6 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { HeapWord* result = NULL; for (uint try_count = 1, gclocker_retry_count = 0; /* we'll return */; try_count += 1) { bool should_try_gc; - bool preventive_collection_required = false; uint gc_count_before; @@ -868,17 +853,14 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { MutexLocker x(Heap_lock); size_t size_in_regions = humongous_obj_size_in_regions(word_size); - preventive_collection_required = policy()->preventive_collection_required((uint)size_in_regions); - if (!preventive_collection_required) { - // Given that humongous objects are not allocated in young - // regions, we'll first try to do the allocation without doing a - // collection hoping that there's enough space in the heap. - result = humongous_obj_allocate(word_size); - if (result != NULL) { - policy()->old_gen_alloc_tracker()-> - add_allocated_humongous_bytes_since_last_gc(size_in_regions * HeapRegion::GrainBytes); - return result; - } + // Given that humongous objects are not allocated in young + // regions, we'll first try to do the allocation without doing a + // collection hoping that there's enough space in the heap. + result = humongous_obj_allocate(word_size); + if (result != NULL) { + policy()->old_gen_alloc_tracker()-> + add_allocated_humongous_bytes_since_last_gc(size_in_regions * HeapRegion::GrainBytes); + return result; } // Only try a GC if the GCLocker does not signal the need for a GC. Wait until @@ -890,10 +872,8 @@ HeapWord* G1CollectedHeap::attempt_allocation_humongous(size_t word_size) { } if (should_try_gc) { - GCCause::Cause gc_cause = preventive_collection_required ? GCCause::_g1_preventive_collection - : GCCause::_g1_humongous_allocation; bool succeeded; - result = do_collection_pause(word_size, gc_count_before, &succeeded, gc_cause); + result = do_collection_pause(word_size, gc_count_before, &succeeded, GCCause::_g1_humongous_allocation); if (result != NULL) { assert(succeeded, "only way to get back a non-NULL result"); log_trace(gc, alloc)("%s: Successfully scheduled collection returning " PTR_FORMAT, diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.cpp b/src/hotspot/share/gc/g1/g1CollectionSet.cpp index 9d1e0347776..a6bbca73709 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.cpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.cpp @@ -100,10 +100,6 @@ void G1CollectionSet::clear_candidates() { _candidates = NULL; } -bool G1CollectionSet::has_candidates() { - return _candidates != NULL && !_candidates->is_empty(); -} - // Add the heap region at the head of the non-incremental collection set void G1CollectionSet::add_old_region(HeapRegion* hr) { assert_at_safepoint_on_vm_thread(); diff --git a/src/hotspot/share/gc/g1/g1CollectionSet.hpp b/src/hotspot/share/gc/g1/g1CollectionSet.hpp index 68c271f6687..90fe22a2021 100644 --- a/src/hotspot/share/gc/g1/g1CollectionSet.hpp +++ b/src/hotspot/share/gc/g1/g1CollectionSet.hpp @@ -223,7 +223,6 @@ class G1CollectionSet { void initialize(uint max_region_length); void clear_candidates(); - bool has_candidates(); void set_candidates(G1CollectionSetCandidates* candidates) { assert(_candidates == NULL, "Trying to replace collection set candidates."); diff --git a/src/hotspot/share/gc/g1/g1Policy.cpp b/src/hotspot/share/gc/g1/g1Policy.cpp index dbf7519a6c3..ffe8b1642b3 100644 --- a/src/hotspot/share/gc/g1/g1Policy.cpp +++ b/src/hotspot/share/gc/g1/g1Policy.cpp @@ -71,8 +71,6 @@ G1Policy::G1Policy(STWGCTimer* gc_timer) : _reserve_regions(0), _young_gen_sizer(), _free_regions_at_end_of_collection(0), - _predicted_surviving_bytes_from_survivor(0), - _predicted_surviving_bytes_from_old(0), _rs_length(0), _pending_cards_at_gc_start(0), _concurrent_start_to_mixed(), @@ -583,7 +581,6 @@ void G1Policy::record_full_collection_end() { // also call this on any additional surv rate groups _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_survival_estimates_for_next_collection(); _survivor_surv_rate_group->reset(); update_young_length_bounds(); @@ -898,8 +895,6 @@ void G1Policy::record_young_collection_end(bool concurrent_operation_is_full_mar _free_regions_at_end_of_collection = _g1h->num_free_regions(); - update_survival_estimates_for_next_collection(); - // Do not update dynamic IHOP due to G1 periodic collection as it is highly likely // that in this case we are not running in a "normal" operating mode. if (_g1h->gc_cause() != GCCause::_g1_periodic_collection) { @@ -1578,88 +1573,6 @@ void G1Policy::calculate_optional_collection_set_regions(G1CollectionSetCandidat num_optional_regions, max_optional_regions, total_prediction_ms); } -// Number of regions required to store the given number of bytes, taking -// into account the target amount of wasted space in PLABs. -static size_t get_num_regions_adjust_for_plab_waste(size_t byte_count) { - size_t byte_count_adjusted = byte_count * (size_t)(100 + TargetPLABWastePct) / 100.0; - - // Round up the region count - return (byte_count_adjusted + HeapRegion::GrainBytes - 1) / HeapRegion::GrainBytes; -} - -bool G1Policy::preventive_collection_required(uint alloc_region_count) { - if (!G1UsePreventiveGC || !Universe::is_fully_initialized()) { - // Don't attempt any preventive GC's if the feature is disabled, - // or before initialization is complete. - return false; - } - - if (_g1h->young_regions_count() == 0 && !_collection_set->has_candidates()) { - return false; - } - - uint eden_count = _g1h->eden_regions_count(); - size_t const eden_surv_bytes_pred = _eden_surv_rate_group->accum_surv_rate_pred(eden_count) * HeapRegion::GrainBytes; - size_t const total_young_predicted_surviving_bytes = eden_surv_bytes_pred + _predicted_surviving_bytes_from_survivor; - - uint required_regions = (uint)(get_num_regions_adjust_for_plab_waste(total_young_predicted_surviving_bytes) + - get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_old)); - - if (required_regions > _g1h->num_free_or_available_regions() - alloc_region_count) { - log_debug(gc, ergo, cset)("Preventive GC, insufficient free or available regions. " - "Predicted need %u. Curr Eden %u (Pred %u). Curr Survivor %u (Pred %u). Curr Old %u (Pred %u) Free or Avail %u (Free %u) Alloc %u", - required_regions, - eden_count, - (uint)get_num_regions_adjust_for_plab_waste(eden_surv_bytes_pred), - _g1h->survivor_regions_count(), - (uint)get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_survivor), - _g1h->old_regions_count(), - (uint)get_num_regions_adjust_for_plab_waste(_predicted_surviving_bytes_from_old), - _g1h->num_free_or_available_regions(), - _g1h->num_free_regions(), - alloc_region_count); - - return true; - } - - return false; -} - -void G1Policy::update_survival_estimates_for_next_collection() { - // Predict the number of bytes of surviving objects from survivor and old - // regions and update the associated members. - - // Survivor regions - size_t survivor_bytes = 0; - const GrowableArray* survivor_regions = _g1h->survivor()->regions(); - for (GrowableArrayIterator it = survivor_regions->begin(); - it != survivor_regions->end(); - ++it) { - survivor_bytes += predict_bytes_to_copy(*it); - } - - _predicted_surviving_bytes_from_survivor = survivor_bytes; - - // Old regions - if (!_collection_set->has_candidates()) { - _predicted_surviving_bytes_from_old = 0; - return; - } - - // Use the minimum old gen collection set as conservative estimate for the number - // of regions to take for this calculation. - G1CollectionSetCandidates *candidates = _collection_set->candidates(); - uint iterate_count = MIN2(candidates->num_remaining(), calc_min_old_cset_length(candidates)); - uint current_index = candidates->cur_idx(); - size_t old_bytes = 0; - for (uint i = 0; i < iterate_count; i++) { - HeapRegion *region = candidates->at(current_index + i); - old_bytes += predict_bytes_to_copy(region); - } - - _predicted_surviving_bytes_from_old = old_bytes; -} - void G1Policy::transfer_survivors_to_cset(const G1SurvivorRegions* survivors) { start_adding_survivor_regions(); diff --git a/src/hotspot/share/gc/g1/g1Policy.hpp b/src/hotspot/share/gc/g1/g1Policy.hpp index efd91c3df9b..450b83340bb 100644 --- a/src/hotspot/share/gc/g1/g1Policy.hpp +++ b/src/hotspot/share/gc/g1/g1Policy.hpp @@ -101,11 +101,6 @@ class G1Policy: public CHeapObj { uint _free_regions_at_end_of_collection; - // These values are predictions of how much we think will survive in each - // section of the heap. - size_t _predicted_surviving_bytes_from_survivor; - size_t _predicted_surviving_bytes_from_old; - size_t _rs_length; size_t _pending_cards_at_gc_start; @@ -360,11 +355,6 @@ class G1Policy: public CHeapObj { double time_remaining_ms, uint& num_optional_regions); - // Returns whether a collection should be done proactively, taking into - // account the current number of free regions and the expected survival - // rates in each section of the heap. - bool preventive_collection_required(uint region_count); - private: // Predict the number of bytes of surviving objects from survivor and old diff --git a/src/hotspot/share/gc/g1/g1VMOperations.cpp b/src/hotspot/share/gc/g1/g1VMOperations.cpp index 4d3d81424d7..8ccd7f2c9fb 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.cpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.cpp @@ -123,15 +123,10 @@ VM_G1CollectForAllocation::VM_G1CollectForAllocation(size_t word_size, VM_CollectForAllocation(word_size, gc_count_before, gc_cause), _gc_succeeded(false) {} -bool VM_G1CollectForAllocation::should_try_allocation_before_gc() { - // Don't allocate before a preventive GC. - return _gc_cause != GCCause::_g1_preventive_collection; -} - void VM_G1CollectForAllocation::doit() { G1CollectedHeap* g1h = G1CollectedHeap::heap(); - if (should_try_allocation_before_gc() && _word_size > 0) { + if (_word_size > 0) { // An allocation has been requested. So, try to do that first. _result = g1h->attempt_allocation_at_safepoint(_word_size, false /* expect_null_cur_alloc_region */); diff --git a/src/hotspot/share/gc/g1/g1VMOperations.hpp b/src/hotspot/share/gc/g1/g1VMOperations.hpp index edf53073789..cfca9e21d07 100644 --- a/src/hotspot/share/gc/g1/g1VMOperations.hpp +++ b/src/hotspot/share/gc/g1/g1VMOperations.hpp @@ -77,9 +77,6 @@ class VM_G1CollectForAllocation : public VM_CollectForAllocation { virtual VMOp_Type type() const { return VMOp_G1CollectForAllocation; } virtual void doit(); bool gc_succeeded() const { return _gc_succeeded; } - -private: - bool should_try_allocation_before_gc(); }; // Concurrent G1 stop-the-world operations such as remark and cleanup. diff --git a/src/hotspot/share/gc/shared/gcCause.cpp b/src/hotspot/share/gc/shared/gcCause.cpp index 37cd32b0ff2..ec0281319f7 100644 --- a/src/hotspot/share/gc/shared/gcCause.cpp +++ b/src/hotspot/share/gc/shared/gcCause.cpp @@ -99,9 +99,6 @@ const char* GCCause::to_string(GCCause::Cause cause) { case _g1_periodic_collection: return "G1 Periodic Collection"; - case _g1_preventive_collection: - return "G1 Preventive Collection"; - case _dcmd_gc_run: return "Diagnostic Command"; diff --git a/src/hotspot/share/gc/shared/gcCause.hpp b/src/hotspot/share/gc/shared/gcCause.hpp index 1def51523d6..f949cf8889a 100644 --- a/src/hotspot/share/gc/shared/gcCause.hpp +++ b/src/hotspot/share/gc/shared/gcCause.hpp @@ -74,7 +74,6 @@ class GCCause : public AllStatic { _g1_compaction_pause, _g1_humongous_allocation, _g1_periodic_collection, - _g1_preventive_collection, _dcmd_gc_run, diff --git a/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java b/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java index d04a1a4374b..616d740cff9 100644 --- a/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java +++ b/test/hotspot/jtreg/gc/g1/TestEvacuationFailure.java @@ -50,7 +50,6 @@ public static void main(String[] args) throws Exception { "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc", GCTestWithEvacuationFailure.class.getName()); diff --git a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java index d0fe28f0bbc..6bcb2c2b503 100644 --- a/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java +++ b/test/hotspot/jtreg/gc/g1/TestGCLogMessages.java @@ -278,7 +278,6 @@ private void testWithEvacuationFailureLogs() throws Exception { "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc+phases=debug", GCTestWithEvacuationFailure.class.getName()); @@ -291,7 +290,6 @@ private void testWithEvacuationFailureLogs() throws Exception { "-Xmn16M", "-Xms32M", "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC", "-Xlog:gc+phases=trace", GCTestWithEvacuationFailure.class.getName()); diff --git a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java index 7030b68714e..12a6054a74a 100644 --- a/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java +++ b/test/hotspot/jtreg/gc/g1/TestVerifyGCType.java @@ -125,8 +125,7 @@ private static void testYoungEvacFail() throws Exception { new String[] {"-XX:+G1EvacuationFailureALot", "-XX:G1EvacuationFailureALotCount=100", "-XX:G1EvacuationFailureALotInterval=1", - "-XX:+UnlockDiagnosticVMOptions", - "-XX:-G1UsePreventiveGC"}); + "-XX:+UnlockDiagnosticVMOptions"}); output.shouldHaveExitValue(0); verifyCollection("Pause Young (Normal)", false, false, true, output.getStdout()); From ccb94acc442767a7047756806c8dc7ecacd8bae9 Mon Sep 17 00:00:00 2001 From: Chris Plummer Date: Wed, 14 Dec 2022 19:37:20 +0000 Subject: [PATCH 211/494] 8287812: Cleanup JDWP agent GetEnv initialization Reviewed-by: alanb, sspitsyn --- .../share/native/libjdwp/debugInit.c | 80 ++++--------------- .../share/native/libjdwp/util.c | 2 +- 2 files changed, 16 insertions(+), 66 deletions(-) diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c index 0951b397c69..b67c784d362 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/debugInit.c @@ -137,58 +137,11 @@ set_event_notification(jvmtiEventMode mode, EventIndex ei) return error; } -typedef struct { - int major; - int minor; -} version_type; - -typedef struct { - version_type runtime; - version_type compiletime; -} compatible_versions_type; - -/* - * List of explicitly compatible JVMTI versions, specified as - * { runtime version, compile-time version } pairs. -1 is a wildcard. - */ -static int nof_compatible_versions = 3; -static compatible_versions_type compatible_versions_list[] = { - /* - * FIXUP: Allow version 0 to be compatible with anything - * Special check for FCS of 1.0. - */ - { { 0, -1 }, { -1, -1 } }, - { { -1, -1 }, { 0, -1 } }, - /* - * 1.2 is runtime compatible with 1.1 -- just make sure to check the - * version before using any new 1.2 features - */ - { { 1, 1 }, { 1, 2 } } -}; - - /* Logic to determine JVMTI version compatibility */ static jboolean compatible_versions(jint major_runtime, jint minor_runtime, jint major_compiletime, jint minor_compiletime) { - /* - * First check to see if versions are explicitly compatible via the - * list specified above. - */ - int i; - for (i = 0; i < nof_compatible_versions; ++i) { - version_type runtime = compatible_versions_list[i].runtime; - version_type comptime = compatible_versions_list[i].compiletime; - - if ((major_runtime == runtime.major || runtime.major == -1) && - (minor_runtime == runtime.minor || runtime.minor == -1) && - (major_compiletime == comptime.major || comptime.major == -1) && - (minor_compiletime == comptime.minor || comptime.minor == -1)) { - return JNI_TRUE; - } - } - return major_runtime == major_compiletime && minor_runtime >= minor_compiletime; } @@ -231,20 +184,6 @@ DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) vmInitialized = JNI_FALSE; gdata->vmDead = JNI_FALSE; - /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ - error = JVM_FUNC_PTR(vm,GetEnv) - (vm, (void **)&(gdata->jvmti), JVMTI_VERSION_1); - if (error != JNI_OK) { - ERROR_MESSAGE(("JDWP unable to access JVMTI Version 1 (0x%x)," - " is your J2SE a 1.5 or newer version?" - " JNIEnv's GetEnv() returned %d", - JVMTI_VERSION_1, error)); - forceExit(1); /* Kill entire process, no core dump */ - } - - /* Check to make sure the version of jvmti.h we compiled with - * matches the runtime version we are using. - */ jvmtiCompileTimeMajorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MAJOR ) >> JVMTI_VERSION_SHIFT_MAJOR; jvmtiCompileTimeMinorVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MINOR ) @@ -252,12 +191,23 @@ DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved) jvmtiCompileTimeMicroVersion = ( JVMTI_VERSION & JVMTI_VERSION_MASK_MICRO ) >> JVMTI_VERSION_SHIFT_MICRO; - /* Check for compatibility */ - if ( !compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(), - jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion) ) { + /* Get the JVMTI Env, IMPORTANT: Do this first! For jvmtiAllocate(). */ + error = JVM_FUNC_PTR(vm,GetEnv) + (vm, (void **)&(gdata->jvmti), JVMTI_VERSION); + if (error != JNI_OK) { + ERROR_MESSAGE(("JDWP unable to access JVMTI Version %d.%d.%d (0x%x)." + " JNIEnv's GetEnv() returned %d.", + jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion, + jvmtiCompileTimeMicroVersion, JVMTI_VERSION, error)); + forceExit(1); /* Kill entire process, no core dump */ + } + + /* Check that the JVMTI compile and runtime versions are compatibile. */ + if (!compatible_versions(jvmtiMajorVersion(), jvmtiMinorVersion(), + jvmtiCompileTimeMajorVersion, jvmtiCompileTimeMinorVersion)) { ERROR_MESSAGE(("This jdwp native library will not work with this VM's " - "version of JVMTI (%d.%d.%d), it needs JVMTI %d.%d[.%d].", + "version of JVMTI (%d.%d.%d). It needs JVMTI %d.%d[.%d].", jvmtiMajorVersion(), jvmtiMinorVersion(), jvmtiMicroVersion(), diff --git a/src/jdk.jdwp.agent/share/native/libjdwp/util.c b/src/jdk.jdwp.agent/share/native/libjdwp/util.c index cdf41f24c79..40f231a2338 100644 --- a/src/jdk.jdwp.agent/share/native/libjdwp/util.c +++ b/src/jdk.jdwp.agent/share/native/libjdwp/util.c @@ -1734,7 +1734,7 @@ getSpecialJvmti(void) jvmtiCapabilities caps; rc = JVM_FUNC_PTR(gdata->jvm,GetEnv) - (gdata->jvm, (void **)&jvmti, JVMTI_VERSION_1); + (gdata->jvm, (void **)&jvmti, JVMTI_VERSION); if (rc != JNI_OK) { return NULL; } From ebc471040e03dc41829d57e1280cabd75b2ad53a Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Wed, 14 Dec 2022 21:40:29 +0000 Subject: [PATCH 212/494] 8298277: Replace "session" with "scope" for FFM access Reviewed-by: mcimadamore --- .../foreign/AbstractMemorySegmentImpl.java | 26 ++++++++-------- .../foreign/HeapMemorySegmentImpl.java | 16 +++++----- .../foreign/MappedMemorySegmentImpl.java | 10 +++---- .../internal/foreign/MemorySessionImpl.java | 6 ++-- .../foreign/NativeMemorySegmentImpl.java | 28 ++++++++--------- .../jdk/internal/foreign/abi/Binding.java | 28 ++++++++--------- .../foreign/abi/BindingSpecializer.java | 10 +++---- .../jdk/internal/foreign/abi/SharedUtils.java | 20 ++++++------- .../internal/foreign/abi/UpcallLinker.java | 6 ++-- .../jdk/internal/foreign/abi/UpcallStubs.java | 6 ++-- .../abi/aarch64/linux/LinuxAArch64Linker.java | 8 ++--- .../abi/aarch64/linux/LinuxAArch64VaList.java | 30 +++++++++---------- .../abi/aarch64/macos/MacOsAArch64Linker.java | 8 ++--- .../foreign/abi/x64/sysv/CallArranger.java | 4 +-- .../foreign/abi/x64/sysv/SysVVaList.java | 24 +++++++-------- .../foreign/abi/x64/sysv/SysVx64Linker.java | 4 +-- .../foreign/abi/x64/windows/CallArranger.java | 4 +-- .../foreign/abi/x64/windows/WinVaList.java | 20 ++++++------- .../abi/x64/windows/Windowsx64Linker.java | 4 +-- 19 files changed, 131 insertions(+), 131 deletions(-) diff --git a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java index 9080e1482a8..10dde1f331b 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/AbstractMemorySegmentImpl.java @@ -77,22 +77,22 @@ public abstract sealed class AbstractMemorySegmentImpl final long length; final boolean readOnly; - final SegmentScope session; + final SegmentScope scope; @ForceInline - AbstractMemorySegmentImpl(long length, boolean readOnly, SegmentScope session) { + AbstractMemorySegmentImpl(long length, boolean readOnly, SegmentScope scope) { this.length = length; this.readOnly = readOnly; - this.session = session; + this.scope = scope; } - abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session); + abstract AbstractMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope scope); abstract ByteBuffer makeByteBuffer(); @Override public AbstractMemorySegmentImpl asReadOnly() { - return dup(0, length, true, session); + return dup(0, length, true, scope); } @Override @@ -113,7 +113,7 @@ public AbstractMemorySegmentImpl asSlice(long offset) { } private AbstractMemorySegmentImpl asSliceNoCheck(long offset, long newSize) { - return dup(offset, newSize, readOnly, session); + return dup(offset, newSize, readOnly, scope); } @Override @@ -359,12 +359,12 @@ public RuntimeException apply(String s, List numbers) { @Override public SegmentScope scope() { - return session; + return scope; } @ForceInline public final MemorySessionImpl sessionImpl() { - return (MemorySessionImpl)session; + return (MemorySessionImpl)scope; } private IndexOutOfBoundsException outOfBoundException(long offset, long length) { @@ -481,11 +481,11 @@ public static AbstractMemorySegmentImpl ofBuffer(Buffer bb) { int size = limit - pos; AbstractMemorySegmentImpl bufferSegment = (AbstractMemorySegmentImpl) NIO_ACCESS.bufferSegment(bb); - final SegmentScope bufferSession; + final SegmentScope bufferScope; if (bufferSegment != null) { - bufferSession = bufferSegment.session; + bufferScope = bufferSegment.scope; } else { - bufferSession = MemorySessionImpl.heapSession(bb); + bufferScope = MemorySessionImpl.heapSession(bb); } boolean readOnly = bb.isReadOnly(); int scaleFactor = getScaleFactor(bb); @@ -508,10 +508,10 @@ public static AbstractMemorySegmentImpl ofBuffer(Buffer bb) { throw new AssertionError("Cannot get here"); } } else if (unmapper == null) { - return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferSession); + return new NativeMemorySegmentImpl(bbAddress + (pos << scaleFactor), size << scaleFactor, readOnly, bufferScope); } else { // we can ignore scale factor here, a mapped buffer is always a byte buffer, so scaleFactor == 0. - return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferSession); + return new MappedMemorySegmentImpl(bbAddress + pos, unmapper, size, readOnly, bufferScope); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java index 4967f438c00..260c41e6907 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/HeapMemorySegmentImpl.java @@ -79,7 +79,7 @@ public long unsafeGetOffset() { } @Override - abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session); + abstract HeapMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope scope); @Override ByteBuffer makeByteBuffer() { @@ -99,7 +99,7 @@ public static final class OfByte extends HeapMemorySegmentImpl { } @Override - OfByte dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfByte dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfByte(this.offset + offset, base, size, readOnly); } @@ -132,7 +132,7 @@ public static final class OfChar extends HeapMemorySegmentImpl { } @Override - OfChar dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfChar dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfChar(this.offset + offset, base, size, readOnly); } @@ -165,7 +165,7 @@ public static final class OfShort extends HeapMemorySegmentImpl { } @Override - OfShort dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfShort dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfShort(this.offset + offset, base, size, readOnly); } @@ -198,7 +198,7 @@ public static final class OfInt extends HeapMemorySegmentImpl { } @Override - OfInt dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfInt dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfInt(this.offset + offset, base, size, readOnly); } @@ -231,7 +231,7 @@ public static final class OfLong extends HeapMemorySegmentImpl { } @Override - OfLong dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfLong dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfLong(this.offset + offset, base, size, readOnly); } @@ -264,7 +264,7 @@ public static final class OfFloat extends HeapMemorySegmentImpl { } @Override - OfFloat dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfFloat dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfFloat(this.offset + offset, base, size, readOnly); } @@ -297,7 +297,7 @@ public static final class OfDouble extends HeapMemorySegmentImpl { } @Override - OfDouble dup(long offset, long size, boolean readOnly, SegmentScope session) { + OfDouble dup(long offset, long size, boolean readOnly, SegmentScope scope) { return new OfDouble(this.offset + offset, base, size, readOnly); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java index 1d9465b8b41..8b7c799d7ad 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MappedMemorySegmentImpl.java @@ -43,20 +43,20 @@ public sealed class MappedMemorySegmentImpl extends NativeMemorySegmentImpl { static final ScopedMemoryAccess SCOPED_MEMORY_ACCESS = ScopedMemoryAccess.getScopedMemoryAccess(); - public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, SegmentScope session) { - super(min, length, readOnly, session); + public MappedMemorySegmentImpl(long min, UnmapperProxy unmapper, long length, boolean readOnly, SegmentScope scope) { + super(min, length, readOnly, scope); this.unmapper = unmapper; } @Override ByteBuffer makeByteBuffer() { return NIO_ACCESS.newMappedByteBuffer(unmapper, min, (int)length, null, - session == MemorySessionImpl.GLOBAL ? null : this); + scope == MemorySessionImpl.GLOBAL ? null : this); } @Override - MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session) { - return new MappedMemorySegmentImpl(min + offset, unmapper, size, readOnly, session); + MappedMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope scope) { + return new MappedMemorySegmentImpl(min + offset, unmapper, size, readOnly, scope); } // mapped segment methods diff --git a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java index b8d1036baab..84fa0a5be35 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/MemorySessionImpl.java @@ -175,9 +175,9 @@ public final Thread ownerThread() { return owner; } - public static boolean sameOwnerThread(SegmentScope session1, SegmentScope session2) { - return ((MemorySessionImpl) session1).ownerThread() == - ((MemorySessionImpl) session2).ownerThread(); + public static boolean sameOwnerThread(SegmentScope scope1, SegmentScope scope2) { + return ((MemorySessionImpl) scope1).ownerThread() == + ((MemorySessionImpl) scope2).ownerThread(); } @Override diff --git a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java index 388937b823d..6d0e532d2d0 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java +++ b/src/java.base/share/classes/jdk/internal/foreign/NativeMemorySegmentImpl.java @@ -52,8 +52,8 @@ public sealed class NativeMemorySegmentImpl extends AbstractMemorySegmentImpl pe final long min; @ForceInline - NativeMemorySegmentImpl(long min, long length, boolean readOnly, SegmentScope session) { - super(length, readOnly, session); + NativeMemorySegmentImpl(long min, long length, boolean readOnly, SegmentScope scope) { + super(length, readOnly, scope); this.min = min; } @@ -69,14 +69,14 @@ public Optional array() { @ForceInline @Override - NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope session) { - return new NativeMemorySegmentImpl(min + offset, size, readOnly, session); + NativeMemorySegmentImpl dup(long offset, long size, boolean readOnly, SegmentScope scope) { + return new NativeMemorySegmentImpl(min + offset, size, readOnly, scope); } @Override ByteBuffer makeByteBuffer() { return NIO_ACCESS.newDirectByteBuffer(min, (int) this.length, null, - session == MemorySessionImpl.GLOBAL ? null : this); + scope == MemorySessionImpl.GLOBAL ? null : this); } @Override @@ -101,8 +101,8 @@ public long maxAlignMask() { // factories - public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, SegmentScope session) { - MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, SegmentScope scope) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) scope; sessionImpl.checkValidState(); if (VM.isDirectMemoryPageAligned()) { byteAlignment = Math.max(byteAlignment, NIO_ACCESS.pageSize()); @@ -119,7 +119,7 @@ public static MemorySegment makeNativeSegment(long byteSize, long byteAlignment, } long alignedBuf = Utils.alignUp(buf, byteAlignment); AbstractMemorySegmentImpl segment = new NativeMemorySegmentImpl(buf, alignedSize, - false, session); + false, scope); sessionImpl.addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { @Override public void cleanup() { @@ -138,21 +138,21 @@ public void cleanup() { // associated with MemorySegment::ofAddress. @ForceInline - public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope session, Runnable action) { - MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope scope, Runnable action) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) scope; if (action == null) { sessionImpl.checkValidState(); } else { sessionImpl.addCloseAction(action); } - return new NativeMemorySegmentImpl(min, byteSize, false, session); + return new NativeMemorySegmentImpl(min, byteSize, false, scope); } @ForceInline - public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope session) { - MemorySessionImpl sessionImpl = (MemorySessionImpl) session; + public static MemorySegment makeNativeSegmentUnchecked(long min, long byteSize, SegmentScope scope) { + MemorySessionImpl sessionImpl = (MemorySessionImpl) scope; sessionImpl.checkValidState(); - return new NativeMemorySegmentImpl(min, byteSize, false, session); + return new NativeMemorySegmentImpl(min, byteSize, false, scope); } @ForceInline diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java index 1949c660832..e047cbbd7fe 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/Binding.java @@ -202,19 +202,19 @@ public interface Binding { */ class Context implements AutoCloseable { private final SegmentAllocator allocator; - private final SegmentScope session; + private final SegmentScope scope; - private Context(SegmentAllocator allocator, SegmentScope session) { + private Context(SegmentAllocator allocator, SegmentScope scope) { this.allocator = allocator; - this.session = session; + this.scope = scope; } public SegmentAllocator allocator() { return allocator; } - public SegmentScope session() { - return session; + public SegmentScope scope() { + return scope; } @Override @@ -242,7 +242,7 @@ public void close() { public static Context ofAllocator(SegmentAllocator allocator) { return new Context(allocator, null) { @Override - public SegmentScope session() { + public SegmentScope scope() { throw new UnsupportedOperationException(); } }; @@ -252,7 +252,7 @@ public SegmentScope session() { * Create a binding context from given scope. The resulting context will throw when * the context's allocator is accessed. */ - public static Context ofSession() { + public static Context ofScope() { Arena arena = Arena.openConfined(); return new Context(null, arena.scope()) { @Override @@ -276,7 +276,7 @@ public SegmentAllocator allocator() { } @Override - public SegmentScope session() { + public SegmentScope scope() { throw new UnsupportedOperationException(); } @@ -678,10 +678,10 @@ public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFun /** * BOX_ADDRESS() - * Pops a 'long' from the operand stack, converts it to a 'MemorySegment', with the given size and memory session - * (either the context session, or the global session), and pushes that onto the operand stack. + * Pops a 'long' from the operand stack, converts it to a 'MemorySegment', with the given size and memory scope + * (either the context scope, or the global scope), and pushes that onto the operand stack. */ - record BoxAddress(long size, boolean needsSession) implements Binding { + record BoxAddress(long size, boolean needsScope) implements Binding { @Override public Tag tag() { @@ -698,9 +698,9 @@ public void verify(Deque> stack) { @Override public void interpret(Deque stack, BindingInterpreter.StoreFunc storeFunc, BindingInterpreter.LoadFunc loadFunc, Context context) { - SegmentScope session = needsSession ? - context.session() : SegmentScope.global(); - stack.push(NativeMemorySegmentImpl.makeNativeSegmentUnchecked((long) stack.pop(), size, session)); + SegmentScope scope = needsScope ? + context.scope() : SegmentScope.global(); + stack.push(NativeMemorySegmentImpl.makeNativeSegmentUnchecked((long) stack.pop(), size, scope)); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java index 3c5edba2443..33ab093b53c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/BindingSpecializer.java @@ -80,9 +80,9 @@ public class BindingSpecializer { private static final String BINDING_CONTEXT_DESC = Binding.Context.class.descriptorString(); private static final String OF_BOUNDED_ALLOCATOR_DESC = methodType(Binding.Context.class, long.class).descriptorString(); - private static final String OF_SESSION_DESC = methodType(Binding.Context.class).descriptorString(); + private static final String OF_SCOPE_DESC = methodType(Binding.Context.class).descriptorString(); private static final String ALLOCATOR_DESC = methodType(SegmentAllocator.class).descriptorString(); - private static final String SESSION_DESC = methodType(SegmentScope.class).descriptorString(); + private static final String SCOPE_DESC = methodType(SegmentScope.class).descriptorString(); private static final String SESSION_IMPL_DESC = methodType(MemorySessionImpl.class).descriptorString(); private static final String CLOSE_DESC = VOID_DESC; private static final String UNBOX_SEGMENT_DESC = methodType(long.class, MemorySegment.class).descriptorString(); @@ -294,7 +294,7 @@ private void specialize() { emitConst(callingSequence.allocationSize()); emitInvokeStatic(Binding.Context.class, "ofBoundedAllocator", OF_BOUNDED_ALLOCATOR_DESC); } else if (callingSequence.forUpcall() && needsSession()) { - emitInvokeStatic(Binding.Context.class, "ofSession", OF_SESSION_DESC); + emitInvokeStatic(Binding.Context.class, "ofScope", OF_SCOPE_DESC); } else { emitGetStatic(Binding.Context.class, "DUMMY", BINDING_CONTEXT_DESC); } @@ -436,7 +436,7 @@ private boolean needsSession() { return callingSequence.argumentBindings() .filter(Binding.BoxAddress.class::isInstance) .map(Binding.BoxAddress.class::cast) - .anyMatch(Binding.BoxAddress::needsSession); + .anyMatch(Binding.BoxAddress::needsScope); } private boolean shouldAcquire(int paramIndex) { @@ -561,7 +561,7 @@ private int newLocal(Class type) { private void emitLoadInternalSession() { assert contextIdx != -1; emitLoad(Object.class, contextIdx); - emitInvokeVirtual(Binding.Context.class, "session", SESSION_DESC); + emitInvokeVirtual(Binding.Context.class, "scope", SCOPE_DESC); } private void emitLoadInternalAllocator() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java index 5ca0a6d7ca8..77e4e05659d 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/SharedUtils.java @@ -288,21 +288,21 @@ public static void checkSymbol(MemorySegment symbol) { throw new IllegalArgumentException("Symbol is NULL: " + symbol); } - public static VaList newVaList(Consumer actions, SegmentScope session) { + public static VaList newVaList(Consumer actions, SegmentScope scope) { return switch (CABI.current()) { - case WIN_64 -> Windowsx64Linker.newVaList(actions, session); - case SYS_V -> SysVx64Linker.newVaList(actions, session); - case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaList(actions, session); - case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaList(actions, session); + case WIN_64 -> Windowsx64Linker.newVaList(actions, scope); + case SYS_V -> SysVx64Linker.newVaList(actions, scope); + case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaList(actions, scope); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaList(actions, scope); }; } - public static VaList newVaListOfAddress(long address, SegmentScope session) { + public static VaList newVaListOfAddress(long address, SegmentScope scope) { return switch (CABI.current()) { - case WIN_64 -> Windowsx64Linker.newVaListOfAddress(address, session); - case SYS_V -> SysVx64Linker.newVaListOfAddress(address, session); - case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaListOfAddress(address, session); - case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaListOfAddress(address, session); + case WIN_64 -> Windowsx64Linker.newVaListOfAddress(address, scope); + case SYS_V -> SysVx64Linker.newVaListOfAddress(address, scope); + case LINUX_AARCH_64 -> LinuxAArch64Linker.newVaListOfAddress(address, scope); + case MAC_OS_AARCH_64 -> MacOsAArch64Linker.newVaListOfAddress(address, scope); }; } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java index 40af3d64dd9..da42eb53584 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallLinker.java @@ -61,7 +61,7 @@ public class UpcallLinker { } } - public static MemorySegment make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, SegmentScope session) { + public static MemorySegment make(ABIDescriptor abi, MethodHandle target, CallingSequence callingSequence, SegmentScope scope) { assert callingSequence.forUpcall(); Binding.VMLoad[] argMoves = argMoveBindings(callingSequence); Binding.VMStore[] retMoves = retMoveBindings(callingSequence); @@ -93,7 +93,7 @@ public static MemorySegment make(ABIDescriptor abi, MethodHandle target, Calling CallRegs conv = new CallRegs(args, rets); long entryPoint = makeUpcallStub(doBindings, abi, conv, callingSequence.needsReturnBuffer(), callingSequence.returnBufferSize()); - return UpcallStubs.makeUpcall(entryPoint, session); + return UpcallStubs.makeUpcall(entryPoint, scope); } private static void checkPrimitive(MethodType type) { @@ -130,7 +130,7 @@ private record InvocationData(MethodHandle leaf, private static Object invokeInterpBindings(Object[] lowLevelArgs, InvocationData invData) throws Throwable { Binding.Context allocator = invData.callingSequence.allocationSize() != 0 ? Binding.Context.ofBoundedAllocator(invData.callingSequence.allocationSize()) - : Binding.Context.ofSession(); + : Binding.Context.ofScope(); try (allocator) { /// Invoke interpreter, got array of high-level arguments back Object[] highLevelArgs = new Object[invData.callingSequence.calleeMethodType().parameterCount()]; diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java index 041a96ac1c0..50f6a14d8d0 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/UpcallStubs.java @@ -50,13 +50,13 @@ private static void freeUpcallStub(long stubAddress) { registerNatives(); } - static MemorySegment makeUpcall(long entry, SegmentScope session) { - ((MemorySessionImpl) session).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { + static MemorySegment makeUpcall(long entry, SegmentScope scope) { + ((MemorySessionImpl) scope).addOrCleanupIfFail(new MemorySessionImpl.ResourceList.ResourceCleanup() { @Override public void cleanup() { freeUpcallStub(entry); } }); - return MemorySegment.ofAddress(entry, 0, session); + return MemorySegment.ofAddress(entry, 0, scope); } } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java index 9114005695d..acf57f12f0c 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64Linker.java @@ -65,14 +65,14 @@ protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType return CallArranger.LINUX.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, SegmentScope session) { - LinuxAArch64VaList.Builder builder = LinuxAArch64VaList.builder(session); + public static VaList newVaList(Consumer actions, SegmentScope scope) { + LinuxAArch64VaList.Builder builder = LinuxAArch64VaList.builder(scope); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(long address, SegmentScope session) { - return LinuxAArch64VaList.ofAddress(address, session); + public static VaList newVaListOfAddress(long address, SegmentScope scope) { + return LinuxAArch64VaList.ofAddress(address, scope); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java index fc43f0193ae..ef471294768 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/linux/LinuxAArch64VaList.java @@ -120,11 +120,11 @@ private LinuxAArch64VaList(MemorySegment segment, MemorySegment stack, this.fpLimit = fpLimit; } - private static LinuxAArch64VaList readFromAddress(long address, SegmentScope session) { - MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), session); + private static LinuxAArch64VaList readFromAddress(long address, SegmentScope scope) { + MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope); MemorySegment stack = stackPtr(segment); // size unknown - MemorySegment gpRegsArea = MemorySegment.ofAddress(grTop(segment).address() - MAX_GP_OFFSET, MAX_GP_OFFSET, session); - MemorySegment fpRegsArea = MemorySegment.ofAddress(vrTop(segment).address() - MAX_FP_OFFSET, MAX_FP_OFFSET, session); + MemorySegment gpRegsArea = MemorySegment.ofAddress(grTop(segment).address() - MAX_GP_OFFSET, MAX_GP_OFFSET, scope); + MemorySegment fpRegsArea = MemorySegment.ofAddress(vrTop(segment).address() - MAX_FP_OFFSET, MAX_FP_OFFSET, scope); return new LinuxAArch64VaList(segment, stack, gpRegsArea, MAX_GP_OFFSET, fpRegsArea, MAX_FP_OFFSET); } @@ -384,12 +384,12 @@ public void skip(MemoryLayout... layouts) { } } - static LinuxAArch64VaList.Builder builder(SegmentScope session) { - return new LinuxAArch64VaList.Builder(session); + static LinuxAArch64VaList.Builder builder(SegmentScope scope) { + return new LinuxAArch64VaList.Builder(scope); } - public static VaList ofAddress(long address, SegmentScope session) { - return readFromAddress(address, session); + public static VaList ofAddress(long address, SegmentScope scope) { + return readFromAddress(address, scope); } @Override @@ -432,7 +432,7 @@ public String toString() { } public static non-sealed class Builder implements VaList.Builder { - private final SegmentScope session; + private final SegmentScope scope; private final MemorySegment gpRegs; private final MemorySegment fpRegs; @@ -440,10 +440,10 @@ public static non-sealed class Builder implements VaList.Builder { private long currentFPOffset = 0; private final List stackArgs = new ArrayList<>(); - Builder(SegmentScope session) { - this.session = session; - this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, session); - this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, session); + Builder(SegmentScope scope) { + this.scope = scope; + this.gpRegs = MemorySegment.allocateNative(LAYOUT_GP_REGS, scope); + this.fpRegs = MemorySegment.allocateNative(LAYOUT_FP_REGS, scope); } @Override @@ -536,12 +536,12 @@ public VaList build() { return EMPTY; } - MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, session); + MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, scope); MemorySegment stackArgsSegment; if (!stackArgs.isEmpty()) { long stackArgsSize = stackArgs.stream() .reduce(0L, (acc, e) -> acc + Utils.alignUp(e.layout.byteSize(), STACK_SLOT_SIZE), Long::sum); - stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, session); + stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, scope); MemorySegment writeCursor = stackArgsSegment; for (SimpleVaArg arg : stackArgs) { final long alignedSize = Utils.alignUp(arg.layout.byteSize(), STACK_SLOT_SIZE); diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java index ab478f70faa..d63adc4c247 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/aarch64/macos/MacOsAArch64Linker.java @@ -65,14 +65,14 @@ protected MemorySegment arrangeUpcall(MethodHandle target, MethodType targetType return CallArranger.MACOS.arrangeUpcall(target, targetType, function, scope); } - public static VaList newVaList(Consumer actions, SegmentScope session) { - MacOsAArch64VaList.Builder builder = MacOsAArch64VaList.builder(session); + public static VaList newVaList(Consumer actions, SegmentScope scope) { + MacOsAArch64VaList.Builder builder = MacOsAArch64VaList.builder(scope); actions.accept(builder); return builder.build(); } - public static VaList newVaListOfAddress(long address, SegmentScope session) { - return MacOsAArch64VaList.ofAddress(address, session); + public static VaList newVaListOfAddress(long address, SegmentScope scope) { + return MacOsAArch64VaList.ofAddress(address, scope); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java index 735aabcd149..3fd51fb2d61 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/CallArranger.java @@ -132,14 +132,14 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe return handle; } - public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) { + public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { target = SharedUtils.adaptUpcallForIMR(target, true /* drop return, since we don't have bindings for it */); } - return UpcallLinker.make(CSysV, target, bindings.callingSequence, session); + return UpcallLinker.make(CSysV, target, bindings.callingSequence, scope); } private static boolean isInMemoryReturn(Optional returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java index 78264f69ae3..36b6bf7ba63 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVVaList.java @@ -130,8 +130,8 @@ private SysVVaList(MemorySegment segment, this.fpLimit = fpLimit; } - private static SysVVaList readFromAddress(long address, SegmentScope session) { - MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), session); + private static SysVVaList readFromAddress(long address, SegmentScope scope) { + MemorySegment segment = MemorySegment.ofAddress(address, LAYOUT.byteSize(), scope); MemorySegment regSaveArea = getRegSaveArea(segment); MemorySegment overflowArgArea = getArgOverflowArea(segment); return new SysVVaList(segment, overflowArgArea, regSaveArea, MAX_GP_OFFSET, MAX_FP_OFFSET); @@ -322,12 +322,12 @@ public void skip(MemoryLayout... layouts) { } } - static SysVVaList.Builder builder(SegmentScope session) { - return new SysVVaList.Builder(session); + static SysVVaList.Builder builder(SegmentScope scope) { + return new SysVVaList.Builder(scope); } - public static VaList ofAddress(long address, SegmentScope session) { - return readFromAddress(address, session); + public static VaList ofAddress(long address, SegmentScope scope) { + return readFromAddress(address, scope); } @Override @@ -359,15 +359,15 @@ public String toString() { } public static non-sealed class Builder implements VaList.Builder { - private final SegmentScope session; + private final SegmentScope scope; private final MemorySegment reg_save_area; private long currentGPOffset = 0; private long currentFPOffset = FP_OFFSET; private final List stackArgs = new ArrayList<>(); - public Builder(SegmentScope session) { - this.session = session; - this.reg_save_area = MemorySegment.allocateNative(LAYOUT_REG_SAVE_AREA, session); + public Builder(SegmentScope scope) { + this.scope = scope; + this.reg_save_area = MemorySegment.allocateNative(LAYOUT_REG_SAVE_AREA, scope); } @Override @@ -446,12 +446,12 @@ public VaList build() { return EMPTY; } - MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, session); + MemorySegment vaListSegment = MemorySegment.allocateNative(LAYOUT, scope); MemorySegment stackArgsSegment; if (!stackArgs.isEmpty()) { long stackArgsSize = stackArgs.stream().reduce(0L, (acc, e) -> acc + Utils.alignUp(e.layout.byteSize(), STACK_SLOT_SIZE), Long::sum); - stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, session); + stackArgsSegment = MemorySegment.allocateNative(stackArgsSize, 16, scope); MemorySegment writeCursor = stackArgsSegment; for (SimpleVaArg arg : stackArgs) { if (arg.layout.byteSize() > 8) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java index e181e9182f9..d4694d2fa10 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/sysv/SysVx64Linker.java @@ -68,8 +68,8 @@ public static VaList newVaList(Consumer actions, SegmentScope sc return builder.build(); } - public static VaList newVaListOfAddress(long address, SegmentScope session) { - return SysVVaList.ofAddress(address, session); + public static VaList newVaListOfAddress(long address, SegmentScope scope) { + return SysVVaList.ofAddress(address, scope); } public static VaList emptyVaList() { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java index 61a68c4bfc5..612e60b5bb2 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/CallArranger.java @@ -131,14 +131,14 @@ public static MethodHandle arrangeDowncall(MethodType mt, FunctionDescriptor cDe return handle; } - public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope session) { + public static MemorySegment arrangeUpcall(MethodHandle target, MethodType mt, FunctionDescriptor cDesc, SegmentScope scope) { Bindings bindings = getBindings(mt, cDesc, true); if (bindings.isInMemoryReturn) { target = SharedUtils.adaptUpcallForIMR(target, false /* need the return value as well */); } - return UpcallLinker.make(CWindows, target, bindings.callingSequence, session); + return UpcallLinker.make(CWindows, target, bindings.callingSequence, scope); } private static boolean isInMemoryReturn(Optional returnLayout) { diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java index 6d9bcf82f48..6e14248176e 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/WinVaList.java @@ -149,12 +149,12 @@ public void skip(MemoryLayout... layouts) { } } - static WinVaList ofAddress(long address, SegmentScope session) { - return new WinVaList(MemorySegment.ofAddress(address, Long.MAX_VALUE, session)); + static WinVaList ofAddress(long address, SegmentScope scope) { + return new WinVaList(MemorySegment.ofAddress(address, Long.MAX_VALUE, scope)); } - static Builder builder(SegmentScope session) { - return new Builder(session); + static Builder builder(SegmentScope scope) { + return new Builder(scope); } @Override @@ -171,12 +171,12 @@ public MemorySegment segment() { public static non-sealed class Builder implements VaList.Builder { - private final SegmentScope session; + private final SegmentScope scope; private final List args = new ArrayList<>(); - public Builder(SegmentScope session) { - ((MemorySessionImpl) session).checkValidState(); - this.session = session; + public Builder(SegmentScope scope) { + ((MemorySessionImpl) scope).checkValidState(); + this.scope = scope; } private Builder arg(MemoryLayout layout, Object value) { @@ -216,7 +216,7 @@ public VaList build() { return EMPTY; } - MemorySegment segment = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size(), session); + MemorySegment segment = MemorySegment.allocateNative(VA_SLOT_SIZE_BYTES * args.size(), scope); MemorySegment cursor = segment; for (SimpleVaArg arg : args) { @@ -225,7 +225,7 @@ public VaList build() { TypeClass typeClass = TypeClass.typeClassFor(arg.layout, false); switch (typeClass) { case STRUCT_REFERENCE -> { - MemorySegment copy = MemorySegment.allocateNative(arg.layout, session); + MemorySegment copy = MemorySegment.allocateNative(arg.layout, scope); copy.copyFrom(msArg); // by-value VH_address.set(cursor, copy); } diff --git a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java index 24d12dd8c56..8725063fbac 100644 --- a/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java +++ b/src/java.base/share/classes/jdk/internal/foreign/abi/x64/windows/Windowsx64Linker.java @@ -68,8 +68,8 @@ public static VaList newVaList(Consumer actions, SegmentScope sc return builder.build(); } - public static VaList newVaListOfAddress(long address, SegmentScope session) { - return WinVaList.ofAddress(address, session); + public static VaList newVaListOfAddress(long address, SegmentScope scope) { + return WinVaList.ofAddress(address, scope); } public static VaList emptyVaList() { From 80cadd40103cf1f490a5d70be784652e27588114 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Wed, 14 Dec 2022 21:57:55 +0000 Subject: [PATCH 213/494] 8298785: gc/TestFullGCCount.java fails with "invalid boolean value: `null' for expression `vm.opt.ExplicitGCInvokesConcurrent'" Reviewed-by: dcubed --- test/hotspot/jtreg/gc/TestFullGCCount.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/hotspot/jtreg/gc/TestFullGCCount.java b/test/hotspot/jtreg/gc/TestFullGCCount.java index 08f8125de83..1c178b755db 100644 --- a/test/hotspot/jtreg/gc/TestFullGCCount.java +++ b/test/hotspot/jtreg/gc/TestFullGCCount.java @@ -30,7 +30,7 @@ * @comment Shenandoah has "ExplicitGCInvokesConcurrent" on by default * @requires !(vm.gc == "Shenandoah" & vm.opt.ExplicitGCInvokesConcurrent != false) * @comment G1 has separate counters for STW Full GC and concurrent GC. - * @requires !(vm.gc == "G1" & vm.opt.ExplicitGCInvokesConcurrent) + * @requires !(vm.gc.G1 & vm.opt.ExplicitGCInvokesConcurrent == true) * @requires vm.gc != "Z" * @modules java.management * @run main/othervm -Xlog:gc gc.TestFullGCCount From 0ed6d0b456e58e4122b97c3d12faabada0d8c530 Mon Sep 17 00:00:00 2001 From: Alisen Chung Date: Wed, 14 Dec 2022 22:10:01 +0000 Subject: [PATCH 214/494] 8297296: java/awt/Mouse/EnterExitEvents/DragWindowTest.java fails with "No MouseReleased event on label!" Reviewed-by: psadhukhan, dnguyen --- test/jdk/ProblemList.txt | 1 - .../Mouse/EnterExitEvents/DragWindowTest.java | 26 ++++++++++++++----- 2 files changed, 20 insertions(+), 7 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 113e11dd6ef..2688ac2c985 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -668,7 +668,6 @@ java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 -java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8297296 macosx-all javax/swing/JFileChooser/8046391/bug8046391.java 8293862 windows-x64 javax/swing/JFileChooser/4847375/bug4847375.java 8293862 windows-x64 java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392 windows-x64 diff --git a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java index 4067bcea32e..4f789668c4a 100644 --- a/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java +++ b/test/jdk/java/awt/Mouse/EnterExitEvents/DragWindowTest.java @@ -34,11 +34,23 @@ * @run main DragWindowTest */ -import java.awt.*; -import java.awt.event.*; -import javax.swing.*; - -import java.util.concurrent.*; +import java.awt.BorderLayout; +import java.awt.Component; +import java.awt.Rectangle; +import java.awt.Robot; +import java.awt.Panel; +import java.awt.Point; +import java.awt.Window; +import java.awt.event.InputEvent; +import java.awt.event.MouseAdapter; +import java.awt.event.MouseEvent; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JButton; +import javax.swing.JPanel; +import javax.swing.SwingUtilities; + +import java.util.concurrent.Callable; import test.java.awt.regtesthelpers.Util; @@ -55,7 +67,7 @@ public class DragWindowTest { public static void main(String[] args) throws Exception { Robot robot = new Robot(); - robot.setAutoDelay(50); + robot.setAutoDelay(100); SwingUtilities.invokeAndWait(new Runnable() { @@ -65,6 +77,7 @@ public void run() { } }); + robot.delay(250); robot.waitForIdle(); Point pointToClick = Util.invokeOnEDT(new Callable() { @@ -134,6 +147,7 @@ private static void createAndShowGUI() { panel.add(button, BorderLayout.CENTER); frame.getContentPane().add(panel); + frame.setLocationRelativeTo(null); frame.setVisible(true); } From 3ef382416f5ff38cd44fa8d4e552f1935156e765 Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Wed, 14 Dec 2022 23:08:32 +0000 Subject: [PATCH 215/494] 8298794: Remove JVM_ACC_PROMOTED_FLAGS breaks minimal build Reviewed-by: ayang, dcubed --- src/hotspot/share/oops/instanceKlassMiscStatus.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/hotspot/share/oops/instanceKlassMiscStatus.cpp b/src/hotspot/share/oops/instanceKlassMiscStatus.cpp index 98e97fa66f1..9df5d3e19e6 100644 --- a/src/hotspot/share/oops/instanceKlassMiscStatus.cpp +++ b/src/hotspot/share/oops/instanceKlassMiscStatus.cpp @@ -58,6 +58,7 @@ void InstanceKlassMiscStatus::assign_class_loader_type(const ClassLoaderData* cl set_shared_class_loader_type(ClassLoader::APP_LOADER); } } +#endif // INCLUDE_CDS #ifdef ASSERT void InstanceKlassMiscStatus::assert_is_safe(bool set) { @@ -66,5 +67,3 @@ void InstanceKlassMiscStatus::assert_is_safe(bool set) { assert(!set || SafepointSynchronize::is_at_safepoint(), "set once or at safepoint"); } #endif // ASSERT - -#endif // INCLUDE_CDS From d1085d1be7bc798ced8d539062fa7a9a3ab0341c Mon Sep 17 00:00:00 2001 From: Matias Saavedra Silva Date: Thu, 15 Dec 2022 05:03:57 +0000 Subject: [PATCH 216/494] 8281946: VM.native_memory should report size of shareable memory Reviewed-by: stuefe, iklam --- src/hotspot/share/cds/filemap.cpp | 14 ++++++++++++++ src/hotspot/share/cds/filemap.hpp | 1 + src/hotspot/share/services/memReporter.cpp | 8 ++++++++ .../jtreg/runtime/NMT/SummarySanityCheck.java | 14 ++++++++++++-- 4 files changed, 35 insertions(+), 2 deletions(-) diff --git a/src/hotspot/share/cds/filemap.cpp b/src/hotspot/share/cds/filemap.cpp index 72a7bb021c3..afc45424f7a 100644 --- a/src/hotspot/share/cds/filemap.cpp +++ b/src/hotspot/share/cds/filemap.cpp @@ -2060,6 +2060,20 @@ size_t FileMapInfo::read_bytes(void* buffer, size_t count) { return count; } +// Get the total size in bytes of a read only region +size_t FileMapInfo::readonly_total() { + size_t total = 0; + if (current_info() != nullptr) { + FileMapRegion* r = FileMapInfo::current_info()->region_at(MetaspaceShared::ro); + if (r->read_only()) total += r->used(); + } + if (dynamic_info() != nullptr) { + FileMapRegion* r = FileMapInfo::dynamic_info()->region_at(MetaspaceShared::ro); + if (r->read_only()) total += r->used(); + } + return total; +} + static MemRegion *closed_heap_regions = NULL; static MemRegion *open_heap_regions = NULL; static int num_closed_heap_regions = 0; diff --git a/src/hotspot/share/cds/filemap.hpp b/src/hotspot/share/cds/filemap.hpp index a67274d532a..c71184b82a6 100644 --- a/src/hotspot/share/cds/filemap.hpp +++ b/src/hotspot/share/cds/filemap.hpp @@ -460,6 +460,7 @@ class FileMapInfo : public CHeapObj { void write_bytes(const void* buffer, size_t count); void write_bytes_aligned(const void* buffer, size_t count); size_t read_bytes(void* buffer, size_t count); + static size_t readonly_total(); MapArchiveResult map_regions(int regions[], int num_regions, char* mapped_base_address, ReservedSpace rs); void unmap_regions(int regions[], int num_regions); void map_or_load_heap_regions() NOT_CDS_JAVA_HEAP_RETURN; diff --git a/src/hotspot/share/services/memReporter.cpp b/src/hotspot/share/services/memReporter.cpp index 92dbb801e02..ec1f032fa88 100644 --- a/src/hotspot/share/services/memReporter.cpp +++ b/src/hotspot/share/services/memReporter.cpp @@ -22,6 +22,7 @@ * */ #include "precompiled.hpp" +#include "cds/filemap.hpp" #include "memory/allocation.hpp" #include "memory/metaspace.hpp" #include "memory/metaspaceUtils.hpp" @@ -205,6 +206,13 @@ void MemSummaryReporter::report_summary_of_type(MEMFLAGS flag, const char* scale = current_scale(); out->print("-%26s (", NMTUtil::flag_to_name(flag)); print_total(reserved_amount, committed_amount); +#if INCLUDE_CDS + if (flag == mtClassShared) { + size_t read_only_bytes = FileMapInfo::readonly_total(); + output()->print(", readonly=" SIZE_FORMAT "%s", + amount_in_current_scale(read_only_bytes), scale); + } +#endif out->print_cr(")"); if (flag == mtClass) { diff --git a/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java b/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java index 099836a12e9..e9576c24faf 100644 --- a/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java +++ b/test/hotspot/jtreg/runtime/NMT/SummarySanityCheck.java @@ -64,8 +64,8 @@ public static void main(String args[]) throws Exception { long totalCommitted = 0, totalReserved = 0; long totalCommittedSum = 0, totalReservedSum = 0; - // Match '- (reserved=KB, committed=KB) - Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB\\)"); + // Match '- (reserved=KB, committed=KB) and some times readonly=KB + Pattern mtTypePattern = Pattern.compile("-\\s+(?[\\w\\s]+)\\(reserved=(?\\d+)KB,\\scommitted=(?\\d+)KB((,\\sreadonly=(?\\d+)KB)|)\\)"); // Match 'Total: reserved=KB, committed=KB' Pattern totalMemoryPattern = Pattern.compile("Total\\:\\sreserved=(?\\d+)KB,\\scommitted=(?\\d+)KB"); @@ -85,6 +85,16 @@ public static void main(String args[]) throws Exception { long typeCommitted = Long.parseLong(typeMatcher.group("committed")); long typeReserved = Long.parseLong(typeMatcher.group("reserved")); + // Only Shared class space has readonly component + if (lines[i].contains("Shared class space") && typeMatcher.group("readonly") != null) { + long typeReadOnly = Long.parseLong(typeMatcher.group("readonly")); + // Make sure readonly is always less or equal to committed + if (typeReadOnly > typeCommitted) { + throwTestException("Readonly (" + typeReadOnly + ") was more than Committed (" + + typeCommitted + ") for mtType: " + typeMatcher.group("typename")); + } + } + // Make sure reserved is always less or equals if (typeCommitted > typeReserved) { throwTestException("Committed (" + typeCommitted + ") was more than Reserved (" From b9074fa1ed489993d60ce873fd8105a95d30782a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Thu, 15 Dec 2022 06:54:33 +0000 Subject: [PATCH 217/494] 8298249: Excessive memory allocation in CipherInputStream AEAD decryption Reviewed-by: ascarpino, valeriep --- .../javax/crypto/CipherInputStream.java | 30 ++++- .../crypto/full/AESGCMCipherInputStream.java | 120 ++++++++++++++++++ 2 files changed, 146 insertions(+), 4 deletions(-) create mode 100644 test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java diff --git a/src/java.base/share/classes/javax/crypto/CipherInputStream.java b/src/java.base/share/classes/javax/crypto/CipherInputStream.java index a7637e4b811..3505d43b11b 100644 --- a/src/java.base/share/classes/javax/crypto/CipherInputStream.java +++ b/src/java.base/share/classes/javax/crypto/CipherInputStream.java @@ -105,11 +105,17 @@ public class CipherInputStream extends FilterInputStream { * operation, given the input length {@code inLen} (in bytes) * The ostart and ofinish indices are reset to 0. * + * If obuffer is null/zero-sized, do not allocate a new buffer. + * This reduces allocation for AEAD ciphers that never return data from update + * * @param inLen the input length (in bytes) */ private void ensureCapacity(int inLen) { + if (obuffer == null || obuffer.length == 0) { + return; + } int minLen = cipher.getOutputSize(inLen); - if (obuffer == null || obuffer.length < minLen) { + if (obuffer.length < minLen) { obuffer = new byte[minLen]; } ostart = 0; @@ -142,7 +148,12 @@ private int getMoreData() throws IOException { done = true; ensureCapacity(0); try { - ofinish = cipher.doFinal(obuffer, 0); + if (obuffer != null && obuffer.length > 0) { + ofinish = cipher.doFinal(obuffer, 0); + } else { + obuffer = cipher.doFinal(); + ofinish = obuffer.length; + } } catch (IllegalBlockSizeException | BadPaddingException | ShortBufferException e) { throw new IOException(e); @@ -155,7 +166,14 @@ private int getMoreData() throws IOException { } ensureCapacity(readin); try { - ofinish = cipher.update(ibuffer, 0, readin, obuffer, ostart); + // initial obuffer is assigned by update/doFinal; + // for AEAD ciphers, obuffer is always null or zero-length here + if (obuffer != null && obuffer.length > 0) { + ofinish = cipher.update(ibuffer, 0, readin, obuffer, ostart); + } else { + obuffer = cipher.update(ibuffer, 0, readin); + ofinish = (obuffer != null) ? obuffer.length : 0; + } } catch (IllegalStateException e) { throw e; } catch (ShortBufferException e) { @@ -343,7 +361,11 @@ public void close() throws IOException { if (!done) { ensureCapacity(0); try { - cipher.doFinal(obuffer, 0); + if (obuffer != null && obuffer.length > 0) { + cipher.doFinal(obuffer, 0); + } else { + cipher.doFinal(); + } } catch (BadPaddingException | IllegalBlockSizeException | ShortBufferException ex) { // Catch exceptions as the rest of the stream is unused. diff --git a/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java new file mode 100644 index 00000000000..69d379a8a83 --- /dev/null +++ b/test/micro/org/openjdk/bench/javax/crypto/full/AESGCMCipherInputStream.java @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022, 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.javax.crypto.full; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.Param; +import org.openjdk.jmh.annotations.Setup; + +import javax.crypto.Cipher; +import javax.crypto.CipherInputStream; +import javax.crypto.spec.GCMParameterSpec; +import javax.crypto.spec.SecretKeySpec; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; + +/** + * This performance test runs AES/GCM encryption and decryption using CipherInputStream. + * + * This test rotates the IV and creates a new GCMParameterSpec for each encrypt + * benchmark operation + */ + +public class AESGCMCipherInputStream extends CryptoBase { + + @Param({"128"}) + private int keyLength; + + @Param({"16384", "1048576"}) + private int dataSize; + + byte[] encryptedData; + byte[] in; + ByteArrayOutputStream out; + private Cipher encryptCipher; + private Cipher decryptCipher; + SecretKeySpec ks; + GCMParameterSpec gcm_spec; + byte[] iv; + + private static final int IV_BUFFER_SIZE = 32; + private static final int IV_MODULO = IV_BUFFER_SIZE - 16; + int iv_index = 0; + + private int next_iv_index() { + int r = iv_index; + iv_index = (iv_index + 1) % IV_MODULO; + return r; + } + + @Setup + public void setup() throws Exception { + setupProvider(); + + // Setup key material + byte[] keystring = fillSecureRandom(new byte[keyLength / 8]); + ks = new SecretKeySpec(keystring, "AES"); + iv = fillSecureRandom(new byte[IV_BUFFER_SIZE]); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + + // Setup Cipher classes + encryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + decryptCipher = makeCipher(prov, "AES/GCM/NoPadding"); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + + // Setup input/output buffers + in = fillRandom(new byte[dataSize]); + encryptedData = new byte[encryptCipher.getOutputSize(in.length)]; + out = new ByteArrayOutputStream(encryptedData.length); + encryptCipher.doFinal(in, 0, in.length, encryptedData, 0); + } + + @Benchmark + public byte[] encrypt() throws Exception { + out.reset(); + gcm_spec = new GCMParameterSpec(96, iv, next_iv_index(), 16); + encryptCipher.init(Cipher.ENCRYPT_MODE, ks, gcm_spec); + ByteArrayInputStream fin = new ByteArrayInputStream(in); + InputStream cin = new CipherInputStream(fin, encryptCipher); + + cin.transferTo(out); + return out.toByteArray(); + } + + @Benchmark + public byte[] decrypt() throws Exception { + out.reset(); + decryptCipher.init(Cipher.DECRYPT_MODE, ks, + encryptCipher.getParameters(). + getParameterSpec(GCMParameterSpec.class)); + ByteArrayInputStream fin = new ByteArrayInputStream(encryptedData); + InputStream cin = new CipherInputStream(fin, decryptCipher); + + cin.transferTo(out); + return out.toByteArray(); + } +} From 3ae718725a72cc2758331e932130d846cfba64e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Jeli=C5=84ski?= Date: Thu, 15 Dec 2022 06:55:25 +0000 Subject: [PATCH 218/494] 8298498: sun/net/www/http/KeepAliveCache/B8291637.java fails with "Server exception terminating: java.net.SocketException: Socket closed" Reviewed-by: dfuchs, jpai --- .../net/www/http/KeepAliveCache/B8291637.java | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java b/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java index 6ba25724123..c96df382017 100644 --- a/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java +++ b/test/jdk/sun/net/www/http/KeepAliveCache/B8291637.java @@ -63,18 +63,28 @@ public void close() { } catch (IOException e) {} } - static void readRequest(Socket s) throws IOException { - InputStream is = s.getInputStream(); - is.read(); - while (is.available() > 0) - is.read(); + static final byte[] requestEnd = new byte[] {'\r', '\n', '\r', '\n' }; + + // Read until the end of a HTTP request + static 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; + } + } } public void run() { try { while (true) { s = serverSocket.accept(); - readRequest(s); + readOneRequest(s.getInputStream()); OutputStream os = s.getOutputStream(); String resp = "" + "HTTP/1.1 200 OK\r\n" + @@ -87,7 +97,10 @@ public void run() { os.flush(); InputStream is = s.getInputStream(); long l1 = System.currentTimeMillis(); - is.read(); + int readResult = is.read(); + if (readResult != -1) { + System.out.println("Unexpected byte received: " + readResult); + } long l2 = System.currentTimeMillis(); long diff = (l2 - l1) / 1000; /* From 5f63f7a742a1071a87ca69463bae6e04a44fe462 Mon Sep 17 00:00:00 2001 From: Alan Bateman Date: Thu, 15 Dec 2022 07:14:02 +0000 Subject: [PATCH 219/494] 8298726: (fs) Change PollingWatchService to record last modified time as FileTime rather than milliseconds Reviewed-by: bpb, jpai --- .../sun/nio/fs/PollingWatchService.java | 24 +++++++++---------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java index f86626d196a..ce76e6ef65a 100644 --- a/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java +++ b/src/java.base/share/classes/sun/nio/fs/PollingWatchService.java @@ -29,13 +29,13 @@ import java.nio.file.DirectoryIteratorException; import java.nio.file.DirectoryStream; import java.nio.file.Files; -import java.nio.file.LinkOption; import java.nio.file.NotDirectoryException; import java.nio.file.Path; import java.nio.file.StandardWatchEventKinds; import java.nio.file.WatchEvent; import java.nio.file.WatchKey; import java.nio.file.attribute.BasicFileAttributes; +import java.nio.file.attribute.FileTime; import java.security.AccessController; import java.security.PrivilegedAction; import java.security.PrivilegedExceptionAction; @@ -51,6 +51,7 @@ import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; +import static java.nio.file.LinkOption.NOFOLLOW_LINKS; /** * Simple WatchService implementation that uses periodic tasks to poll @@ -220,10 +221,10 @@ public Void run() { * Entry in directory cache to record file last-modified-time and tick-count */ private static class CacheEntry { - private long lastModified; + private FileTime lastModified; private int lastTickCount; - CacheEntry(long lastModified, int lastTickCount) { + CacheEntry(FileTime lastModified, int lastTickCount) { this.lastModified = lastModified; this.lastTickCount = lastTickCount; } @@ -232,11 +233,11 @@ int lastTickCount() { return lastTickCount; } - long lastModified() { + FileTime lastModified() { return lastModified; } - void update(long lastModified, int tickCount) { + void update(FileTime lastModified, int tickCount) { this.lastModified = lastModified; this.lastTickCount = tickCount; } @@ -278,8 +279,7 @@ private class PollingWatchKey extends AbstractWatchKey { try (DirectoryStream stream = Files.newDirectoryStream(dir)) { for (Path entry: stream) { // don't follow links - long lastModified = - Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis(); + FileTime lastModified = Files.getLastModifiedTime(entry, NOFOLLOW_LINKS); entries.put(entry.getFileName(), new CacheEntry(lastModified, tickCount)); } } catch (DirectoryIteratorException e) { @@ -356,10 +356,9 @@ synchronized void poll() { // iterate over all entries in directory try { for (Path entry: stream) { - long lastModified = 0L; + FileTime lastModified; try { - lastModified = - Files.getLastModifiedTime(entry, LinkOption.NOFOLLOW_LINKS).toMillis(); + lastModified = Files.getLastModifiedTime(entry, NOFOLLOW_LINKS); } catch (IOException x) { // unable to get attributes of entry. If file has just // been deleted then we'll report it as deleted on the @@ -371,8 +370,7 @@ synchronized void poll() { CacheEntry e = entries.get(entry.getFileName()); if (e == null) { // new file found - entries.put(entry.getFileName(), - new CacheEntry(lastModified, tickCount)); + entries.put(entry.getFileName(), new CacheEntry(lastModified, tickCount)); // queue ENTRY_CREATE if event enabled if (events.contains(StandardWatchEventKinds.ENTRY_CREATE)) { @@ -391,7 +389,7 @@ synchronized void poll() { } // check if file has changed - if (e.lastModified != lastModified) { + if (!e.lastModified().equals(lastModified)) { if (events.contains(StandardWatchEventKinds.ENTRY_MODIFY)) { signalEvent(StandardWatchEventKinds.ENTRY_MODIFY, entry.getFileName()); From 98fa48c330941efe6588a907b383802a11ed0e6b Mon Sep 17 00:00:00 2001 From: Matthias Baesken Date: Thu, 15 Dec 2022 08:11:09 +0000 Subject: [PATCH 220/494] 8298093: improve cleanup and error handling of awt_parseColorModel in awt_parseImage.c Reviewed-by: lucy, clanger --- .../native/libawt/awt/image/awt_parseImage.c | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c b/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c index 4b6b24183be..c8d1464f8aa 100644 --- a/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c +++ b/src/java.desktop/share/native/libawt/awt/image/awt_parseImage.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2022, 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 @@ -454,6 +454,7 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, int i; static jobject s_jdefCM = NULL; + cmP->nBits = NULL; if (JNU_IsNull(env, jcmodel)) { JNU_ThrowNullPointerException(env, "null ColorModel object"); @@ -485,7 +486,6 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, return -1; } - cmP->nBits = NULL; if (SAFE_TO_ALLOC_2(cmP->numComponents, sizeof(jint))) { cmP->nBits = (jint *)malloc(cmP->numComponents * sizeof(jint)); } @@ -508,7 +508,9 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, cmP->csType = (*env)->GetIntField(env, cmP->jcmodel, g_CMcsTypeID); cmP->cmType = getColorModelType(env, jcmodel); - JNU_CHECK_EXCEPTION_RETURN(env, -1); + if ((*env)->ExceptionCheck(env)) { + goto cleanup; + } cmP->isDefaultCM = FALSE; cmP->isDefaultCompatCM = FALSE; @@ -530,14 +532,21 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, if (s_jdefCM == NULL) { jobject defCM; jclass jcm = (*env)->FindClass(env, "java/awt/image/ColorModel"); - CHECK_NULL_RETURN(jcm, -1); + if (jcm == NULL) { + goto cleanup; + } defCM = (*env)->CallStaticObjectMethod(env, jcm, g_CMgetRGBdefaultMID, NULL); + if ((*env)->ExceptionCheck(env)) { + (*env)->ExceptionClear(env); + JNU_ThrowNullPointerException(env, "Unable to find default CM"); + goto cleanup; + } s_jdefCM = (*env)->NewGlobalRef(env, defCM); if (defCM == NULL || s_jdefCM == NULL) { (*env)->ExceptionClear(env); JNU_ThrowNullPointerException(env, "Unable to find default CM"); - return -1; + goto cleanup; } } cmP->isDefaultCM = ((*env)->IsSameObject(env, s_jdefCM, jcmodel)); @@ -549,12 +558,12 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, if (cmP->csType != java_awt_color_ColorSpace_TYPE_RGB || !cmP->is_sRGB) { - return -1; + goto cleanup; } for (i = 0; i < cmP->numComponents; i++) { if (cmP->nBits[i] != 8) { - return -1; + goto cleanup; } } } @@ -572,7 +581,7 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, cmP->jrgb, NULL); if (rgb == NULL) { - return -1; + goto cleanup; } for (i=0; i < cmP->mapSize; i++) { if ((rgb[i]&0xff000000) == 0) { @@ -590,6 +599,10 @@ int awt_parseColorModel (JNIEnv *env, jobject jcmodel, int imageType, } return 1; + +cleanup: + free(cmP->nBits); + return -1; } void awt_freeParsedRaster(RasterS_t *rasterP, int freeRasterP) { From b17c52422c91ad1e7ff35844676f6269a1b87f79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Erik=20=C3=96sterlund?= Date: Thu, 15 Dec 2022 09:26:13 +0000 Subject: [PATCH 221/494] 8298059: Linked stack watermarks don't support nesting Reviewed-by: stefank, sspitsyn, rehn, pchilanomate --- .../share/runtime/keepStackGCProcessed.cpp | 4 +-- src/hotspot/share/runtime/stackWatermark.cpp | 34 ++++++++++++++----- src/hotspot/share/runtime/stackWatermark.hpp | 10 ++++-- test/hotspot/jtreg/ProblemList-zgc.txt | 3 -- 4 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/hotspot/share/runtime/keepStackGCProcessed.cpp b/src/hotspot/share/runtime/keepStackGCProcessed.cpp index df851b9f1cc..06ab94dab39 100644 --- a/src/hotspot/share/runtime/keepStackGCProcessed.cpp +++ b/src/hotspot/share/runtime/keepStackGCProcessed.cpp @@ -44,7 +44,7 @@ KeepStackGCProcessedMark::KeepStackGCProcessedMark(JavaThread* jt) : return; } StackWatermark* their_watermark = StackWatermarkSet::get(jt, StackWatermarkKind::gc); - our_watermark->link_watermark(their_watermark); + our_watermark->push_linked_watermark(their_watermark); } KeepStackGCProcessedMark::~KeepStackGCProcessedMark() { @@ -52,7 +52,7 @@ KeepStackGCProcessedMark::~KeepStackGCProcessedMark() { return; } StackWatermark* our_watermark = StackWatermarkSet::get(JavaThread::current(), StackWatermarkKind::gc); - our_watermark->link_watermark(NULL); + our_watermark->pop_linked_watermark(); } void KeepStackGCProcessedMark::finish_processing() { diff --git a/src/hotspot/share/runtime/stackWatermark.cpp b/src/hotspot/share/runtime/stackWatermark.cpp index 1b66856f3c2..e1d8244f284 100644 --- a/src/hotspot/share/runtime/stackWatermark.cpp +++ b/src/hotspot/share/runtime/stackWatermark.cpp @@ -36,7 +36,7 @@ #include "utilities/macros.hpp" #include "utilities/preserveException.hpp" -class StackWatermarkFramesIterator : public CHeapObj { +class StackWatermarkFramesIterator : public CHeapObj { JavaThread* _jt; uintptr_t _caller; uintptr_t _callee; @@ -166,7 +166,7 @@ StackWatermark::StackWatermark(JavaThread* jt, StackWatermarkKind kind, uint32_t _iterator(NULL), _lock(Mutex::stackwatermark, "StackWatermark_lock"), _kind(kind), - _linked_watermark(NULL) { + _linked_watermarks() { } StackWatermark::~StackWatermark() { @@ -250,9 +250,15 @@ void StackWatermark::process_one() { } } -void StackWatermark::link_watermark(StackWatermark* watermark) { - assert(watermark == NULL || _linked_watermark == NULL, "nesting not supported"); - _linked_watermark = watermark; +void StackWatermark::push_linked_watermark(StackWatermark* watermark) { + assert(JavaThread::current() == _jt, "This code is not thread safe"); + _linked_watermarks.push(watermark); +} + +void StackWatermark::pop_linked_watermark() { + assert(JavaThread::current() == _jt, "This code is not thread safe"); + assert(_linked_watermarks.length() > 0, "Mismatched push and pop?"); + _linked_watermarks.pop(); } uintptr_t StackWatermark::watermark() { @@ -288,12 +294,22 @@ bool StackWatermark::processing_completed_acquire() const { return processing_completed(Atomic::load_acquire(&_state)); } +void StackWatermark::process_linked_watermarks() { + assert(JavaThread::current() == _jt, "This code is not thread safe"); + + // Finish processing all linked stack watermarks + for (StackWatermark* watermark : _linked_watermarks) { + watermark->finish_processing(NULL /* context */); + } +} + void StackWatermark::on_safepoint() { start_processing(); - StackWatermark* linked_watermark = _linked_watermark; - if (linked_watermark != NULL) { - linked_watermark->finish_processing(NULL /* context */); - } + + // If the thread waking up from a safepoint expected certain other + // stack watermarks (potentially from different threads) are processed, + // then we have to perform processing of said linked watermarks here. + process_linked_watermarks(); } void StackWatermark::start_processing() { diff --git a/src/hotspot/share/runtime/stackWatermark.hpp b/src/hotspot/share/runtime/stackWatermark.hpp index 98a056eae41..52d34ea5cfb 100644 --- a/src/hotspot/share/runtime/stackWatermark.hpp +++ b/src/hotspot/share/runtime/stackWatermark.hpp @@ -28,6 +28,7 @@ #include "memory/allStatic.hpp" #include "runtime/mutex.hpp" #include "runtime/stackWatermarkKind.hpp" +#include "utilities/growableArray.hpp" class frame; class JavaThread; @@ -83,7 +84,7 @@ class StackWatermarkState : public AllStatic { // ---------- <-- watermark (callee SP from the snapshot, SP at the // point of unwinding, might be above or below // due to frame resizing) -class StackWatermark : public CHeapObj { +class StackWatermark : public CHeapObj { friend class StackWatermarkFramesIterator; protected: volatile uint32_t _state; @@ -93,7 +94,7 @@ class StackWatermark : public CHeapObj { StackWatermarkFramesIterator* _iterator; Mutex _lock; StackWatermarkKind _kind; - StackWatermark* _linked_watermark; + GrowableArrayCHeap _linked_watermarks; void process_one(); @@ -116,6 +117,8 @@ class StackWatermark : public CHeapObj { // opposed to due to frames being unwound by the owning thread. virtual bool process_on_iteration() { return true; } + void process_linked_watermarks(); + bool processing_started(uint32_t state) const; bool processing_completed(uint32_t state) const; @@ -129,7 +132,8 @@ class StackWatermark : public CHeapObj { StackWatermark* next() const { return _next; } void set_next(StackWatermark* n) { _next = n; } - void link_watermark(StackWatermark* watermark); + void push_linked_watermark(StackWatermark* watermark); + void pop_linked_watermark(); uintptr_t watermark(); uintptr_t last_processed(); diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 887eb36e0d4..0d8414feba8 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -83,6 +83,3 @@ vmTestbase/nsk/monitoring/stress/lowmem/lowmem033/TestDescription.java 8297979 g vmTestbase/nsk/monitoring/stress/lowmem/lowmem034/TestDescription.java 8297979 generic-all vmTestbase/nsk/monitoring/stress/lowmem/lowmem035/TestDescription.java 8297979 generic-all vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 generic-all - -vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java 8298059 generic-x64 -vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java 8298059 generic-x64 From 323e574a50520735f41549f36907563e1b4a1040 Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 15 Dec 2022 11:28:06 +0000 Subject: [PATCH 222/494] 8298371: monitors_on_stack extracts unprocessed oops Backport-of: b754aa5e3f231aea8da5274c330dc55dd78b0f67 --- src/hotspot/share/runtime/continuationFreezeThaw.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index 645b6619cc8..ef4bacbbb98 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -1461,7 +1461,7 @@ static bool monitors_on_stack(JavaThread* thread) { ContinuationEntry* ce = thread->last_continuation(); RegisterMap map(thread, RegisterMap::UpdateMap::include, - RegisterMap::ProcessFrames::skip, + RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); map.set_include_argument_oops(false); for (frame f = thread->last_frame(); Continuation::is_frame_in_continuation(ce, f); f = f.sender(&map)) { From 22a6b5910290cb8a3876f94213ba60db86e60718 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Thu, 15 Dec 2022 11:33:56 +0000 Subject: [PATCH 223/494] 8298727: Trees.getPath may crash for unnamed package Reviewed-by: vromero --- .../com/sun/tools/javac/comp/Enter.java | 4 +- .../processing/model/EmptyPackageInfo.java | 134 ++++++++++++++++++ 2 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 test/langtools/tools/javac/processing/model/EmptyPackageInfo.java diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java index 7c134aa891e..01245b24af7 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Enter.java @@ -356,10 +356,12 @@ public void visitTopLevel(JCCompilationUnit tree) { tree.packge.complete(); // Find all classes in package. Env topEnv = topLevelEnv(tree); - Env packageEnv = isPkgInfo ? topEnv.dup(pd) : null; + Env packageEnv = null; // Save environment of package-info.java file. if (isPkgInfo) { + packageEnv = topEnv.dup(pd != null ? pd : tree); + Env env0 = typeEnvs.get(tree.packge); if (env0 != null) { JCCompilationUnit tree0 = env0.toplevel; diff --git a/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java new file mode 100644 index 00000000000..4acf1e3abac --- /dev/null +++ b/test/langtools/tools/javac/processing/model/EmptyPackageInfo.java @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2022, 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 8298727 + * @summary Verify empty package-info.java is handled properly + * @library /tools/lib + * @modules jdk.compiler/com.sun.tools.javac.api + * jdk.compiler/com.sun.tools.javac.main + * @build toolbox.TestRunner toolbox.ToolBox EmptyPackageInfo + * @run main EmptyPackageInfo + */ + +import com.sun.source.tree.Tree; +import com.sun.source.util.JavacTask; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import com.sun.source.util.Trees; +import java.util.ArrayList; +import java.util.List; +import javax.tools.ToolProvider; +import toolbox.TestRunner; +import toolbox.TestRunner.Test; +import toolbox.ToolBox; + +public class EmptyPackageInfo extends TestRunner { + + public static void main(String... args) throws Exception { + new EmptyPackageInfo().runTests(m -> new Object[] { Paths.get(m.getName()) }); + } + + private final ToolBox tb = new ToolBox(); + + public EmptyPackageInfo() { + super(System.err); + } + + @Test + public void testEmptyPackageInfo(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo = src.resolve("package-info.java"); + + tb.writeFile(packInfo, "/**javadoc*/\n"); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var task = + (JavacTask) compiler.getTask(null, + fm, + null, + null, + null, + fm.getJavaFileObjects(packInfo)); + task.analyze(); + var pack = task.getElements().getPackageElement(""); + var trees = Trees.instance(task); + var packPath = trees.getPath(pack); + var packTree = packPath.getLeaf(); + if (packTree.getKind() != Tree.Kind.COMPILATION_UNIT) { + throw new AssertionError("Unexpected tree kind: " + packTree.getKind()); + } + var actualJavadoc = trees.getDocComment(packPath); + var expectedJavadoc = "javadoc"; + if (!expectedJavadoc.equals(actualJavadoc)) { + throw new AssertionError("Unexpected javadoc, " + + "expected: " + expectedJavadoc + + ", got: " + actualJavadoc); + } + } + } + + @Test + public void testMultipleFiles(Path outerBase) throws Exception { + Path src = outerBase.resolve("src"); + Path classes = outerBase.resolve("classes"); + Path packInfo1 = src.resolve("test1").resolve("package-info.java"); + Path packInfo2 = src.resolve("test2").resolve("package-info.java"); + + tb.writeFile(packInfo1, ""); + tb.writeFile(packInfo2, ""); + Files.createDirectories(classes); + + var compiler = ToolProvider.getSystemJavaCompiler(); + + try (var fm = compiler.getStandardFileManager(null, + null, + null)) { + var diags = new ArrayList(); + var task = + (JavacTask) compiler.getTask(null, + fm, + d -> diags.add(d.getCode()), + null, + null, + fm.getJavaFileObjects(packInfo1, + packInfo2)); + task.analyze(); + var expectedDiags = + List.of("compiler.warn.pkg-info.already.seen"); + if (!expectedDiags.equals(diags)) { + throw new AssertionError("Unexpected diags, " + + "expected: " + expectedDiags + + ", got: " + diags); + } + } + } +} From 48f6127325108e573b41d19213e65af99956a31f Mon Sep 17 00:00:00 2001 From: Stefan Karlsson Date: Thu, 15 Dec 2022 11:44:21 +0000 Subject: [PATCH 224/494] 8298376: ZGC: thaws stackChunk with stale oops Backport-of: ed8a2120ca1e9756c6ab5eeebfe24c15d549f04e --- src/hotspot/share/oops/stackChunkOop.hpp | 2 ++ src/hotspot/share/oops/stackChunkOop.inline.hpp | 13 ++++++++++++- .../share/runtime/continuationJavaClasses.hpp | 3 ++- .../runtime/continuationJavaClasses.inline.hpp | 5 +++-- 4 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/hotspot/share/oops/stackChunkOop.hpp b/src/hotspot/share/oops/stackChunkOop.hpp index f6ce1ecc500..c1c0aee8f24 100644 --- a/src/hotspot/share/oops/stackChunkOop.hpp +++ b/src/hotspot/share/oops/stackChunkOop.hpp @@ -91,6 +91,8 @@ class stackChunkOopDesc : public instanceOopDesc { inline int max_thawing_size() const; inline void set_max_thawing_size(int value); + inline oop cont() const; + template inline oop cont() const; inline void set_cont(oop value); template diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index 5de21075666..41ce22a7c34 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -86,7 +86,18 @@ inline void stackChunkOopDesc::set_max_thawing_size(int value) { jdk_internal_vm_StackChunk::set_maxThawingSize(this, (jint)value); } -inline oop stackChunkOopDesc::cont() const { return jdk_internal_vm_StackChunk::cont(as_oop()); } +inline oop stackChunkOopDesc::cont() const { return UseCompressedOops ? cont() : cont(); /* jdk_internal_vm_StackChunk::cont(as_oop()); */ } +template +inline oop stackChunkOopDesc::cont() const { + // The state of the cont oop is used by ZCollectedHeap::requires_barriers, + // to determine the age of the stackChunkOopDesc. For that to work, it is + // only the GC that is allowed to perform a load barrier on the oop. + // This function is used by non-GC code and therfore create a stack-local + // copy on the oop and perform the load barrier on that copy instead. + oop obj = jdk_internal_vm_StackChunk::cont_raw

    (as_oop()); + obj = (oop)NativeAccess<>::oop_load(&obj); + return obj; +} inline void stackChunkOopDesc::set_cont(oop value) { jdk_internal_vm_StackChunk::set_cont(this, value); } template inline void stackChunkOopDesc::set_cont_raw(oop value) { jdk_internal_vm_StackChunk::set_cont_raw

    (this, value); } diff --git a/src/hotspot/share/runtime/continuationJavaClasses.hpp b/src/hotspot/share/runtime/continuationJavaClasses.hpp index 2186dbe3535..d8634161a4b 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.hpp @@ -124,7 +124,8 @@ class jdk_internal_vm_StackChunk: AllStatic { static inline void set_maxThawingSize(oop chunk, int value); // cont oop's processing is essential for the chunk's GC protocol - static inline oop cont(oop chunk); + template + static inline oop cont_raw(oop chunk); static inline void set_cont(oop chunk, oop value); template static inline void set_cont_raw(oop chunk, oop value); diff --git a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp index 1d0ff75225a..5bba4016033 100644 --- a/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp +++ b/src/hotspot/share/runtime/continuationJavaClasses.inline.hpp @@ -81,8 +81,9 @@ inline void jdk_internal_vm_StackChunk::set_parent_access(oop chunk, oop value) chunk->obj_field_put_access(_parent_offset, value); } -inline oop jdk_internal_vm_StackChunk::cont(oop chunk) { - return chunk->obj_field(_cont_offset); +template +inline oop jdk_internal_vm_StackChunk::cont_raw(oop chunk) { + return (oop)RawAccess<>::oop_load(chunk->field_addr

    (_cont_offset)); } inline void jdk_internal_vm_StackChunk::set_cont(oop chunk, oop value) { From 2c42499266377a32aa0ff96a0241d76d7517cf2e Mon Sep 17 00:00:00 2001 From: Per Minborg Date: Thu, 15 Dec 2022 15:46:05 +0000 Subject: [PATCH 225/494] 8298050: Add links to graph output for javadoc Reviewed-by: darcy --- .../build/tools/taglet/SealedGraph.java | 38 ++++++++++++++----- 1 file changed, 29 insertions(+), 9 deletions(-) diff --git a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java index da79c17b387..df719d6fce6 100644 --- a/make/jdk/src/classes/build/tools/taglet/SealedGraph.java +++ b/make/jdk/src/classes/build/tools/taglet/SealedGraph.java @@ -40,6 +40,7 @@ import static java.lang.System.lineSeparator; import static java.nio.file.StandardOpenOption.*; +import static java.util.stream.Collectors.joining; import static jdk.javadoc.doclet.Taglet.Location.TYPE; /** @@ -98,7 +99,7 @@ public String toString(List tags, Element element) { .map(Objects::toString) .collect(Collectors.toUnmodifiableSet()); - String dotContent = Renderer.graph(typeElement, exports); + String dotContent = new Renderer().graph(typeElement, exports); try { Files.writeString(dotFile, dotContent, WRITE, CREATE, TRUNCATE_EXISTING); @@ -133,13 +134,10 @@ private String getImage(String typeName, String file, int height, boolean useBor (height <= 0 ? "" : " height=\"" + height + "\"")); } - private static final class Renderer { - - private Renderer() { - } + private final class Renderer { // Generates a graph in DOT format - static String graph(TypeElement rootClass, Set exports) { + String graph(TypeElement rootClass, Set exports) { final State state = new State(rootClass); traverse(state, rootClass, exports); return state.render(); @@ -155,17 +153,21 @@ static void traverse(State state, TypeElement node, Set exports) { } } - private static final class State { + private final class State { private static final String LABEL = "label"; private static final String TOOLTIP = "tooltip"; + private static final String LINK = "href"; private static final String STYLE = "style"; + private final TypeElement rootNode; + private final StringBuilder builder; private final Map> nodeStyleMap; public State(TypeElement rootNode) { + this.rootNode = rootNode; nodeStyleMap = new LinkedHashMap<>(); builder = new StringBuilder() .append("digraph G {") @@ -188,12 +190,30 @@ public void addNode(TypeElement node) { var styles = nodeStyleMap.computeIfAbsent(id(node), n -> new LinkedHashMap<>()); styles.put(LABEL, node.getSimpleName().toString()); styles.put(TOOLTIP, node.getQualifiedName().toString()); + styles.put(LINK, relativeLink(node)); if (!(node.getModifiers().contains(Modifier.SEALED) || node.getModifiers().contains(Modifier.FINAL))) { // This indicates that the hierarchy is not closed styles.put(STYLE, "dashed"); } } + // A permitted class must be in the same package or in the same module. + // This implies the module is always the same. + private String relativeLink(TypeElement node) { + var util = SealedGraph.this.docletEnvironment.getElementUtils(); + var rootPackage = util.getPackageOf(rootNode); + var nodePackage = util.getPackageOf(node); + var backNavigator = rootPackage.getQualifiedName().toString().chars() + .filter(c -> c == '.') + .mapToObj(c -> "../") + .collect(joining()) + + "../"; + var forwardNavigator = nodePackage.getQualifiedName().toString() + .replace(".", "/"); + + return backNavigator + forwardNavigator + "/" + node.getSimpleName() + ".html"; + } + public void addEdge(TypeElement node, TypeElement subNode) { builder.append(" ") .append(quotedId(subNode)) @@ -209,8 +229,8 @@ public String render() { .append('"').append(nodeName).append("\" ") .append(styles.entrySet().stream() .map(e -> e.getKey() + "=\"" + e.getValue() + "\"") - .collect(Collectors.joining(" ", "[", "]"))) - .append(System.lineSeparator()); + .collect(joining(" ", "[", "]"))) + .append(lineSeparator()); }); builder.append("}"); return builder.toString(); From 0288210f25e3d56870d1aa58ad076c97aad1c232 Mon Sep 17 00:00:00 2001 From: Alexander Zvegintsev Date: Thu, 15 Dec 2022 16:43:06 +0000 Subject: [PATCH 226/494] 8298859: ProblemList java/awt/Mouse/EnterExitEvents/DragWindowTest.java on macosx-all Reviewed-by: jdv --- test/jdk/ProblemList.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 2688ac2c985..33badcdeadf 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -668,6 +668,7 @@ java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 java/awt/image/multiresolution/MultiResolutionJOptionPaneIconTest.java 8274106 macosx-aarch64 javax/swing/JFrame/8175301/ScaledFrameBackgroundTest.java 8274106 macosx-aarch64 +java/awt/Mouse/EnterExitEvents/DragWindowTest.java 8298823 macosx-all javax/swing/JFileChooser/8046391/bug8046391.java 8293862 windows-x64 javax/swing/JFileChooser/4847375/bug4847375.java 8293862 windows-x64 java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java 8280392 windows-x64 From ca39eb906692568347e7f264520593188f9276cf Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 15 Dec 2022 17:27:08 +0000 Subject: [PATCH 227/494] 7093322: (fs spec) Files.newBufferedWriter should be clear when coding errors are detected Reviewed-by: alanb --- src/java.base/share/classes/java/nio/file/Files.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 601dd99d461..682340614a6 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -2938,7 +2938,12 @@ public static BufferedReader newBufferedReader(Path path) throws IOException { * a size of {@code 0} if it exists. * *

    The {@code Writer} methods to write text throw {@code IOException} - * if the text cannot be encoded using the specified charset. + * if the text cannot be encoded using the specified charset. Due to + * buffering, an {@code IOException} caused by an encoding error + * (unmappable-character or malformed-input) may be thrown when {@linkplain + * BufferedWriter#write(char[],int,int) writing}, {@linkplain + * BufferedWriter#flush flushing}, or {@linkplain BufferedWriter#close + * closing} the buffered writer. * * @param path * the path to the file From 831b35fad352887717d5cc8f001ad822ac9a5c46 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 15 Dec 2022 17:27:39 +0000 Subject: [PATCH 228/494] 7093322: (fs spec) Files.newBufferedWriter should be clear when coding errors are detected Reviewed-by: alanb --- src/java.base/share/classes/java/nio/file/Files.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/java.base/share/classes/java/nio/file/Files.java b/src/java.base/share/classes/java/nio/file/Files.java index 601dd99d461..682340614a6 100644 --- a/src/java.base/share/classes/java/nio/file/Files.java +++ b/src/java.base/share/classes/java/nio/file/Files.java @@ -2938,7 +2938,12 @@ public static BufferedReader newBufferedReader(Path path) throws IOException { * a size of {@code 0} if it exists. * *

    The {@code Writer} methods to write text throw {@code IOException} - * if the text cannot be encoded using the specified charset. + * if the text cannot be encoded using the specified charset. Due to + * buffering, an {@code IOException} caused by an encoding error + * (unmappable-character or malformed-input) may be thrown when {@linkplain + * BufferedWriter#write(char[],int,int) writing}, {@linkplain + * BufferedWriter#flush flushing}, or {@linkplain BufferedWriter#close + * closing} the buffered writer. * * @param path * the path to the file From 0ef353925e645dd519e17aeb7a83e927271f8b95 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Thu, 15 Dec 2022 19:20:12 +0000 Subject: [PATCH 229/494] 8298416: Console should be declared `sealed` Reviewed-by: jpai, alanb --- .../share/classes/java/io/Console.java | 661 ++++++------------ .../share/classes/java/io/ConsoleImpl.java | 366 ++++++++++ .../unix/native/libjava/Console_md.c | 5 +- 3 files changed, 578 insertions(+), 454 deletions(-) create mode 100644 src/java.base/share/classes/java/io/ConsoleImpl.java diff --git a/src/java.base/share/classes/java/io/Console.java b/src/java.base/share/classes/java/io/Console.java index 0f83a72c23d..2f7496f6d93 100644 --- a/src/java.base/share/classes/java/io/Console.java +++ b/src/java.base/share/classes/java/io/Console.java @@ -33,8 +33,6 @@ import jdk.internal.access.SharedSecrets; import jdk.internal.io.JdkConsoleProvider; import jdk.internal.util.StaticProperty; -import sun.nio.cs.StreamDecoder; -import sun.nio.cs.StreamEncoder; import sun.security.action.GetPropertyAction; /** @@ -82,7 +80,7 @@ * manually zero the returned character array after processing to minimize the * lifetime of sensitive data in memory. * - *

    {@code
    + * {@snippet lang=java :
      * Console cons;
      * char[] passwd;
      * if ((cons = System.console()) != null &&
    @@ -90,301 +88,232 @@
      *     ...
      *     java.util.Arrays.fill(passwd, ' ');
      * }
    - * }
    + * } * * @author Xueming Shen * @since 1.6 */ +public sealed class Console implements Flushable permits ConsoleImpl, ProxyingConsole { + /** + * Package private no-arg constructor. + */ + Console() {} -public class Console implements Flushable -{ - /** - * Retrieves the unique {@link java.io.PrintWriter PrintWriter} object - * associated with this console. - * - * @return The printwriter associated with this console - */ + /** + * Retrieves the unique {@link java.io.PrintWriter PrintWriter} object + * associated with this console. + * + * @return The printwriter associated with this console + */ public PrintWriter writer() { - return pw; + throw newUnsupportedOperationException(); } - /** - * Retrieves the unique {@link java.io.Reader Reader} object associated - * with this console. - *

    - * This method is intended to be used by sophisticated applications, for - * example, a {@link java.util.Scanner} object which utilizes the rich - * parsing/scanning functionality provided by the {@code Scanner}: - *

    -    * Console con = System.console();
    -    * if (con != null) {
    -    *     Scanner sc = new Scanner(con.reader());
    -    *     ...
    -    * }
    -    * 
    - *

    - * For simple applications requiring only line-oriented reading, use - * {@link #readLine}. - *

    - * The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) }, - * {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and - * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)} - * on the returned object will not read in characters beyond the line - * bound for each invocation, even if the destination buffer has space for - * more characters. The {@code Reader}'s {@code read} methods may block if a - * line bound has not been entered or reached on the console's input device. - * A line bound is considered to be any one of a line feed ({@code '\n'}), - * a carriage return ({@code '\r'}), a carriage return followed immediately - * by a linefeed, or an end of stream. - * - * @return The reader associated with this console - */ + /** + * Retrieves the unique {@link java.io.Reader Reader} object associated + * with this console. + *

    + * This method is intended to be used by sophisticated applications, for + * example, a {@link java.util.Scanner} object which utilizes the rich + * parsing/scanning functionality provided by the {@code Scanner}: + *

    +     * Console con = System.console();
    +     * if (con != null) {
    +     *     Scanner sc = new Scanner(con.reader());
    +     *     ...
    +     * }
    +     * 
    + *

    + * For simple applications requiring only line-oriented reading, use + * {@link #readLine}. + *

    + * The bulk read operations {@link java.io.Reader#read(char[]) read(char[]) }, + * {@link java.io.Reader#read(char[], int, int) read(char[], int, int) } and + * {@link java.io.Reader#read(java.nio.CharBuffer) read(java.nio.CharBuffer)} + * on the returned object will not read in characters beyond the line + * bound for each invocation, even if the destination buffer has space for + * more characters. The {@code Reader}'s {@code read} methods may block if a + * line bound has not been entered or reached on the console's input device. + * A line bound is considered to be any one of a line feed ({@code '\n'}), + * a carriage return ({@code '\r'}), a carriage return followed immediately + * by a linefeed, or an end of stream. + * + * @return The reader associated with this console + */ public Reader reader() { - return reader; + throw newUnsupportedOperationException(); } - /** - * Writes a formatted string to this console's output stream using - * the specified format string and arguments. - * - * @param fmt - * A format string as described in Format string syntax - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * The Java Virtual Machine Specification. - * The behaviour on a - * {@code null} argument depends on the conversion. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the Details section - * of the formatter class specification. - * - * @return This console - */ + /** + * Writes a formatted string to this console's output stream using + * the specified format string and arguments. + * + * @param fmt + * A format string as described in Format string syntax + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java Virtual Machine Specification. + * The behaviour on a + * {@code null} argument depends on the conversion. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section + * of the formatter class specification. + * + * @return This console + */ public Console format(String fmt, Object ...args) { - formatter.format(fmt, args).flush(); - return this; + throw newUnsupportedOperationException(); } - /** - * A convenience method to write a formatted string to this console's - * output stream using the specified format string and arguments. - * - *

    An invocation of this method of the form - * {@code con.printf(format, args)} behaves in exactly the same way - * as the invocation of - *

    con.format(format, args)
    . - * - * @param format - * A format string as described in Format string syntax. - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The number of arguments is - * variable and may be zero. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * The Java Virtual Machine Specification. - * The behaviour on a - * {@code null} argument depends on the conversion. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the Details section of the - * formatter class specification. - * - * @return This console - */ + /** + * A convenience method to write a formatted string to this console's + * output stream using the specified format string and arguments. + * + *

    An invocation of this method of the form + * {@code con.printf(format, args)} behaves in exactly the same way + * as the invocation of + *

    con.format(format, args)
    . + * + * @param format + * A format string as described in Format string syntax. + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The number of arguments is + * variable and may be zero. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java Virtual Machine Specification. + * The behaviour on a + * {@code null} argument depends on the conversion. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section of the + * formatter class specification. + * + * @return This console + */ public Console printf(String format, Object ... args) { - return format(format, args); + throw newUnsupportedOperationException(); } - /** - * Provides a formatted prompt, then reads a single line of text from the - * console. - * - * @param fmt - * A format string as described in Format string syntax. - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * The Java Virtual Machine Specification. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the Details section - * of the formatter class specification. - * - * @throws IOError - * If an I/O error occurs. - * - * @return A string containing the line read from the console, not - * including any line-termination characters, or {@code null} - * if an end of stream has been reached. - */ + /** + * Provides a formatted prompt, then reads a single line of text from the + * console. + * + * @param fmt + * A format string as described in Format string syntax. + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java Virtual Machine Specification. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details section + * of the formatter class specification. + * + * @throws IOError + * If an I/O error occurs. + * + * @return A string containing the line read from the console, not + * including any line-termination characters, or {@code null} + * if an end of stream has been reached. + */ public String readLine(String fmt, Object ... args) { - String line = null; - synchronized (writeLock) { - synchronized(readLock) { - if (!fmt.isEmpty()) - pw.format(fmt, args); - try { - char[] ca = readline(false); - if (ca != null) - line = new String(ca); - } catch (IOException x) { - throw new IOError(x); - } - } - } - return line; + throw newUnsupportedOperationException(); } - /** - * Reads a single line of text from the console. - * - * @throws IOError - * If an I/O error occurs. - * - * @return A string containing the line read from the console, not - * including any line-termination characters, or {@code null} - * if an end of stream has been reached. - */ + /** + * Reads a single line of text from the console. + * + * @throws IOError + * If an I/O error occurs. + * + * @return A string containing the line read from the console, not + * including any line-termination characters, or {@code null} + * if an end of stream has been reached. + */ public String readLine() { - return readLine(""); + throw newUnsupportedOperationException(); } - /** - * Provides a formatted prompt, then reads a password or passphrase from - * the console with echoing disabled. - * - * @param fmt - * A format string as described in Format string syntax - * for the prompt text. - * - * @param args - * Arguments referenced by the format specifiers in the format - * string. If there are more arguments than format specifiers, the - * extra arguments are ignored. The maximum number of arguments is - * limited by the maximum dimension of a Java array as defined by - * The Java Virtual Machine Specification. - * - * @throws IllegalFormatException - * If a format string contains an illegal syntax, a format - * specifier that is incompatible with the given arguments, - * insufficient arguments given the format string, or other - * illegal conditions. For specification of all possible - * formatting errors, see the Details - * section of the formatter class specification. - * - * @throws IOError - * If an I/O error occurs. - * - * @return A character array containing the password or passphrase read - * from the console, not including any line-termination characters, - * or {@code null} if an end of stream has been reached. - */ + /** + * Provides a formatted prompt, then reads a password or passphrase from + * the console with echoing disabled. + * + * @param fmt + * A format string as described in Format string syntax + * for the prompt text. + * + * @param args + * Arguments referenced by the format specifiers in the format + * string. If there are more arguments than format specifiers, the + * extra arguments are ignored. The maximum number of arguments is + * limited by the maximum dimension of a Java array as defined by + * The Java Virtual Machine Specification. + * + * @throws IllegalFormatException + * If a format string contains an illegal syntax, a format + * specifier that is incompatible with the given arguments, + * insufficient arguments given the format string, or other + * illegal conditions. For specification of all possible + * formatting errors, see the Details + * section of the formatter class specification. + * + * @throws IOError + * If an I/O error occurs. + * + * @return A character array containing the password or passphrase read + * from the console, not including any line-termination characters, + * or {@code null} if an end of stream has been reached. + */ public char[] readPassword(String fmt, Object ... args) { - char[] passwd = null; - synchronized (writeLock) { - synchronized(readLock) { - installShutdownHook(); - try { - restoreEcho = echo(false); - } catch (IOException x) { - throw new IOError(x); - } - IOError ioe = null; - try { - if (!fmt.isEmpty()) - pw.format(fmt, args); - passwd = readline(true); - } catch (IOException x) { - ioe = new IOError(x); - } finally { - try { - if (restoreEcho) - restoreEcho = echo(true); - } catch (IOException x) { - if (ioe == null) - ioe = new IOError(x); - else - ioe.addSuppressed(x); - } - if (ioe != null) - throw ioe; - } - pw.println(); - } - } - return passwd; + throw newUnsupportedOperationException(); } - private void installShutdownHook() { - if (shutdownHookInstalled) - return; - try { - // Add a shutdown hook to restore console's echo state should - // it be necessary. - SharedSecrets.getJavaLangAccess() - .registerShutdownHook(0 /* shutdown hook invocation order */, - false /* only register if shutdown is not in progress */, - new Runnable() { - public void run() { - try { - if (restoreEcho) { - echo(true); - } - } catch (IOException x) { } - } - }); - } catch (IllegalStateException e) { - // shutdown is already in progress and readPassword is first used - // by a shutdown hook - } - shutdownHookInstalled = true; - } - - /** - * Reads a password or passphrase from the console with echoing disabled - * - * @throws IOError - * If an I/O error occurs. - * - * @return A character array containing the password or passphrase read - * from the console, not including any line-termination characters, - * or {@code null} if an end of stream has been reached. - */ + /** + * Reads a password or passphrase from the console with echoing disabled + * + * @throws IOError + * If an I/O error occurs. + * + * @return A character array containing the password or passphrase read + * from the console, not including any line-termination characters, + * or {@code null} if an end of stream has been reached. + */ public char[] readPassword() { - return readPassword(""); + throw newUnsupportedOperationException(); } /** @@ -392,10 +321,9 @@ public char[] readPassword() { * immediately . */ public void flush() { - pw.flush(); + throw newUnsupportedOperationException(); } - /** * Returns the {@link java.nio.charset.Charset Charset} object used for * the {@code Console}. @@ -410,171 +338,16 @@ public void flush() { * @since 17 */ public Charset charset() { - assert CHARSET != null : "charset() should not return null"; - return CHARSET; + throw newUnsupportedOperationException(); } - private Object readLock; - private Object writeLock; - private Reader reader; - private Writer out; - private PrintWriter pw; - private Formatter formatter; - private char[] rcb; - private boolean restoreEcho; - private boolean shutdownHookInstalled; - private static native String encoding(); - /* - * Sets the console echo status to {@code on} and returns the previous - * console on/off status. - * @param on the echo status to set to. {@code true} for echo on and - * {@code false} for echo off - * @return true if the previous console echo status is on - */ - private static native boolean echo(boolean on) throws IOException; - - private char[] readline(boolean zeroOut) throws IOException { - int len = reader.read(rcb, 0, rcb.length); - if (len < 0) - return null; //EOL - if (rcb[len-1] == '\r') - len--; //remove CR at end; - else if (rcb[len-1] == '\n') { - len--; //remove LF at end; - if (len > 0 && rcb[len-1] == '\r') - len--; //remove the CR, if there is one - } - char[] b = new char[len]; - if (len > 0) { - System.arraycopy(rcb, 0, b, 0, len); - if (zeroOut) { - Arrays.fill(rcb, 0, len, ' '); - } - } - return b; - } - - private char[] grow() { - assert Thread.holdsLock(readLock); - char[] t = new char[rcb.length * 2]; - System.arraycopy(rcb, 0, t, 0, rcb.length); - rcb = t; - return rcb; - } - - class LineReader extends Reader { - private Reader in; - private char[] cb; - private int nChars, nextChar; - boolean leftoverLF; - LineReader(Reader in) { - this.in = in; - cb = new char[1024]; - nextChar = nChars = 0; - leftoverLF = false; - } - public void close () {} - public boolean ready() throws IOException { - //in.ready synchronizes on readLock already - return in.ready(); - } - - public int read(char[] cbuf, int offset, int length) - throws IOException - { - int off = offset; - int end = offset + length; - if (offset < 0 || offset > cbuf.length || length < 0 || - end < 0 || end > cbuf.length) { - throw new IndexOutOfBoundsException(); - } - synchronized(readLock) { - boolean eof = false; - char c = 0; - for (;;) { - if (nextChar >= nChars) { //fill - int n = 0; - do { - n = in.read(cb, 0, cb.length); - } while (n == 0); - if (n > 0) { - nChars = n; - nextChar = 0; - if (n < cb.length && - cb[n-1] != '\n' && cb[n-1] != '\r') { - /* - * we're in canonical mode so each "fill" should - * come back with an eol. if there no lf or nl at - * the end of returned bytes we reached an eof. - */ - eof = true; - } - } else { /*EOF*/ - if (off - offset == 0) - return -1; - return off - offset; - } - } - if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') { - /* - * if invoked by our readline, skip the leftover, otherwise - * return the LF. - */ - nextChar++; - } - leftoverLF = false; - while (nextChar < nChars) { - c = cbuf[off++] = cb[nextChar]; - cb[nextChar++] = 0; - if (c == '\n') { - return off - offset; - } else if (c == '\r') { - if (off == end) { - /* no space left even the next is LF, so return - * whatever we have if the invoker is not our - * readLine() - */ - if (cbuf == rcb) { - cbuf = grow(); - end = cbuf.length; - } else { - leftoverLF = true; - return off - offset; - } - } - if (nextChar == nChars && in.ready()) { - /* - * we have a CR and we reached the end of - * the read in buffer, fill to make sure we - * don't miss a LF, if there is one, it's possible - * that it got cut off during last round reading - * simply because the read in buffer was full. - */ - nChars = in.read(cb, 0, cb.length); - nextChar = 0; - } - if (nextChar < nChars && cb[nextChar] == '\n') { - cbuf[off++] = '\n'; - nextChar++; - } - return off - offset; - } else if (off == end) { - if (cbuf == rcb) { - cbuf = grow(); - end = cbuf.length; - } else { - return off - offset; - } - } - } - if (eof) - return off - offset; - } - } - } + private static UnsupportedOperationException newUnsupportedOperationException() { + return new UnsupportedOperationException( + "Console class itself does not provide implementation"); } - private static final Charset CHARSET; + private static native String encoding(); + static final Charset CHARSET; static { Charset cs = null; boolean istty = istty(); @@ -619,31 +392,15 @@ private static Console instantiateConsole(boolean istty) { .filter(Objects::nonNull) .findAny() .map(jc -> (Console) new ProxyingConsole(jc)) - .orElse(istty ? new Console() : null); + .orElse(istty ? new ConsoleImpl() : null); }; return AccessController.doPrivileged(pa); } catch (ServiceConfigurationError ignore) { // default to built-in Console - return istty ? new Console() : null; + return istty ? new ConsoleImpl() : null; } } private static final Console cons; private static native boolean istty(); - - Console() { - readLock = new Object(); - writeLock = new Object(); - out = StreamEncoder.forOutputStreamWriter( - new FileOutputStream(FileDescriptor.out), - writeLock, - CHARSET); - pw = new PrintWriter(out, true) { public void close() {} }; - formatter = new Formatter(out); - reader = new LineReader(StreamDecoder.forInputStreamReader( - new FileInputStream(FileDescriptor.in), - readLock, - CHARSET)); - rcb = new char[1024]; - } } diff --git a/src/java.base/share/classes/java/io/ConsoleImpl.java b/src/java.base/share/classes/java/io/ConsoleImpl.java new file mode 100644 index 00000000000..9fb9bbad53f --- /dev/null +++ b/src/java.base/share/classes/java/io/ConsoleImpl.java @@ -0,0 +1,366 @@ +/* + * Copyright (c) 2022, 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. + */ + +package java.io; + +import java.util.*; +import java.nio.charset.Charset; +import jdk.internal.access.SharedSecrets; +import sun.nio.cs.StreamDecoder; +import sun.nio.cs.StreamEncoder; + +/** + * Console implementation based on the platform's TTY. + */ + +final class ConsoleImpl extends Console { + /** + * {@inheritDoc} + */ + @Override + public PrintWriter writer() { + return pw; + } + + /** + * {@inheritDoc} + */ + @Override + public Reader reader() { + return reader; + } + + /** + * {@inheritDoc} + */ + @Override + public Console format(String fmt, Object ...args) { + formatter.format(fmt, args).flush(); + return this; + } + + /** + * {@inheritDoc} + */ + @Override + public Console printf(String format, Object ... args) { + return format(format, args); + } + + /** + * {@inheritDoc} + */ + @Override + public String readLine(String fmt, Object ... args) { + String line = null; + synchronized (writeLock) { + synchronized(readLock) { + if (!fmt.isEmpty()) + pw.format(fmt, args); + try { + char[] ca = readline(false); + if (ca != null) + line = new String(ca); + } catch (IOException x) { + throw new IOError(x); + } + } + } + return line; + } + + /** + * {@inheritDoc} + */ + @Override + public String readLine() { + return readLine(""); + } + + /** + * {@inheritDoc} + */ + @Override + public char[] readPassword(String fmt, Object ... args) { + char[] passwd = null; + synchronized (writeLock) { + synchronized(readLock) { + installShutdownHook(); + try { + restoreEcho = echo(false); + } catch (IOException x) { + throw new IOError(x); + } + IOError ioe = null; + try { + if (!fmt.isEmpty()) + pw.format(fmt, args); + passwd = readline(true); + } catch (IOException x) { + ioe = new IOError(x); + } finally { + try { + if (restoreEcho) + restoreEcho = echo(true); + } catch (IOException x) { + if (ioe == null) + ioe = new IOError(x); + else + ioe.addSuppressed(x); + } + if (ioe != null) + throw ioe; + } + pw.println(); + } + } + return passwd; + } + + private void installShutdownHook() { + if (shutdownHookInstalled) + return; + try { + // Add a shutdown hook to restore console's echo state should + // it be necessary. + SharedSecrets.getJavaLangAccess() + .registerShutdownHook(0 /* shutdown hook invocation order */, + false /* only register if shutdown is not in progress */, + new Runnable() { + public void run() { + try { + if (restoreEcho) { + echo(true); + } + } catch (IOException x) { } + } + }); + } catch (IllegalStateException e) { + // shutdown is already in progress and readPassword is first used + // by a shutdown hook + } + shutdownHookInstalled = true; + } + + /** + * {@inheritDoc} + */ + @Override + public char[] readPassword() { + return readPassword(""); + } + + /** + * {@inheritDoc} + */ + @Override + public void flush() { + pw.flush(); + } + + /** + * {@inheritDoc} + */ + @Override + public Charset charset() { + assert CHARSET != null : "charset() should not return null"; + return CHARSET; + } + + private final Object readLock; + private final Object writeLock; + private final Reader reader; + private final Writer out; + private final PrintWriter pw; + private final Formatter formatter; + private char[] rcb; + private boolean restoreEcho; + private boolean shutdownHookInstalled; + + private char[] readline(boolean zeroOut) throws IOException { + int len = reader.read(rcb, 0, rcb.length); + if (len < 0) + return null; //EOL + if (rcb[len-1] == '\r') + len--; //remove CR at end; + else if (rcb[len-1] == '\n') { + len--; //remove LF at end; + if (len > 0 && rcb[len-1] == '\r') + len--; //remove the CR, if there is one + } + char[] b = new char[len]; + if (len > 0) { + System.arraycopy(rcb, 0, b, 0, len); + if (zeroOut) { + Arrays.fill(rcb, 0, len, ' '); + } + } + return b; + } + + private char[] grow() { + assert Thread.holdsLock(readLock); + char[] t = new char[rcb.length * 2]; + System.arraycopy(rcb, 0, t, 0, rcb.length); + rcb = t; + return rcb; + } + + /* + * Sets the console echo status to {@code on} and returns the previous + * console on/off status. + * @param on the echo status to set to. {@code true} for echo on and + * {@code false} for echo off + * @return true if the previous console echo status is on + */ + private static native boolean echo(boolean on) throws IOException; + + class LineReader extends Reader { + private final Reader in; + private final char[] cb; + private int nChars, nextChar; + boolean leftoverLF; + LineReader(Reader in) { + this.in = in; + cb = new char[1024]; + nextChar = nChars = 0; + leftoverLF = false; + } + public void close () {} + public boolean ready() throws IOException { + //in.ready synchronizes on readLock already + return in.ready(); + } + + public int read(char[] cbuf, int offset, int length) + throws IOException + { + int off = offset; + int end = offset + length; + if (offset < 0 || offset > cbuf.length || length < 0 || + end < 0 || end > cbuf.length) { + throw new IndexOutOfBoundsException(); + } + synchronized(readLock) { + boolean eof = false; + char c; + for (;;) { + if (nextChar >= nChars) { //fill + int n; + do { + n = in.read(cb, 0, cb.length); + } while (n == 0); + if (n > 0) { + nChars = n; + nextChar = 0; + if (n < cb.length && + cb[n-1] != '\n' && cb[n-1] != '\r') { + /* + * we're in canonical mode so each "fill" should + * come back with an eol. if there is no lf or nl at + * the end of returned bytes we reached an eof. + */ + eof = true; + } + } else { /*EOF*/ + if (off - offset == 0) + return -1; + return off - offset; + } + } + if (leftoverLF && cbuf == rcb && cb[nextChar] == '\n') { + /* + * if invoked by our readline, skip the leftover, otherwise + * return the LF. + */ + nextChar++; + } + leftoverLF = false; + while (nextChar < nChars) { + c = cbuf[off++] = cb[nextChar]; + cb[nextChar++] = 0; + if (c == '\n') { + return off - offset; + } else if (c == '\r') { + if (off == end) { + /* no space left even the next is LF, so return + * whatever we have if the invoker is not our + * readLine() + */ + if (cbuf == rcb) { + cbuf = grow(); + } else { + leftoverLF = true; + return off - offset; + } + } + if (nextChar == nChars && in.ready()) { + /* + * we have a CR and we reached the end of + * the read in buffer, fill to make sure we + * don't miss a LF, if there is one, it's possible + * that it got cut off during last round reading + * simply because the read in buffer was full. + */ + nChars = in.read(cb, 0, cb.length); + nextChar = 0; + } + if (nextChar < nChars && cb[nextChar] == '\n') { + cbuf[off++] = '\n'; + nextChar++; + } + return off - offset; + } else if (off == end) { + if (cbuf == rcb) { + cbuf = grow(); + end = cbuf.length; + } else { + return off - offset; + } + } + } + if (eof) + return off - offset; + } + } + } + } + + ConsoleImpl() { + readLock = new Object(); + writeLock = new Object(); + out = StreamEncoder.forOutputStreamWriter( + new FileOutputStream(FileDescriptor.out), + writeLock, + CHARSET); + pw = new PrintWriter(out, true) { public void close() {} }; + formatter = new Formatter(out); + reader = new LineReader(StreamDecoder.forInputStreamReader( + new FileInputStream(FileDescriptor.in), + readLock, + CHARSET)); + rcb = new char[1024]; + } +} diff --git a/src/java.base/unix/native/libjava/Console_md.c b/src/java.base/unix/native/libjava/Console_md.c index 829ceada934..ba7e133e625 100644 --- a/src/java.base/unix/native/libjava/Console_md.c +++ b/src/java.base/unix/native/libjava/Console_md.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2005, 2022, 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,7 @@ #include "jni_util.h" #include "jvm.h" #include "java_io_Console.h" +#include "java_io_ConsoleImpl.h" #include #include @@ -45,7 +46,7 @@ Java_java_io_Console_encoding(JNIEnv *env, jclass cls) } JNIEXPORT jboolean JNICALL -Java_java_io_Console_echo(JNIEnv *env, +Java_java_io_ConsoleImpl_echo(JNIEnv *env, jclass cls, jboolean on) { From ae8988e834032d9d6a4b644c3ebf9ee1957c9522 Mon Sep 17 00:00:00 2001 From: Julian Waters Date: Thu, 15 Dec 2022 19:38:39 +0000 Subject: [PATCH 230/494] 8297912: HotSpot Style Guide should permit alignas (Second Proposal Attempt) Reviewed-by: kbarrett, stuefe, kvn --- doc/hotspot-style.html | 50 +++++++++++++++++++++++++++++++++++++++++- doc/hotspot-style.md | 47 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 95 insertions(+), 2 deletions(-) diff --git a/doc/hotspot-style.html b/doc/hotspot-style.html index 6aa6047ede9..777d69b0a2e 100644 --- a/doc/hotspot-style.html +++ b/doc/hotspot-style.html @@ -72,6 +72,7 @@

    HotSpot Coding Style

  • Expression SFINAE
  • enum
  • +
  • alignas
  • thread_local
  • nullptr
  • <atomic>
  • @@ -598,7 +599,7 @@

    C++ Standard Library

    std::numeric_limits.
  • #include <type_traits>.
  • #include <cstddef> to use -std::nullptr_t.
  • +std::nullptr_t and std::max_align_t.

    TODO: Rather than directly #including (permitted) Standard Library headers, use a convention of #including wrapper headers (in some @@ -670,6 +671,53 @@

    enum

    constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants.

    +

    alignas

    +

    Alignment-specifiers (alignas n2341) +are permitted, with restrictions.

    +

    Alignment-specifiers are permitted when the requested +alignment is a fundamental alignment (not greater than +alignof(std::max_align_t) C++14 +3.11/2).

    +

    Alignment-specifiers with an extended alignment +(greater than alignof(std::max_align_t) C++14 +3.11/3) may only be used to align variables with static or automatic +storage duration (C++14 +3.7.1, 3.7.3). As a consequence, over-aligned types are +forbidden; this may change if HotSpot updates to using C++17 or later +(p0035r4).

    +

    Large extended alignments should be avoided, particularly +for stack allocated objects. What is a large value may depend on the +platform and configuration. There may also be hard limits for some +platforms.

    +

    An alignment-specifier must always be applied to a +definition (C++14 +10.6.2/6). (C++ allows an alignment-specifier to optionally +also be applied to a declaration, so long as the definition has +equivalent alignment. There isn't any known benefit from duplicating the +alignment in a non-definition declaration, so such duplication should be +avoided in HotSpot code.)

    +

    Enumerations are forbidden from having alignment-specifiers. +Aligned enumerations were originally permitted but insufficiently +specified, and were later (C++20) removed (CWG 2354). +Permitting such usage in HotSpot now would just cause problems in the +future.

    +

    Alignment-specifiers are forbidden in typedef +and alias-declarations. This may work or may have worked in +some versions of some compilers, but was later (C++14) explicitly +disallowed (CWG +1437).

    +

    The HotSpot macro ATTRIBUTE_ALIGNED provides similar +capabilities for platforms that define it. This macro predates the use +by HotSpot of C++ versions providing alignas. New code +should use alignas.

    thread_local

    Avoid use of thread_local (n2659); diff --git a/doc/hotspot-style.md b/doc/hotspot-style.md index eeb9d21e74c..555453498d3 100644 --- a/doc/hotspot-style.md +++ b/doc/hotspot-style.md @@ -573,7 +573,7 @@ There are a few exceptions to this rule. * `#include ` to use placement `new`, `std::nothrow`, and `std::nothrow_t`. * `#include ` to use `std::numeric_limits`. * `#include `. -* `#include ` to use `std::nullptr_t`. +* `#include ` to use `std::nullptr_t` and `std::max_align_t`. TODO: Rather than directly \#including (permitted) Standard Library headers, use a convention of \#including wrapper headers (in some @@ -651,6 +651,51 @@ constant members. Compilers having such bugs are no longer supported. Except where an enum is semantically appropriate, new code should use integral constants. +### alignas + +_Alignment-specifiers_ (`alignas` +[n2341](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2341.pdf)) +are permitted, with restrictions. + +_Alignment-specifiers_ are permitted when the requested alignment is a +_fundamental alignment_ (not greater than `alignof(std::max_align_t)` +[C++14 3.11/2](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). + +_Alignment-specifiers_ with an _extended alignment_ (greater than +`alignof(std::max_align_t)` +[C++14 3.11/3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)) +may only be used to align variables with static or automatic storage duration +([C++14 3.7.1, 3.7.3](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). +As a consequence, _over-aligned types_ are forbidden; this may change if +HotSpot updates to using C++17 or later +([p0035r4](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0035r4.html)). + +Large _extended alignments_ should be avoided, particularly for stack +allocated objects. What is a large value may depend on the platform and +configuration. There may also be hard limits for some platforms. + +An _alignment-specifier_ must always be applied to a definition +([C++14 10.6.2/6](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4296.pdf)). +(C++ allows an _alignment-specifier_ to optionally also be applied to a +declaration, so long as the definition has equivalent alignment. There isn't +any known benefit from duplicating the alignment in a non-definition +declaration, so such duplication should be avoided in HotSpot code.) + +Enumerations are forbidden from having _alignment-specifiers_. Aligned +enumerations were originally permitted but insufficiently specified, and were +later (C++20) removed +([CWG 2354](https://cplusplus.github.io/CWG/issues/2354.html)). +Permitting such usage in HotSpot now would just cause problems in the future. + +_Alignment-specifiers_ are forbidden in `typedef` and _alias-declarations_. +This may work or may have worked in some versions of some compilers, but was +later (C++14) explicitly disallowed +([CWG 1437](https://cplusplus.github.io/CWG/issues/1437.html)). + +The HotSpot macro `ATTRIBUTE_ALIGNED` provides similar capabilities for +platforms that define it. This macro predates the use by HotSpot of C++ +versions providing `alignas`. New code should use `alignas`. + ### thread_local Avoid use of `thread_local` From 4b313b51b1787113961c289a41708e31fa19cacc Mon Sep 17 00:00:00 2001 From: Matthew Donovan Date: Thu, 15 Dec 2022 19:48:35 +0000 Subject: [PATCH 231/494] 8297798: Timeout with DTLSOverDatagram test template Reviewed-by: jnimeh, rhalade --- test/jdk/ProblemList.txt | 2 - .../javax/net/ssl/DTLS/DTLSOverDatagram.java | 179 +++++++----------- .../javax/net/ssl/DTLS/InvalidRecords.java | 33 ++-- 3 files changed, 79 insertions(+), 135 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 33badcdeadf..5abeef70b3a 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -586,8 +586,6 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic- sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all -javax/net/ssl/DTLS/CipherSuite.java 8202059 macosx-x64 - sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all sun/security/smartcardio/TestChannel.java 8039280 generic-all diff --git a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java index 0118bcb3810..1820dbe5423 100644 --- a/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java +++ b/test/jdk/javax/net/ssl/DTLS/DTLSOverDatagram.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, 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 @@ * @run main/othervm DTLSOverDatagram */ +import java.io.IOException; import java.nio.*; import java.net.*; import java.util.*; @@ -42,6 +43,7 @@ import jdk.test.lib.security.SSLContextBuilder; import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; import jdk.test.lib.hexdump.HexPrinter; @@ -50,8 +52,6 @@ */ public class DTLSOverDatagram { - private static final int MAX_HANDSHAKE_LOOPS = 200; - private static final int MAX_APP_READ_LOOPS = 60; private static final int SOCKET_TIMEOUT = 10 * 1000; // in millis private static final int BUFFER_SIZE = 1024; private static final int MAXIMUM_PACKET_SIZE = 1024; @@ -75,8 +75,9 @@ public class DTLSOverDatagram { private static final ByteBuffer CLIENT_APP = ByteBuffer.wrap("Hi Server, I'm Client".getBytes()); - private static Exception clientException = null; - private static Exception serverException = null; + private final AtomicBoolean exceptionOccurred = new AtomicBoolean(false); + + private final CountDownLatch serverStarted = new CountDownLatch(1); /* * ============================================================= * The test case @@ -148,18 +149,12 @@ void handshake(SSLEngine engine, DatagramSocket socket, SocketAddress peerAddr, String side) throws Exception { boolean endLoops = false; - int loops = MAX_HANDSHAKE_LOOPS; + int loops = 0; engine.beginHandshake(); - while (!endLoops && - (serverException == null) && (clientException == null)) { - - if (--loops < 0) { - throw new RuntimeException( - "Too many loops to produce handshake packets"); - } + while (!endLoops && !exceptionOccurred.get()) { SSLEngineResult.HandshakeStatus hs = engine.getHandshakeStatus(); - log(side, "=======handshake(" + loops + ", " + hs + ")======="); + log(side, "=======handshake(" + ++loops + ", " + hs + ")======="); switch (hs) { case NEED_UNWRAP, NEED_UNWRAP_AGAIN -> { @@ -313,16 +308,10 @@ void deliverAppData(SSLEngine engine, DatagramSocket socket, void receiveAppData(SSLEngine engine, DatagramSocket socket, ByteBuffer expectedApp) throws Exception { - int loops = MAX_APP_READ_LOOPS; - while ((serverException == null) && (clientException == null)) { - if (--loops < 0) { - throw new RuntimeException( - "Too much loops to receive application data"); - } - + while (!exceptionOccurred.get()) { byte[] buf = new byte[BUFFER_SIZE]; - DatagramPacket packet = new DatagramPacket(buf, buf.length); - socket.receive(packet); + DatagramPacket packet = readFromSocket(socket, buf); + ByteBuffer netBuffer = ByteBuffer.wrap(buf, 0, packet.getLength()); ByteBuffer recBuffer = ByteBuffer.allocate(BUFFER_SIZE); SSLEngineResult rs = engine.unwrap(netBuffer, recBuffer); @@ -338,19 +327,31 @@ void receiveAppData(SSLEngine engine, } } + /* + Some tests failed with receive time-out errors when the client tried to read + from the server. The server thread had exited normally so the read _should_ + succeed. So let's try to read a couple of times before giving up. + */ + DatagramPacket readFromSocket(DatagramSocket socket, byte[] buffer) throws IOException { + for (int i = 1 ; i <= 2 ; ++i) { + try { + DatagramPacket packet = new DatagramPacket(buffer, buffer.length); + socket.receive(packet); + return packet; + } catch (SocketTimeoutException exc) { + System.out.println("Attempt " + i + ": Timeout occurred reading from socket."); + } + } + throw new IOException("Did not receive data after 2 attempts."); + } + // produce handshake packets boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, String side, List packets) throws Exception { boolean endLoops = false; - int loops = MAX_HANDSHAKE_LOOPS / 2; - while (!endLoops && - (serverException == null) && (clientException == null)) { - - if (--loops < 0) { - throw new RuntimeException( - "Too many loops to produce handshake packets"); - } + int loops = 0; + while (!endLoops && !exceptionOccurred.get()) { ByteBuffer oNet = ByteBuffer.allocate(32768); ByteBuffer oApp = ByteBuffer.allocate(0); @@ -360,7 +361,7 @@ boolean produceHandshakePackets(SSLEngine engine, SocketAddress socketAddr, SSLEngineResult.Status rs = r.getStatus(); SSLEngineResult.HandshakeStatus hs = r.getHandshakeStatus(); log(side, "----produce handshake packet(" + - loops + ", " + rs + ", " + hs + ")----"); + ++loops + ", " + rs + ", " + hs + ")----"); verifySSLEngineResultStatus(r, side); @@ -518,10 +519,6 @@ SSLContext getDTLSContext() throws Exception { * The remainder is support stuff to kickstart the testing. */ - // Will the handshaking and application data exchange succeed? - public boolean isGoodJob() { - return true; - } public final void runTest(DTLSOverDatagram testCase) throws Exception { InetSocketAddress serverSocketAddress = new InetSocketAddress @@ -541,97 +538,51 @@ public final void runTest(DTLSOverDatagram testCase) throws Exception { InetSocketAddress clientSocketAddr = new InetSocketAddress( InetAddress.getLoopbackAddress(), clientSocket.getLocalPort()); - ExecutorService pool = Executors.newFixedThreadPool(2); - Future server, client; + ExecutorService pool = Executors.newFixedThreadPool(1); + Future server; - try { - server = pool.submit(new ServerCallable( + server = pool.submit(() -> runServer( testCase, serverSocket, clientSocketAddr)); - client = pool.submit(new ClientCallable( - testCase, clientSocket, serverSocketAddr)); - } finally { - pool.shutdown(); - } - - boolean failed = false; + pool.shutdown(); - // wait for client to finish - try { - System.out.println("Client finished: " + client.get()); - } catch (CancellationException | InterruptedException - | ExecutionException e) { - System.out.println("Exception on client side: "); - e.printStackTrace(System.out); - failed = true; - } - - // wait for server to finish - try { - System.out.println("Client finished: " + server.get()); - } catch (CancellationException | InterruptedException - | ExecutionException e) { - System.out.println("Exception on server side: "); - e.printStackTrace(System.out); - failed = true; - } - - if (failed) { - throw new RuntimeException("Test failed"); - } + runClient(testCase, clientSocket, serverSocketAddr); + server.get(); } } - record ServerCallable(DTLSOverDatagram testCase, DatagramSocket socket, - InetSocketAddress clientSocketAddr) implements Callable { + Void runServer(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress clientSocketAddr) throws Exception { + try { + serverStarted.countDown(); + testCase.doServerSide(socket, clientSocketAddr); - @Override - public String call() throws Exception { - try { - testCase.doServerSide(socket, clientSocketAddr); - } catch (Exception e) { - System.out.println("Exception in ServerCallable.call():"); - e.printStackTrace(System.out); - serverException = e; - - if (testCase.isGoodJob()) { - throw e; - } else { - return "Well done, server!"; - } - } + } catch (Exception exc) { + exceptionOccurred.set(true); - if (testCase.isGoodJob()) { - return "Well done, server!"; - } else { - throw new Exception("No expected exception"); - } + // log for debugging clarity + System.out.println("Unexpected exception in server"); + exc.printStackTrace(System.err); + throw exc; } + + return null; } - record ClientCallable(DTLSOverDatagram testCase, DatagramSocket socket, - InetSocketAddress serverSocketAddr) implements Callable { + private void runClient(DTLSOverDatagram testCase, DatagramSocket socket, + InetSocketAddress serverSocketAddr) throws Exception { + if(!serverStarted.await(5, TimeUnit.SECONDS)) { + throw new Exception("Server did not start within 5 seconds."); + } - @Override - public String call() throws Exception { - try { - testCase.doClientSide(socket, serverSocketAddr); - } catch (Exception e) { - System.out.println("Exception in ClientCallable.call():"); - e.printStackTrace(System.out); - clientException = e; - - if (testCase.isGoodJob()) { - throw e; - } else { - return "Well done, client!"; - } - } + try { + testCase.doClientSide(socket, serverSocketAddr); + } catch (Exception exc) { + exceptionOccurred.set(true); - if (testCase.isGoodJob()) { - return "Well done, client!"; - } else { - throw new Exception("No expected exception"); - } + // log for debugging clarity + System.out.println("Unexpected exception in client."); + exc.printStackTrace(System.err); + throw exc; } } diff --git a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java index af5bdc36134..304cb0695d6 100644 --- a/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java +++ b/test/jdk/javax/net/ssl/DTLS/InvalidRecords.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -36,27 +36,32 @@ import java.net.DatagramPacket; import java.net.SocketAddress; +import java.util.concurrent.atomic.AtomicBoolean; /** - * Test that if handshake messages are crasged, the handshake would fail + * Test that if handshake messages are changed, the handshake would fail * because of handshaking hash verification. */ public class InvalidRecords extends DTLSOverDatagram { - boolean needInvalidRecords = true; + private static final AtomicBoolean needInvalidRecords = new AtomicBoolean(true); public static void main(String[] args) throws Exception { InvalidRecords testCase = new InvalidRecords(); testCase.runTest(testCase); - } - @Override - public boolean isGoodJob() { - return false; + if (needInvalidRecords.get()) { + // if this is true, the createHandshakePacket() method + // was NOT called twice to create ClientHello messages + throw new RuntimeException( + "The invalid handshake packet was not" + + " rejected as it should have been."); + } } + @Override DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { - if ((ba.length >= 60) && + if (needInvalidRecords.get() && (ba.length >= 60) && (ba[0x00] == (byte)0x16) && (ba[0x0D] == (byte)0x01) && (ba[0x3B] == (byte)0x00) && (ba[0x3C] > 0)) { @@ -65,18 +70,8 @@ DatagramPacket createHandshakePacket(byte[] ba, SocketAddress socketAddr) { // ba[0x3B]: length of session ID // ba[0x3C]: length of cookie - if (!needInvalidRecords) { - // The 2nd ClientHello with cookie. The 1st one should be - // rejected as expected. - // - // This may happen if the last few bytes of the packet are - // for supported_version extension. - throw new RuntimeException( - "the crashed handshake message was rejected as expected"); - } - // ClientHello with cookie - needInvalidRecords = false; + needInvalidRecords.set(false); System.out.println("invalidate ClientHello message"); if (ba[ba.length - 1] == (byte)0xFF) { ba[ba.length - 1] = (byte)0xFE; From 10737e168c967a08e257927251861bf2c14795ab Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Thu, 15 Dec 2022 19:54:25 +0000 Subject: [PATCH 232/494] 8298468: Clean up class_loader parameters Reviewed-by: dholmes, iklam --- src/hotspot/share/cds/cdsProtectionDomain.cpp | 3 +- .../share/classfile/loaderConstraints.cpp | 70 ++++++++---------- .../share/classfile/loaderConstraints.hpp | 13 ++-- .../share/classfile/systemDictionary.cpp | 74 +++++++++---------- .../share/classfile/systemDictionary.hpp | 8 +- 5 files changed, 76 insertions(+), 92 deletions(-) diff --git a/src/hotspot/share/cds/cdsProtectionDomain.cpp b/src/hotspot/share/cds/cdsProtectionDomain.cpp index 7f8c25d9ae5..a5257cfd52b 100644 --- a/src/hotspot/share/cds/cdsProtectionDomain.cpp +++ b/src/hotspot/share/cds/cdsProtectionDomain.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "cds/cdsProtectionDomain.hpp" #include "classfile/classLoader.hpp" +#include "classfile/classLoaderData.inline.hpp" #include "classfile/classLoaderExt.hpp" #include "classfile/javaClasses.hpp" #include "classfile/moduleEntry.hpp" @@ -125,7 +126,7 @@ PackageEntry* CDSProtectionDomain::get_package_entry_from_class(InstanceKlass* i } TempNewSymbol pkg_name = ClassLoader::package_from_class_name(ik->name()); if (pkg_name != NULL) { - pkg_entry = SystemDictionaryShared::class_loader_data(class_loader)->packages()->lookup_only(pkg_name); + pkg_entry = ClassLoaderData::class_loader_data(class_loader())->packages()->lookup_only(pkg_name); } else { pkg_entry = NULL; } diff --git a/src/hotspot/share/classfile/loaderConstraints.cpp b/src/hotspot/share/classfile/loaderConstraints.cpp index 26bf3e7911e..32ac2e07d00 100644 --- a/src/hotspot/share/classfile/loaderConstraints.cpp +++ b/src/hotspot/share/classfile/loaderConstraints.cpp @@ -47,11 +47,11 @@ class LoaderConstraint : public CHeapObj { // not class loaders. GrowableArray* _loaders; // initiating loaders public: - LoaderConstraint(InstanceKlass* klass, oop class_loader1, oop class_loader2) : + LoaderConstraint(InstanceKlass* klass, ClassLoaderData* loader1, ClassLoaderData* loader2) : _klass(klass) { _loaders = new (mtClass) GrowableArray(10, mtClass); - add_loader(class_loader1); - add_loader(class_loader2); + add_loader_data(loader1); + add_loader_data(loader2); } LoaderConstraint(const LoaderConstraint& src) = delete; LoaderConstraint& operator=(const LoaderConstraint&) = delete; @@ -61,7 +61,7 @@ class LoaderConstraint : public CHeapObj { InstanceKlass* klass() const { return _klass; } void set_klass(InstanceKlass* k) { _klass = k; } - void extend_loader_constraint(Symbol* class_name, Handle loader, InstanceKlass* klass); + void extend_loader_constraint(Symbol* class_name, ClassLoaderData* loader, InstanceKlass* klass); int num_loaders() const { return _loaders->length(); } ClassLoaderData* loader_data(int i) { return _loaders->at(i); } @@ -71,11 +71,6 @@ class LoaderConstraint : public CHeapObj { assert(_loaders->at(n)->is_unloading(), "should be unloading"); _loaders->remove_at(n); } - - // convenience - void add_loader(oop p) { - _loaders->push(ClassLoaderData::class_loader_data(p)); - } }; // For this class name, these are the set of LoaderConstraints for classes loaded with this name. @@ -114,15 +109,15 @@ class ConstraintSet { // copied into hashtable as ResourceHashtable _loader_constraint_table; void LoaderConstraint::extend_loader_constraint(Symbol* class_name, - Handle loader, + ClassLoaderData* loader, InstanceKlass* klass) { - add_loader(loader()); + add_loader_data(loader); LogTarget(Info, class, loader, constraints) lt; if (lt.is_enabled()) { ResourceMark rm; lt.print("extending constraint for name %s by adding loader: %s %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id(), + loader->loader_name_and_id(), _klass == NULL ? " and setting class object" : ""); } if (_klass == NULL) { @@ -137,7 +132,7 @@ void LoaderConstraint::extend_loader_constraint(Symbol* class_name, // entries in the table could be being dynamically resized. LoaderConstraint* LoaderConstraintTable::find_loader_constraint( - Symbol* name, Handle loader) { + Symbol* name, ClassLoaderData* loader_data) { assert_lock_strong(SystemDictionary_lock); ConstraintSet* set = _loader_constraint_table.get(name); @@ -145,8 +140,6 @@ LoaderConstraint* LoaderConstraintTable::find_loader_constraint( return nullptr; } - ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(loader()); - for (int i = 0; i < set->num_constraints(); i++) { LoaderConstraint* p = set->constraint_at(i); for (int i = p->num_loaders() - 1; i >= 0; i--) { @@ -162,9 +155,10 @@ LoaderConstraint* LoaderConstraintTable::find_loader_constraint( } // Either add it to an existing entry in the table or make a new one. -void LoaderConstraintTable::add_loader_constraint(Symbol* name, InstanceKlass* klass, oop class_loader1, oop class_loader2) { +void LoaderConstraintTable::add_loader_constraint(Symbol* name, InstanceKlass* klass, + ClassLoaderData* loader1, ClassLoaderData* loader2) { assert_lock_strong(SystemDictionary_lock); - LoaderConstraint* constraint = new LoaderConstraint(klass, class_loader1, class_loader2); + LoaderConstraint* constraint = new LoaderConstraint(klass, loader1, loader2); // The klass may be null if it hasn't been loaded yet, for instance while checking // a parameter name to a method call. We impose this constraint that the @@ -256,22 +250,22 @@ void LoaderConstraintTable::purge_loader_constraints() { } void log_ldr_constraint_msg(Symbol* class_name, const char* reason, - Handle class_loader1, Handle class_loader2) { + ClassLoaderData* loader1, ClassLoaderData* loader2) { LogTarget(Info, class, loader, constraints) lt; if (lt.is_enabled()) { ResourceMark rm; lt.print("Failed to add constraint for name: %s, loader[0]: %s," " loader[1]: %s, Reason: %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id(), - ClassLoaderData::class_loader_data(class_loader2())->loader_name_and_id(), + loader1->loader_name_and_id(), + loader2->loader_name_and_id(), reason); } } bool LoaderConstraintTable::add_entry(Symbol* class_name, - InstanceKlass* klass1, Handle class_loader1, - InstanceKlass* klass2, Handle class_loader2) { + InstanceKlass* klass1, ClassLoaderData* loader1, + InstanceKlass* klass2, ClassLoaderData* loader2) { LogTarget(Info, class, loader, constraints) lt; if (klass1 != NULL && klass2 != NULL) { @@ -282,20 +276,20 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, log_ldr_constraint_msg(class_name, "The class objects presented by loader[0] and loader[1] " "are different", - class_loader1, class_loader2); + loader1, loader2); return false; } } InstanceKlass* klass = klass1 != NULL ? klass1 : klass2; - LoaderConstraint* pp1 = find_loader_constraint(class_name, class_loader1); + LoaderConstraint* pp1 = find_loader_constraint(class_name, loader1); if (pp1 != NULL && pp1->klass() != NULL) { if (klass != NULL) { if (klass != pp1->klass()) { log_ldr_constraint_msg(class_name, "The class object presented by loader[0] does not match " "the stored class object in the constraint", - class_loader1, class_loader2); + loader1, loader2); return false; } } else { @@ -303,14 +297,14 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, } } - LoaderConstraint* pp2 = find_loader_constraint(class_name, class_loader2); + LoaderConstraint* pp2 = find_loader_constraint(class_name, loader2); if (pp2 != NULL && pp2->klass() != NULL) { if (klass != NULL) { if (klass != pp2->klass()) { log_ldr_constraint_msg(class_name, "The class object presented by loader[1] does not match " "the stored class object in the constraint", - class_loader1, class_loader2); + loader1, loader2); return false; } } else { @@ -320,15 +314,14 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, if (pp1 == NULL && pp2 == NULL) { - add_loader_constraint(class_name, klass, class_loader1(), class_loader2()); + add_loader_constraint(class_name, klass, loader1, loader2); if (lt.is_enabled()) { ResourceMark rm; lt.print("adding new constraint for name: %s, loader[0]: %s," " loader[1]: %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id(), - ClassLoaderData::class_loader_data(class_loader2())->loader_name_and_id() - ); + loader1->loader_name_and_id(), + loader2->loader_name_and_id()); } } else if (pp1 == pp2) { /* constraint already imposed */ @@ -339,16 +332,15 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, lt.print("setting class object in existing constraint for" " name: %s and loader %s", class_name->as_C_string(), - ClassLoaderData::class_loader_data(class_loader1())->loader_name_and_id() - ); + loader1->loader_name_and_id()); } } else { assert(pp1->klass() == klass, "loader constraints corrupted"); } } else if (pp1 == NULL) { - pp2->extend_loader_constraint(class_name, class_loader1, klass); + pp2->extend_loader_constraint(class_name, loader1, klass); } else if (pp2 == NULL) { - pp1->extend_loader_constraint(class_name, class_loader2, klass); + pp1->extend_loader_constraint(class_name, loader1, klass); } else { merge_loader_constraints(class_name, pp1, pp2, klass); } @@ -359,7 +351,7 @@ bool LoaderConstraintTable::add_entry(Symbol* class_name, // return true if the constraint was updated, false if the constraint is // violated bool LoaderConstraintTable::check_or_update(InstanceKlass* k, - Handle loader, + ClassLoaderData* loader, Symbol* name) { LogTarget(Info, class, loader, constraints) lt; LoaderConstraint* p = find_loader_constraint(name, loader); @@ -369,7 +361,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, lt.print("constraint check failed for name %s, loader %s: " "the presented class object differs from that stored", name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id()); + loader->loader_name_and_id()); } return false; } else { @@ -380,7 +372,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, lt.print("updating constraint for name %s, loader %s, " "by setting class object", name->as_C_string(), - ClassLoaderData::class_loader_data(loader())->loader_name_and_id()); + loader->loader_name_and_id()); } } return true; @@ -388,7 +380,7 @@ bool LoaderConstraintTable::check_or_update(InstanceKlass* k, } InstanceKlass* LoaderConstraintTable::find_constrained_klass(Symbol* name, - Handle loader) { + ClassLoaderData* loader) { LoaderConstraint *p = find_loader_constraint(name, loader); if (p != NULL && p->klass() != NULL) { assert(p->klass()->is_instance_klass(), "sanity"); diff --git a/src/hotspot/share/classfile/loaderConstraints.hpp b/src/hotspot/share/classfile/loaderConstraints.hpp index c97de342cc6..c3fc93b6522 100644 --- a/src/hotspot/share/classfile/loaderConstraints.hpp +++ b/src/hotspot/share/classfile/loaderConstraints.hpp @@ -35,17 +35,18 @@ class Symbol; class LoaderConstraintTable : public AllStatic { private: - static LoaderConstraint* find_loader_constraint(Symbol* name, Handle loader); + static LoaderConstraint* find_loader_constraint(Symbol* name, ClassLoaderData* loader); - static void add_loader_constraint(Symbol* name, InstanceKlass* klass, oop class_loader1, oop class_loader2); + static void add_loader_constraint(Symbol* name, InstanceKlass* klass, + ClassLoaderData* loader1, ClassLoaderData* loader2); static void merge_loader_constraints(Symbol* class_name, LoaderConstraint* pp1, LoaderConstraint* pp2, InstanceKlass* klass); public: // Check class loader constraints - static bool add_entry(Symbol* name, InstanceKlass* klass1, Handle loader1, - InstanceKlass* klass2, Handle loader2); + static bool add_entry(Symbol* name, InstanceKlass* klass1, ClassLoaderData* loader1, + InstanceKlass* klass2, ClassLoaderData* loader2); // Note: The main entry point for this module is via SystemDictionary. // SystemDictionary::check_signature_loaders(Symbol* signature, @@ -53,10 +54,10 @@ class LoaderConstraintTable : public AllStatic { // Handle loader1, Handle loader2, // bool is_method) - static InstanceKlass* find_constrained_klass(Symbol* name, Handle loader); + static InstanceKlass* find_constrained_klass(Symbol* name, ClassLoaderData* loader); // Class loader constraints - static bool check_or_update(InstanceKlass* k, Handle loader, Symbol* name); + static bool check_or_update(InstanceKlass* k, ClassLoaderData* loader, Symbol* name); static void purge_loader_constraints(); diff --git a/src/hotspot/share/classfile/systemDictionary.cpp b/src/hotspot/share/classfile/systemDictionary.cpp index ea878c54bc7..2916c8db35e 100644 --- a/src/hotspot/share/classfile/systemDictionary.cpp +++ b/src/hotspot/share/classfile/systemDictionary.cpp @@ -180,6 +180,11 @@ oop SystemDictionary::get_platform_class_loader_impl(TRAPS) { return result.get_oop(); } +// Helper function +inline ClassLoaderData* class_loader_data(Handle class_loader) { + return ClassLoaderData::class_loader_data(class_loader()); +} + ClassLoaderData* SystemDictionary::register_loader(Handle class_loader, bool create_mirror_cld) { if (create_mirror_cld) { // Add a new class loader data to the graph. @@ -1064,7 +1069,7 @@ bool SystemDictionary::is_shared_class_visible_impl(Symbol* class_name, // Need to reload it now. TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name); if (pkg_name != NULL) { - pkg_entry = ClassLoaderData::class_loader_data(class_loader())->packages()->lookup_only(pkg_name); + pkg_entry = class_loader_data(class_loader)->packages()->lookup_only(pkg_name); } } @@ -1180,7 +1185,7 @@ InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* i // The lambda proxy class and its nest host have the same class loader and class loader data, // as verified in SystemDictionaryShared::add_lambda_proxy_class() assert(shared_nest_host->class_loader() == class_loader(), "mismatched class loader"); - assert(shared_nest_host->class_loader_data() == ClassLoaderData::class_loader_data(class_loader()), "mismatched class loader data"); + assert(shared_nest_host->class_loader_data() == class_loader_data(class_loader), "mismatched class loader data"); ik->set_nest_host(shared_nest_host); return loaded_ik; @@ -1228,7 +1233,7 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik, // loaders, including the bootstrap loader via the placeholder table, // this lock is currently a nop. - ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader()); + ClassLoaderData* loader_data = class_loader_data(class_loader); { HandleMark hm(THREAD); Handle lockObject = get_loader_lock_or_null(class_loader); @@ -1264,12 +1269,11 @@ InstanceKlass* SystemDictionary::load_instance_class_impl(Symbol* class_name, Ha ResourceMark rm(THREAD); PackageEntry* pkg_entry = NULL; bool search_only_bootloader_append = false; - ClassLoaderData *loader_data = class_loader_data(class_loader); // Find the package in the boot loader's package entry table. TempNewSymbol pkg_name = ClassLoader::package_from_class_name(class_name); if (pkg_name != NULL) { - pkg_entry = loader_data->packages()->lookup_only(pkg_name); + pkg_entry = class_loader_data(class_loader)->packages()->lookup_only(pkg_name); } // Prior to attempting to load the class, enforce the boot loader's @@ -1410,22 +1414,22 @@ InstanceKlass* SystemDictionary::load_instance_class(Symbol* name, // If everything was OK (no exceptions, no null return value), and // class_loader is NOT the defining loader, do a little more bookkeeping. if (loaded_class != NULL && - loaded_class->class_loader() != class_loader()) { + loaded_class->class_loader() != class_loader()) { - check_constraints(loaded_class, class_loader, false, CHECK_NULL); + ClassLoaderData* loader_data = class_loader_data(class_loader); + check_constraints(loaded_class, loader_data, false, CHECK_NULL); // Record dependency for non-parent delegation. // This recording keeps the defining class loader of the klass (loaded_class) found // from being unloaded while the initiating class loader is loaded // even if the reference to the defining class loader is dropped // before references to the initiating class loader. - ClassLoaderData* loader_data = class_loader_data(class_loader); loader_data->record_dependency(loaded_class); { // Grabbing the Compile_lock prevents systemDictionary updates // during compilations. MutexLocker mu(THREAD, Compile_lock); - update_dictionary(THREAD, loaded_class, class_loader); + update_dictionary(THREAD, loaded_class, loader_data); } if (JvmtiExport::should_post_class_load()) { @@ -1469,9 +1473,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // classloader lock held // Parallel classloaders will call find_or_define_instance_class // which will require a token to perform the define class - Symbol* name_h = k->name(); - Dictionary* dictionary = loader_data->dictionary(); - check_constraints(k, class_loader, true, CHECK); + check_constraints(k, loader_data, true, CHECK); // Register class just loaded with class loader (placed in ArrayList) // Note we do this before updating the dictionary, as this can @@ -1495,7 +1497,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load // Add to systemDictionary - so other classes can see it. // Grabs and releases SystemDictionary_lock - update_dictionary(THREAD, k, class_loader); + update_dictionary(THREAD, k, loader_data); } // notify jvmti @@ -1528,7 +1530,7 @@ void SystemDictionary::define_instance_class(InstanceKlass* k, Handle class_load InstanceKlass* SystemDictionary::find_or_define_helper(Symbol* class_name, Handle class_loader, InstanceKlass* k, TRAPS) { - Symbol* name_h = k->name(); // passed in class_name may be null + Symbol* name_h = k->name(); ClassLoaderData* loader_data = class_loader_data(class_loader); Dictionary* dictionary = loader_data->dictionary(); @@ -1725,7 +1727,7 @@ void SystemDictionary::initialize(TRAPS) { // if initiating loader, then ok if InstanceKlass matches existing entry void SystemDictionary::check_constraints(InstanceKlass* k, - Handle class_loader, + ClassLoaderData* loader_data, bool defining, TRAPS) { ResourceMark rm(THREAD); @@ -1733,8 +1735,7 @@ void SystemDictionary::check_constraints(InstanceKlass* k, bool throwException = false; { - Symbol *name = k->name(); - ClassLoaderData *loader_data = class_loader_data(class_loader); + Symbol* name = k->name(); MutexLocker mu(THREAD, SystemDictionary_lock); @@ -1755,13 +1756,13 @@ void SystemDictionary::check_constraints(InstanceKlass* k, } if (throwException == false) { - if (LoaderConstraintTable::check_or_update(k, class_loader, name) == false) { + if (LoaderConstraintTable::check_or_update(k, loader_data, name) == false) { throwException = true; ss.print("loader constraint violation: loader %s", loader_data->loader_name_and_id()); ss.print(" wants to load %s %s.", k->external_kind(), k->external_name()); - Klass *existing_klass = LoaderConstraintTable::find_constrained_klass(name, class_loader); - if (existing_klass != NULL && existing_klass->class_loader() != class_loader()) { + Klass *existing_klass = LoaderConstraintTable::find_constrained_klass(name, loader_data); + if (existing_klass != NULL && existing_klass->class_loader_data() != loader_data) { ss.print(" A different %s with the same name was previously loaded by %s. (%s)", existing_klass->external_kind(), existing_klass->class_loader_data()->loader_name_and_id(), @@ -1784,23 +1785,20 @@ void SystemDictionary::check_constraints(InstanceKlass* k, // have been called. void SystemDictionary::update_dictionary(JavaThread* current, InstanceKlass* k, - Handle class_loader) { + ClassLoaderData* loader_data) { // Compile_lock prevents systemDictionary updates during compilations assert_locked_or_safepoint(Compile_lock); - Symbol* name = k->name(); - ClassLoaderData *loader_data = class_loader_data(class_loader); + Symbol* name = k->name(); - { - MutexLocker mu1(SystemDictionary_lock); + MutexLocker mu1(SystemDictionary_lock); - // Make a new dictionary entry. - Dictionary* dictionary = loader_data->dictionary(); - InstanceKlass* sd_check = dictionary->find_class(current, name); - if (sd_check == NULL) { - dictionary->add_klass(current, name, k); - } - SystemDictionary_lock->notify_all(); + // Make a new dictionary entry. + Dictionary* dictionary = loader_data->dictionary(); + InstanceKlass* sd_check = dictionary->find_class(current, name); + if (sd_check == NULL) { + dictionary->add_klass(current, name, k); } + SystemDictionary_lock->notify_all(); } @@ -1831,7 +1829,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass( klass = Universe::typeArrayKlassObj(t); } else { MutexLocker mu(current, SystemDictionary_lock); - klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader); + klass = LoaderConstraintTable::find_constrained_klass(ss.as_symbol(), class_loader_data(class_loader)); } // If element class already loaded, allocate array klass if (klass != NULL) { @@ -1840,7 +1838,7 @@ Klass* SystemDictionary::find_constrained_instance_or_array_klass( } else { MutexLocker mu(current, SystemDictionary_lock); // Non-array classes are easy: simply check the constraint table. - klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader); + klass = LoaderConstraintTable::find_constrained_klass(class_name, class_loader_data(class_loader)); } return klass; @@ -1880,8 +1878,8 @@ bool SystemDictionary::add_loader_constraint(Symbol* class_name, MutexLocker mu_s(SystemDictionary_lock); InstanceKlass* klass1 = dictionary1->find_class(current, constraint_name); InstanceKlass* klass2 = dictionary2->find_class(current, constraint_name); - bool result = LoaderConstraintTable::add_entry(constraint_name, klass1, class_loader1, - klass2, class_loader2); + bool result = LoaderConstraintTable::add_entry(constraint_name, klass1, loader_data1, + klass2, loader_data2); #if INCLUDE_CDS if (Arguments::is_dumping_archive() && klass_being_linked != NULL && !klass_being_linked->is_shared()) { @@ -2443,10 +2441,6 @@ void SystemDictionary::invoke_bootstrap_method(BootstrapInfo& bootstrap_specifie } -ClassLoaderData* SystemDictionary::class_loader_data(Handle class_loader) { - return ClassLoaderData::class_loader_data(class_loader()); -} - bool SystemDictionary::is_nonpublic_Object_method(Method* m) { assert(m != NULL, "Unexpected NULL Method*"); return !m->is_public() && m->method_holder() == vmClasses::Object_klass(); diff --git a/src/hotspot/share/classfile/systemDictionary.hpp b/src/hotspot/share/classfile/systemDictionary.hpp index e56cf832828..82afbcbf0fb 100644 --- a/src/hotspot/share/classfile/systemDictionary.hpp +++ b/src/hotspot/share/classfile/systemDictionary.hpp @@ -201,10 +201,6 @@ class SystemDictionary : AllStatic { // Returns java system loader static oop java_system_loader(); - // Returns the class loader data to be used when looking up/updating the - // system dictionary. - static ClassLoaderData *class_loader_data(Handle class_loader); - // Returns java platform loader static oop java_platform_loader(); @@ -381,9 +377,9 @@ class SystemDictionary : AllStatic { static Symbol* find_placeholder(Symbol* name, ClassLoaderData* loader_data); // Class loader constraints - static void check_constraints(InstanceKlass* k, Handle loader, + static void check_constraints(InstanceKlass* k, ClassLoaderData* loader, bool defining, TRAPS); - static void update_dictionary(JavaThread* current, InstanceKlass* k, Handle loader); + static void update_dictionary(JavaThread* current, InstanceKlass* k, ClassLoaderData* loader_data); }; #endif // SHARE_CLASSFILE_SYSTEMDICTIONARY_HPP From 3cdbd878e68dc1131093137a7357710ad303ae8c Mon Sep 17 00:00:00 2001 From: David Holmes Date: Thu, 15 Dec 2022 21:15:34 +0000 Subject: [PATCH 233/494] 8298241: Replace C-style casts with JavaThread::cast Reviewed-by: coleenp, stefank, sspitsyn --- src/hotspot/cpu/aarch64/frame_aarch64.cpp | 4 ++-- src/hotspot/os/posix/signals_posix.cpp | 2 +- .../os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp | 12 ++++-------- .../windows_aarch64/javaThread_windows_aarch64.cpp | 14 ++++---------- src/hotspot/share/classfile/javaClasses.cpp | 2 +- src/hotspot/share/jvmci/jvmci.cpp | 2 +- src/hotspot/share/jvmci/jvmciRuntime.cpp | 2 +- src/hotspot/share/oops/instanceStackChunkKlass.cpp | 2 +- src/hotspot/share/oops/stackChunkOop.inline.hpp | 2 +- src/hotspot/share/prims/jvmtiEnv.cpp | 2 +- src/hotspot/share/prims/jvmtiEnvBase.cpp | 2 +- src/hotspot/share/prims/jvmtiImpl.cpp | 8 ++++---- src/hotspot/share/prims/scopedMemoryAccess.cpp | 2 +- src/hotspot/share/runtime/continuation.cpp | 5 ++--- .../share/runtime/continuationFreezeThaw.cpp | 4 ++-- src/hotspot/share/runtime/frame.cpp | 2 +- src/hotspot/share/runtime/javaThread.hpp | 2 +- src/hotspot/share/runtime/objectMonitor.cpp | 6 +++--- src/hotspot/share/runtime/synchronizer.cpp | 2 +- 19 files changed, 33 insertions(+), 44 deletions(-) diff --git a/src/hotspot/cpu/aarch64/frame_aarch64.cpp b/src/hotspot/cpu/aarch64/frame_aarch64.cpp index c076f4312b1..3ea2cc5e6ac 100644 --- a/src/hotspot/cpu/aarch64/frame_aarch64.cpp +++ b/src/hotspot/cpu/aarch64/frame_aarch64.cpp @@ -734,12 +734,12 @@ extern "C" void pf(uintptr_t sp, uintptr_t fp, uintptr_t pc, uintptr_t bcx, uintptr_t thread) { if (!reg_map) { reg_map = NEW_C_HEAP_OBJ(RegisterMap, mtInternal); - ::new (reg_map) RegisterMap((JavaThread*)thread, + ::new (reg_map) RegisterMap(reinterpret_cast(thread), RegisterMap::UpdateMap::skip, RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); } else { - *reg_map = RegisterMap((JavaThread*)thread, + *reg_map = RegisterMap(reinterpret_cast(thread), RegisterMap::UpdateMap::skip, RegisterMap::ProcessFrames::include, RegisterMap::WalkContinuation::skip); diff --git a/src/hotspot/os/posix/signals_posix.cpp b/src/hotspot/os/posix/signals_posix.cpp index 1c634130be0..464e0a483be 100644 --- a/src/hotspot/os/posix/signals_posix.cpp +++ b/src/hotspot/os/posix/signals_posix.cpp @@ -639,7 +639,7 @@ int JVM_HANDLE_XXX_SIGNAL(int sig, siginfo_t* info, // Call platform dependent signal handler. if (!signal_was_handled) { - JavaThread* const jt = (t != NULL && t->is_Java_thread()) ? (JavaThread*) t : NULL; + JavaThread* const jt = (t != NULL && t->is_Java_thread()) ? JavaThread::cast(t) : NULL; signal_was_handled = PosixSignals::pd_hotspot_signal_handler(sig, info, uc, jt); } diff --git a/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp b/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp index 10352994df6..38a5547a553 100644 --- a/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp +++ b/src/hotspot/os_cpu/bsd_aarch64/javaThread_bsd_aarch64.cpp @@ -50,13 +50,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - assert(this->is_Java_thread(), "must be JavaThread"); - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than ucontext info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -75,11 +72,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } frame ret_frame(ret_sp, ret_fp, addr); - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_sp, NULL, addr); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -98,4 +95,3 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) } void JavaThread::cache_global_variables() { } - diff --git a/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp b/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp index 6af1fee4f8b..8e97fa6b5c1 100644 --- a/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp +++ b/src/hotspot/os_cpu/windows_aarch64/javaThread_windows_aarch64.cpp @@ -49,15 +49,10 @@ bool JavaThread::pd_get_top_frame_for_profiling(frame* fr_addr, void* ucontext, } bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) { - - assert(this->is_Java_thread(), "must be JavaThread"); - - JavaThread* jt = (JavaThread *)this; - // If we have a last_Java_frame, then we should use it even if // isInJava == true. It should be more reliable than CONTEXT info. - if (jt->has_last_Java_frame() && jt->frame_anchor()->walkable()) { - *fr_addr = jt->pd_last_frame(); + if (has_last_Java_frame() && frame_anchor()->walkable()) { + *fr_addr = pd_last_frame(); return true; } @@ -71,11 +66,11 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) return false; } - if (!ret_frame.safe_for_sender(jt)) { + if (!ret_frame.safe_for_sender(this)) { #if COMPILER2_OR_JVMCI // C2 and JVMCI use ebp as a general register see if NULL fp helps frame ret_frame2(ret_frame.sp(), NULL, ret_frame.pc()); - if (!ret_frame2.safe_for_sender(jt)) { + if (!ret_frame2.safe_for_sender(this)) { // nothing else to try if the frame isn't good return false; } @@ -88,7 +83,6 @@ bool JavaThread::pd_get_top_frame(frame* fr_addr, void* ucontext, bool isInJava) *fr_addr = ret_frame; return true; } - // nothing else to try return false; } diff --git a/src/hotspot/share/classfile/javaClasses.cpp b/src/hotspot/share/classfile/javaClasses.cpp index 0d2092a893a..4b16bc7e526 100644 --- a/src/hotspot/share/classfile/javaClasses.cpp +++ b/src/hotspot/share/classfile/javaClasses.cpp @@ -1714,7 +1714,7 @@ void java_lang_Thread::serialize_offsets(SerializeClosure* f) { #endif JavaThread* java_lang_Thread::thread(oop java_thread) { - return (JavaThread*)java_thread->address_field(_eetop_offset); + return reinterpret_cast(java_thread->address_field(_eetop_offset)); } void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) { diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index e1b26c18dfb..7f4373a9bac 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -108,7 +108,7 @@ void JVMCI::initialize_compiler(TRAPS) { } JVMCIRuntime* runtime; if (UseJVMCINativeLibrary) { - runtime = JVMCI::compiler_runtime((JavaThread*) THREAD); + runtime = JVMCI::compiler_runtime(THREAD); } else { runtime = JVMCI::java_runtime(); } diff --git a/src/hotspot/share/jvmci/jvmciRuntime.cpp b/src/hotspot/share/jvmci/jvmciRuntime.cpp index 96d95e65baa..e256e6d83bf 100644 --- a/src/hotspot/share/jvmci/jvmciRuntime.cpp +++ b/src/hotspot/share/jvmci/jvmciRuntime.cpp @@ -986,7 +986,7 @@ static void _flush_log() { static void _fatal() { Thread* thread = Thread::current_or_null_safe(); if (thread != nullptr && thread->is_Java_thread()) { - JavaThread* jthread = (JavaThread*) thread; + JavaThread* jthread = JavaThread::cast(thread); JVMCIRuntime* runtime = jthread->libjvmci_runtime(); if (runtime != nullptr) { int javaVM_id = runtime->get_shared_library_javavm_id(); diff --git a/src/hotspot/share/oops/instanceStackChunkKlass.cpp b/src/hotspot/share/oops/instanceStackChunkKlass.cpp index db22e5b574c..37512d332b4 100644 --- a/src/hotspot/share/oops/instanceStackChunkKlass.cpp +++ b/src/hotspot/share/oops/instanceStackChunkKlass.cpp @@ -168,7 +168,7 @@ class DescribeStackChunkClosure { public: DescribeStackChunkClosure(stackChunkOop chunk) : _chunk(chunk), - _map((JavaThread*)nullptr, + _map(nullptr, RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::skip, RegisterMap::WalkContinuation::include), diff --git a/src/hotspot/share/oops/stackChunkOop.inline.hpp b/src/hotspot/share/oops/stackChunkOop.inline.hpp index 41ce22a7c34..6e59da94076 100644 --- a/src/hotspot/share/oops/stackChunkOop.inline.hpp +++ b/src/hotspot/share/oops/stackChunkOop.inline.hpp @@ -203,7 +203,7 @@ inline void stackChunkOopDesc::iterate_stack(StackChunkFrameClosureType* closure bool should_continue = true; if (f.is_stub()) { - RegisterMap full_map((JavaThread*)nullptr, + RegisterMap full_map(nullptr, RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::skip, RegisterMap::WalkContinuation::include); diff --git a/src/hotspot/share/prims/jvmtiEnv.cpp b/src/hotspot/share/prims/jvmtiEnv.cpp index c3f48424e1f..ee0425777c6 100644 --- a/src/hotspot/share/prims/jvmtiEnv.cpp +++ b/src/hotspot/share/prims/jvmtiEnv.cpp @@ -583,7 +583,7 @@ JvmtiEnv::SetEventNotificationMode(jvmtiEventMode mode, jvmtiEvent event_type, j // ThreadsListHandle that is common to both thread-specific and // global code paths. - JvmtiEventController::set_user_enabled(this, (JavaThread*) NULL, (oop) NULL, event_type, enabled); + JvmtiEventController::set_user_enabled(this, NULL, (oop) NULL, event_type, enabled); } else { // We have a specified event_thread. ThreadsListHandle tlh; diff --git a/src/hotspot/share/prims/jvmtiEnvBase.cpp b/src/hotspot/share/prims/jvmtiEnvBase.cpp index db3a68fdf9b..8f78f0727fe 100644 --- a/src/hotspot/share/prims/jvmtiEnvBase.cpp +++ b/src/hotspot/share/prims/jvmtiEnvBase.cpp @@ -2333,7 +2333,7 @@ VirtualThreadGetOwnedMonitorInfoClosure::do_thread(Thread *target) { javaVFrame *jvf = JvmtiEnvBase::get_vthread_jvf(_vthread_h()); if (!java_thread->is_exiting() && java_thread->threadObj() != NULL) { - _result = ((JvmtiEnvBase *)_env)->get_owned_monitors((JavaThread*)target, + _result = ((JvmtiEnvBase *)_env)->get_owned_monitors(java_thread, java_thread, jvf, _owned_monitors_list); diff --git a/src/hotspot/share/prims/jvmtiImpl.cpp b/src/hotspot/share/prims/jvmtiImpl.cpp index 0ef3dd955de..81a5c50ea18 100644 --- a/src/hotspot/share/prims/jvmtiImpl.cpp +++ b/src/hotspot/share/prims/jvmtiImpl.cpp @@ -745,7 +745,7 @@ bool VM_BaseGetOrSetLocal::allow_nested_vm_operations() const { // Constructor for non-object getter VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, bool self) - : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, _DEFAULT_VALUE, false, self), + : VM_BaseGetOrSetLocal(NULL, depth, index, type, _DEFAULT_VALUE, false, self), _thread(thread), _eb(false, NULL, NULL) { @@ -753,7 +753,7 @@ VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, B // Constructor for object or non-object setter VM_GetOrSetLocal::VM_GetOrSetLocal(JavaThread* thread, jint depth, jint index, BasicType type, jvalue value, bool self) - : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, value, true, self), + : VM_BaseGetOrSetLocal(NULL, depth, index, type, value, true, self), _thread(thread), _eb(type == T_OBJECT, JavaThread::current(), thread) { @@ -816,7 +816,7 @@ VM_GetReceiver::VM_GetReceiver( // Constructor for non-object getter VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Handle vthread_h, jint depth, jint index, BasicType type, bool self) - : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, _DEFAULT_VALUE, false, self) + : VM_BaseGetOrSetLocal(NULL, depth, index, type, _DEFAULT_VALUE, false, self) { _env = env; _vthread_h = vthread_h; @@ -825,7 +825,7 @@ VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Hand // Constructor for object or non-object setter VM_VirtualThreadGetOrSetLocal::VM_VirtualThreadGetOrSetLocal(JvmtiEnv* env, Handle vthread_h, jint depth, jint index, BasicType type, jvalue value, bool self) - : VM_BaseGetOrSetLocal((JavaThread*)NULL, depth, index, type, value, true, self) + : VM_BaseGetOrSetLocal(NULL, depth, index, type, value, true, self) { _env = env; _vthread_h = vthread_h; diff --git a/src/hotspot/share/prims/scopedMemoryAccess.cpp b/src/hotspot/share/prims/scopedMemoryAccess.cpp index 6bc815a1b94..0908232f686 100644 --- a/src/hotspot/share/prims/scopedMemoryAccess.cpp +++ b/src/hotspot/share/prims/scopedMemoryAccess.cpp @@ -80,7 +80,7 @@ class CloseScopedMemoryClosure : public HandshakeClosure { void do_thread(Thread* thread) { - JavaThread* jt = (JavaThread*)thread; + JavaThread* jt = JavaThread::cast(thread); if (!jt->has_last_Java_frame()) { return; diff --git a/src/hotspot/share/runtime/continuation.cpp b/src/hotspot/share/runtime/continuation.cpp index 63f48a1afe3..8cbe32502e7 100644 --- a/src/hotspot/share/runtime/continuation.cpp +++ b/src/hotspot/share/runtime/continuation.cpp @@ -426,9 +426,8 @@ static JNINativeMethod CONT_methods[] = { }; void CONT_RegisterNativeMethods(JNIEnv *env, jclass cls) { - Thread* thread = Thread::current(); - assert(thread->is_Java_thread(), ""); - ThreadToNativeFromVM trans((JavaThread*)thread); + JavaThread* thread = JavaThread::current(); + ThreadToNativeFromVM trans(thread); int status = env->RegisterNatives(cls, CONT_methods, sizeof(CONT_methods)/sizeof(JNINativeMethod)); guarantee(status == JNI_OK, "register jdk.internal.vm.Continuation natives"); guarantee(!env->ExceptionOccurred(), "register jdk.internal.vm.Continuation natives"); diff --git a/src/hotspot/share/runtime/continuationFreezeThaw.cpp b/src/hotspot/share/runtime/continuationFreezeThaw.cpp index ef4bacbbb98..ba632e0a297 100644 --- a/src/hotspot/share/runtime/continuationFreezeThaw.cpp +++ b/src/hotspot/share/runtime/continuationFreezeThaw.cpp @@ -2563,7 +2563,7 @@ static void print_frame_layout(const frame& f, bool callee_complete, outputStrea FrameValues values; assert(f.get_cb() != nullptr, ""); RegisterMap map(f.is_heap_frame() ? - (JavaThread*)nullptr : + nullptr : JavaThread::current(), RegisterMap::UpdateMap::include, RegisterMap::ProcessFrames::skip, @@ -2574,7 +2574,7 @@ static void print_frame_layout(const frame& f, bool callee_complete, outputStrea frame::update_map_with_saved_link(&map, ContinuationHelper::Frame::callee_link_address(f)); } const_cast(f).describe(values, 0, &map); - values.print_on((JavaThread*)nullptr, st); + values.print_on(static_cast(nullptr), st); } #endif diff --git a/src/hotspot/share/runtime/frame.cpp b/src/hotspot/share/runtime/frame.cpp index 7b002d7e771..fe499dc2b46 100644 --- a/src/hotspot/share/runtime/frame.cpp +++ b/src/hotspot/share/runtime/frame.cpp @@ -1565,7 +1565,7 @@ void FrameValues::validate() { prev = fv; } } - // if (error) { tty->cr(); print_on((JavaThread*)nullptr, tty); } + // if (error) { tty->cr(); print_on(static_cast(nullptr), tty); } assert(!error, "invalid layout"); } #endif // ASSERT diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index ed61a36ebf2..0e43718a338 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -822,7 +822,7 @@ class JavaThread: public Thread { // We don't assert it is Thread::current here as that is done at the // external JNI entry points where the JNIEnv is passed into the VM. static JavaThread* thread_from_jni_environment(JNIEnv* env) { - JavaThread* current = (JavaThread*)((intptr_t)env - in_bytes(jni_environment_offset())); + JavaThread* current = reinterpret_cast(((intptr_t)env - in_bytes(jni_environment_offset()))); // We can't normally get here in a thread that has completed its // execution and so "is_terminated", except when the call is from // AsyncGetCallTrace, which can be triggered by a signal at any point in diff --git a/src/hotspot/share/runtime/objectMonitor.cpp b/src/hotspot/share/runtime/objectMonitor.cpp index 3cb09e462bf..72c53107e46 100644 --- a/src/hotspot/share/runtime/objectMonitor.cpp +++ b/src/hotspot/share/runtime/objectMonitor.cpp @@ -1879,7 +1879,7 @@ int ObjectMonitor::TrySpin(JavaThread* current) { ctr = _SpinDuration; if (ctr <= 0) return 0; - if (NotRunnable(current, (JavaThread*) owner_raw())) { + if (NotRunnable(current, static_cast(owner_raw()))) { return 0; } @@ -1928,9 +1928,9 @@ int ObjectMonitor::TrySpin(JavaThread* current) { // the spin without prejudice or apply a "penalty" to the // spin count-down variable "ctr", reducing it by 100, say. - JavaThread* ox = (JavaThread*) owner_raw(); + JavaThread* ox = static_cast(owner_raw()); if (ox == NULL) { - ox = (JavaThread*)try_set_owner_from(NULL, current); + ox = static_cast(try_set_owner_from(NULL, current)); if (ox == NULL) { // The CAS succeeded -- this thread acquired ownership // Take care of some bookkeeping to exit spin state. diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 9e190e876c2..40fee8f0ba6 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -372,7 +372,7 @@ bool ObjectSynchronizer::quick_enter(oop obj, JavaThread* current, if (m->object_peek() == NULL) { return false; } - JavaThread* const owner = (JavaThread*) m->owner_raw(); + JavaThread* const owner = static_cast(m->owner_raw()); // Lock contention and Transactional Lock Elision (TLE) diagnostics // and observability From 5412439445fadcf66101018a9bd051f8e5d751e8 Mon Sep 17 00:00:00 2001 From: Brian Burkhalter Date: Thu, 15 Dec 2022 22:47:29 +0000 Subject: [PATCH 234/494] 8298187: (fs) BsdFileAttributeViews::setTimes does not support lastAccessTime on HFS+ Reviewed-by: alanb --- .../sun/nio/fs/BsdFileAttributeViews.java | 105 ++++++++++++++---- .../sun/nio/fs/BsdNativeDispatcher.java | 21 ++++ .../native/libnio/fs/BsdNativeDispatcher.c | 55 ++++++--- .../attribute/BasicFileAttributeView.java | 4 +- .../sun/nio/fs/UnixConstants.java.template | 2 +- 5 files changed, 152 insertions(+), 35 deletions(-) diff --git a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java index 56e71ba033c..e071f25f22c 100644 --- a/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java +++ b/src/java.base/macosx/classes/sun/nio/fs/BsdFileAttributeViews.java @@ -28,7 +28,8 @@ import java.io.IOException; import java.nio.file.attribute.FileTime; import java.util.concurrent.TimeUnit; -import static sun.nio.fs.BsdNativeDispatcher.setattrlist; +import static sun.nio.fs.BsdNativeDispatcher.*; +import static sun.nio.fs.UnixNativeDispatcher.lutimes; class BsdFileAttributeViews { // @@ -49,28 +50,94 @@ private static void setTimes(UnixPath path, FileTime lastModifiedTime, // permission check path.checkWrite(); - int commonattr = 0; - long modValue = 0L; - if (lastModifiedTime != null) { - modValue = lastModifiedTime.to(TimeUnit.NANOSECONDS); - commonattr |= UnixConstants.ATTR_CMN_MODTIME; - } - long accValue = 0L; - if (lastAccessTime != null) { - accValue = lastAccessTime.to(TimeUnit.NANOSECONDS); - commonattr |= UnixConstants.ATTR_CMN_ACCTIME; + boolean useLutimes = false; + try { + useLutimes = !followLinks && + UnixFileAttributes.get(path, false).isSymbolicLink(); + } catch (UnixException x) { + x.rethrowAsIOException(path); } - long createValue = 0L; - if (createTime != null) { - createValue = createTime.to(TimeUnit.NANOSECONDS); - commonattr |= UnixConstants.ATTR_CMN_CRTIME; + + int fd = -1; + if (!useLutimes) { + try { + fd = path.openForAttributeAccess(followLinks); + } catch (UnixException x) { + x.rethrowAsIOException(path); + } } try { - setattrlist(path, commonattr, modValue, accValue, createValue, - followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); - } catch (UnixException x) { - x.rethrowAsIOException(path); + // not all volumes support setattrlist(2), so set the last + // modified and last access times using futimens(2)/lutimes(3) + if (lastModifiedTime != null || lastAccessTime != null) { + // if not changing both attributes then need existing attributes + if (lastModifiedTime == null || lastAccessTime == null) { + try { + UnixFileAttributes attrs = UnixFileAttributes.get(fd); + if (lastModifiedTime == null) + lastModifiedTime = attrs.lastModifiedTime(); + if (lastAccessTime == null) + lastAccessTime = attrs.lastAccessTime(); + } catch (UnixException x) { + x.rethrowAsIOException(path); + } + } + + // update times + TimeUnit timeUnit = useLutimes ? + TimeUnit.MICROSECONDS : TimeUnit.NANOSECONDS; + long modValue = lastModifiedTime.to(timeUnit); + long accessValue= lastAccessTime.to(timeUnit); + + boolean retry = false; + try { + if (useLutimes) + lutimes(path, accessValue, modValue); + else + futimens(fd, accessValue, modValue); + } catch (UnixException x) { + // if futimens fails with EINVAL and one/both of the times is + // negative then we adjust the value to the epoch and retry. + if (x.errno() == UnixConstants.EINVAL && + (modValue < 0L || accessValue < 0L)) { + retry = true; + } else { + x.rethrowAsIOException(path); + } + } + if (retry) { + if (modValue < 0L) modValue = 0L; + if (accessValue < 0L) accessValue= 0L; + try { + if (useLutimes) + lutimes(path, accessValue, modValue); + else + futimens(fd, accessValue, modValue); + } catch (UnixException x) { + x.rethrowAsIOException(path); + } + } + } + + // set the creation time using setattrlist + if (createTime != null) { + long createValue = createTime.to(TimeUnit.NANOSECONDS); + int commonattr = UnixConstants.ATTR_CMN_CRTIME; + try { + if (useLutimes) + setattrlist(path, commonattr, 0L, 0L, createValue, + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + else + fsetattrlist(fd, commonattr, 0L, 0L, createValue, + followLinks ? 0 : UnixConstants.FSOPT_NOFOLLOW); + } catch (UnixException x) { + x.rethrowAsIOException(path); + } + } + } finally { + if (!useLutimes) + close(fd, e -> null); } } diff --git a/src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java b/src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java index 0b6448ab42c..5a7de593c63 100644 --- a/src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java +++ b/src/java.base/macosx/classes/sun/nio/fs/BsdNativeDispatcher.java @@ -104,6 +104,27 @@ private static native void setattrlist0(long pathAddress, int commonattr, long createTime, long options) throws UnixException; + /** + * fsetattrlist(int fd, struct attrlist* attrList, void* attrBuf, + * size_t attrBufSize, unsigned long options) + */ + static void fsetattrlist(int fd, int commonattr, long modTime, + long accTime, long createTime, long options) + throws UnixException + { + long comp = Blocker.begin(); + try { + fsetattrlist0(fd, commonattr, modTime, accTime, + createTime, options); + } finally { + Blocker.end(comp); + } + } + private static native void fsetattrlist0(int fd, int commonattr, + long modTime, long accTime, + long createTime, long options) + throws UnixException; + // initialize field IDs private static native void initIDs(); diff --git a/src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c b/src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c index 325da794216..8776411be07 100644 --- a/src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c +++ b/src/java.base/macosx/native/libnio/fs/BsdNativeDispatcher.c @@ -39,6 +39,7 @@ #define ISREADONLY MNT_RDONLY #endif #include +#include #include #include @@ -243,17 +244,11 @@ Java_sun_nio_fs_BsdNativeDispatcher_clonefile0(JNIEnv* env, jclass this, return 0; } -JNIEXPORT void JNICALL -Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this, - jlong pathAddress, int commonattr, jlong modTime, jlong accTime, - jlong createTime, jlong options) +size_t initattrlist(jint commonattr, jlong modTime, jlong accTime, + jlong createTime, const int attrsize, char* buf, struct attrlist *attrList) { - const char* path = (const char*)jlong_to_ptr(pathAddress); - // attributes must align on 4-byte boundaries per the getattrlist(2) spec - const int attrsize = ((sizeof(struct timespec) + 3)/4)*4; - char buf[3*attrsize]; - int count = 0; + // attributes are ordered per the getattrlist(2) spec if ((commonattr & ATTR_CMN_CRTIME) != 0) { struct timespec* t = (struct timespec*)buf; @@ -274,12 +269,46 @@ Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this, count++; } + memset(attrList, 0, sizeof(struct attrlist)); + attrList->bitmapcount = ATTR_BIT_MAP_COUNT; + attrList->commonattr = commonattr; + + return count*attrsize; +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_BsdNativeDispatcher_setattrlist0(JNIEnv* env, jclass this, + jlong pathAddress, int commonattr, jlong modTime, jlong accTime, + jlong createTime, jlong options) +{ + const char* path = (const char*)jlong_to_ptr(pathAddress); + // attributes must align on 4-byte boundaries per the getattrlist(2) spec + const int attrsize = ((sizeof(struct timespec) + 3)/4)*4; + char buf[3*attrsize]; + + struct attrlist attrList; + size_t attrBufSize = initattrlist(commonattr, modTime, accTime, createTime, + attrsize, buf, &attrList); + + if (setattrlist(path, &attrList, (void*)buf, attrBufSize, options) != 0) { + throwUnixException(env, errno); + } +} + +JNIEXPORT void JNICALL +Java_sun_nio_fs_BsdNativeDispatcher_fsetattrlist0(JNIEnv* env, jclass this, + jint fd, int commonattr, jlong modTime, jlong accTime, + jlong createTime, jlong options) +{ + // attributes must align on 4-byte boundaries per the getattrlist(2) spec + const int attrsize = ((sizeof(struct timespec) + 3)/4)*4; + char buf[3*attrsize]; + struct attrlist attrList; - memset(&attrList, 0, sizeof(struct attrlist)); - attrList.bitmapcount = ATTR_BIT_MAP_COUNT; - attrList.commonattr = commonattr; + size_t attrBufSize = initattrlist(commonattr, modTime, accTime, createTime, + attrsize, buf, &attrList); - if (setattrlist(path, &attrList, (void*)buf, count*attrsize, options) != 0) { + if (fsetattrlist(fd, &attrList, (void*)buf, attrBufSize, options) != 0) { throwUnixException(env, errno); } } diff --git a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java index 37508cfd200..97e6fb94cd3 100644 --- a/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java +++ b/src/java.base/share/classes/java/nio/file/attribute/BasicFileAttributeView.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2007, 2020, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2007, 2022, 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 @@ -134,7 +134,7 @@ public interface BasicFileAttributeView * *

    This method updates the file's timestamp attributes. The values are * converted to the epoch and precision supported by the file system. - * Converting from finer to coarser granularities result in precision loss. + * Converting from finer to coarser granularities results in precision loss. * The behavior of this method when attempting to set a timestamp that is * not supported or to a value that is outside the range supported by the * underlying file store is not defined. It may or not fail by throwing an diff --git a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template index 459e2d7abd3..a8a521caf8e 100644 --- a/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template +++ b/src/java.base/unix/classes/sun/nio/fs/UnixConstants.java.template @@ -153,7 +153,7 @@ class UnixConstants { static final int PREFIX_CLONE_NOFOLLOW = CLONE_NOFOLLOW; static final int PREFIX_CLONE_NOOWNERCOPY = CLONE_NOOWNERCOPY; - // flags used with setattrlist + // flags used with fsetattrlist static final int PREFIX_ATTR_CMN_CRTIME = ATTR_CMN_CRTIME; static final int PREFIX_ATTR_CMN_MODTIME = ATTR_CMN_MODTIME; static final int PREFIX_ATTR_CMN_ACCTIME = ATTR_CMN_ACCTIME; From c7d7e7e3be768b35447d65661ec328204aeb40e4 Mon Sep 17 00:00:00 2001 From: "Daniel D. Daugherty" Date: Fri, 16 Dec 2022 00:01:08 +0000 Subject: [PATCH 235/494] 8298888: ProblemList gc/g1/TestVerifyGCType.java on linux and macosx 8298889: ProblemList runtime/StackGuardPages/TestStackGuardPages.java on linux 8298891: ProblemList vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java with ZGC 8298892: ProblemList vmTestbase/nsk/sysdict/vm/stress/chain/chain008/chain008.java with ZGC Reviewed-by: bpb, lmesnik --- test/hotspot/jtreg/ProblemList-zgc.txt | 2 ++ test/hotspot/jtreg/ProblemList.txt | 2 ++ 2 files changed, 4 insertions(+) diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 887eb36e0d4..5735d6c51fe 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -86,3 +86,5 @@ vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 g vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java 8298059 generic-x64 vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java 8298059 generic-x64 +vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all +vmTestbase/nsk/sysdict/vm/stress/chain/chain008/chain008.java 8298596 linux-x64 diff --git a/test/hotspot/jtreg/ProblemList.txt b/test/hotspot/jtreg/ProblemList.txt index 66121e1dcb1..39f5c2ee63f 100644 --- a/test/hotspot/jtreg/ProblemList.txt +++ b/test/hotspot/jtreg/ProblemList.txt @@ -80,6 +80,7 @@ gc/stress/gclocker/TestGCLockerWithG1.java 8180622 generic-all gc/stress/TestJNIBlockFullGC/TestJNIBlockFullGC.java 8192647 generic-all gc/metaspace/CompressedClassSpaceSizeInJmapHeap.java 8241293,8298073 macosx-x64,macosx-aarch64 gc/stress/TestStressG1Humongous.java 8286554 windows-x64 +gc/g1/TestVerifyGCType.java 8298215 linux-all,macosx-all ############################################################################# @@ -97,6 +98,7 @@ runtime/os/TestTracePageSizes.java#Serial 8267460 linux-aarch64 runtime/ErrorHandling/CreateCoredumpOnCrash.java 8267433 macosx-x64 runtime/vthread/RedefineClass.java 8297286 generic-all runtime/vthread/TestObjectAllocationSampleEvent.java 8297286 generic-all +runtime/StackGuardPages/TestStackGuardPages.java 8293452 linux-all applications/jcstress/copy.java 8229852 linux-all From 2bb727c4eaf8a948f17f6416a1e6fbaeade4d7ce Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 16 Dec 2022 00:43:56 +0000 Subject: [PATCH 236/494] 8290899: java/lang/String/StringRepeat.java test requests too much heap on windows x86 Reviewed-by: jpai, phh --- test/jdk/java/lang/String/StringRepeat.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/jdk/java/lang/String/StringRepeat.java b/test/jdk/java/lang/String/StringRepeat.java index 491bfe9f86f..c36e512f8ba 100644 --- a/test/jdk/java/lang/String/StringRepeat.java +++ b/test/jdk/java/lang/String/StringRepeat.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2022, 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 @@ * @test * @summary This exercises String#repeat patterns with 16 * 1024 * 1024 repeats. * @requires os.maxMemory >= 2G + * @requires !(os.family == "windows" & sun.arch.data.model == "32") * @run main/othervm -Xmx2g StringRepeat 16777216 */ From a3364612f7d49f3633661b9ba4e9b721534cafad Mon Sep 17 00:00:00 2001 From: David Holmes Date: Fri, 16 Dec 2022 01:08:30 +0000 Subject: [PATCH 237/494] 8298081: DiagnoseSyncOnValueBasedClasses doesn't report useful information for virtual threads Reviewed-by: gziemski, pchilanomate --- src/hotspot/share/runtime/javaThread.cpp | 8 ++++ src/hotspot/share/runtime/javaThread.hpp | 5 ++- src/hotspot/share/runtime/synchronizer.cpp | 4 +- .../Monitor/SyncOnValueBasedClassTest.java | 40 +++++++++++++++++-- 4 files changed, 51 insertions(+), 6 deletions(-) diff --git a/src/hotspot/share/runtime/javaThread.cpp b/src/hotspot/share/runtime/javaThread.cpp index f51aa24774d..0fa2776bca4 100644 --- a/src/hotspot/share/runtime/javaThread.cpp +++ b/src/hotspot/share/runtime/javaThread.cpp @@ -1758,6 +1758,14 @@ void JavaThread::print_vthread_stack_on(outputStream* st) { } } +void JavaThread::print_active_stack_on(outputStream* st) { + if (is_vthread_mounted()) { + print_vthread_stack_on(st); + } else { + print_stack_on(st); + } +} + #if INCLUDE_JVMTI // Rebind JVMTI thread state from carrier to virtual or from virtual to carrier. JvmtiThreadState* JavaThread::rebind_to_jvmti_thread_state_of(oop thread_oop) { diff --git a/src/hotspot/share/runtime/javaThread.hpp b/src/hotspot/share/runtime/javaThread.hpp index 0e43718a338..10fc8b6efb5 100644 --- a/src/hotspot/share/runtime/javaThread.hpp +++ b/src/hotspot/share/runtime/javaThread.hpp @@ -938,10 +938,13 @@ class JavaThread: public Thread { Klass* security_get_caller_class(int depth); // Print stack trace in external format + // These variants print carrier/platform thread information only. void print_stack_on(outputStream* st); void print_stack() { print_stack_on(tty); } + // This prints the currently mounted virtual thread. void print_vthread_stack_on(outputStream* st); - + // This prints the active stack: either carrier/platform or virtual. + void print_active_stack_on(outputStream* st); // Print stack trace for checked JNI warnings and JNI fatal errors. // This is the external format from above, but selecting the platform // or vthread as applicable. diff --git a/src/hotspot/share/runtime/synchronizer.cpp b/src/hotspot/share/runtime/synchronizer.cpp index 40fee8f0ba6..36302a8390f 100644 --- a/src/hotspot/share/runtime/synchronizer.cpp +++ b/src/hotspot/share/runtime/synchronizer.cpp @@ -429,7 +429,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread if (DiagnoseSyncOnValueBasedClasses == FATAL_EXIT) { ResourceMark rm(current); stringStream ss; - current->print_stack_on(&ss); + current->print_active_stack_on(&ss); char* base = (char*)strstr(ss.base(), "at"); char* newline = (char*)strchr(ss.base(), '\n'); if (newline != NULL) { @@ -444,7 +444,7 @@ void ObjectSynchronizer::handle_sync_on_value_based_class(Handle obj, JavaThread vblog.info("Synchronizing on object " INTPTR_FORMAT " of klass %s", p2i(obj()), obj->klass()->external_name()); if (current->has_last_Java_frame()) { LogStream info_stream(vblog.info()); - current->print_stack_on(&info_stream); + current->print_active_stack_on(&info_stream); } else { vblog.info("Cannot find the last Java frame"); } diff --git a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java index bc889564004..1cfa6ff5dff 100644 --- a/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java +++ b/test/hotspot/jtreg/runtime/Monitor/SyncOnValueBasedClassTest.java @@ -33,7 +33,8 @@ * @requires vm.flagless * @requires vm.flavor != "zero" * @library /test/lib - * @run driver/timeout=180000 SyncOnValueBasedClassTest + * @enablePreview + * @run main/othervm/timeout=180000 --enable-preview SyncOnValueBasedClassTest */ public class SyncOnValueBasedClassTest { @@ -62,7 +63,7 @@ private static void initTestObjects() { private static void generateTests() { initTestObjects(); - String[] commonFatalTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", "-XX:DiagnoseSyncOnValueBasedClasses=1"}; + String[] commonFatalTestsFlags = {"--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", "-XX:DiagnoseSyncOnValueBasedClasses=1"}; fatalTests = new String[specificFlags.length * testObjects.size()][]; for (int i = 0; i < specificFlags.length; i++) { for (int j = 0; j < testObjects.size(); j++) { @@ -72,7 +73,7 @@ private static void generateTests() { .toArray(String[]::new); } } - String[] commonLogTestsFlags = {"-XX:+UnlockDiagnosticVMOptions", "-XX:DiagnoseSyncOnValueBasedClasses=2"}; + String[] commonLogTestsFlags = {"--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:DiagnoseSyncOnValueBasedClasses=2"}; logTests = new String[specificFlags.length][]; for (int i = 0; i < specificFlags.length; i++) { logTests[i] = Stream.of(commonLogTestsFlags, specificFlags[i], new String[] {"SyncOnValueBasedClassTest$LogTest"}) @@ -96,6 +97,7 @@ public static void main(String[] args) throws Exception { output.shouldHaveExitValue(0); checkOutput(output); } + virtualThreadTests(); } private static void checkOutput(OutputAnalyzer output) { @@ -163,4 +165,36 @@ public void run() { } } } + + // Very basic sanity tests to show things work for virtual threads too. + private static void virtualThreadTests() throws Exception { + final String[] vtTest = { "--enable-preview", "-XX:+UnlockDiagnosticVMOptions", "-XX:-CreateCoredumpOnCrash", + "", "SyncOnValueBasedClassTest$VTTest" }; + // Fatal test + vtTest[3] = "-XX:DiagnoseSyncOnValueBasedClasses=1"; + ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(vtTest); + OutputAnalyzer output = ProcessTools.executeProcess(pb); + output.shouldContain("fatal error: Synchronizing on object"); + output.shouldNotContain("synchronization on value based class did not fail"); + output.shouldNotHaveExitValue(0); + + // Log test + vtTest[3] = "-XX:DiagnoseSyncOnValueBasedClasses=2"; + pb = ProcessTools.createJavaProcessBuilder(vtTest); + output = ProcessTools.executeProcess(pb); + output.shouldHaveExitValue(0); + output.shouldContain("Synchronizing on object"); + output.shouldContain("synchronization on value based class did not fail"); + } + + static class VTTest { + public static void main(String[] args) throws Exception { + var thread = Thread.ofVirtual().start(() -> { + synchronized (Character.valueOf('H')) { + System.out.println("synchronization on value based class did not fail"); + } + }); + thread.join(); + } + } } From e41686b4050d6b32fb451de8af39a78ec8bed0fd Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Fri, 16 Dec 2022 05:16:40 +0000 Subject: [PATCH 238/494] 8298710: Fix typos in test/jdk/sun/security/tools/jarsigner/ Co-authored-by: Michael Ernst Reviewed-by: lancea --- .../javax/security/auth/x500/X500Principal/EscapedChars.java | 2 +- test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java | 2 +- .../FindHeaderEndVsManifestDigesterFindFirstSection.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java b/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java index 23b995d6578..693ed910ba1 100644 --- a/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java +++ b/test/jdk/javax/security/auth/x500/X500Principal/EscapedChars.java @@ -38,7 +38,7 @@ public static void main(String[] args) throws Exception { System.out.println("RFC2253 DN is " + xp.getName(X500Principal.RFC2253)); - System.out.println("CANONICAL DN is is " + + System.out.println("CANONICAL DN is " + xp.getName(X500Principal.CANONICAL)); String dn1 = xp.getName(X500Principal.CANONICAL); diff --git a/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java b/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java index 24beb9f2f24..843a49bf33d 100644 --- a/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java +++ b/test/jdk/sun/security/tools/jarsigner/DigestDontIgnoreCase.java @@ -47,7 +47,7 @@ */ /* *

    mfDigest.equalsIgnoreCase(base64Digests[i])
    - * previously in JarSigner.java on on line 985 + * previously in JarSigner.java on line 985 * @see jdk.security.jarsigner.JarSigner#updateDigests */ public class DigestDontIgnoreCase { diff --git a/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java b/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java index e84edaf8e48..97436b76d31 100644 --- a/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java +++ b/test/jdk/sun/security/tools/jarsigner/FindHeaderEndVsManifestDigesterFindFirstSection.java @@ -217,7 +217,7 @@ public void startOfNextLengthWithBlankLine() throws Exception { *
  • which is then passed on as the third parameter to the constructor * of a new {@link ManifestDigester.Section#Section} by *
    new Section(0, pos.endOfSection + 1, pos.startOfNext, rawBytes)));
    - * in in ManifestDigester.java:128
  • + * in ManifestDigester.java:128 *
  • where it is assigned to * {@link ManifestDigester.Section#lengthWithBlankLine} by *
    this.lengthWithBlankLine = lengthWithBlankLine;
    From 03a694afda81f575f8a24e655d53b2b029e3d968 Mon Sep 17 00:00:00 2001 From: Sergey Bylokhov Date: Fri, 16 Dec 2022 06:33:08 +0000 Subject: [PATCH 239/494] 8298083: The "CheckBox/RadioButton[Enabled/Disabled].textForeground" stoped working Reviewed-by: prr Backport-of: 5540a8c5b7160ab5c67bb84631e3de54fa5aeceb --- .../com/sun/java/swing/plaf/gtk/GTKStyle.java | 14 +------ .../javax/swing/plaf/synth/SynthStyle.java | 10 +---- test/jdk/ProblemList.txt | 1 + .../JRadioButton/4314194/bug4314194.java | 40 +++++++++++++------ 4 files changed, 31 insertions(+), 34 deletions(-) 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 f645add8f45..9f1b468007f 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, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -286,18 +286,6 @@ else if (type == ColorType.TEXT_FOREGROUND) { } } } - - if ((c instanceof JCheckBox) && (state & SynthConstants.DISABLED) != 0) { - if (UIManager.getColor("CheckBox.disabledText") != null) { - return UIManager.getColor("CheckBox.disabledText"); - } - } else if ((c instanceof JRadioButton) && - (state & SynthConstants.DISABLED) != 0) { - if (UIManager.getColor("RadioButton.disabledText") != null) { - return UIManager.getColor("RadioButton.disabledText"); - } - } - return getColorForState(context, type); } diff --git a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java index e648fbf108e..f25b25166bc 100644 --- a/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java +++ b/src/java.desktop/share/classes/javax/swing/plaf/synth/SynthStyle.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2002, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2002, 2022, 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 @@ -779,14 +779,6 @@ public Color getColor(SynthContext context, ColorType type) { (type == ColorType.FOREGROUND || type == ColorType.TEXT_FOREGROUND)) { return getColorForState(context, type); - } else if (c instanceof JCheckBox) { - if (UIManager.getColor("CheckBox.disabledText") != null) { - return UIManager.getColor("CheckBox.disabledText"); - } - } else if (c instanceof JRadioButton) { - if (UIManager.getColor("RadioButton.disabledText") != null) { - return UIManager.getColor("RadioButton.disabledText"); - } } } diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 4e00b2c1482..17bad35da71 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -662,6 +662,7 @@ javax/swing/JFileChooser/6798062/bug6798062.java 8146446 windows-all javax/swing/JPopupMenu/4870644/bug4870644.java 8194130 macosx-all,linux-all javax/swing/dnd/8139050/NativeErrorsInTableDnD.java 8202765 macosx-all,linux-all javax/swing/JEditorPane/6917744/bug6917744.java 8213124 macosx-all +javax/swing/JRadioButton/4314194/bug4314194.java 8298153 linux-all # Several tests which fail on some hidpi systems/macosx12-aarch64 system java/awt/Window/8159168/SetShapeTest.java 8274106 macosx-aarch64 diff --git a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java index e783b147ca6..57ee1a2bb3f 100644 --- a/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java +++ b/test/jdk/javax/swing/JRadioButton/4314194/bug4314194.java @@ -23,7 +23,7 @@ /* * @test * @key headful - * @bug 4314194 8075916 + * @bug 4314194 8075916 8298083 * @summary Verifies disabled color for JCheckbox and JRadiobutton is honored in all L&F * @run main bug4314194 */ @@ -40,13 +40,14 @@ import javax.swing.SwingUtilities; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; +import javax.swing.plaf.synth.SynthLookAndFeel; public class bug4314194 { - private static JFrame frame; - private static JRadioButton radioButton; - private static JCheckBox checkBox; - private static Point point; - private static Rectangle rect; + private static volatile JFrame frame; + private static volatile JRadioButton radioButton; + private static volatile JCheckBox checkBox; + private static volatile Point point; + private static volatile Rectangle rect; private static Robot robot; private static final Color radioButtonColor = Color.RED; private static final Color checkboxColor = Color.GREEN; @@ -87,9 +88,25 @@ private static void setLookAndFeel(UIManager.LookAndFeelInfo laf) { } } - private static void createUI() { - UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); - UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + private static void createUI(String laf) { + if (UIManager.getLookAndFeel() instanceof SynthLookAndFeel) { + // reset "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", null); + UIManager.getDefaults().put("RadioButton.disabledText", null); + // set "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", checkboxColor); + // for some reason the RadioButton[Disabled] does not work + // see https://bugs.openjdk.org/browse/JDK-8298149 + //UIManager.getDefaults().put("RadioButton[Disabled].textForeground", radioButtonColor); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", radioButtonColor); + } else { + // reset "synth" properties + UIManager.getDefaults().put("CheckBox[Disabled].textForeground", null); + UIManager.getDefaults().put("RadioButton[Enabled].textForeground", null); + // set "basic" properties + UIManager.getDefaults().put("CheckBox.disabledText", checkboxColor); + UIManager.getDefaults().put("RadioButton.disabledText", radioButtonColor); + } checkBox = new JCheckBox("\u2588".repeat(5)); radioButton = new JRadioButton("\u2588".repeat(5)); @@ -98,7 +115,7 @@ private static void createUI() { checkBox.setEnabled(false); radioButton.setEnabled(false); - frame = new JFrame("bug4314194"); + frame = new JFrame(laf); frame.getContentPane().add(radioButton, BorderLayout.SOUTH); frame.getContentPane().add(checkBox, BorderLayout.NORTH); frame.pack(); @@ -122,7 +139,7 @@ public static void main(String[] args) throws Exception { System.out.println("Testing L&F: " + laf.getClassName()); SwingUtilities.invokeAndWait(() -> setLookAndFeel(laf)); try { - SwingUtilities.invokeAndWait(() -> createUI()); + SwingUtilities.invokeAndWait(() -> createUI(laf.getName())); robot.waitForIdle(); robot.delay(1000); @@ -141,4 +158,3 @@ public static void main(String[] args) throws Exception { } } } - From fa322e40b68abf0a253040d14414d41f4e01e028 Mon Sep 17 00:00:00 2001 From: Jaikiran Pai Date: Fri, 16 Dec 2022 07:10:36 +0000 Subject: [PATCH 240/494] 8298709: Fix typos in src/java.desktop/ and various test classes of client component Co-authored-by: Michael Ernst Reviewed-by: iris, prr --- .../share/classes/javax/swing/text/Document.java | 2 +- .../DeviceIdentificationTest/DeviceIdentificationTest.java | 2 +- .../HTMLDataFlavors/ManualHTMLDataFlavorTest.java | 2 +- test/jdk/java/awt/print/PrinterJob/PageFormatChange.java | 2 +- test/jdk/javax/imageio/stream/DeleteOnExitTest.sh | 2 +- test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java | 2 +- test/jdk/javax/sound/midi/Sequencer/SequencerState.java | 2 +- test/jdk/javax/swing/JColorChooser/Test4193384.java | 2 +- test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java | 2 +- test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java | 2 +- .../sun/swingset3/demos/tree/resources/TreeDemo.properties | 2 +- .../lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java | 4 ++-- .../src/org/netbeans/jemmy/operators/ComponentOperator.java | 2 +- .../src/org/netbeans/jemmy/operators/JTreeOperator.java | 2 +- .../jemmy/src/org/netbeans/jemmy/operators/Operator.java | 6 +++--- test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java | 2 +- 16 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/java.desktop/share/classes/javax/swing/text/Document.java b/src/java.desktop/share/classes/javax/swing/text/Document.java index c23da3c19e8..b36d7b984e3 100644 --- a/src/java.desktop/share/classes/javax/swing/text/Document.java +++ b/src/java.desktop/share/classes/javax/swing/text/Document.java @@ -278,7 +278,7 @@ *

    Removing text from a DefaultStyledDocument is similar to removing text from * a PlainDocument. The only difference is the extra level of Elements. * Consider what would happen if you deleted two characters at Offset 1 - * from Figure 10, above. Since the the second Element of Paragraph 1 is + * from Figure 10, above. Since the second Element of Paragraph 1 is * completely contained in the deleted region, it would be removed. * Assuming the attributes of Paragraph 1's first child matched those of * Paragraph2's first child, the results would be those shown in Figure 11. diff --git a/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java b/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java index 425588d6693..684ac9e2538 100644 --- a/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java +++ b/test/jdk/java/awt/Multiscreen/DeviceIdentificationTest/DeviceIdentificationTest.java @@ -24,7 +24,7 @@ * @test * @bug 6614214 8198613 * @summary Verifies that we enter the fs mode on the correct screen. - * Here is how to test: start the test on on a multi-screen system. + * Here is how to test: start the test on a multi-screen system. * Verify that the display is correctly tracked by dragging the frame back * and forth between screens. Then verify that the correct device enters * the full-screen mode - when "Enter FS mode" is pressed it should enter on diff --git a/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java b/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java index 015d46f03b2..bd1ea752edb 100644 --- a/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java +++ b/test/jdk/java/awt/datatransfer/HTMLDataFlavors/ManualHTMLDataFlavorTest.java @@ -121,7 +121,7 @@ public void init() { "6) The output should contain data in three different formats", " provided by the system clipboard", " - Data after the \"ALL:\" marker should include the data", - " from the the \"SELECTION:\" marker", + " from the \"SELECTION:\" marker", " - Data after the \"FRAGMENT\" marker should include the data", " from the \"SELECTION:\" marker and may be some closing", " tags could be added to the mark-up", diff --git a/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java b/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java index 7cb9a2bd3ff..2515e11e9ec 100644 --- a/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java +++ b/test/jdk/java/awt/print/PrinterJob/PageFormatChange.java @@ -34,7 +34,7 @@ public class PageFormatChange { static String[] text = { - "This is is a manual test intended to be run on Windows, and you", + "This is a manual test intended to be run on Windows, and you", "must have at least two printers installed, and ideally the second", "printer should support large paper sizes. When the pageDialog appears", "first change printers, then choose a large paper size, then OK", diff --git a/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh b/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh index feafda7bf25..0e66b03d3d3 100644 --- a/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh +++ b/test/jdk/javax/imageio/stream/DeleteOnExitTest.sh @@ -22,7 +22,7 @@ # @test # @bug 6291034 # @run shell DeleteOnExitTest.sh -# @summary Verify that temporary imageio files files are deleted on VM exit. +# @summary Verify that temporary imageio files are deleted on VM exit. if [ -z "${TESTSRC}" ]; then echo "TESTSRC undefined: defaulting to ." diff --git a/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java b/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java index ab17680cefc..bdf3368f5b0 100644 --- a/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java +++ b/test/jdk/javax/print/attribute/ServiceDlgPageRangeTest.java @@ -99,7 +99,7 @@ public static void main(java.lang.String[] args) throws Exception { } catch (InterruptedException e) { if (!testPassed && testGeneratedInterrupt) { throw new RuntimeException("PageRanges option is not disabled " - + "for for Non serv-formatted flvrs"); + + "for Non serv-formatted flvrs"); } } if (!testGeneratedInterrupt) { diff --git a/test/jdk/javax/sound/midi/Sequencer/SequencerState.java b/test/jdk/javax/sound/midi/Sequencer/SequencerState.java index 01b49e2e471..01b1c6a45d8 100644 --- a/test/jdk/javax/sound/midi/Sequencer/SequencerState.java +++ b/test/jdk/javax/sound/midi/Sequencer/SequencerState.java @@ -55,7 +55,7 @@ private static boolean hasSequencer() { public static void main(String[] args) throws Exception { - out("4913027: several Sequencer methods should should specify behaviour on closed Sequencer"); + out("4913027: several Sequencer methods should specify behaviour on closed Sequencer"); if (hasSequencer()) { boolean passed = testAll(); if (passed) { diff --git a/test/jdk/javax/swing/JColorChooser/Test4193384.java b/test/jdk/javax/swing/JColorChooser/Test4193384.java index 826e9893696..b32006e905c 100644 --- a/test/jdk/javax/swing/JColorChooser/Test4193384.java +++ b/test/jdk/javax/swing/JColorChooser/Test4193384.java @@ -51,7 +51,7 @@ private static void test(Color[] colors) { float[] hsb = new float[3]; for (int i = 0; i < colors.length; i++) { Color color = colors[i]; - // Make sure sure that there wasn't a regression + // Make sure that there wasn't a regression // in java.awt.Color and the conversion methods Color.RGBtoHSB(color.getRed(), color.getGreen(), color.getBlue(), hsb); if (!color.equals(Color.getHSBColor(hsb[0], hsb[1], hsb[2]))) { diff --git a/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java b/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java index b769c6d8268..4cc16e53e71 100644 --- a/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/EditorPaneDemoTest.java @@ -52,7 +52,7 @@ /* * @test * @key headful screenshots - * @summary Verifies SwingSet3 EditorPaneDemo by navigating and and validating + * @summary Verifies SwingSet3 EditorPaneDemo by navigating and validating * the page contents in all pages * * @library /sanity/client/lib/jemmy/src diff --git a/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java b/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java index 6b7b270173f..0e80df72a63 100644 --- a/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java +++ b/test/jdk/sanity/client/SwingSet/src/TabbedPaneDemoTest.java @@ -39,7 +39,7 @@ * @test * @key headful * @summary Verifies SwingSet3 TabbedPaneDemo by iterating through tab placement - * positions, opening each tab and verifying the the tab gets selected. + * positions, opening each tab and verifying the tab gets selected. * * @library /sanity/client/lib/jemmy/src * @library /sanity/client/lib/Extensions/src diff --git a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties index 77c6f82fc1e..3d584efb05a 100644 --- a/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties +++ b/test/jdk/sanity/client/lib/SwingSet3/src/com/sun/swingset3/demos/tree/resources/TreeDemo.properties @@ -1,6 +1,6 @@ ### Tree Demo ### -TreeDemo.accessible_description=This demo shows shows a sample usage of a JTree component. +TreeDemo.accessible_description=This demo shows a sample usage of a JTree component. TreeDemo.tooltip=JTree demo TreeDemo.name=Tree Demo TreeDemo.music=Music diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java index c7b27be0895..0e2c6866fd0 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/WindowWaiter.java @@ -286,7 +286,7 @@ public Window waitWindow(Window o, ComponentChooser ch) } /** - * Wait till the count of windows which meet the the search criteria becomes + * Wait till the count of windows which meet the search criteria becomes * equal to count. * * @param ch a component chooser used to define and apply the search @@ -300,7 +300,7 @@ public static void waitWindowCount(ComponentChooser ch, int count) } /** - * Wait till the count of windows which meet the the search criteria becomes + * Wait till the count of windows which meet the search criteria becomes * equal to count. * * @param owner The owner window of all the windows to be checked diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java index 99a076b7b4d..4575c4dbe98 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/ComponentOperator.java @@ -252,7 +252,7 @@ public ComponentOperator(ContainerOperator cont, int index) { /** * Constructor. Waits for a component in a container to show. The component - * is is the first {@code java.awt.Component} that shows and that lies + * is the first {@code java.awt.Component} that shows and that lies * below the container in the display containment hierarchy. Uses cont's * timeout and output for waiting and to init operator. * diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java index e97862832e2..29d7c238b79 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/JTreeOperator.java @@ -66,7 +66,7 @@ *

    Timeouts used:
    * JTreeOperator.WaitNodeExpandedTimeout - time to wait node expanded
    * JTreeOperator.WaitNodeCollapsedTimeout - time to wait node collapsed
    - * JTreeOperator.WaitAfterNodeExpandedTimeout - time to to sleep after node + * JTreeOperator.WaitAfterNodeExpandedTimeout - time to sleep after node * expanded
    * JTreeOperator.WaitNextNodeTimeout - time to wait next node displayed
    * JTreeOperator.WaitNodeVisibleTimeout - time to wait node visible
    diff --git a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java index 840362b73bd..e29bf9b116b 100644 --- a/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java +++ b/test/jdk/sanity/client/lib/jemmy/src/org/netbeans/jemmy/operators/Operator.java @@ -366,7 +366,7 @@ public Timeouts getTimeouts() { } /** - * Returns component visualizer. Visualizer is used from from + * Returns component visualizer. Visualizer is used from * makeComponentVisible() method. * * @return a visualizer assigned to this operator. @@ -378,7 +378,7 @@ public ComponentVisualizer getVisualizer() { } /** - * Changes component visualizer. Visualizer is used from from + * Changes component visualizer. Visualizer is used from * makeComponentVisible() method. * * @param vo a visualizer to assign to this operator. @@ -1080,7 +1080,7 @@ public String map() { } /** - * Interface used to make component visible & ready to to make operations + * Interface used to make component visible & ready to make operations * with. */ public interface ComponentVisualizer { diff --git a/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java b/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java index 9e0194b4985..9c5cf3de2e3 100644 --- a/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java +++ b/test/jdk/sun/java2d/pipe/hw/RSLAPITest/RSLAPITest.java @@ -75,7 +75,7 @@ private static void testInvalidType(AccelSurface surface, int type) { if (ret != 0l) { System.err.printf( "FAILED: surface.getNativeResource(%d) returned" + - " 0x%s. It should have have returned 0L\n", + " 0x%s. It should have returned 0L\n", type, ret); failed = true; } From c47e64e4f3be80f434dd4dea9b6e8d282b2c2b32 Mon Sep 17 00:00:00 2001 From: Stefan Johansson Date: Fri, 16 Dec 2022 08:06:09 +0000 Subject: [PATCH 241/494] 8297979: ZGC: Ensure consistent MemoryUsage from MemoryMXBean.getHeapMemoryUsage() Reviewed-by: stefank, ayang --- src/hotspot/share/gc/z/zCollectedHeap.cpp | 4 +++ src/hotspot/share/gc/z/zCollectedHeap.hpp | 2 ++ test/hotspot/jtreg/ProblemList-zgc.txt | 37 ----------------------- 3 files changed, 6 insertions(+), 37 deletions(-) diff --git a/src/hotspot/share/gc/z/zCollectedHeap.cpp b/src/hotspot/share/gc/z/zCollectedHeap.cpp index 0d333626ea0..5abc6ccf580 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.cpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.cpp @@ -224,6 +224,10 @@ bool ZCollectedHeap::uses_stack_watermark_barrier() const { return true; } +MemoryUsage ZCollectedHeap::memory_usage() { + return _heap.serviceability_memory_pool()->get_memory_usage(); +} + GrowableArray ZCollectedHeap::memory_managers() { GrowableArray memory_managers(2); memory_managers.append(_heap.serviceability_cycle_memory_manager()); diff --git a/src/hotspot/share/gc/z/zCollectedHeap.hpp b/src/hotspot/share/gc/z/zCollectedHeap.hpp index d1d14576e0b..37f41282c94 100644 --- a/src/hotspot/share/gc/z/zCollectedHeap.hpp +++ b/src/hotspot/share/gc/z/zCollectedHeap.hpp @@ -31,6 +31,7 @@ #include "gc/z/zInitialize.hpp" #include "gc/z/zRuntimeWorkers.hpp" #include "memory/metaspace.hpp" +#include "services/memoryUsage.hpp" class ZDirector; class ZDriver; @@ -90,6 +91,7 @@ class ZCollectedHeap : public CollectedHeap { virtual bool uses_stack_watermark_barrier() const; + virtual MemoryUsage memory_usage(); virtual GrowableArray memory_managers(); virtual GrowableArray memory_pools(); diff --git a/test/hotspot/jtreg/ProblemList-zgc.txt b/test/hotspot/jtreg/ProblemList-zgc.txt index 5735d6c51fe..815ed5bed84 100644 --- a/test/hotspot/jtreg/ProblemList-zgc.txt +++ b/test/hotspot/jtreg/ProblemList-zgc.txt @@ -47,43 +47,6 @@ serviceability/sa/ClhsdbPstack.java#core 8248912 generic- vmTestbase/gc/gctests/MemoryEaterMT/MemoryEaterMT.java 8289582 windows-x64 -vmTestbase/nsk/monitoring/stress/lowmem/lowmem001/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem002/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem003/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem004/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem005/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem006/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem007/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem008/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem009/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem010/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem011/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem012/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem013/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem014/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem015/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem016/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem017/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem018/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem019/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem020/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem021/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem022/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem023/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem024/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem025/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem026/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem027/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem028/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem029/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem030/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem031/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem032/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem033/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem034/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem035/TestDescription.java 8297979 generic-all -vmTestbase/nsk/monitoring/stress/lowmem/lowmem036/TestDescription.java 8297979 generic-all - vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter001/TestDescription.java 8298059 generic-x64 vmTestbase/nsk/jdi/ExceptionRequest/addInstanceFilter/instancefilter004/TestDescription.java 8298059 generic-x64 vmTestbase/nsk/monitoring/MemoryPoolMBean/isCollectionUsageThresholdExceeded/isexceeded002/TestDescription.java 8298302 generic-all From 226e579c3004a37a09f3329a8ef09c0933126bd6 Mon Sep 17 00:00:00 2001 From: Fei Yang Date: Fri, 16 Dec 2022 08:45:52 +0000 Subject: [PATCH 242/494] 8298088: RISC-V: Make Address a discriminated union internally Reviewed-by: fjiang, yadongwang, shade --- src/hotspot/cpu/riscv/assembler_riscv.cpp | 45 +++++--- src/hotspot/cpu/riscv/assembler_riscv.hpp | 134 ++++++++++++++++------ 2 files changed, 130 insertions(+), 49 deletions(-) diff --git a/src/hotspot/cpu/riscv/assembler_riscv.cpp b/src/hotspot/cpu/riscv/assembler_riscv.cpp index 2fb75c802cf..6a581a4d081 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.cpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.cpp @@ -40,8 +40,20 @@ int AbstractAssembler::code_fill_byte() { return 0; } -Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _offset(0), _mode(literal) { - _target = target; +#ifdef ASSERT + +void Address::assert_is_literal() const { + assert(_mode == literal, "addressing mode is non-literal: %d", _mode); +} + +void Address::assert_is_nonliteral() const { + assert(_mode != literal, "unexpected literal addressing mode"); + assert(_mode != no_mode, "unexpected no_mode addressing mode"); +} + +#endif // ASSERT + +static RelocationHolder address_relocation(address target, relocInfo::relocType rtype) { switch (rtype) { case relocInfo::oop_type: case relocInfo::metadata_type: @@ -49,30 +61,29 @@ Address::Address(address target, relocInfo::relocType rtype) : _base(noreg), _of // but in cases like icBuffer they are literals in the code stream that // we don't have a section for. We use none so that we get a literal address // which is always patchable. - break; + return RelocationHolder::none; case relocInfo::external_word_type: - _rspec = external_word_Relocation::spec(target); - break; + return external_word_Relocation::spec(target); case relocInfo::internal_word_type: - _rspec = internal_word_Relocation::spec(target); - break; + return internal_word_Relocation::spec(target); case relocInfo::opt_virtual_call_type: - _rspec = opt_virtual_call_Relocation::spec(); - break; + return opt_virtual_call_Relocation::spec(); case relocInfo::static_call_type: - _rspec = static_call_Relocation::spec(); - break; + return static_call_Relocation::spec(); case relocInfo::runtime_call_type: - _rspec = runtime_call_Relocation::spec(); - break; + return runtime_call_Relocation::spec(); case relocInfo::poll_type: case relocInfo::poll_return_type: - _rspec = Relocation::spec_simple(rtype); - break; + return Relocation::spec_simple(rtype); case relocInfo::none: - _rspec = RelocationHolder::none; - break; + return RelocationHolder::none; default: ShouldNotReachHere(); + return RelocationHolder::none; } } + +Address::Address(address target, relocInfo::relocType rtype) : + _mode(literal), + _literal(target, address_relocation(target, rtype)) +{} diff --git a/src/hotspot/cpu/riscv/assembler_riscv.hpp b/src/hotspot/cpu/riscv/assembler_riscv.hpp index debc809d5ae..62a81bd1551 100644 --- a/src/hotspot/cpu/riscv/assembler_riscv.hpp +++ b/src/hotspot/cpu/riscv/assembler_riscv.hpp @@ -30,6 +30,10 @@ #include "asm/register.hpp" #include "assembler_riscv.inline.hpp" #include "metaprogramming/enableIf.hpp" +#include "utilities/debug.hpp" +#include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" +#include #define XLEN 64 @@ -153,62 +157,128 @@ const FloatRegister g_FPArgReg[Argument::n_float_register_parameters_c] = { class Address { public: - enum mode { no_mode, base_plus_offset, pcrel, literal }; + enum mode { no_mode, base_plus_offset, literal }; private: - Register _base; - Register _index; - int64_t _offset; - enum mode _mode; + struct Nonliteral { + Nonliteral(Register base, Register index, int64_t offset) + : _base(base), _index(index), _offset(offset) {} + Register _base; + Register _index; + int64_t _offset; + }; + + struct Literal { + Literal(address target, const RelocationHolder& rspec) + : _target(target), _rspec(rspec) {} + // If the target is far we'll need to load the ea of this to a + // register to reach it. Otherwise if near we can do PC-relative + // addressing. + address _target; + + RelocationHolder _rspec; + }; + + void assert_is_nonliteral() const NOT_DEBUG_RETURN; + void assert_is_literal() const NOT_DEBUG_RETURN; - RelocationHolder _rspec; + // Discriminated union, based on _mode. + // - no_mode: uses dummy _nonliteral, for ease of copying. + // - literal: only _literal is used. + // - others: only _nonliteral is used. + enum mode _mode; + union { + Nonliteral _nonliteral; + Literal _literal; + }; - // If the target is far we'll need to load the ea of this to a - // register to reach it. Otherwise if near we can do PC-relative - // addressing. - address _target; + // Helper for copy constructor and assignment operator. + // Copy mode-relevant part of a into this. + void copy_data(const Address& a) { + assert(_mode == a._mode, "precondition"); + if (_mode == literal) { + new (&_literal) Literal(a._literal); + } else { + // non-literal mode or no_mode. + new (&_nonliteral) Nonliteral(a._nonliteral); + } + } public: - Address() - : _base(noreg), _index(noreg), _offset(0), _mode(no_mode), _target(NULL) { } + // no_mode initializes _nonliteral for ease of copying. + Address() : + _mode(no_mode), + _nonliteral(noreg, noreg, 0) + {} - Address(Register r) - : _base(r), _index(noreg), _offset(0), _mode(base_plus_offset), _target(NULL) { } + Address(Register r) : + _mode(base_plus_offset), + _nonliteral(r, noreg, 0) + {} template::value)> - Address(Register r, T o) - : _base(r), _index(noreg), _offset(o), _mode(base_plus_offset), _target(NULL) {} + Address(Register r, T o) : + _mode(base_plus_offset), + _nonliteral(r, noreg, o) + {} - Address(Register r, ByteSize disp) - : Address(r, in_bytes(disp)) {} + Address(Register r, ByteSize disp) : Address(r, in_bytes(disp)) {} - Address(address target, RelocationHolder const& rspec) - : _base(noreg), - _index(noreg), - _offset(0), - _mode(literal), - _rspec(rspec), - _target(target) { } + Address(address target, const RelocationHolder& rspec) : + _mode(literal), + _literal(target, rspec) + {} Address(address target, relocInfo::relocType rtype = relocInfo::external_word_type); + Address(const Address& a) : _mode(a._mode) { copy_data(a); } + + // Verify the value is trivially destructible regardless of mode, so our + // destructor can also be trivial, and so our assignment operator doesn't + // need to destruct the old value before copying over it. + static_assert(std::is_trivially_destructible::value, "must be"); + static_assert(std::is_trivially_destructible::value, "must be"); + + Address& operator=(const Address& a) { + _mode = a._mode; + copy_data(a); + return *this; + } + + ~Address() = default; + const Register base() const { - guarantee((_mode == base_plus_offset | _mode == pcrel | _mode == literal), "wrong mode"); - return _base; + assert_is_nonliteral(); + return _nonliteral._base; } + long offset() const { - return _offset; + assert_is_nonliteral(); + return _nonliteral._offset; } + Register index() const { - return _index; + assert_is_nonliteral(); + return _nonliteral._index; } + mode getMode() const { return _mode; } - bool uses(Register reg) const { return _base == reg; } - const address target() const { return _target; } - const RelocationHolder& rspec() const { return _rspec; } + bool uses(Register reg) const { + return base() == reg; + } + + const address target() const { + assert_is_literal(); + return _literal._target; + } + + const RelocationHolder& rspec() const { + assert_is_literal(); + return _literal._rspec; + } }; // Convenience classes From 0ba473489151d74c8a15b75ff4964ac480fecb28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Markus=20Gr=C3=B6nlund?= Date: Fri, 16 Dec 2022 10:46:37 +0000 Subject: [PATCH 243/494] 8287699: jdk/jfr/api/consumer/TestRecordingFileWrite.java fails with exception: java.lang.Exception: Found event that should not be there. Reviewed-by: egahlin --- src/hotspot/share/jfr/support/jfrThreadLocal.cpp | 3 +++ test/jdk/ProblemList.txt | 1 - 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp index 19bbe25798c..ff4d255fc98 100644 --- a/src/hotspot/share/jfr/support/jfrThreadLocal.cpp +++ b/src/hotspot/share/jfr/support/jfrThreadLocal.cpp @@ -208,6 +208,9 @@ void JfrThreadLocal::on_exit(Thread* t) { assert(t != NULL, "invariant"); JfrThreadLocal * const tl = t->jfr_thread_local(); assert(!tl->is_dead(), "invariant"); + if (JfrRecorder::is_recording()) { + JfrCheckpointManager::write_checkpoint(t); + } if (t->is_Java_thread()) { JavaThread* const jt = JavaThread::cast(t); send_java_thread_end_event(jt, JfrThreadLocal::jvm_thread_id(jt)); diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index 17bad35da71..977c7da4b28 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -755,7 +755,6 @@ jdk/jfr/startupargs/TestStartName.java 8214685 windows- jdk/jfr/startupargs/TestStartDuration.java 8214685 windows-x64 jdk/jfr/jvm/TestWaste.java 8282427 generic-all jdk/jfr/api/consumer/recordingstream/TestOnEvent.java 8255404 linux-x64 -jdk/jfr/api/consumer/TestRecordingFileWrite.java 8287699 generic-all ############################################################################ From f771c56e16a39724712ca0d8c2dd55b9ce260f4d Mon Sep 17 00:00:00 2001 From: Maurizio Cimadamore Date: Fri, 16 Dec 2022 10:49:22 +0000 Subject: [PATCH 244/494] 8298797: Specification of some restricted methods is incorrect Reviewed-by: jvernee, pminborg --- .../share/classes/java/lang/foreign/Linker.java | 4 +--- .../java/lang/foreign/MemorySegment.java | 17 +++++++---------- .../classes/java/lang/foreign/SymbolLookup.java | 8 ++------ .../share/classes/java/lang/foreign/VaList.java | 4 +--- .../classes/java/lang/foreign/ValueLayout.java | 1 + .../handle/lookup/MethodHandleLookup.java | 8 +++++++- 6 files changed, 19 insertions(+), 23 deletions(-) diff --git a/src/java.base/share/classes/java/lang/foreign/Linker.java b/src/java.base/share/classes/java/lang/foreign/Linker.java index 4789292de03..6e83806a038 100644 --- a/src/java.base/share/classes/java/lang/foreign/Linker.java +++ b/src/java.base/share/classes/java/lang/foreign/Linker.java @@ -180,9 +180,7 @@ public sealed interface Linker permits AbstractLinker { * * @return a linker for the ABI associated with the OS and processor where the Java runtime is currently executing. * @throws UnsupportedOperationException if the underlying native platform is not supported. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static Linker nativeLinker() { diff --git a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java index 76c2de64242..a1da55b8c0e 100644 --- a/src/java.base/share/classes/java/lang/foreign/MemorySegment.java +++ b/src/java.base/share/classes/java/lang/foreign/MemorySegment.java @@ -1065,9 +1065,7 @@ static MemorySegment ofAddress(long address) { * @param byteSize the size (in bytes) of the returned native segment. * @return a zero-length native segment with the given address and size. * @throws IllegalArgumentException if {@code byteSize < 0}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static MemorySegment ofAddress(long address, long byteSize) { @@ -1088,7 +1086,10 @@ static MemorySegment ofAddress(long address, long byteSize) { * {@snippet lang = java: * ofAddress(address, byteSize, scope, null); *} - * + * This method is restricted. + * Restricted methods are unsafe, and, if used incorrectly, their use might crash + * the JVM or, worse, silently result in memory corruption. Thus, clients should refrain from depending on + * restricted methods, and use safe and supported functionalities, where possible. * @param address the returned segment's address. * @param byteSize the desired size. * @param scope the scope associated with the returned native segment. @@ -1097,9 +1098,7 @@ static MemorySegment ofAddress(long address, long byteSize) { * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive @ForceInline @@ -1140,9 +1139,7 @@ static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope) * @throws IllegalStateException if {@code scope} is not {@linkplain SegmentScope#isAlive() alive}. * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static MemorySegment ofAddress(long address, long byteSize, SegmentScope scope, Runnable cleanupAction) { diff --git a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java index 50575f6b106..b2c5711922a 100644 --- a/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java +++ b/src/java.base/share/classes/java/lang/foreign/SymbolLookup.java @@ -189,9 +189,7 @@ static SymbolLookup loaderLookup() { * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given name. * @throws IllegalArgumentException if {@code name} does not identify a valid library. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static SymbolLookup libraryLookup(String name, SegmentScope scope) { @@ -215,9 +213,7 @@ static SymbolLookup libraryLookup(String name, SegmentScope scope) { * @param scope the scope associated with symbols obtained from the returned lookup. * @return a new symbol lookup suitable to find symbols in a library with the given path. * @throws IllegalArgumentException if {@code path} does not point to a valid library. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is either absent, or does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static SymbolLookup libraryLookup(Path path, SegmentScope scope) { diff --git a/src/java.base/share/classes/java/lang/foreign/VaList.java b/src/java.base/share/classes/java/lang/foreign/VaList.java index 0f6dd9fef47..4d8fab97575 100644 --- a/src/java.base/share/classes/java/lang/foreign/VaList.java +++ b/src/java.base/share/classes/java/lang/foreign/VaList.java @@ -247,9 +247,7 @@ public sealed interface VaList permits WinVaList, SysVVaList, LinuxAArch64VaList * @throws WrongThreadException if this method is called from a thread {@code T}, * such that {@code scope.isAccessibleBy(T) == false}. * @throws UnsupportedOperationException if the underlying native platform is not supported. - * @throws IllegalCallerException if access to this method occurs from a module {@code M} and the command line option - * {@code --enable-native-access} is specified, but does not mention the module name {@code M}, or - * {@code ALL-UNNAMED} in case {@code M} is an unnamed module. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. */ @CallerSensitive static VaList ofAddress(long address, SegmentScope scope) { diff --git a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java index f9a62419598..9ff1f08d7b9 100644 --- a/src/java.base/share/classes/java/lang/foreign/ValueLayout.java +++ b/src/java.base/share/classes/java/lang/foreign/ValueLayout.java @@ -424,6 +424,7 @@ sealed interface OfAddress extends ValueLayout permits ValueLayouts.OfAddressImp * restricted methods, and use safe and supported functionalities, where possible. * * @return an unbounded address layout with same characteristics as this layout. + * @throws IllegalCallerException If the caller is in a module that does not have native access enabled. * @see #isUnbounded() */ @CallerSensitive diff --git a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java index 6bd7121c651..62014baf8af 100644 --- a/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java +++ b/test/jdk/java/foreign/handles/lookup_module/handle/lookup/MethodHandleLookup.java @@ -50,9 +50,15 @@ static Object[][] restrictedMethods() { return new Object[][]{ { MethodHandles.lookup().findStatic(Linker.class, "nativeLinker", MethodType.methodType(Linker.class)), "Linker::nativeLinker" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class)), + "MemorySegment::ofAddress/2" }, { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class)), - "MemorySegment::ofAddressNative" }, + "MemorySegment::ofAddress/3" }, + { MethodHandles.lookup().findStatic(MemorySegment.class, "ofAddress", + MethodType.methodType(MemorySegment.class, long.class, long.class, SegmentScope.class, Runnable.class)), + "MemorySegment::ofAddress/4" }, { MethodHandles.lookup().findStatic(SymbolLookup.class, "libraryLookup", MethodType.methodType(SymbolLookup.class, String.class, SegmentScope.class)), "SymbolLookup::libraryLookup(String)" }, From 909d0cb4d9475fd367b8bc64a6b50c5a324e9a01 Mon Sep 17 00:00:00 2001 From: Michal Karm Babacek Date: Fri, 16 Dec 2022 12:28:39 +0000 Subject: [PATCH 245/494] 8298588: WebSockets: HandshakeUrlEncodingTest unnecessarily depends on a response body Reviewed-by: dfuchs --- .../websocket/HandshakeUrlEncodingTest.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java index e83381c17e3..969ab72be55 100644 --- a/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java +++ b/test/jdk/java/net/httpclient/websocket/HandshakeUrlEncodingTest.java @@ -112,21 +112,22 @@ public void test(String uri, boolean sameClient) { .join(); fail("Expected to throw"); } catch (CompletionException ce) { - Throwable t = getCompletionCause(ce); + final Throwable t = getCompletionCause(ce); if (!(t instanceof WebSocketHandshakeException)) { throw new AssertionError("Unexpected exception", t); } - WebSocketHandshakeException wse = (WebSocketHandshakeException) t; + final WebSocketHandshakeException wse = (WebSocketHandshakeException) t; assertNotNull(wse.getResponse()); - assertNotNull(wse.getResponse().body()); - assertEquals(wse.getResponse().body().getClass(), String.class); - String body = (String)wse.getResponse().body(); - String expectedBody = "/?&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; - assertEquals(body, expectedBody); - out.println("Status code is " + wse.getResponse().statusCode()); - out.println("Response is " + body); + assertNotNull(wse.getResponse().uri()); assertNotNull(wse.getResponse().statusCode()); + final String rawQuery = wse.getResponse().uri().getRawQuery(); + final String expectedRawQuery = "&raw=abc+def/ghi=xyz&encoded=abc%2Bdef%2Fghi%3Dxyz"; + assertEquals(rawQuery, expectedRawQuery); + final String body = (String) wse.getResponse().body(); + final String expectedBody = "/?" + expectedRawQuery; + assertEquals(body, expectedBody); out.println("Status code is " + wse.getResponse().statusCode()); + out.println("Response is " + wse.getResponse()); assertEquals(wse.getResponse().statusCode(), 400); } } From ac2fcf3f7598caf8384282ec1178ec0b66c8408a Mon Sep 17 00:00:00 2001 From: Ivan Walulya Date: Fri, 16 Dec 2022 12:59:44 +0000 Subject: [PATCH 246/494] 8296374: Check for young region in G1BarrierSet::invalidate instead of card-by-card check Reviewed-by: ayang, tschatzl --- src/hotspot/share/gc/g1/g1BarrierSet.cpp | 36 ++++++++++++++---------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/src/hotspot/share/gc/g1/g1BarrierSet.cpp b/src/hotspot/share/gc/g1/g1BarrierSet.cpp index 0e441ba0868..5032cb99bf4 100644 --- a/src/hotspot/share/gc/g1/g1BarrierSet.cpp +++ b/src/hotspot/share/gc/g1/g1BarrierSet.cpp @@ -107,22 +107,28 @@ void G1BarrierSet::invalidate(MemRegion mr) { } volatile CardValue* byte = _card_table->byte_for(mr.start()); CardValue* last_byte = _card_table->byte_for(mr.last()); - // skip initial young cards - for (; byte <= last_byte && *byte == G1CardTable::g1_young_card_val(); byte++); - if (byte <= last_byte) { - OrderAccess::storeload(); - // Enqueue if necessary. - Thread* thr = Thread::current(); - G1DirtyCardQueueSet& qset = G1BarrierSet::dirty_card_queue_set(); - G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thr); - for (; byte <= last_byte; byte++) { - CardValue bv = *byte; - if ((bv != G1CardTable::g1_young_card_val()) && - (bv != G1CardTable::dirty_card_val())) { - *byte = G1CardTable::dirty_card_val(); - qset.enqueue(queue, byte); - } + // skip young gen cards + if (*byte == G1CardTable::g1_young_card_val()) { + // MemRegion should not span multiple regions for the young gen. + DEBUG_ONLY(HeapRegion* containing_hr = G1CollectedHeap::heap()->heap_region_containing(mr.start());) + assert(containing_hr->is_young(), "it should be young"); + assert(containing_hr->is_in(mr.start()), "it should contain start"); + assert(containing_hr->is_in(mr.last()), "it should also contain last"); + return; + } + + OrderAccess::storeload(); + // Enqueue if necessary. + Thread* thr = Thread::current(); + G1DirtyCardQueueSet& qset = G1BarrierSet::dirty_card_queue_set(); + G1DirtyCardQueue& queue = G1ThreadLocalData::dirty_card_queue(thr); + for (; byte <= last_byte; byte++) { + CardValue bv = *byte; + assert(bv != G1CardTable::g1_young_card_val(), "Invalid card"); + if (bv != G1CardTable::dirty_card_val()) { + *byte = G1CardTable::dirty_card_val(); + qset.enqueue(queue, byte); } } } From f4caaca100d334b671eed56287dfe7a1009c47d7 Mon Sep 17 00:00:00 2001 From: Justin King Date: Fri, 16 Dec 2022 14:00:56 +0000 Subject: [PATCH 247/494] 8298852: Use of uninitialized memory in MetadataFactory::free_metadata Reviewed-by: coleenp, stefank, dholmes --- src/hotspot/share/memory/metadataFactory.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/metadataFactory.hpp b/src/hotspot/share/memory/metadataFactory.hpp index 4f9f7490e11..84fdc6acf8a 100644 --- a/src/hotspot/share/memory/metadataFactory.hpp +++ b/src/hotspot/share/memory/metadataFactory.hpp @@ -70,6 +70,7 @@ class MetadataFactory : AllStatic { assert(!md->on_stack(), "can't deallocate things on stack"); assert(!md->is_shared(), "cannot deallocate if in shared spaces"); md->deallocate_contents(loader_data); + bool is_klass = md->is_klass(); // Call the destructor. This is currently used for MethodData which has a member // that needs to be destructed to release resources. Most Metadata derived classes have noop // destructors and/or cleanup using deallocate_contents. @@ -77,7 +78,7 @@ class MetadataFactory : AllStatic { // or volatile so we can call the destructor of the type T points to. using U = std::remove_cv_t; md->~U(); - loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass()); + loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, is_klass); } } }; From b14794db00ded878dbfc7080f9d57a0f65c02dee Mon Sep 17 00:00:00 2001 From: Coleen Phillimore Date: Fri, 16 Dec 2022 14:09:55 +0000 Subject: [PATCH 248/494] 8298852: Use of uninitialized memory in MetadataFactory::free_metadata Backport-of: f4caaca100d334b671eed56287dfe7a1009c47d7 --- src/hotspot/share/memory/metadataFactory.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/hotspot/share/memory/metadataFactory.hpp b/src/hotspot/share/memory/metadataFactory.hpp index 4f9f7490e11..84fdc6acf8a 100644 --- a/src/hotspot/share/memory/metadataFactory.hpp +++ b/src/hotspot/share/memory/metadataFactory.hpp @@ -70,6 +70,7 @@ class MetadataFactory : AllStatic { assert(!md->on_stack(), "can't deallocate things on stack"); assert(!md->is_shared(), "cannot deallocate if in shared spaces"); md->deallocate_contents(loader_data); + bool is_klass = md->is_klass(); // Call the destructor. This is currently used for MethodData which has a member // that needs to be destructed to release resources. Most Metadata derived classes have noop // destructors and/or cleanup using deallocate_contents. @@ -77,7 +78,7 @@ class MetadataFactory : AllStatic { // or volatile so we can call the destructor of the type T points to. using U = std::remove_cv_t; md->~U(); - loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, md->is_klass()); + loader_data->metaspace_non_null()->deallocate((MetaWord*)md, size, is_klass); } } }; From 9e10f00edbf37e5e5db8efc4f1e0c2a76541aab2 Mon Sep 17 00:00:00 2001 From: Tobias Hartmann Date: Fri, 16 Dec 2022 14:39:48 +0000 Subject: [PATCH 249/494] 8298919: Add a regression test for JDK-8298520 Reviewed-by: chagedorn, roland --- .../loopopts/TestUnexpectedOpaque1.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) create mode 100644 test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java diff --git a/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java b/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java new file mode 100644 index 00000000000..51c6b016f34 --- /dev/null +++ b/test/hotspot/jtreg/compiler/loopopts/TestUnexpectedOpaque1.java @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2022, 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 stress randomness + * @bug 8298520 + * @requires vm.compiler2.enabled + * @summary Dying subgraph confuses logic that tries to find the OpaqueZeroTripGuard. + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestUnexpectedOpaque1::* -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN -XX:StressSeed=1642564308 compiler.loopopts.TestUnexpectedOpaque1 + * @run main/othervm -Xcomp -XX:CompileCommand=compileonly,compiler.loopopts.TestUnexpectedOpaque1::* -XX:-TieredCompilation + * -XX:+UnlockDiagnosticVMOptions -XX:+StressIGVN compiler.loopopts.TestUnexpectedOpaque1 + */ + +package compiler.loopopts; + +public class TestUnexpectedOpaque1 { + + static int cnt = 0; + + static int test() { + int res = 42; + for (int i = 500; i > 0; --i) { + res |= 1; + if (res != 0) { + return 43; + } + cnt++; + } + return Float.floatToIntBits(44F); + } + + public static void main(String[] args) { + test(); + } +} From 81e23ab3403a983ccddf27b1169a49e2ca061296 Mon Sep 17 00:00:00 2001 From: Eric Caspole Date: Fri, 16 Dec 2022 16:30:31 +0000 Subject: [PATCH 250/494] 8298809: Clean up vm/compiler/InterfaceCalls JMH Reviewed-by: kvn --- .../bench/vm/compiler/InterfaceCalls.java | 234 +++++------------- 1 file changed, 58 insertions(+), 176 deletions(-) diff --git a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java index 59920591f67..e313b948c9f 100644 --- a/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java +++ b/test/micro/org/openjdk/bench/vm/compiler/InterfaceCalls.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2022, 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,250 +44,132 @@ @Fork(value = 3) public class InterfaceCalls { - interface AnInterface { - public int getInt(); + interface FirstInterface { + public int getIntFirst(); } interface SecondInterface { - public int get1(); + public int getIntSecond(); } - interface OnlyHasOneImplInterface { - public int getLong(); - } - - interface AloneInterface { - public int getNumber(); - } - - class SingleImplementor implements OnlyHasOneImplInterface { - public int getLong() { + class FirstClass implements FirstInterface, SecondInterface { + public int getIntFirst() { return 1; } - } - - class Extender1 extends SingleImplementor { - } - class FirstClass implements AnInterface { - public int getInt() { + public int getIntSecond() { return 1; } } - class SecondClass implements AnInterface { - public int getInt() { + class SecondClass implements FirstInterface, SecondInterface { + public int getIntFirst() { return 2; } - } - class ThirdClass implements AnInterface { - public int getInt() { - return -3; + public int getIntSecond() { + return 1; } } - class FourthClass implements AnInterface { - public int getInt() { - return -4; + class ThirdClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -3; } - } - class FifthClass implements AnInterface { - public int getInt() { - return -5; + public int getIntSecond() { + return 1; } } - class MultiClass1 implements AnInterface, SecondInterface { - public int get1() { - return 1; + class FourthClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -4; } - public int getInt() { - return 2; + public int getIntSecond() { + return 1; } } - class MultiClass2 implements AnInterface, SecondInterface { - public int get1() { - return -1; - } - - public int getInt() { - return -2; + class FifthClass implements FirstInterface, SecondInterface { + public int getIntFirst() { + return -5; } - } - class Aloner implements AloneInterface { - public int getNumber() { - return 7; + public int getIntSecond() { + return 1; } } - public Object dummy1; - - public Object dummy2; - - public Object dummy3; - - public AnInterface multi1a, multi2a; - - public SecondInterface multi1b, multi2b; - - public Object multic, multic2; - - public AnInterface[] as = new AnInterface[5]; - - public AnInterface multi; - - public OnlyHasOneImplInterface single1; + final int asLength = 5; + public FirstInterface[] as = new FirstInterface[asLength]; - public OnlyHasOneImplInterface single2; - - public AloneInterface alone; - - int count; @Setup public void setupSubclass() { - dummy1 = new FirstClass(); - dummy2 = new SecondClass(); - dummy3 = new ThirdClass(); as[0] = new FirstClass(); as[1] = new SecondClass(); as[2] = new ThirdClass(); as[3] = new FourthClass(); as[4] = new FifthClass(); - MultiClass1 mc1 = new MultiClass1(); - multi1a = mc1; - multi1b = mc1; - multic = mc1; - MultiClass2 mc2 = new MultiClass2(); - multi2a = mc2; - multi2b = mc2; - multic2 = mc2; - single1 = new SingleImplementor(); - single2 = new Extender1(); - alone = new Aloner(); - } - - private void swapMultiParts() { - AnInterface tmpa = multi1a; - SecondInterface tmpb = multi1b; - multi1a = multi2a; - multi2a = tmpa; - multi1b = multi2b; - multi2b = tmpb; - } - - @SuppressWarnings("unused") - private void swapMulti() { - Object tmp = multic; - multic = multic2; - multic2 = tmp; } /** - * Tests a call where there are multiple implementors but only one of the implementors is every used here so the - * call-site is monomorphic + * Tests a call where there are multiple implementors but only one of the + * implementors is every used here so the call-site is monomorphic */ @Benchmark public int testMonomorphic() { - return as[0].getInt(); - } - - /** Tests a interface call that only has one single implementation */ - @Benchmark - public int testSingle() { - return alone.getNumber(); + return as[0].getIntFirst(); } - /** - * Tests a call where there is a single implementation but multiple classes that inherit that implementation and both - * these implementors are used. - */ - @Benchmark - public int testSingle2() { - OnlyHasOneImplInterface oi; - if ((count & 1) == 0) { - oi = single1; - } else { - oi = single2; - } - count++; - return oi.getLong(); - } + int l = 0; /** - * Tests calling two different interface methods in two different interfaces on the same receiver. Make sure to switch - * between two different types of receivers to achieve polymorhpism + * Interface call address computation within loop but the receiver preexists + * the loop and the ac can be moved outside of the loop */ @Benchmark - public void testCall2Poly2(Blackhole bh) { - bh.consume(multi1a.getInt()); - bh.consume(multi1b.get1()); - swapMultiParts(); - } - - @Benchmark - public int testCallMulti1Poly2NoSwap() { - return multi1a.getInt(); + public int test1stInt2Types() { + FirstInterface ai = as[l]; + l = 1 - l; + return ai.getIntFirst(); } - /** - * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different - * interfaces take different amounts of time (They do for hotspot) - */ @Benchmark - public int testCallMulti1Poly2() { - swapMultiParts(); - return multi1a.getInt(); + public int test1stInt3Types() { + FirstInterface ai = as[l]; + l = ++ l % 3; + return ai.getIntFirst(); } - /** - * This test goes together with Multi2 below It tests if a class implements multiple interfaces if the different - * interfaces take different amounts of time (They do for hotspot) - */ @Benchmark - public int testCallMulti2Poly2() { - swapMultiParts(); - return multi1b.get1(); + public int test1stInt5Types() { + FirstInterface ai = as[l]; + l = ++ l % asLength; + return ai.getIntFirst(); } - /** Interface call with three different receivers */ @Benchmark - public void testCallPoly3(Blackhole bh) { - for (int kk = 0; kk < 3; kk++) { - bh.consume(as[kk].getInt()); - } + public int test2ndInt2Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = 1 - l; + return ai.getIntSecond(); } - /** Interface call with five different receivers. */ @Benchmark - public void testCallPoly5(Blackhole bh) { - for (int kk = 0; kk < 5; kk++) { - bh.consume(as[kk].getInt()); - } + public int test2ndInt3Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = ++ l % 3; + return ai.getIntSecond(); } - int l; - - /** - * Interface call address computation within loop but the receiver preexists the loop and the ac can be moved outside - * of the loop - */ @Benchmark - public int testAC1() { - AnInterface ai = as[l]; - l = 1 - l; - return ai.getInt(); + public int test2ndInt5Types() { + SecondInterface ai = (SecondInterface) as[l]; + l = ++ l % asLength; + return ai.getIntSecond(); } - /** Tests an interface cast followed by an interface call. */ - @Benchmark - public int testInterfaceCastAndCall() throws Exception { - return ((AnInterface) dummy1).getInt() + ((AnInterface) dummy2).getInt() - + ((AnInterface) dummy3).getInt(); - } } From 0eeaeb8e7ba40be5e93eb87c7e3dc94230062746 Mon Sep 17 00:00:00 2001 From: Naoto Sato Date: Fri, 16 Dec 2022 17:16:20 +0000 Subject: [PATCH 251/494] 8298808: Check `script` code on detecting the base locales Reviewed-by: joehw --- .../build/tools/cldrconverter/CLDRConverter.java | 13 +++++++++++-- .../cldrconverter/ResourceBundleGenerator.java | 2 +- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java index e0e95c9e6a2..290226e5a1d 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/CLDRConverter.java @@ -633,7 +633,7 @@ static String getLanguageCode(String id) { /** * Examine if the id includes the country (territory) code. If it does, it returns * the country code. - * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". + * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it returns "SG". * It does NOT return UN M.49 code, e.g., '001', as those three digit numbers cannot * be translated into package names. */ @@ -645,13 +645,21 @@ static String getCountryCode(String id) { /** * Examine if the id includes the region code. If it does, it returns * the region code. - * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it return "SG". + * Otherwise, it returns null. eg. when the id is "zh_Hans_SG", it returns "SG". * It DOES return UN M.49 code, e.g., '001', as well as ISO 3166 two letter country codes. */ static String getRegionCode(String id) { return Locale.forLanguageTag(id.replaceAll("_", "-")).getCountry(); } + /** + * Examine if the id includes the script code. If it does, it returns + * the script code. + */ + static String getScriptCode(String id) { + return Locale.forLanguageTag(id.replaceAll("_", "-")).getScript(); + } + private static class KeyComparator implements Comparator { static KeyComparator INSTANCE = new KeyComparator(); @@ -1020,6 +1028,7 @@ private static String toLocaleName(String tag) { private static void setupBaseLocales(String localeList) { Arrays.stream(localeList.split(",")) .map(Locale::forLanguageTag) + .map(l -> new Locale.Builder().setLocale(l).setScript("Latn").build()) .map(l -> Control.getControl(Control.FORMAT_DEFAULT) .getCandidateLocales("", l)) .forEach(BASE_LOCALES::addAll); diff --git a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java index 344bb0ea21f..6b2b5b4c0c0 100644 --- a/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java +++ b/make/jdk/src/classes/build/tools/cldrconverter/ResourceBundleGenerator.java @@ -417,11 +417,11 @@ public Map parentLocales() { private static final Locale.Builder LOCALE_BUILDER = new Locale.Builder(); private static boolean isBaseLocale(String localeID) { localeID = localeID.replaceAll("-", "_"); - // ignore script here Locale locale = LOCALE_BUILDER .clear() .setLanguage(CLDRConverter.getLanguageCode(localeID)) .setRegion(CLDRConverter.getRegionCode(localeID)) + .setScript(CLDRConverter.getScriptCode(localeID)) .build(); return CLDRConverter.BASE_LOCALES.contains(locale); } From bf9a8ce0bb975a3d50e92148f92850ef930d64b0 Mon Sep 17 00:00:00 2001 From: Matthew Donovan Date: Fri, 16 Dec 2022 17:51:57 +0000 Subject: [PATCH 252/494] 8249826: 5 javax/net/ssl/SSLEngine tests use @ignore w/o bug-id Reviewed-by: xuelei, rhalade, ssahoo --- test/jdk/ProblemList.txt | 7 +++++++ test/jdk/javax/net/ssl/SSLEngine/Basics.java | 2 -- test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java | 2 +- test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java | 1 - test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java | 2 +- .../javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java | 1 - test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java | 2 +- test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java | 3 +-- 8 files changed, 11 insertions(+), 9 deletions(-) diff --git a/test/jdk/ProblemList.txt b/test/jdk/ProblemList.txt index ab264783f71..9421e7fa52b 100644 --- a/test/jdk/ProblemList.txt +++ b/test/jdk/ProblemList.txt @@ -586,6 +586,13 @@ sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java 8161536 generic- sun/security/tools/keytool/ListKeychainStore.sh 8156889 macosx-all +javax/net/ssl/SSLEngine/TestAllSuites.java 8298874 generic-all +javax/net/ssl/SSLEngine/IllegalRecordVersion.java 8298873 generic-all +javax/net/ssl/SSLEngine/EngineCloseOnAlert.java 8298868 generic-all +javax/net/ssl/SSLEngine/ConnectionTest.java 8298869 generic-all +javax/net/ssl/SSLEngine/CheckStatus.java 8298872 generic-all +javax/net/ssl/SSLEngine/Basics.java 8298867 generic-all + sun/security/provider/KeyStore/DKSTest.sh 8180266 windows-all sun/security/smartcardio/TestChannel.java 8039280 generic-all diff --git a/test/jdk/javax/net/ssl/SSLEngine/Basics.java b/test/jdk/javax/net/ssl/SSLEngine/Basics.java index 6e38c884e06..177422cb489 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/Basics.java +++ b/test/jdk/javax/net/ssl/SSLEngine/Basics.java @@ -26,8 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon * * This is intended to test many of the basic API calls to the SSLEngine * interface. This doesn't really exercise much of the SSL code. diff --git a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java index ec3a96c2b35..69d1e07621f 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java +++ b/test/jdk/javax/net/ssl/SSLEngine/CheckStatus.java @@ -25,7 +25,7 @@ * @test * @bug 4948079 * @summary SSLEngineResult needs updating [none yet] - * @ignore the dependent implementation details are changed + * * @run main/othervm -Djsse.enableCBCProtection=false CheckStatus * * @author Brad Wetmore diff --git a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java index d6e32eff5de..a18444ccc7a 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java +++ b/test/jdk/javax/net/ssl/SSLEngine/ConnectionTest.java @@ -26,7 +26,6 @@ * @bug 4495742 * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction - * @ignore the dependent implementation details are changed * @author Brad Wetmore * * @run main/othervm ConnectionTest diff --git a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java index 8d60396fb91..1ddd9edfa59 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java +++ b/test/jdk/javax/net/ssl/SSLEngine/EngineCloseOnAlert.java @@ -26,7 +26,7 @@ * @bug 8133632 * @summary javax.net.ssl.SSLEngine does not properly handle received * SSL fatal alerts - * @ignore the dependent implementation details are changed + * * @run main/othervm EngineCloseOnAlert */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java index 475879a3262..5dc19f1475e 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java +++ b/test/jdk/javax/net/ssl/SSLEngine/IllegalHandshakeMessage.java @@ -30,7 +30,6 @@ * @test * @bug 8180643 * @summary Illegal handshake message - * @ignore the dependent implementation details are changed * @run main/othervm IllegalHandshakeMessage */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java b/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java index aeb4c50aac9..cab26528790 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java +++ b/test/jdk/javax/net/ssl/SSLEngine/IllegalRecordVersion.java @@ -28,7 +28,7 @@ * @test * @bug 8042449 * @summary Issue for negative byte major record version - * @ignore the dependent implementation details are changed + * * @run main/othervm IllegalRecordVersion */ diff --git a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java index 9c633b58f70..3285479a86c 100644 --- a/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java +++ b/test/jdk/javax/net/ssl/SSLEngine/TestAllSuites.java @@ -24,8 +24,7 @@ /* * @test * @bug 4495742 - * @ignore JSSE supported cipher suites are changed with CR 6916074, - * need to update this test case in JDK 7 soon + * * @run main/timeout=180 TestAllSuites * @summary Add non-blocking SSL/TLS functionality, usable with any * I/O abstraction From bfa921ae6ce068c53dfa708d6d3d2cddbad5fc33 Mon Sep 17 00:00:00 2001 From: Kim Barrett Date: Fri, 16 Dec 2022 20:47:40 +0000 Subject: [PATCH 253/494] 8160404: RelocationHolder constructors have bugs Reviewed-by: kvn, jrose, jvernee --- src/hotspot/cpu/x86/assembler_x86.cpp | 2 +- src/hotspot/share/code/relocInfo.cpp | 41 +++- src/hotspot/share/code/relocInfo.hpp | 271 ++++++++++++++++---------- 3 files changed, 205 insertions(+), 109 deletions(-) diff --git a/src/hotspot/cpu/x86/assembler_x86.cpp b/src/hotspot/cpu/x86/assembler_x86.cpp index 020f8739317..6446accbfac 100644 --- a/src/hotspot/cpu/x86/assembler_x86.cpp +++ b/src/hotspot/cpu/x86/assembler_x86.cpp @@ -2495,7 +2495,7 @@ void Assembler::jmp_literal(address dest, RelocationHolder const& rspec) { assert(dest != NULL, "must have a target"); intptr_t disp = dest - (pc() + sizeof(int32_t)); assert(is_simm32(disp), "must be 32bit offset (jmp)"); - emit_data(disp, rspec.reloc(), call32_operand); + emit_data(disp, rspec, call32_operand); } void Assembler::jmpb_0(Label& L, const char* file, int line) { diff --git a/src/hotspot/share/code/relocInfo.cpp b/src/hotspot/share/code/relocInfo.cpp index 65b860c9d85..3c2f0277114 100644 --- a/src/hotspot/share/code/relocInfo.cpp +++ b/src/hotspot/share/code/relocInfo.cpp @@ -36,6 +36,9 @@ #include "utilities/align.hpp" #include "utilities/copy.hpp" +#include +#include + const RelocationHolder RelocationHolder::none; // its type is relocInfo::none @@ -235,12 +238,44 @@ Relocation* RelocIterator::reloc() { APPLY_TO_RELOCATIONS(EACH_TYPE); #undef EACH_TYPE assert(t == relocInfo::none, "must be padding"); - return new(_rh) Relocation(t); + _rh = RelocationHolder::none; + return _rh.reloc(); } +// Verify all the destructors are trivial, so we don't need to worry about +// destroying old contents of a RelocationHolder being assigned or destroyed. +#define VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(Reloc) \ + static_assert(std::is_trivially_destructible::value, "must be"); -//////// Methods for flyweight Relocation types +#define VERIFY_TRIVIALLY_DESTRUCTIBLE(name) \ + VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(PASTE_TOKENS(name, _Relocation)); + +APPLY_TO_RELOCATIONS(VERIFY_TRIVIALLY_DESTRUCTIBLE) +VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX(Relocation) + +#undef VERIFY_TRIVIALLY_DESTRUCTIBLE_AUX +#undef VERIFY_TRIVIALLY_DESTRUCTIBLE + +// Define all the copy_into functions. These rely on all Relocation types +// being trivially destructible (verified above). So it doesn't matter +// whether the target holder has been previously initialized or not. There's +// no need to consider that distinction and destruct the relocation in an +// already initialized holder. +#define DEFINE_COPY_INTO_AUX(Reloc) \ + void Reloc::copy_into(RelocationHolder& holder) const { \ + copy_into_helper(*this, holder); \ + } +#define DEFINE_COPY_INTO(name) \ + DEFINE_COPY_INTO_AUX(PASTE_TOKENS(name, _Relocation)) + +APPLY_TO_RELOCATIONS(DEFINE_COPY_INTO) +DEFINE_COPY_INTO_AUX(Relocation) + +#undef DEFINE_COPY_INTO_AUX +#undef DEFINE_COPY_INTO + +//////// Methods for RelocationHolder RelocationHolder RelocationHolder::plus(int offset) const { if (offset != 0) { @@ -264,6 +299,8 @@ RelocationHolder RelocationHolder::plus(int offset) const { return (*this); } +//////// Methods for flyweight Relocation types + // some relocations can compute their own values address Relocation::value() { ShouldNotReachHere(); diff --git a/src/hotspot/share/code/relocInfo.hpp b/src/hotspot/share/code/relocInfo.hpp index c0232c79efc..fdaf5502983 100644 --- a/src/hotspot/share/code/relocInfo.hpp +++ b/src/hotspot/share/code/relocInfo.hpp @@ -28,8 +28,10 @@ #include "memory/allocation.hpp" #include "oops/oopsHierarchy.hpp" #include "runtime/osInfo.hpp" -#include "utilities/macros.hpp" #include "utilities/globalDefinitions.hpp" +#include "utilities/macros.hpp" + +#include class nmethod; class CodeBlob; @@ -471,24 +473,70 @@ inline relocInfo prefix_relocInfo(int datalen = 0) { // the holder is "one size fits all". class RelocationHolder { friend class Relocation; - friend class CodeSection; private: - // this preallocated memory must accommodate all subclasses of Relocation - // (this number is assertion-checked in Relocation::operator new) - enum { _relocbuf_size = 5 }; - void* _relocbuf[ _relocbuf_size ]; + // A Relocation is "held" by placement constructing a Relocation into + // _relocbuf. Hence, _relocbuf must accomodate all subclasses of + // Relocation. We also need the Relocation base class to be at the same + // address as the start of the object, e.g. at the address of _relocbuf. + // Both of these requirements are checked (see emplace_relocation). + // The placement of the base class subobject isn't guaranteed by C++, since + // these aren't standard layout classes, but all supported implementations + // provide that behavior. If that changes, we can instead add a Relocation* + // _reloc member to capture the result of the placement new, and use that to + // access the base subobject. + static const size_t _relocbuf_size = 5 * sizeof(void*); + alignas(void*) char _relocbuf[_relocbuf_size]; + + template + void emplace_relocation(const Args&... args) { + static_assert(std::is_base_of::value, "not Relocation"); + static_assert(sizeof(Reloc) <= sizeof(_relocbuf), "_relocbuf too small"); + Relocation* reloc = ::new (_relocbuf) Reloc(args...); + // Verify the base class subobject of the object constructed into + // _relocbuf is at the same address as the derived object. + assert(static_cast(reloc) == _relocbuf, "invariant"); + } + + // Support for Relocation::copy_into. + // reloc should be a most derived object. + template + void copy_into_impl(const Reloc& reloc) { + emplace_relocation(reloc); + } + + // Tag for selecting the constructor below and carrying the type of the + // relocation object the new holder will (initially) contain. + template struct Construct {}; + + // Constructor used by construct(). Constructs a new holder containing a + // relocation of type Reloc that is constructed using the provided args. + template + RelocationHolder(Construct, const Args&... args) { + emplace_relocation(args...); + } public: - Relocation* reloc() const { return (Relocation*) &_relocbuf[0]; } + Relocation* reloc() const { return (Relocation*)_relocbuf; } inline relocInfo::relocType type() const; // Add a constant offset to a relocation. Helper for class Address. RelocationHolder plus(int offset) const; - inline RelocationHolder(); // initializes type to none + // Return a holder containing a relocation of type Reloc, constructed using args. + template + static RelocationHolder construct(const Args&... args) { + return RelocationHolder(Construct(), args...); + } + + RelocationHolder(); // Initializes type to none. - inline RelocationHolder(Relocation* r); // make a copy + // Depends on the destructor for all relocation types being trivial + // (verified in .cpp file). + ~RelocationHolder() = default; + + RelocationHolder(const RelocationHolder& from); + RelocationHolder& operator=(const RelocationHolder& from); static const RelocationHolder none; }; @@ -636,7 +684,6 @@ class RelocIterator : public StackObj { // So, the RelocIterator unpacks relocInfos into Relocations. class Relocation { - friend class RelocationHolder; friend class RelocIterator; private: @@ -658,19 +705,18 @@ class Relocation { assert(_binding != NULL, "must now be bound"); } - Relocation(relocInfo::relocType rtype) : _binding(NULL), _rtype(rtype) { } + explicit Relocation(relocInfo::relocType rtype) : _binding(NULL), _rtype(rtype) { } - static RelocationHolder newHolder() { - return RelocationHolder(); + // Helper for copy_into functions for derived classes. + // Forwards operation to RelocationHolder::copy_into_impl so that + // RelocationHolder only needs to befriend this class, rather than all + // derived classes that implement copy_into. + template + static void copy_into_helper(const Reloc& reloc, RelocationHolder& holder) { + holder.copy_into_impl(reloc); } public: - void* operator new(size_t size, const RelocationHolder& holder) throw() { - assert(size <= sizeof(holder._relocbuf), "Make _relocbuf bigger!"); - assert((void* const *)holder.reloc() == &holder._relocbuf[0], "ptrs must agree"); - return holder.reloc(); - } - // make a generic relocation for a given type (if possible) static RelocationHolder spec_simple(relocInfo::relocType rtype); @@ -793,8 +839,20 @@ class Relocation { int format() const { return binding()->format(); } public: + // Make a filler relocation. + Relocation() : Relocation(relocInfo::none) {} + + // Intentionally public non-virtual destructor, even though polymorphic. We + // never heap allocate a Relocation, so never delete through a base pointer. + // RelocationHolder depends on the destructor for all relocation types being + // trivial, so this must not be virtual (and hence non-trivial). + ~Relocation() = default; + relocInfo::relocType type() const { return _rtype; } + // Copy this relocation into holder. + virtual void copy_into(RelocationHolder& holder) const; + // is it a call instruction? virtual bool is_call() { return false; } @@ -818,17 +876,20 @@ class Relocation { // certain inlines must be deferred until class Relocation is defined: -inline RelocationHolder::RelocationHolder() { - // initialize the vtbl, just to keep things type-safe - new(*this) Relocation(relocInfo::none); -} +inline RelocationHolder::RelocationHolder() : + RelocationHolder(Construct()) +{} +inline RelocationHolder::RelocationHolder(const RelocationHolder& from) { + from.reloc()->copy_into(*this); +} -inline RelocationHolder::RelocationHolder(Relocation* r) { - // wordwise copy from r (ok if it copies garbage after r) - for (int i = 0; i < _relocbuf_size; i++) { - _relocbuf[i] = ((void**)r)[i]; - } +inline RelocationHolder& RelocationHolder::operator=(const RelocationHolder& from) { + // All Relocation types are trivially destructible (verified in .cpp file), + // so we don't need to destruct our old value before copying over it. + // If not for that we would need to decide what to do about self-assignment. + from.reloc()->copy_into(*this); + return *this; } relocInfo::relocType RelocationHolder::type() const { @@ -876,29 +937,29 @@ class DataRelocation : public Relocation { }; class post_call_nop_Relocation : public Relocation { - friend class RelocIterator; + friend class RelocationHolder; public: post_call_nop_Relocation() : Relocation(relocInfo::post_call_nop_type) { } static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) post_call_nop_Relocation(); - return rh; + return RelocationHolder::construct(); } + + void copy_into(RelocationHolder& holder) const; }; class entry_guard_Relocation : public Relocation { - friend class RelocIterator; + friend class RelocationHolder; public: entry_guard_Relocation() : Relocation(relocInfo::entry_guard_type) { } static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) entry_guard_Relocation(); - return rh; + return RelocationHolder::construct(); } + + void copy_into(RelocationHolder& holder) const; }; // A CallRelocation always points at a call instruction. @@ -923,9 +984,7 @@ class oop_Relocation : public DataRelocation { // an oop in the CodeBlob's oop pool static RelocationHolder spec(int oop_index, int offset = 0) { assert(oop_index > 0, "must be a pool-resident oop"); - RelocationHolder rh = newHolder(); - new(rh) oop_Relocation(oop_index, offset); - return rh; + return RelocationHolder::construct(oop_index, offset); } // an oop in the instruction stream static RelocationHolder spec_for_immediate() { @@ -935,11 +994,11 @@ class oop_Relocation : public DataRelocation { "Must return true so we will search for oops as roots etc. in the code."); const int oop_index = 0; const int offset = 0; // if you want an offset, use the oop pool - RelocationHolder rh = newHolder(); - new(rh) oop_Relocation(oop_index, offset); - return rh; + return RelocationHolder::construct(oop_index, offset); } + void copy_into(RelocationHolder& holder) const; + private: jint _oop_index; // if > 0, index into CodeBlob::oop_at jint _offset; // byte offset to apply to the oop itself @@ -947,7 +1006,7 @@ class oop_Relocation : public DataRelocation { oop_Relocation(int oop_index, int offset) : DataRelocation(relocInfo::oop_type), _oop_index(oop_index), _offset(offset) { } - friend class RelocIterator; + friend class RelocationHolder; oop_Relocation() : DataRelocation(relocInfo::oop_type) {} public: @@ -980,19 +1039,17 @@ class metadata_Relocation : public DataRelocation { // an metadata in the CodeBlob's metadata pool static RelocationHolder spec(int metadata_index, int offset = 0) { assert(metadata_index > 0, "must be a pool-resident metadata"); - RelocationHolder rh = newHolder(); - new(rh) metadata_Relocation(metadata_index, offset); - return rh; + return RelocationHolder::construct(metadata_index, offset); } // an metadata in the instruction stream static RelocationHolder spec_for_immediate() { const int metadata_index = 0; const int offset = 0; // if you want an offset, use the metadata pool - RelocationHolder rh = newHolder(); - new(rh) metadata_Relocation(metadata_index, offset); - return rh; + return RelocationHolder::construct(metadata_index, offset); } + void copy_into(RelocationHolder& holder) const; + private: jint _metadata_index; // if > 0, index into nmethod::metadata_at jint _offset; // byte offset to apply to the metadata itself @@ -1000,7 +1057,7 @@ class metadata_Relocation : public DataRelocation { metadata_Relocation(int metadata_index, int offset) : DataRelocation(relocInfo::metadata_type), _metadata_index(metadata_index), _offset(offset) { } - friend class RelocIterator; + friend class RelocationHolder; metadata_Relocation() : DataRelocation(relocInfo::metadata_type) { } // Fixes a Metadata pointer in the code. Most platforms embeds the @@ -1035,11 +1092,11 @@ class virtual_call_Relocation : public CallRelocation { // The oop_limit helps find the last associated set-oop. // (See comments at the top of this file.) static RelocationHolder spec(address cached_value, jint method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) virtual_call_Relocation(cached_value, method_index); - return rh; + return RelocationHolder::construct(cached_value, method_index); } + void copy_into(RelocationHolder& holder) const; + private: address _cached_value; // location of set-value instruction jint _method_index; // resolved method for a Java call @@ -1051,7 +1108,7 @@ class virtual_call_Relocation : public CallRelocation { assert(cached_value != NULL, "first oop address must be specified"); } - friend class RelocIterator; + friend class RelocationHolder; virtual_call_Relocation() : CallRelocation(relocInfo::virtual_call_type) { } public: @@ -1074,11 +1131,11 @@ class virtual_call_Relocation : public CallRelocation { class opt_virtual_call_Relocation : public CallRelocation { public: static RelocationHolder spec(int method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) opt_virtual_call_Relocation(method_index); - return rh; + return RelocationHolder::construct(method_index); } + void copy_into(RelocationHolder& holder) const; + private: jint _method_index; // resolved method for a Java call @@ -1086,7 +1143,7 @@ class opt_virtual_call_Relocation : public CallRelocation { : CallRelocation(relocInfo::opt_virtual_call_type), _method_index(method_index) { } - friend class RelocIterator; + friend class RelocationHolder; opt_virtual_call_Relocation() : CallRelocation(relocInfo::opt_virtual_call_type) {} public: @@ -1106,11 +1163,11 @@ class opt_virtual_call_Relocation : public CallRelocation { class static_call_Relocation : public CallRelocation { public: static RelocationHolder spec(int method_index = 0) { - RelocationHolder rh = newHolder(); - new(rh) static_call_Relocation(method_index); - return rh; + return RelocationHolder::construct(method_index); } + void copy_into(RelocationHolder& holder) const; + private: jint _method_index; // resolved method for a Java call @@ -1118,7 +1175,7 @@ class static_call_Relocation : public CallRelocation { : CallRelocation(relocInfo::static_call_type), _method_index(method_index) { } - friend class RelocIterator; + friend class RelocationHolder; static_call_Relocation() : CallRelocation(relocInfo::static_call_type) {} public: @@ -1137,11 +1194,11 @@ class static_call_Relocation : public CallRelocation { class static_stub_Relocation : public Relocation { public: static RelocationHolder spec(address static_call) { - RelocationHolder rh = newHolder(); - new(rh) static_stub_Relocation(static_call); - return rh; + return RelocationHolder::construct(static_call); } + void copy_into(RelocationHolder& holder) const; + private: address _static_call; // location of corresponding static_call @@ -1149,7 +1206,7 @@ class static_stub_Relocation : public Relocation { : Relocation(relocInfo::static_stub_type), _static_call(static_call) { } - friend class RelocIterator; + friend class RelocationHolder; static_stub_Relocation() : Relocation(relocInfo::static_stub_type) { } public: @@ -1166,29 +1223,27 @@ class runtime_call_Relocation : public CallRelocation { public: static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) runtime_call_Relocation(); - return rh; + return RelocationHolder::construct(); } + void copy_into(RelocationHolder& holder) const; + private: - friend class RelocIterator; + friend class RelocationHolder; runtime_call_Relocation() : CallRelocation(relocInfo::runtime_call_type) { } - - public: }; class runtime_call_w_cp_Relocation : public CallRelocation { public: static RelocationHolder spec() { - RelocationHolder rh = newHolder(); - new(rh) runtime_call_w_cp_Relocation(); - return rh; + return RelocationHolder::construct(); } + void copy_into(RelocationHolder& holder) const; + private: - friend class RelocIterator; + friend class RelocationHolder; runtime_call_w_cp_Relocation() : CallRelocation(relocInfo::runtime_call_w_cp_type), _offset(-4) /* <0 = invalid */ { } @@ -1218,10 +1273,11 @@ class runtime_call_w_cp_Relocation : public CallRelocation { class trampoline_stub_Relocation : public Relocation { public: static RelocationHolder spec(address static_call) { - RelocationHolder rh = newHolder(); - return (new (rh) trampoline_stub_Relocation(static_call)); + return RelocationHolder::construct(static_call); } + void copy_into(RelocationHolder& holder) const; + private: address _owner; // Address of the NativeCall that owns the trampoline. @@ -1229,7 +1285,7 @@ class trampoline_stub_Relocation : public Relocation { : Relocation(relocInfo::trampoline_stub_type), _owner(owner) { } - friend class RelocIterator; + friend class RelocationHolder; trampoline_stub_Relocation() : Relocation(relocInfo::trampoline_stub_type) { } public: @@ -1248,19 +1304,17 @@ class external_word_Relocation : public DataRelocation { public: static RelocationHolder spec(address target) { assert(target != NULL, "must not be null"); - RelocationHolder rh = newHolder(); - new(rh) external_word_Relocation(target); - return rh; + return RelocationHolder::construct(target); } // Use this one where all 32/64 bits of the target live in the code stream. // The target must be an intptr_t, and must be absolute (not relative). static RelocationHolder spec_for_immediate() { - RelocationHolder rh = newHolder(); - new(rh) external_word_Relocation(NULL); - return rh; + return RelocationHolder::construct(nullptr); } + void copy_into(RelocationHolder& holder) const; + // Some address looking values aren't safe to treat as relocations // and should just be treated as constants. static bool can_be_relocated(address target) { @@ -1274,7 +1328,7 @@ class external_word_Relocation : public DataRelocation { external_word_Relocation(address target) : DataRelocation(relocInfo::external_word_type), _target(target) { } - friend class RelocIterator; + friend class RelocationHolder; external_word_Relocation() : DataRelocation(relocInfo::external_word_type) { } public: @@ -1296,18 +1350,16 @@ class internal_word_Relocation : public DataRelocation { public: static RelocationHolder spec(address target) { assert(target != NULL, "must not be null"); - RelocationHolder rh = newHolder(); - new(rh) internal_word_Relocation(target); - return rh; + return RelocationHolder::construct(target); } // use this one where all the bits of the target can fit in the code stream: static RelocationHolder spec_for_immediate() { - RelocationHolder rh = newHolder(); - new(rh) internal_word_Relocation(NULL); - return rh; + return RelocationHolder::construct(nullptr); } + void copy_into(RelocationHolder& holder) const; + // default section -1 means self-relative internal_word_Relocation(address target, int section = -1, relocInfo::relocType type = relocInfo::internal_word_type) @@ -1317,7 +1369,7 @@ class internal_word_Relocation : public DataRelocation { address _target; // address in CodeBlob int _section; // section providing base address, if any - friend class RelocIterator; + friend class RelocationHolder; internal_word_Relocation(relocInfo::relocType type = relocInfo::internal_word_type) : DataRelocation(type) { } @@ -1341,11 +1393,11 @@ class internal_word_Relocation : public DataRelocation { class section_word_Relocation : public internal_word_Relocation { public: static RelocationHolder spec(address target, int section) { - RelocationHolder rh = newHolder(); - new(rh) section_word_Relocation(target, section); - return rh; + return RelocationHolder::construct(target, section); } + void copy_into(RelocationHolder& holder) const; + section_word_Relocation(address target, int section) : internal_word_Relocation(target, section, relocInfo::section_word_type) { assert(target != NULL, "must not be null"); @@ -1356,7 +1408,7 @@ class section_word_Relocation : public internal_word_Relocation { void unpack_data(); private: - friend class RelocIterator; + friend class RelocationHolder; section_word_Relocation() : internal_word_Relocation(relocInfo::section_word_type) { } }; @@ -1366,25 +1418,32 @@ class poll_Relocation : public Relocation { void fix_relocation_after_move(const CodeBuffer* src, CodeBuffer* dest); public: poll_Relocation(relocInfo::relocType type = relocInfo::poll_type) : Relocation(type) { } + + void copy_into(RelocationHolder& holder) const; }; class poll_return_Relocation : public poll_Relocation { public: poll_return_Relocation() : poll_Relocation(relocInfo::relocInfo::poll_return_type) { } + + void copy_into(RelocationHolder& holder) const; }; // We know all the xxx_Relocation classes, so now we can define these: -#define EACH_CASE(name) \ -inline name##_Relocation* RelocIterator::name##_reloc() { \ - assert(type() == relocInfo::name##_type, "type must agree"); \ - /* The purpose of the placed "new" is to re-use the same */ \ - /* stack storage for each new iteration. */ \ - name##_Relocation* r = new(_rh) name##_Relocation(); \ - r->set_binding(this); \ - r->name##_Relocation::unpack_data(); \ - return r; \ +#define EACH_CASE_AUX(Accessor, Reloc) \ +inline Reloc* RelocIterator::Accessor() { \ + static const RelocationHolder proto = RelocationHolder::construct(); \ + assert(type() == proto.type(), "type must agree"); \ + _rh = proto; \ + Reloc* r = static_cast(_rh.reloc()); \ + r->set_binding(this); \ + r->Reloc::unpack_data(); \ + return r; \ } +#define EACH_CASE(name) \ + EACH_CASE_AUX(PASTE_TOKENS(name, _reloc), PASTE_TOKENS(name, _Relocation)) APPLY_TO_RELOCATIONS(EACH_CASE); +#undef EACH_CASE_AUX #undef EACH_CASE inline RelocIterator::RelocIterator(CompiledMethod* nm, address begin, address limit) { From c997b5bffd0ebbd6d68332572639c8cea05ccdb1 Mon Sep 17 00:00:00 2001 From: Damon Nguyen Date: Fri, 16 Dec 2022 21:15:29 +0000 Subject: [PATCH 254/494] 8298133: JDK 20 RDP1 L10n resource files update - msgdrop 10 Reviewed-by: achung, naoto, joehw, cjplummer, almatvee --- .../launcher/resources/launcher_de.properties | 4 +- .../launcher/resources/launcher_ja.properties | 4 +- .../resources/launcher_zh_CN.properties | 4 +- .../security/tools/keytool/Resources_de.java | 9 ++- .../security/tools/keytool/Resources_ja.java | 9 ++- .../tools/keytool/Resources_zh_CN.java | 9 ++- .../rowset/RowSetResourceBundle_de.properties | 2 +- .../rowset/RowSetResourceBundle_ja.properties | 2 +- .../RowSetResourceBundle_zh_CN.properties | 2 +- .../internal/res/XSLTErrorResources_de.java | 4 +- .../internal/res/XSLTErrorResources_ja.java | 4 +- .../res/XSLTErrorResources_zh_CN.java | 4 +- .../xsltc/compiler/util/ErrorMessages_de.java | 14 +++- .../xsltc/compiler/util/ErrorMessages_ja.java | 14 +++- .../compiler/util/ErrorMessages_zh_CN.java | 14 +++- .../impl/msg/DOMMessages_de.properties | 17 +++++ .../impl/msg/DOMMessages_ja.properties | 17 +++++ .../impl/msg/DOMMessages_zh_CN.properties | 17 +++++ .../impl/msg/DatatypeMessages_de.properties | 17 +++++ .../impl/msg/DatatypeMessages_ja.properties | 17 +++++ .../msg/DatatypeMessages_zh_CN.properties | 17 +++++ .../msg/JAXPValidationMessages_de.properties | 17 +++++ .../msg/JAXPValidationMessages_ja.properties | 17 +++++ .../JAXPValidationMessages_zh_CN.properties | 17 +++++ .../impl/msg/SAXMessages_de.properties | 17 +++++ .../impl/msg/SAXMessages_ja.properties | 17 +++++ .../impl/msg/SAXMessages_zh_CN.properties | 17 +++++ .../impl/msg/XIncludeMessages_de.properties | 17 +++++ .../impl/msg/XIncludeMessages_ja.properties | 17 +++++ .../msg/XIncludeMessages_zh_CN.properties | 17 +++++ .../impl/msg/XMLMessages_de.properties | 17 +++++ .../impl/msg/XMLMessages_ja.properties | 17 +++++ .../impl/msg/XMLMessages_zh_CN.properties | 17 +++++ .../impl/msg/XMLSchemaMessages_de.properties | 18 +++++ .../impl/msg/XMLSchemaMessages_ja.properties | 18 +++++ .../msg/XMLSchemaMessages_zh_CN.properties | 18 +++++ .../msg/XMLSerializerMessages_de.properties | 17 +++++ .../msg/XMLSerializerMessages_ja.properties | 17 +++++ .../XMLSerializerMessages_zh_CN.properties | 17 +++++ .../impl/msg/XPointerMessages_de.properties | 17 +++++ .../impl/msg/XPointerMessages_ja.properties | 17 +++++ .../msg/XPointerMessages_zh_CN.properties | 17 +++++ .../internal/res/XPATHErrorResources_de.java | 35 ++++++---- .../internal/res/XPATHErrorResources_ja.java | 35 ++++++---- .../res/XPATHErrorResources_zh_CN.java | 35 ++++++---- .../javac/resources/compiler_de.properties | 27 ++++++-- .../javac/resources/compiler_ja.properties | 27 ++++++-- .../javac/resources/compiler_zh_CN.properties | 27 ++++++-- .../tools/javac/resources/javac_de.properties | 6 +- .../tools/javac/resources/javac_ja.properties | 6 +- .../javac/resources/javac_zh_CN.properties | 6 +- .../sun/tools/jar/resources/jar_de.properties | 6 +- .../sun/tools/jar/resources/jar_ja.properties | 18 +++-- .../tools/jar/resources/jar_zh_CN.properties | 6 +- .../html/resources/standard_de.properties | 27 ++++++-- .../html/resources/standard_ja.properties | 27 ++++++-- .../html/resources/standard_zh_CN.properties | 27 ++++++-- .../toolkit/resources/doclets_de.properties | 11 +++- .../toolkit/resources/doclets_ja.properties | 11 +++- .../resources/doclets_zh_CN.properties | 11 +++- .../doclint/resources/doclint_de.properties | 2 +- .../doclint/resources/doclint_ja.properties | 2 +- .../resources/doclint_zh_CN.properties | 2 +- .../tool/resources/javadoc_de.properties | 4 +- .../tool/resources/javadoc_ja.properties | 4 +- .../tool/resources/javadoc_zh_CN.properties | 4 +- .../tools/javap/resources/javap_de.properties | 4 +- .../tools/javap/resources/javap_ja.properties | 2 + .../javap/resources/javap_zh_CN.properties | 4 +- .../tools/jdeps/resources/jdeps_de.properties | 2 + .../tools/jdeps/resources/jdeps_ja.properties | 2 + .../jdeps/resources/jdeps_zh_CN.properties | 2 + .../example/debug/tty/TTYResources_de.java | 3 +- .../example/debug/tty/TTYResources_ja.java | 3 +- .../example/debug/tty/TTYResources_zh_CN.java | 3 +- .../sun/tools/jdi/resources/jdi_de.properties | 10 +-- .../sun/tools/jdi/resources/jdi_ja.properties | 12 ++-- .../tools/jdi/resources/jdi_zh_CN.properties | 6 +- .../tools/jlink/resources/jlink_de.properties | 4 +- .../tools/jlink/resources/jlink_ja.properties | 6 +- .../jlink/resources/jlink_zh_CN.properties | 4 +- .../tools/jmod/resources/jmod_de.properties | 6 +- .../tools/jmod/resources/jmod_ja.properties | 6 +- .../jmod/resources/jmod_zh_CN.properties | 6 +- .../resources/LinuxResources_de.properties | 3 +- .../resources/LinuxResources_ja.properties | 2 +- .../resources/LinuxResources_zh_CN.properties | 2 +- .../resources/MacResources_de.properties | 8 ++- .../resources/MacResources_ja.properties | 14 ++-- .../resources/MacResources_zh_CN.properties | 14 ++-- .../resources/HelpResources_de.properties | 61 ++--------------- .../resources/HelpResources_ja.properties | 65 +++---------------- .../resources/HelpResources_zh_CN.properties | 61 ++--------------- .../resources/MainResources_de.properties | 10 +-- .../resources/MainResources_ja.properties | 8 ++- .../resources/MainResources_zh_CN.properties | 8 ++- .../resources/WinResources_de.properties | 3 +- .../resources/WinResources_ja.properties | 2 +- .../resources/WinResources_zh_CN.properties | 2 +- 99 files changed, 930 insertions(+), 345 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 c63dc912e27..e0017634973 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 @@ -34,8 +34,8 @@ java.launcher.opt.footer = \ -cp \n Zeigt den Startbildschirm mit einem angegebenen Bild an\n Skalierte HiDPI-Bilder werden automatisch unterst\u00FCtzt und verwendet,\n falls verf\u00FCgbar. Der nicht skalierte Bilddateiname (Beispiel: image.ext)\n muss immer als Argument an die Option "-splash" \u00FCbergeben werden.\n Das am besten geeignete angegebene skalierte Bild wird\n automatisch ausgew\u00E4hlt.\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\u00E4sst zu, das Klassen von Vorschaufeatures dieses Release abh\u00E4ngig sind\nUm ein Argument f\u00FCr eine lange Option anzugeben, k\u00F6nnen 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\u00E4ngen\n -Xcheck:jni F\u00FChrt zus\u00E4tzliche Pr\u00FCfungen f\u00FCr JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug F\u00FChrt nichts aus. Wird aus Gr\u00FCnden der Abw\u00E4rtskompatibilit\u00E4t bereitgestellt.\n -Xdiag Zeigt zus\u00E4tzliche Diagnosemeldungen an\n -Xfuture Aktiviert strengste Pr\u00FCfungen, als m\u00F6glicher zuk\u00FCnftiger Standardwert erwartet.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden.\n -Xint Nur Ausf\u00FChrung 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\u00FCr weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausf\u00FChrung im gemischten Modus (Standard)\n -Xmn Legt die anf\u00E4ngliche und maximale Gr\u00F6\u00DFe (in Byte) des Heaps\n f\u00FCr die Young Generation (Nursery) fest\n -Xms Legt die anf\u00E4ngliche Java-Heap-Gr\u00F6\u00DFe fest\n -Xmx Legt die maximale Java-Heap-Gr\u00F6\u00DFe 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\u00F6glich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verl\u00E4uft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern f\u00FChren. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:all\n Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und f\u00E4hrt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und f\u00E4hrt fort\n -Xss Legt die Stackgr\u00F6\u00DFe des Java-Threads fest\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zuk\u00FCnftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in \ - zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu \u00F6ffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n \u00DCberschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardm\u00E4\u00DFig aktiviert.\n\nDiese zus\u00E4tzlichen Optionen k\u00F6nnen jederzeit ohne vorherige Ank\u00FCndigung ge\u00E4ndert werden.\n +java.launcher.X.usage=\n -Xbatch Deaktiviert die Hintergrundkompilierung\n -Xbootclasspath/a:\n An das Ende des Bootstrap Classpaths anh\u00E4ngen\n -Xcheck:jni F\u00FChrt zus\u00E4tzliche Pr\u00FCfungen f\u00FCr JNI-Funktionen aus\n -Xcomp Erzwingt die Kompilierung von Methoden beim ersten Aufruf\n -Xdebug F\u00FChrt nichts aus. Wird aus Gr\u00FCnden der Abw\u00E4rtskompatibilit\u00E4t bereitgestellt.\n -Xdiag Zeigt zus\u00E4tzliche Diagnosemeldungen an\n -Xfuture Aktiviert strengste Pr\u00FCfungen, als m\u00F6glicher zuk\u00FCnftiger Standardwert erwartet.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden.\n -Xint Nur Ausf\u00FChrung 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\u00FCr weitere Einzelheiten.\n -Xloggc: Protokolliert den GC-Status in einer Datei mit Zeitstempeln.\n Diese Option ist veraltet und kann in einem\n zuk\u00FCnftigen Release entfernt werden. Wird durch -Xlog:gc: ersetzt.\n -Xmixed Ausf\u00FChrung im gemischten Modus (Standard)\n -Xmn Legt die anf\u00E4ngliche und maximale Gr\u00F6\u00DFe (in Byte) des Heaps\n f\u00FCr die Young Generation (Nursery) fest\n -Xms Legt die anf\u00E4ngliche Java-Heap-Gr\u00F6\u00DFe fest\n -Xmx Legt die maximale Java-Heap-Gr\u00F6\u00DFe 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\u00F6glich (Standard)\n -Xshare:off Versucht nicht, freigegebene Klassendaten zu verwenden\n -Xshare:on Erfordert die Verwendung freigegebener Klassendaten, verl\u00E4uft sonst nicht erfolgreich.\n Diese Testoption kann zeitweise zu\n Fehlern f\u00FChren. Sie darf nicht in Produktionsumgebungen verwendet werden.\n -XshowSettings Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:all\n Zeigt alle Einstellungen an und f\u00E4hrt fort\n -XshowSettings:locale\n Zeigt alle gebietsschemabezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:properties\n Zeigt alle Eigenschaftseinstellungen an und f\u00E4hrt fort\n -XshowSettings:vm\n Zeigt alle VM-bezogenen Einstellungen an und f\u00E4hrt fort\n -XshowSettings:system\n (Nur Linux) Zeigt die Konfiguration des Hostsystems oder Containers an\n und f\u00E4hrt fort\n -Xss Legt die Stackgr\u00F6\u00DFe des Java-Threads fest\n Die tats\u00E4chliche Gr\u00F6\u00DFe kann auf ein Vielfaches der\n Systemseitengr\u00F6\u00DFe aufgerundet werden, wenn f\u00FCr das Betriebssystem erforderlich.\n -Xverify Legt den Modus der Bytecodeverifizierung fest\n Beachten Sie, dass die Option -Xverify:none veraltet ist und\n in einem zuk\u00FCnftigen Release entfernt werden kann.\n --add-reads =(,)*\n Aktualisiert , damit gelesen wird, ungeachtet\n der Moduldeklaration. \n \ +kann ALL-UNNAMED sein, um alle unbenannten\n Module zu lesen.\n --add-exports /=(,)*\n Aktualisiert , um in zu exportieren,\n ungeachtet der Moduldeklaration.\n kann ALL-UNNAMED sein, um in alle\n unbenannten Module zu exportieren.\n --add-opens /=(,)*\n Aktualisiert , um in\n zu \u00F6ffnen, ungeachtet der Moduldeklaration.\n --limit-modules [,...]\n Grenzt die Gesamtmenge der beobachtbaren Module ein\n --patch-module =({0})*\n \u00DCberschreibt oder erweitert ein Modul mit Klassen und Ressourcen\n in JAR-Dateien oder Verzeichnissen.\n --source \n Legt die Version der Quelle im Quelldateimodus fest.\n --finalization=\n Steuert, ob die JVM Objekte finalisiert.\n Dabei ist entweder "enabled" oder "disabled".\n Die Finalisierung ist standardm\u00E4\u00DFig aktiviert.\n\nDiese zus\u00E4tzlichen Optionen k\u00F6nnen jederzeit ohne vorherige Ank\u00FCndigung ge\u00E4ndert werden.\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\nDie folgenden Optionen sind f\u00FCr macOS spezifisch:\n -XstartOnFirstThread\n F\u00FChrt die main()-Methode f\u00FCr den ersten (AppKit-)Thread aus\n -Xdock:name=\n Setzt den im Dock angezeigten Standardanwendungsnamen au\u00DFer Kraft\n -Xdock:icon=\n Setzt das im Dock angezeigte Standardsymbol au\u00DFer Kraft\n\n 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 8b6f4118f58..51def14218d 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 @@ -36,8 +36,8 @@ java.launcher.opt.footer = \ -cp <\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304A\ # Translators please note do not translate the options themselves java.launcher.X.usage=\n -Xbatch \u30D0\u30C3\u30AF\u30B0\u30E9\u30A6\u30F3\u30C9\u30FB\u30B3\u30F3\u30D1\u30A4\u30EB\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -Xbootclasspath/a:\n \u30D6\u30FC\u30C8\u30B9\u30C8\u30E9\u30C3\u30D7\u30FB\u30AF\u30E9\u30B9\u30FB\u30D1\u30B9\u306E\u6700\u5F8C\u306B\u8FFD\u52A0\u3057\u307E\u3059\n -Xcheck:jni JNI\u95A2\u6570\u306B\u5BFE\u3059\u308B\u8FFD\u52A0\u306E\u30C1\u30A7\u30C3\u30AF\u3092\u5B9F\u884C\u3057\u307E\u3059\n -Xcomp \u521D\u56DE\u547C\u51FA\u3057\u6642\u306B\u30E1\u30BD\u30C3\u30C9\u306E\u30B3\u30F3\u30D1\u30A4\u30EB\u3092\u5F37\u5236\u3057\u307E\u3059\n -Xdebug \u4F55\u3082\u884C\u3044\u307E\u305B\u3093\u3002\u4E0B\u4F4D\u4E92\u63DB\u6027\u306E\u305F\u3081\u306B\u7528\u610F\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n -Xdiag \u8FFD\u52A0\u306E\u8A3A\u65AD\u30E1\u30C3\u30BB\u30FC\u30B8\u3092\u8868\u793A\u3057\u307E\u3059\n -Xfuture \u5C06\u6765\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u3092\u898B\u8D8A\u3057\u3066\u3001\u6700\u3082\u53B3\u5BC6\u306A\u30C1\u30A7\u30C3\u30AF\u3092\u6709\u52B9\u306B\u3057\u307E\u3059\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n -Xint \u30A4\u30F3\u30BF\u30D7\u30EA\u30BF\u30FB\u30E2\u30FC\u30C9\u306E\u5B9F\u884C\u306E\u307F\n -Xinternalversion\n -version\u30AA\u30D7\u30B7\u30E7\u30F3\u3088\u308A\u8A73\u7D30\u306AJVM\u30D0\u30FC\u30B8\u30E7\u30F3\u60C5\u5831\u3092\n \u8868\u793A\u3057\u307E\u3059\n -Xlog: Java Virtual Machine (JVM)\u7D71\u5408\u30ED\u30AE\u30F3\u30B0\u30FB\u30D5\u30EC\u30FC\u30E0\u30EF\u30FC\u30AF\u3067\u306E\n \u30ED\u30AE\u30F3\u30B0\u3092\u69CB\u6210\u307E\u305F\u306F\u6709\u52B9\u5316\u3057\u307E\u3059\u3002\u8A73\u7D30\u306F\u3001-Xlog:help\u3092\n \u4F7F\u7528\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n -Xloggc: \u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u304C\u4ED8\u3044\u305F\u30D5\u30A1\u30A4\u30EB\u306BGC\u30B9\u30C6\u30FC\u30BF\u30B9\u306E\u30ED\u30B0\u3092\u8A18\u9332\u3057\u307E\u3059\n \u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002-Xlog:gc:\u3067\u7F6E\u63DB\u3055\u308C\u3066\u3044\u307E\u3059\u3002\n -Xmixed \u6DF7\u5408\u30E2\u30FC\u30C9\u306E\u5B9F\u884C(\u30C7\u30D5\u30A9\u30EB\u30C8)\n -Xmn \u82E5\u3044\u4E16\u4EE3(\u30CA\u30FC\u30B5\u30EA)\u306E\u30D2\u30FC\u30D7\u306E\u521D\u671F\u30B5\u30A4\u30BA\u304A\u3088\u3073\u6700\u5927\u30B5\u30A4\u30BA\n (\u30D0\u30A4\u30C8\u5358\u4F4D)\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xms Java\u306E\u521D\u671F\u30D2\u30FC\u30D7\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xmx Java\u306E\u6700\u5927\u30D2\u30FC\u30D7\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xnoclassgc \u30AF\u30E9\u30B9\u306E\u30AC\u30D9\u30FC\u30B8\u30FB\u30B3\u30EC\u30AF\u30B7\u30E7\u30F3\u3092\u7121\u52B9\u306B\u3057\u307E\u3059\n -Xrs Java/VM\u306B\u3088\u308BOS\u30B7\u30B0\u30CA\u30EB\u306E\u4F7F\u7528\u3092\u524A\u6E1B\u3057\u307E\u3059(\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u3092\u53C2\u7167)\n -Xshare:auto \u53EF\u80FD\u3067\u3042\u308C\u3070\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u3092\u4F7F\u7528\u3057\u307E\u3059(\u30C7\u30D5\u30A9\u30EB\u30C8)\n -Xshare:off \ -\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u8A66\u307F\u307E\u305B\u3093\n -Xshare:on \u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u5FC5\u9808\u306B\u3057\u3001\u3067\u304D\u306A\u3051\u308C\u3070\u5931\u6557\u3057\u307E\u3059\u3002\n \u3053\u308C\u306F\u30C6\u30B9\u30C8\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u3001\u65AD\u7D9A\u7684\u306A\u5931\u6557\u306B\u3064\u306A\u304C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u672C\u756A\u74B0\u5883\u3067\u306F\u4F7F\u7528\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n -XshowSettings \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:all\n \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:locale\n \u3059\u3079\u3066\u306E\u30ED\u30B1\u30FC\u30EB\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:properties\n \u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:vm\n \u3059\u3079\u3066\u306EVM\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:system\n (Linux\u306E\u307F)\u30DB\u30B9\u30C8\u30FB\u30B7\u30B9\u30C6\u30E0\u307E\u305F\u306F\u30B3\u30F3\u30C6\u30CA\u3092\u8868\u793A\u3057\u307E\u3059\n \u69CB\u6210\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -Xss java\u30B9\u30EC\u30C3\u30C9\u306E\u30B9\u30BF\u30C3\u30AF\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n -Xverify \u30D0\u30A4\u30C8\u30B3\u30FC\u30C9\u30FB\u30D9\u30EA\u30D5\u30A1\u30A4\u30A2\u306E\u30E2\u30FC\u30C9\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n \u30AA\u30D7\u30B7\u30E7\u30F3-Xverify:none\u306F\u975E\u63A8\u5968\u306B\u306A\u308A\u3001\n \u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n --add-reads =(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u8AAD\u307F\u53D6\u308A\u307E\u3059\u3002 \n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\n \u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\n --add-exports /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3067\u304D\u307E\u3059\u3002\n --add-opens /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u306B\u958B\u304D\u307E\u3059\u3002\n --limit-modules [,...]\n \ -\u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9818\u57DF\u3092\u5236\u9650\u3057\u307E\u3059\n --patch-module =({0})*\n JAR\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30EA\u30BD\u30FC\u30B9\u3067\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u62E1\u5F35\u3057\u307E\u3059\u3002\n --source \n \u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u30FB\u30E2\u30FC\u30C9\u3067\u30BD\u30FC\u30B9\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\n --finalization=\n JVM\u304C\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u3092\u5B9F\u884C\u3059\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059\n \u306F"enabled"\u307E\u305F\u306F"disabled"\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002\n \u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002\n\n\u3053\u306E\u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\n +\u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u8A66\u307F\u307E\u305B\u3093\n -Xshare:on \u5171\u6709\u30AF\u30E9\u30B9\u30FB\u30C7\u30FC\u30BF\u306E\u4F7F\u7528\u3092\u5FC5\u9808\u306B\u3057\u3001\u3067\u304D\u306A\u3051\u308C\u3070\u5931\u6557\u3057\u307E\u3059\u3002\n \u3053\u308C\u306F\u30C6\u30B9\u30C8\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u3042\u308A\u3001\u65AD\u7D9A\u7684\u306A\u5931\u6557\u306B\u3064\u306A\u304C\u308B\n \u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\u672C\u756A\u74B0\u5883\u3067\u306F\u4F7F\u7528\u3057\u306A\u3044\u3067\u304F\u3060\u3055\u3044\u3002\n -XshowSettings \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:all\n \u3059\u3079\u3066\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:locale\n \u3059\u3079\u3066\u306E\u30ED\u30B1\u30FC\u30EB\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:properties\n \u3059\u3079\u3066\u306E\u30D7\u30ED\u30D1\u30C6\u30A3\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:vm\n \u3059\u3079\u3066\u306EVM\u95A2\u9023\u306E\u8A2D\u5B9A\u3092\u8868\u793A\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -XshowSettings:system\n (Linux\u306E\u307F)\u30DB\u30B9\u30C8\u30FB\u30B7\u30B9\u30C6\u30E0\u307E\u305F\u306F\u30B3\u30F3\u30C6\u30CA\u3092\u8868\u793A\u3057\u307E\u3059\n \u69CB\u6210\u3057\u3066\u7D9A\u884C\u3057\u307E\u3059\n -Xss java\u30B9\u30EC\u30C3\u30C9\u306E\u30B9\u30BF\u30C3\u30AF\u30FB\u30B5\u30A4\u30BA\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n \u5B9F\u969B\u306E\u30B5\u30A4\u30BA\u306F\u3001\u6B21\u306E\u500D\u6570\u306B\u5207\u308A\u4E0A\u3052\u3089\u308C\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059: \n \u30AA\u30DA\u30EC\u30FC\u30C6\u30A3\u30F3\u30B0\u30FB\u30B7\u30B9\u30C6\u30E0\u306E\u8981\u4EF6\u306B\u5FDC\u3058\u305F\u30B7\u30B9\u30C6\u30E0\u30FB\u30DA\u30FC\u30B8\u30FB\u30B5\u30A4\u30BA\u3002\n -Xverify \u30D0\u30A4\u30C8\u30B3\u30FC\u30C9\u30FB\u30D9\u30EA\u30D5\u30A1\u30A4\u30A2\u306E\u30E2\u30FC\u30C9\u3092\u8A2D\u5B9A\u3057\u307E\u3059\n \u30AA\u30D7\u30B7\u30E7\u30F3-Xverify:none\u306F\u975E\u63A8\u5968\u306B\u306A\u308A\u3001\n \u5C06\u6765\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002\n --add-reads =(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u8AAD\u307F\u53D6\u308A\u307E\u3059\u3002 \n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u3092\n \u8AAD\u307F\u53D6\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002\n --add-exports /=(,)*\n \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3057\u307E\u3059\u3002\n \u3092ALL-UNNAMED\u306B\u8A2D\u5B9A\u3059\u308B\u3068\u3001\u3059\u3079\u3066\u306E\u540D\u524D\u306E\u306A\u3044\u30E2\u30B8\u30E5\u30FC\u30EB\u306B\n \u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3067\u304D\u307E\u3059\u3002\n --add-opens /=(,)*\n \ + \u30E2\u30B8\u30E5\u30FC\u30EB\u5BA3\u8A00\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3092\u66F4\u65B0\u3057\u3066\u3092\n \u306B\u958B\u304D\u307E\u3059\u3002\n --limit-modules [,...]\n \u53C2\u7167\u53EF\u80FD\u306A\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u9818\u57DF\u3092\u5236\u9650\u3057\u307E\u3059\n --patch-module =({0})*\n JAR\u30D5\u30A1\u30A4\u30EB\u307E\u305F\u306F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30EA\u30BD\u30FC\u30B9\u3067\n \u30E2\u30B8\u30E5\u30FC\u30EB\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u62E1\u5F35\u3057\u307E\u3059\u3002\n --source \n \u30BD\u30FC\u30B9\u30D5\u30A1\u30A4\u30EB\u30FB\u30E2\u30FC\u30C9\u3067\u30BD\u30FC\u30B9\u306E\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u8A2D\u5B9A\u3057\u307E\u3059\u3002\n --finalization=\n JVM\u304C\u30AA\u30D6\u30B8\u30A7\u30AF\u30C8\u306E\u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u3092\u5B9F\u884C\u3059\u308B\u304B\u3069\u3046\u304B\u3092\u5236\u5FA1\u3057\u307E\u3059\n \u306F"enabled"\u307E\u305F\u306F"disabled"\u306E\u3044\u305A\u308C\u304B\u3067\u3059\u3002\n \u30D5\u30A1\u30A4\u30CA\u30E9\u30A4\u30BA\u306F\u30C7\u30D5\u30A9\u30EB\u30C8\u3067\u6709\u52B9\u306B\u306A\u3063\u3066\u3044\u307E\u3059\u3002\n\n\u3053\u306E\u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u4E88\u544A\u306A\u3057\u306B\u5909\u66F4\u3055\u308C\u308B\u3053\u3068\u304C\u3042\u308A\u307E\u3059\u3002\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n\u6B21\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306FmacOS\u56FA\u6709\u3067\u3059:\n -XstartOnFirstThread\n main()\u30E1\u30BD\u30C3\u30C9\u3092\u6700\u521D(AppKit)\u306E\u30B9\u30EC\u30C3\u30C9\u3067\u5B9F\u884C\u3059\u308B\n -Xdock:name=\n Dock\u306B\u8868\u793A\u3055\u308C\u308B\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u540D\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n -Xdock:icon=\n Dock\u306B\u8868\u793A\u3055\u308C\u308B\u30C7\u30D5\u30A9\u30EB\u30C8\u30FB\u30A2\u30A4\u30B3\u30F3\u3092\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3059\u308B\n\n 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 dd1ac2df1a4..3288d9ae117 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 @@ -34,8 +34,8 @@ java.launcher.opt.footer = \ -cp <\u76EE\u5F55\u548C zip/jar \u6587\u4EF6\u76 \u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u542F\u7528\u65AD\u8A00\n -da[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n -disableassertions[:<\u7A0B\u5E8F\u5305\u540D\u79F0>...|:<\u7C7B\u540D>]\n \u6309\u6307\u5B9A\u7684\u7C92\u5EA6\u7981\u7528\u65AD\u8A00\n -esa | -enablesystemassertions\n \u542F\u7528\u7CFB\u7EDF\u65AD\u8A00\n -dsa | -disablesystemassertions\n \u7981\u7528\u7CFB\u7EDF\u65AD\u8A00\n -agentlib:<\u5E93\u540D>[=<\u9009\u9879>]\n \u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93 <\u5E93\u540D>, \u4F8B\u5982 -agentlib:jdwp\n \u53E6\u8BF7\u53C2\u9605 -agentlib:jdwp=help\n -agentpath:<\u8DEF\u5F84\u540D>[=<\u9009\u9879>]\n \u6309\u5B8C\u6574\u8DEF\u5F84\u540D\u52A0\u8F7D\u672C\u673A\u4EE3\u7406\u5E93\n -javaagent:[=<\u9009\u9879>]\n \u52A0\u8F7D Java \u7F16\u7A0B\u8BED\u8A00\u4EE3\u7406, \u8BF7\u53C2\u9605 java.lang.instrument\n -splash:<\u56FE\u50CF\u8DEF\u5F84>\n \u4F7F\u7528\u6307\u5B9A\u7684\u56FE\u50CF\u663E\u793A\u542F\u52A8\u5C4F\u5E55\n \u81EA\u52A8\u652F\u6301\u548C\u4F7F\u7528 HiDPI \u7F29\u653E\u56FE\u50CF\n (\u5982\u679C\u53EF\u7528)\u3002\u5E94\u59CB\u7EC8\u5C06\u672A\u7F29\u653E\u7684\u56FE\u50CF\u6587\u4EF6\u540D (\u4F8B\u5982, image.ext)\n \u4F5C\u4E3A\u53C2\u6570\u4F20\u9012\u7ED9 -splash \u9009\u9879\u3002\n \u5C06\u81EA\u52A8\u9009\u53D6\u63D0\u4F9B\u7684\u6700\u5408\u9002\u7684\u7F29\u653E\n \u56FE\u50CF\u3002\n \u6709\u5173\u8BE6\u7EC6\u4FE1\u606F, \u8BF7\u53C2\u9605 SplashScreen API \u6587\u6863\n @argument \u6587\u4EF6\n \u4E00\u4E2A\u6216\u591A\u4E2A\u5305\u542B\u9009\u9879\u7684\u53C2\u6570\u6587\u4EF6\n --disable-@files\n \u963B\u6B62\u8FDB\u4E00\u6B65\u6269\u5C55\u53C2\u6570\u6587\u4EF6\n --enable-preview\n \u5141\u8BB8\u7C7B\u4F9D\u8D56\u4E8E\u6B64\u53D1\u884C\u7248\u7684\u9884\u89C8\u529F\u80FD\n\u8981\u4E3A\u957F\u9009\u9879\u6307\u5B9A\u53C2\u6570, \u53EF\u4EE5\u4F7F\u7528 --<\u540D\u79F0>=<\u503C> \u6216\n--<\u540D\u79F0> <\u503C>\u3002\n # Translators please note do not translate the options themselves -java.launcher.X.usage=\n -Xbatch \u7981\u7528\u540E\u53F0\u7F16\u8BD1\n -Xbootclasspath/a:<\u4EE5 {0} \u5206\u9694\u7684\u76EE\u5F55\u548C zip/jar \u6587\u4EF6>\n \u9644\u52A0\u5728\u5F15\u5BFC\u7C7B\u8DEF\u5F84\u672B\u5C3E\n -Xcheck:jni \u5BF9 JNI \u51FD\u6570\u6267\u884C\u5176\u4ED6\u68C0\u67E5\n -Xcomp \u5F3A\u5236\u5728\u9996\u6B21\u8C03\u7528\u65F6\u7F16\u8BD1\u65B9\u6CD5\n -Xdebug \u4E0D\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002\u4E3A\u5B9E\u73B0\u5411\u540E\u517C\u5BB9\u800C\u63D0\u4F9B\u3002\n -Xdiag \u663E\u793A\u9644\u52A0\u8BCA\u65AD\u6D88\u606F\n -Xfuture \u542F\u7528\u6700\u4E25\u683C\u7684\u68C0\u67E5\uFF0C\u9884\u671F\u5C06\u6765\u7684\u9ED8\u8BA4\u503C\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n -Xint \u4EC5\u89E3\u91CA\u6A21\u5F0F\u6267\u884C\n -Xinternalversion\n \u663E\u793A\u6BD4 -version \u9009\u9879\u66F4\u8BE6\u7EC6\u7684\n JVM \u7248\u672C\u4FE1\u606F\n -Xlog: \u914D\u7F6E\u6216\u542F\u7528\u91C7\u7528 Java \u865A\u62DF\n \u673A (Java Virtual Machine, JVM) \u7EDF\u4E00\u8BB0\u5F55\u6846\u67B6\u8FDB\u884C\u4E8B\u4EF6\u8BB0\u5F55\u3002\u4F7F\u7528 -Xlog:help\n \u53EF\u4E86\u89E3\u8BE6\u7EC6\u4FE1\u606F\u3002\n -Xloggc: \u5C06 GC \u72B6\u6001\u8BB0\u5F55\u5728\u6587\u4EF6\u4E2D\uFF08\u5E26\u65F6\u95F4\u6233\uFF09\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u5C06\u6765\u7684\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\u5B83\u5C06\u66FF\u6362\u4E3A -Xlog:gc:\u3002\n -Xmixed \u6DF7\u5408\u6A21\u5F0F\u6267\u884C\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xmn \u4E3A\u5E74\u8F7B\u4EE3\uFF08\u65B0\u751F\u4EE3\uFF09\u8BBE\u7F6E\u521D\u59CB\u548C\u6700\u5927\u5806\u5927\u5C0F\n \uFF08\u4EE5\u5B57\u8282\u4E3A\u5355\u4F4D\uFF09\n -Xms \u8BBE\u7F6E\u521D\u59CB Java \u5806\u5927\u5C0F\n -Xmx \u8BBE\u7F6E\u6700\u5927 Java \u5806\u5927\u5C0F\n -Xnoclassgc \u7981\u7528\u7C7B\u5783\u573E\u6536\u96C6\n -Xrs \u51CF\u5C11 Java/VM \u5BF9\u64CD\u4F5C\u7CFB\u7EDF\u4FE1\u53F7\u7684\u4F7F\u7528\uFF08\u8BF7\u53C2\u89C1\u6587\u6863\uFF09\n -Xshare:auto \u5728\u53EF\u80FD\u7684\u60C5\u51B5\u4E0B\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xshare:off \u4E0D\u5C1D\u8BD5\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\n -Xshare:on \u8981\u6C42\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF0C\u5426\u5219\u5C06\u5931\u8D25\u3002\n \u8FD9\u662F\u4E00\u4E2A\u6D4B\u8BD5\u9009\u9879\uFF0C\u53EF\u80FD\u5BFC\u81F4\u95F4\u6B47\u6027\n \u6545\u969C\u3002\u4E0D\u5E94\u5728\u751F\u4EA7\u73AF\u5883\u4E2D\u4F7F\u7528\u5B83\u3002\n -XshowSettings \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:all\n \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:locale\n \u663E\u793A\u6240\u6709\u4E0E\u533A\u57DF\u8BBE\u7F6E\u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:properties\n \u663E\u793A\u6240\u6709\u5C5E\u6027\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:vm\n \u663E\u793A\u6240\u6709\u4E0E vm \u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:system\n \uFF08\u4EC5 Linux\uFF09\u663E\u793A\u4E3B\u673A\u7CFB\u7EDF\u6216\u5BB9\u5668\n \u914D\u7F6E\u5E76\u7EE7\u7EED\n -Xss \u8BBE\u7F6E Java \u7EBF\u7A0B\u5806\u6808\u5927\u5C0F\n -Xverify \ -\u8BBE\u7F6E\u5B57\u8282\u7801\u9A8C\u8BC1\u5668\u7684\u6A21\u5F0F\n \u8BF7\u6CE8\u610F\uFF0C\u9009\u9879 -Xverify:none \u5DF2\u8FC7\u65F6\uFF0C\n \u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n --add-reads =(,)*\n \u66F4\u65B0 \u4EE5\u8BFB\u53D6 \uFF0C\u800C\u65E0\u8BBA\n \u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002 \n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u8BFB\u53D6\u6240\u6709\u672A\u547D\u540D\n \u6A21\u5757\u3002\n --add-exports /=(,)*\n \u66F4\u65B0 \u4EE5\u5C06 \u5BFC\u51FA\u5230 \uFF0C\n \u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u5BFC\u51FA\u5230\u6240\u6709\n \u672A\u547D\u540D\u6A21\u5757\u3002\n --add-opens /=(,)*\n \u66F4\u65B0 \u4EE5\u5728 \u4E2D\u6253\u5F00\n \uFF0C\u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n --limit-modules [,...]\n \u9650\u5236\u53EF\u89C2\u5BDF\u6A21\u5757\u7684\u9886\u57DF\n --patch-module =({0})*\n \u4F7F\u7528 JAR \u6587\u4EF6\u6216\u76EE\u5F55\u4E2D\u7684\u7C7B\u548C\u8D44\u6E90\n \u8986\u76D6\u6216\u589E\u5F3A\u6A21\u5757\u3002\n --source \n \u8BBE\u7F6E\u6E90\u6587\u4EF6\u6A21\u5F0F\u4E2D\u6E90\u7684\u7248\u672C\u3002\n --finalization=\n \u63A7\u5236 JVM \u662F\u5426\u6267\u884C\u5BF9\u8C61\u6700\u7EC8\u5904\u7406\uFF0C\n \u5176\u4E2D \u4E3A "enabled" \u6216 "disabled" \u4E4B\u4E00\u3002\n \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C\u6700\u7EC8\u5904\u7406\u5904\u4E8E\u542F\u7528\u72B6\u6001\u3002\n\n\u8FD9\u4E9B\u989D\u5916\u9009\u9879\u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002\n +java.launcher.X.usage=\n -Xbatch \u7981\u7528\u540E\u53F0\u7F16\u8BD1\n -Xbootclasspath/a:<\u4EE5 {0} \u5206\u9694\u7684\u76EE\u5F55\u548C zip/jar \u6587\u4EF6>\n \u9644\u52A0\u5728\u5F15\u5BFC\u7C7B\u8DEF\u5F84\u672B\u5C3E\n -Xcheck:jni \u5BF9 JNI \u51FD\u6570\u6267\u884C\u5176\u4ED6\u68C0\u67E5\n -Xcomp \u5F3A\u5236\u5728\u9996\u6B21\u8C03\u7528\u65F6\u7F16\u8BD1\u65B9\u6CD5\n -Xdebug \u4E0D\u6267\u884C\u4EFB\u4F55\u64CD\u4F5C\u3002\u4E3A\u5B9E\u73B0\u5411\u540E\u517C\u5BB9\u800C\u63D0\u4F9B\u3002\n -Xdiag \u663E\u793A\u9644\u52A0\u8BCA\u65AD\u6D88\u606F\n -Xfuture \u542F\u7528\u6700\u4E25\u683C\u7684\u68C0\u67E5\uFF0C\u9884\u671F\u5C06\u6765\u7684\u9ED8\u8BA4\u503C\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n -Xint \u4EC5\u89E3\u91CA\u6A21\u5F0F\u6267\u884C\n -Xinternalversion\n \u663E\u793A\u6BD4 -version \u9009\u9879\u66F4\u8BE6\u7EC6\u7684\n JVM \u7248\u672C\u4FE1\u606F\n -Xlog: \u914D\u7F6E\u6216\u542F\u7528\u91C7\u7528 Java \u865A\u62DF\n \u673A (Java Virtual Machine, JVM) \u7EDF\u4E00\u8BB0\u5F55\u6846\u67B6\u8FDB\u884C\u4E8B\u4EF6\u8BB0\u5F55\u3002\u4F7F\u7528 -Xlog:help\n \u53EF\u4E86\u89E3\u8BE6\u7EC6\u4FE1\u606F\u3002\n -Xloggc: \u5C06 GC \u72B6\u6001\u8BB0\u5F55\u5728\u6587\u4EF6\u4E2D\uFF08\u5E26\u65F6\u95F4\u6233\uFF09\u3002\n \u6B64\u9009\u9879\u5DF2\u8FC7\u65F6\uFF0C\u53EF\u80FD\u4F1A\u5728\n \u5C06\u6765\u7684\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\u5B83\u5C06\u66FF\u6362\u4E3A -Xlog:gc:\u3002\n -Xmixed \u6DF7\u5408\u6A21\u5F0F\u6267\u884C\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xmn \u4E3A\u5E74\u8F7B\u4EE3\uFF08\u65B0\u751F\u4EE3\uFF09\u8BBE\u7F6E\u521D\u59CB\u548C\u6700\u5927\u5806\u5927\u5C0F\n \uFF08\u4EE5\u5B57\u8282\u4E3A\u5355\u4F4D\uFF09\n -Xms \u8BBE\u7F6E\u521D\u59CB Java \u5806\u5927\u5C0F\n -Xmx \u8BBE\u7F6E\u6700\u5927 Java \u5806\u5927\u5C0F\n -Xnoclassgc \u7981\u7528\u7C7B\u5783\u573E\u6536\u96C6\n -Xrs \u51CF\u5C11 Java/VM \u5BF9\u64CD\u4F5C\u7CFB\u7EDF\u4FE1\u53F7\u7684\u4F7F\u7528\uFF08\u8BF7\u53C2\u89C1\u6587\u6863\uFF09\n -Xshare:auto \u5728\u53EF\u80FD\u7684\u60C5\u51B5\u4E0B\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF08\u9ED8\u8BA4\u503C\uFF09\n -Xshare:off \u4E0D\u5C1D\u8BD5\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\n -Xshare:on \u8981\u6C42\u4F7F\u7528\u5171\u4EAB\u7C7B\u6570\u636E\uFF0C\u5426\u5219\u5C06\u5931\u8D25\u3002\n \u8FD9\u662F\u4E00\u4E2A\u6D4B\u8BD5\u9009\u9879\uFF0C\u53EF\u80FD\u5BFC\u81F4\u95F4\u6B47\u6027\n \u6545\u969C\u3002\u4E0D\u5E94\u5728\u751F\u4EA7\u73AF\u5883\u4E2D\u4F7F\u7528\u5B83\u3002\n -XshowSettings \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:all\n \u663E\u793A\u6240\u6709\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:locale\n \u663E\u793A\u6240\u6709\u4E0E\u533A\u57DF\u8BBE\u7F6E\u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:properties\n \u663E\u793A\u6240\u6709\u5C5E\u6027\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:vm\n \u663E\u793A\u6240\u6709\u4E0E vm \u76F8\u5173\u7684\u8BBE\u7F6E\u5E76\u7EE7\u7EED\n -XshowSettings:system\n \uFF08\u4EC5 Linux\uFF09\u663E\u793A\u4E3B\u673A\u7CFB\u7EDF\u6216\u5BB9\u5668\n \u914D\u7F6E\u5E76\u7EE7\u7EED\n -Xss \u8BBE\u7F6E Java \u7EBF\u7A0B\u5806\u6808\u5927\u5C0F\n \ +\u5B9E\u9645\u5927\u5C0F\u53EF\u4EE5\u820D\u5165\u5230\n \u64CD\u4F5C\u7CFB\u7EDF\u8981\u6C42\u7684\u7CFB\u7EDF\u9875\u9762\u5927\u5C0F\u7684\u500D\u6570\u3002\n -Xverify \u8BBE\u7F6E\u5B57\u8282\u7801\u9A8C\u8BC1\u5668\u7684\u6A21\u5F0F\n \u8BF7\u6CE8\u610F\uFF0C\u9009\u9879 -Xverify:none \u5DF2\u8FC7\u65F6\uFF0C\n \u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002\n --add-reads =(,)*\n \u66F4\u65B0 \u4EE5\u8BFB\u53D6 \uFF0C\u800C\u65E0\u8BBA\n \u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002 \n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u8BFB\u53D6\u6240\u6709\u672A\u547D\u540D\n \u6A21\u5757\u3002\n --add-exports /=(,)*\n \u66F4\u65B0 \u4EE5\u5C06 \u5BFC\u51FA\u5230 \uFF0C\n \u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n \u53EF\u4EE5\u662F ALL-UNNAMED\uFF0C\u5C06\u5BFC\u51FA\u5230\u6240\u6709\n \u672A\u547D\u540D\u6A21\u5757\u3002\n --add-opens /=(,)*\n \u66F4\u65B0 \u4EE5\u5728 \u4E2D\u6253\u5F00\n \uFF0C\u800C\u65E0\u8BBA\u6A21\u5757\u5982\u4F55\u58F0\u660E\u3002\n --limit-modules [,...]\n \u9650\u5236\u53EF\u89C2\u5BDF\u6A21\u5757\u7684\u9886\u57DF\n --patch-module =({0})*\n \u4F7F\u7528 JAR \u6587\u4EF6\u6216\u76EE\u5F55\u4E2D\u7684\u7C7B\u548C\u8D44\u6E90\n \u8986\u76D6\u6216\u589E\u5F3A\u6A21\u5757\u3002\n --source \n \u8BBE\u7F6E\u6E90\u6587\u4EF6\u6A21\u5F0F\u4E2D\u6E90\u7684\u7248\u672C\u3002\n --finalization=\n \u63A7\u5236 JVM \u662F\u5426\u6267\u884C\u5BF9\u8C61\u6700\u7EC8\u5904\u7406\uFF0C\n \u5176\u4E2D \u4E3A "enabled" \u6216 "disabled" \u4E4B\u4E00\u3002\n \u9ED8\u8BA4\u60C5\u51B5\u4E0B\uFF0C\u6700\u7EC8\u5904\u7406\u5904\u4E8E\u542F\u7528\u72B6\u6001\u3002\n\n\u8FD9\u4E9B\u989D\u5916\u9009\u9879\u5982\u6709\u66F4\u6539, \u6055\u4E0D\u53E6\u884C\u901A\u77E5\u3002\n # Translators please note do not translate the options themselves java.launcher.X.macosx.usage=\n\u4EE5\u4E0B\u9009\u9879\u662F\u7279\u5B9A\u4E8E macOS \u7684\u9009\u9879\uFF1A\n -XstartOnFirstThread\n \u5728\u7B2C\u4E00\u4E2A (AppKit) \u7EBF\u7A0B\u4E0A\u8FD0\u884C main() \u65B9\u6CD5\n -Xdock:name=\n \u8986\u76D6\u505C\u9760\u680F\u4E2D\u663E\u793A\u7684\u9ED8\u8BA4\u5E94\u7528\u7A0B\u5E8F\u540D\u79F0\n -Xdock:icon=\n \u8986\u76D6\u505C\u9760\u680F\u4E2D\u663E\u793A\u7684\u9ED8\u8BA4\u56FE\u6807\n\n diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java index b2b3b6eb1cd..0ca86491dc4 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_de.java @@ -71,6 +71,8 @@ public class Resources_de extends java.util.ListResourceBundle { "{0} Secret Key generiert"}, //-genseckey {"Generated.keysize.bit.keyAlgName.secret.key", "{0}-Bit {1} Secret Key generiert"}, //-genseckey + {"key.algorithm.weak", "%1$s verwendet den Algorithmus %2$s. Das gilt als Sicherheitsrisiko."}, + {"key.size.weak", "%1$s verwendet %2$s. Dies gilt als Sicherheitsrisiko."}, {"Imports.entries.from.a.JDK.1.1.x.style.identity.database", "Importiert Eintr\u00E4ge aus einer Identity-Datenbank im JDK 1.1.x-Stil"}, //-identitydb {"Imports.a.certificate.or.a.certificate.chain", @@ -369,6 +371,8 @@ public class Resources_de extends java.util.ListResourceBundle { {"Enter.alias.name.", "Aliasnamen eingeben: "}, {".RETURN.if.same.as.for.otherAlias.", "\t(RETURN, wenn identisch mit <{0}>)"}, + {"enter.dname.components", + "Geben Sie den Distinguished Name ein. Geben Sie einen einzelnen Punkt (.) an, um eine Unterkomponente leer zu lassen, oder dr\u00FCcken Sie die Eingabetaste, um den Standardwert in Klammern zu verwenden."}, {"What.is.your.first.and.last.name.", "Wie lautet Ihr Vor- und Nachname?"}, {"What.is.the.name.of.your.organizational.unit.", @@ -381,6 +385,8 @@ public class Resources_de extends java.util.ListResourceBundle { "Wie lautet der Name Ihres Bundeslands?"}, {"What.is.the.two.letter.country.code.for.this.unit.", "Wie lautet der L\u00E4ndercode (zwei Buchstaben) f\u00FCr diese Einheit?"}, + {"no.field.in.dname", + "Mindestens ein Feld muss ausgef\u00FCllt werden. Wiederholen Sie die Eingabe."}, {"Is.name.correct.", "Ist {0} richtig?"}, {"no", "Nein"}, {"yes", "Ja"}, @@ -449,6 +455,7 @@ public class Resources_de extends java.util.ListResourceBundle { // generating cert/cert req using weak algorithms {"the.certificate.request", "Die Zertifikatsanforderung"}, {"the.issuer", "Der Aussteller"}, + {"the.generated.secretkey", "Der generierte Secret Key"}, {"the.generated.certificate", "Das generierte Zertifikat"}, {"the.generated.crl", "Die generierte CRL"}, {"the.generated.certificate.request", "Die generierte Zertifikatsanforderung"}, @@ -477,7 +484,7 @@ public class Resources_de extends java.util.ListResourceBundle { {"whose.sigalg.disabled", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko und ist deaktiviert."}, {"whose.sigalg.usagesignedjar", "%1$s verwendet den Signaturalgorithmus %2$s. Das gilt als Sicherheitsrisiko und kann nach %3$s nicht zum Signieren von JAR-Archiven verwendet werden."}, {"Unable.to.parse.denyAfter.string.in.exception.message", "denyAfter-Datumszeichenfolge in Ausnahmemeldung kann nicht geparst werden"}, - {"whose.sigalg.weak", "%1$s verwendet den Signaturalgorithmus %2$s. Dies gilt als Sicherheitsrisiko. Dieser Algorithmus wird in einem zuk\u00FCnftigen Update deaktiviert."}, + {"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. Dies gilt als Sicherheitsrisiko. Diese Schl\u00FCsselgr\u00F6\u00DFe wird in einem zuk\u00FCnftigen Update deaktiviert."}, {"jks.storetype.warning", "Der %1$s-Keystore verwendet ein propriet\u00E4res Format. Es wird empfohlen, auf PKCS12 zu migrieren, das ein Industriestandardformat mit \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\" ist."}, diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java index 45e8d5ef601..371aed4f127 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_ja.java @@ -71,6 +71,8 @@ public class Resources_ja extends java.util.ListResourceBundle { "{0}\u79D8\u5BC6\u30AD\u30FC\u3092\u751F\u6210\u3057\u307E\u3057\u305F"}, //-genseckey {"Generated.keysize.bit.keyAlgName.secret.key", "{0}\u30D3\u30C3\u30C8{1}\u79D8\u5BC6\u30AD\u30FC\u3092\u751F\u6210\u3057\u307E\u3057\u305F"}, //-genseckey + {"key.algorithm.weak", "%1$s\u306F%2$s\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"}, + {"key.size.weak", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"}, {"Imports.entries.from.a.JDK.1.1.x.style.identity.database", "JDK 1.1.x-style\u30A2\u30A4\u30C7\u30F3\u30C6\u30A3\u30C6\u30A3\u30FB\u30C7\u30FC\u30BF\u30D9\u30FC\u30B9\u304B\u3089\u30A8\u30F3\u30C8\u30EA\u3092\u30A4\u30F3\u30DD\u30FC\u30C8\u3057\u307E\u3059"}, //-identitydb {"Imports.a.certificate.or.a.certificate.chain", @@ -369,6 +371,8 @@ public class Resources_ja extends java.util.ListResourceBundle { {"Enter.alias.name.", "\u5225\u540D\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044: "}, {".RETURN.if.same.as.for.otherAlias.", "\t(<{0}>\u3068\u540C\u3058\u5834\u5408\u306FRETURN\u3092\u62BC\u3057\u3066\u304F\u3060\u3055\u3044)"}, + {"enter.dname.components", + "\u8B58\u5225\u540D\u3092\u5165\u529B\u3057\u307E\u3059\u3002\u30B5\u30D6\u30B3\u30F3\u30DD\u30FC\u30CD\u30F3\u30C8\u3092\u7A7A\u306E\u307E\u307E\u306B\u3059\u308B\u5834\u5408\u306F\u30C9\u30C3\u30C8(.)\u30921\u3064\u5165\u529B\u3057\u3001\u4E2D\u30AB\u30C3\u30B3\u5185\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u5024\u3092\u4F7F\u7528\u3059\u308B\u5834\u5408\u306F[ENTER]\u3092\u62BC\u3057\u307E\u3059\u3002"}, {"What.is.your.first.and.last.name.", "\u59D3\u540D\u306F\u4F55\u3067\u3059\u304B\u3002"}, {"What.is.the.name.of.your.organizational.unit.", @@ -381,6 +385,8 @@ public class Resources_ja extends java.util.ListResourceBundle { "\u90FD\u9053\u5E9C\u770C\u540D\u307E\u305F\u306F\u5DDE\u540D\u306F\u4F55\u3067\u3059\u304B\u3002"}, {"What.is.the.two.letter.country.code.for.this.unit.", "\u3053\u306E\u5358\u4F4D\u306B\u8A72\u5F53\u3059\u308B2\u6587\u5B57\u306E\u56FD\u30B3\u30FC\u30C9\u306F\u4F55\u3067\u3059\u304B\u3002"}, + {"no.field.in.dname", + "\u5C11\u306A\u304F\u3068\u30821\u3064\u306E\u30D5\u30A3\u30FC\u30EB\u30C9\u3092\u6307\u5B9A\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002\u518D\u5EA6\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, {"Is.name.correct.", "{0}\u3067\u3088\u308D\u3057\u3044\u3067\u3059\u304B\u3002"}, {"no", "\u3044\u3044\u3048"}, {"yes", "\u306F\u3044"}, @@ -449,6 +455,7 @@ public class Resources_ja extends java.util.ListResourceBundle { // generating cert/cert req using weak algorithms {"the.certificate.request", "\u8A3C\u660E\u66F8\u30EA\u30AF\u30A8\u30B9\u30C8"}, {"the.issuer", "\u767A\u884C\u8005"}, + {"the.generated.secretkey", "\u751F\u6210\u3055\u308C\u305F\u79D8\u5BC6\u30AD\u30FC"}, {"the.generated.certificate", "\u751F\u6210\u3055\u308C\u305F\u8A3C\u660E\u66F8"}, {"the.generated.crl", "\u751F\u6210\u3055\u308C\u305FCRL"}, {"the.generated.certificate.request", "\u751F\u6210\u3055\u308C\u305F\u8A3C\u660E\u66F8\u30EA\u30AF\u30A8\u30B9\u30C8"}, @@ -477,7 +484,7 @@ public class Resources_ja extends java.util.ListResourceBundle { {"whose.sigalg.disabled", "%1$s\u306F%2$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u3001\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059\u3002"}, {"whose.sigalg.usagesignedjar", "%1$s\u306F%2$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002%3$s\u306E\u5F8C\u3067JAR\u306B\u7F72\u540D\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002"}, {"Unable.to.parse.denyAfter.string.in.exception.message", "\u4F8B\u5916\u30E1\u30C3\u30BB\u30FC\u30B8\u306EdenyAfter\u65E5\u4ED8\u6587\u5B57\u5217\u3092\u89E3\u6790\u3067\u304D\u307E\u305B\u3093"}, - {"whose.sigalg.weak", "%1$s\u306F%2$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"}, + {"whose.sigalg.weak", "%1$s\u306F%2$s\u7F72\u540D\u30A2\u30EB\u30B4\u30EA\u30BA\u30E0\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002"}, {"whose.key.disabled", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u3001\u7121\u52B9\u5316\u3055\u308C\u3066\u3044\u307E\u3059\u3002"}, {"whose.key.weak", "%1$s\u306F%2$s\u3092\u4F7F\u7528\u3057\u3066\u304A\u308A\u3001\u3053\u308C\u306F\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u30FB\u30EA\u30B9\u30AF\u3068\u307F\u306A\u3055\u308C\u307E\u3059\u3002\u3053\u306E\u30AD\u30FC\u30FB\u30B5\u30A4\u30BA\u306F\u5C06\u6765\u306E\u66F4\u65B0\u3067\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002"}, {"jks.storetype.warning", "%1$s\u30AD\u30FC\u30B9\u30C8\u30A2\u306F\u72EC\u81EA\u306E\u5F62\u5F0F\u3092\u4F7F\u7528\u3057\u3066\u3044\u307E\u3059\u3002\"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\"\u3092\u4F7F\u7528\u3059\u308B\u696D\u754C\u6A19\u6E96\u306E\u5F62\u5F0F\u3067\u3042\u308BPKCS12\u306B\u79FB\u884C\u3059\u308B\u3053\u3068\u3092\u304A\u85A6\u3081\u3057\u307E\u3059\u3002"}, diff --git a/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java b/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java index 67a47428995..0ea8df66003 100644 --- a/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java +++ b/src/java.base/share/classes/sun/security/tools/keytool/Resources_zh_CN.java @@ -71,6 +71,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u5DF2\u751F\u6210{0}\u5BC6\u94A5"}, //-genseckey {"Generated.keysize.bit.keyAlgName.secret.key", "\u5DF2\u751F\u6210 {0} \u4F4D{1}\u5BC6\u94A5"}, //-genseckey + {"key.algorithm.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002"}, + {"key.size.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002"}, {"Imports.entries.from.a.JDK.1.1.x.style.identity.database", "\u4ECE JDK 1.1.x \u6837\u5F0F\u7684\u8EAB\u4EFD\u6570\u636E\u5E93\u5BFC\u5165\u6761\u76EE"}, //-identitydb {"Imports.a.certificate.or.a.certificate.chain", @@ -369,6 +371,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"Enter.alias.name.", "\u8F93\u5165\u522B\u540D: "}, {".RETURN.if.same.as.for.otherAlias.", "\t(\u5982\u679C\u548C <{0}> \u76F8\u540C, \u5219\u6309\u56DE\u8F66)"}, + {"enter.dname.components", + "\u8F93\u5165\u552F\u4E00\u5224\u522B\u540D\u3002\u63D0\u4F9B\u5355\u4E2A\u70B9 (.) \u4EE5\u5C06\u5B50\u7EC4\u4EF6\u7559\u7A7A\uFF0C\u6216\u6309 ENTER \u4EE5\u4F7F\u7528\u5927\u62EC\u53F7\u4E2D\u7684\u9ED8\u8BA4\u503C\u3002"}, {"What.is.your.first.and.last.name.", "\u60A8\u7684\u540D\u5B57\u4E0E\u59D3\u6C0F\u662F\u4EC0\u4E48?"}, {"What.is.the.name.of.your.organizational.unit.", @@ -381,6 +385,8 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { "\u60A8\u6240\u5728\u7684\u7701/\u5E02/\u81EA\u6CBB\u533A\u540D\u79F0\u662F\u4EC0\u4E48?"}, {"What.is.the.two.letter.country.code.for.this.unit.", "\u8BE5\u5355\u4F4D\u7684\u53CC\u5B57\u6BCD\u56FD\u5BB6/\u5730\u533A\u4EE3\u7801\u662F\u4EC0\u4E48?"}, + {"no.field.in.dname", + "\u5FC5\u987B\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u5B57\u6BB5\u3002\u8BF7\u518D\u6B21\u8F93\u5165\u3002"}, {"Is.name.correct.", "{0}\u662F\u5426\u6B63\u786E?"}, {"no", "\u5426"}, {"yes", "\u662F"}, @@ -449,6 +455,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { // generating cert/cert req using weak algorithms {"the.certificate.request", "\u8BC1\u4E66\u8BF7\u6C42"}, {"the.issuer", "\u53D1\u5E03\u8005"}, + {"the.generated.secretkey", "\u751F\u6210\u7684\u5BC6\u94A5"}, {"the.generated.certificate", "\u751F\u6210\u7684\u8BC1\u4E66"}, {"the.generated.crl", "\u751F\u6210\u7684 CRL"}, {"the.generated.certificate.request", "\u751F\u6210\u7684\u8BC1\u4E66\u8BF7\u6C42"}, @@ -477,7 +484,7 @@ public class Resources_zh_CN extends java.util.ListResourceBundle { {"whose.sigalg.disabled", "%1$s \u4F7F\u7528\u7684 %2$s \u7B7E\u540D\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u800C\u4E14\u88AB\u7981\u7528\u3002"}, {"whose.sigalg.usagesignedjar", "%1$s \u4F7F\u7528\u7684 %2$s \u7B7E\u540D\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\uFF0C\u65E0\u6CD5\u7528\u4E8E\u5728 %3$s \u540E\u5BF9 JAR \u8FDB\u884C\u7B7E\u540D\u3002"}, {"Unable.to.parse.denyAfter.string.in.exception.message", "\u65E0\u6CD5\u89E3\u6790\u5F02\u5E38\u9519\u8BEF\u6D88\u606F\u4E2D\u7684 denyAfter \u65E5\u671F\u5B57\u7B26\u4E32"}, - {"whose.sigalg.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u7B7E\u540D\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u7B97\u6CD5\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"}, + {"whose.sigalg.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u7B7E\u540D\u7B97\u6CD5\u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002"}, {"whose.key.disabled", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u800C\u4E14\u88AB\u7981\u7528\u3002"}, {"whose.key.weak", "%1$s \u4F7F\u7528\u7684 %2$s \u88AB\u89C6\u4E3A\u5B58\u5728\u5B89\u5168\u98CE\u9669\u3002\u6B64\u5BC6\u94A5\u5927\u5C0F\u5C06\u5728\u672A\u6765\u7684\u66F4\u65B0\u4E2D\u88AB\u7981\u7528\u3002"}, {"jks.storetype.warning", "%1$s \u5BC6\u94A5\u5E93\u4F7F\u7528\u4E13\u7528\u683C\u5F0F\u3002\u5EFA\u8BAE\u4F7F\u7528 \"keytool -importkeystore -srckeystore %2$s -destkeystore %2$s -deststoretype pkcs12\" \u8FC1\u79FB\u5230\u884C\u4E1A\u6807\u51C6\u683C\u5F0F PKCS12\u3002"}, diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties index 1b722e58c84..1b11186a95a 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_de.properties @@ -95,7 +95,7 @@ joinrowsetimpl.numnotequal = Elementanzahl in rowset nicht gleich \u00DCbereinst joinrowsetimpl.notdefined = Kein definierter Join-Typ joinrowsetimpl.notsupported = Join-Typ wird nicht unterst\u00FCtzt joinrowsetimpl.initerror = JoinRowSet-Initialisierungsfehler -joinrowsetimpl.genericerr = Generischer Anfangsfehler bei joinrowset +joinrowsetimpl.genericerr = Generischer JoinRowSet-Initialisierungsfehler joinrowsetimpl.emptyrowset = Leeres rowset kann nicht zu diesem JoinRowSet hinzugef\u00FCgt werden #JdbcRowSetImpl exceptions diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties index cd40ad2ef42..ef439225771 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_ja.properties @@ -95,7 +95,7 @@ joinrowsetimpl.numnotequal = \u884C\u30BB\u30C3\u30C8\u306E\u8981\u7D20\u6570\u3 joinrowsetimpl.notdefined = \u5B9A\u7FA9\u3055\u308C\u305F\u7D50\u5408\u306E\u30BF\u30A4\u30D7\u3067\u306F\u3042\u308A\u307E\u305B\u3093 joinrowsetimpl.notsupported = \u3053\u306E\u30BF\u30A4\u30D7\u306E\u7D50\u5408\u306F\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093 joinrowsetimpl.initerror = JoinRowSet\u521D\u671F\u5316\u30A8\u30E9\u30FC -joinrowsetimpl.genericerr = \u6C4E\u7528joinrowset\u306E\u521D\u671F\u30A8\u30E9\u30FC +joinrowsetimpl.genericerr = \u4E00\u822C\u7684\u306Ajoinrowset\u521D\u671F\u30A8\u30E9\u30FC joinrowsetimpl.emptyrowset = \u3053\u306EJoinRowSet\u306B\u7A7A\u306E\u884C\u30BB\u30C3\u30C8\u3092\u8FFD\u52A0\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 #JdbcRowSetImpl exceptions diff --git a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties index a9f1203518c..2e6cd2e6ca6 100644 --- a/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties +++ b/src/java.sql.rowset/share/classes/com/sun/rowset/RowSetResourceBundle_zh_CN.properties @@ -95,7 +95,7 @@ joinrowsetimpl.numnotequal = RowSet \u4E2D\u7684\u5143\u7D20\u4E2A\u6570\u4E0D\u joinrowsetimpl.notdefined = \u8FD9\u4E0D\u662F\u5B9A\u4E49\u7684\u8054\u63A5\u7C7B\u578B joinrowsetimpl.notsupported = \u4E0D\u652F\u6301\u6B64\u8054\u63A5\u7C7B\u578B joinrowsetimpl.initerror = JoinRowSet \u521D\u59CB\u5316\u9519\u8BEF -joinrowsetimpl.genericerr = \u4E00\u822C JoinRowSet \u521D\u59CB\u5316\u9519\u8BEF +joinrowsetimpl.genericerr = \u4E00\u822C joinrowset \u521D\u59CB\u9519\u8BEF joinrowsetimpl.emptyrowset = \u65E0\u6CD5\u5C06\u7A7A RowSet \u6DFB\u52A0\u5230\u6B64 JoinRowSet #JdbcRowSetImpl exceptions diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java index 07ea3779a20..a6f8370a2d7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,6 +31,7 @@ * Array. You also need to update MAX_CODE for error strings * and MAX_WARNING for warnings ( Needed for only information * purpose ) + * @LastModified: May 2022 */ public class XSLTErrorResources_de extends ListResourceBundle { @@ -1333,7 +1334,6 @@ public Object[][] getContents() // for the Xalan Process command line. "Process" is the name of a Java class, // and should not be translated. { "xslProc_option", "Xalan-J-Befehlszeile - \"Process\"-Klassenoptionen:"}, - { "xslProc_option", "Xalan-J-Befehlszeile - \"Process\"-Klassenoptionen:"}, { "xslProc_invalid_xsltc_option", "Option {0} wird im XSLTC-Modus nicht unterst\u00FCtzt."}, { "xslProc_invalid_xalan_option", "Option {0} kann nur mit -XSLTC verwendet werden."}, { "xslProc_no_input", "Fehler: Kein Stylesheet und keine Eingabe-XML angegeben. F\u00FChren Sie diesen Befehl ohne Optionen f\u00FCr Verwendungsanweisungen aus."}, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java index 5356ee53c92..cf8a0f2563b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,6 +31,7 @@ * Array. You also need to update MAX_CODE for error strings * and MAX_WARNING for warnings ( Needed for only information * purpose ) + * @LastModified: May 2022 */ public class XSLTErrorResources_ja extends ListResourceBundle { @@ -1333,7 +1334,6 @@ public Object[][] getContents() // for the Xalan Process command line. "Process" is the name of a Java class, // and should not be translated. { "xslProc_option", "Xalan-J\u30B3\u30DE\u30F3\u30C9\u884C\u30D7\u30ED\u30BB\u30B9\u30FB\u30AF\u30E9\u30B9\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:"}, - { "xslProc_option", "Xalan-J\u30B3\u30DE\u30F3\u30C9\u884C\u30D7\u30ED\u30BB\u30B9\u30FB\u30AF\u30E9\u30B9\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:"}, { "xslProc_invalid_xsltc_option", "\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306FXSLTC\u30E2\u30FC\u30C9\u3067\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, { "xslProc_invalid_xalan_option", "\u30AA\u30D7\u30B7\u30E7\u30F3{0}\u306F-XSLTC\u3068\u3068\u3082\u306B\u306E\u307F\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002"}, { "xslProc_no_input", "\u30A8\u30E9\u30FC: \u30B9\u30BF\u30A4\u30EB\u30B7\u30FC\u30C8\u307E\u305F\u306F\u5165\u529Bxml\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u4F7F\u7528\u65B9\u6CD5\u306E\u6307\u793A\u306B\u3064\u3044\u3066\u306F\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u4ED8\u3051\u305A\u306B\u3053\u306E\u30B3\u30DE\u30F3\u30C9\u3092\u5B9F\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002"}, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java index 07b91a7ae21..dd079666cd8 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/res/XSLTErrorResources_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -31,6 +31,7 @@ * Array. You also need to update MAX_CODE for error strings * and MAX_WARNING for warnings ( Needed for only information * purpose ) + * @LastModified: May 2022 */ public class XSLTErrorResources_zh_CN extends ListResourceBundle { @@ -1333,7 +1334,6 @@ public Object[][] getContents() // for the Xalan Process command line. "Process" is the name of a Java class, // and should not be translated. { "xslProc_option", "Xalan-J \u547D\u4EE4\u884C Process \u7C7B\u9009\u9879:"}, - { "xslProc_option", "Xalan-J \u547D\u4EE4\u884C Process \u7C7B\u9009\u9879:"}, { "xslProc_invalid_xsltc_option", "XSLTC \u6A21\u5F0F\u4E0B\u4E0D\u652F\u6301\u9009\u9879{0}\u3002"}, { "xslProc_invalid_xalan_option", "\u9009\u9879{0}\u53EA\u80FD\u4E0E -XSLTC \u4E00\u8D77\u4F7F\u7528\u3002"}, { "xslProc_no_input", "\u9519\u8BEF: \u672A\u6307\u5B9A\u6837\u5F0F\u8868\u6216\u8F93\u5165 xml\u3002\u8FD0\u884C\u6B64\u547D\u4EE4\u65F6, \u7528\u6CD5\u6307\u4EE4\u4E0D\u5E26\u4EFB\u4F55\u9009\u9879\u3002"}, diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java index ea6eecee48d..a73fe47191f 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_de.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +24,7 @@ /** * @author Morten Jorgensen + * @LastModified: Jan 2022 */ public class ErrorMessages_de extends ListResourceBundle { @@ -980,9 +981,16 @@ public Object[][] getContents() "Interner XSLTC-Fehler: Eine Methode im Translet \u00FCberschreitet die Java Virtual Machine-L\u00E4ngeneinschr\u00E4nkung einer Methode von 64 KB. Ursache hierf\u00FCr sind in der Regel sehr gro\u00DFe Vorlagen in einem Stylesheet. Versuchen Sie, das Stylesheet mit kleineren Vorlagen umzustrukturieren." }, - {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "Wenn die Java-Sicherheit aktiviert ist, ist die Unterst\u00FCtzung f\u00FCr das Deserialisieren von TemplatesImpl deaktiviert. Dies kann durch Setzen der Systemeigenschaft jdk.xml.enableTemplatesImplDeserialization auf \"True\" au\u00DFer Kraft gesetzt werden."} + {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "Wenn die Java-Sicherheit aktiviert ist, wird die Unterst\u00FCtzung f\u00FCr das Deserialisieren von TemplatesImpl deaktiviert. Dieses Verhalten kann durch Setzen der Systemeigenschaft jdk.xml.enableTemplatesImplDeserialization auf \"true\" au\u00DFer Kraft gesetzt werden."}, - }; + {ErrorMsg.XPATH_GROUP_LIMIT, + "JAXP0801001: Im Compiler ist ein XPath-Ausdruck mit {0} Gruppen aufgetreten, der den von \"{2}\" festgelegten Grenzwert \"{1}\" \u00FCberschreitet."}, + + {ErrorMsg.XPATH_OPERATOR_LIMIT, + "JAXP0801002: Im Compiler ist ein XPath-Ausdruck mit {0} Operatoren aufgetreten, der den von \"{2}\" festgelegten Grenzwert \"{1}\" \u00FCberschreitet."}, + {ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT, + "JAXP0801003: Im Compiler sind XPath-Ausdr\u00FCcke mit insgesamt {0} Operatoren aufgetreten, die den von \"{2}\" festgelegten Grenzwert \"{1}\" \u00FCberschreiten."}, + }; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java index 1b6a3ef0aba..ba170bdfffa 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_ja.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +24,7 @@ /** * @author Morten Jorgensen + * @LastModified: Jan 2022 */ public class ErrorMessages_ja extends ListResourceBundle { @@ -980,9 +981,16 @@ public Object[][] getContents() "\u5185\u90E8XSLTC\u30A8\u30E9\u30FC: \u30C8\u30E9\u30F3\u30B9\u30EC\u30C3\u30C8\u5185\u306E\u30E1\u30BD\u30C3\u30C9\u304C\u3001Java\u4EEE\u60F3\u30DE\u30B7\u30F3\u306E\u5236\u9650(1\u30E1\u30BD\u30C3\u30C9\u306E\u9577\u3055\u306F\u6700\u592764\u30AD\u30ED\u30D0\u30A4\u30C8)\u3092\u8D85\u3048\u3066\u3044\u307E\u3059\u3002\u4E00\u822C\u7684\u306B\u3001\u30B9\u30BF\u30A4\u30EB\u30B7\u30FC\u30C8\u5185\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306E\u30B5\u30A4\u30BA\u304C\u5927\u304D\u904E\u304E\u308B\u3053\u3068\u304C\u539F\u56E0\u3068\u3057\u3066\u8003\u3048\u3089\u308C\u307E\u3059\u3002\u5C0F\u3055\u3044\u30B5\u30A4\u30BA\u306E\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u3092\u4F7F\u7528\u3057\u3066\u3001\u30B9\u30BF\u30A4\u30EB\u30B7\u30FC\u30C8\u3092\u518D\u69CB\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002" }, - {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "Java\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u304C\u6709\u52B9\u5316\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001TemplatesImpl\u306E\u30C7\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u306E\u30B5\u30DD\u30FC\u30C8\u306F\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002\u3053\u308C\u306F\u3001jdk.xml.enableTemplatesImplDeserialization\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3092true\u306B\u8A2D\u5B9A\u3057\u3066\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3067\u304D\u307E\u3059\u3002"} + {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "Java\u30BB\u30AD\u30E5\u30EA\u30C6\u30A3\u304C\u6709\u52B9\u5316\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u3001TemplatesImpl\u306E\u30C7\u30B7\u30EA\u30A2\u30E9\u30A4\u30BA\u306E\u30B5\u30DD\u30FC\u30C8\u306F\u7121\u52B9\u5316\u3055\u308C\u307E\u3059\u3002\u3053\u308C\u306F\u3001jdk.xml.enableTemplatesImplDeserialization\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u3092true\u306B\u8A2D\u5B9A\u3057\u3066\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3067\u304D\u307E\u3059\u3002"}, - }; + {ErrorMsg.XPATH_GROUP_LIMIT, + "JAXP0801001: \u30B3\u30F3\u30D1\u30A4\u30E9\u306F\u3001''{2}''\u3067\u8A2D\u5B9A\u3055\u308C\u305F''{1}''\u5236\u9650\u3092\u8D85\u3048\u308B''{0}''\u30B0\u30EB\u30FC\u30D7\u3092\u542B\u3080XPath\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002"}, + + {ErrorMsg.XPATH_OPERATOR_LIMIT, + "JAXP0801002: \u30B3\u30F3\u30D1\u30A4\u30E9\u306F\u3001''{2}''\u3067\u8A2D\u5B9A\u3055\u308C\u305F''{1}''\u5236\u9650\u3092\u8D85\u3048\u308B''{0}''\u6F14\u7B97\u5B50\u3092\u542B\u3080XPath\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002"}, + {ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT, + "JAXP0801003: \u30B3\u30F3\u30D1\u30A4\u30E9\u306F\u3001''{2}''\u3067\u8A2D\u5B9A\u3055\u308C\u305F''{1}''\u5236\u9650\u3092\u8D85\u3048\u308B\u7D2F\u7A4D''{0}''\u6F14\u7B97\u5B50\u3092\u542B\u3080XPath\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002"}, + }; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java index 569fe5fe3fb..7a96e488a9a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/xsltc/compiler/util/ErrorMessages_zh_CN.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2016, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2022, Oracle and/or its affiliates. All rights reserved. */ /* * Licensed to the Apache Software Foundation (ASF) under one or more @@ -24,6 +24,7 @@ /** * @author Morten Jorgensen + * @LastModified: Jan 2022 */ public class ErrorMessages_zh_CN extends ListResourceBundle { @@ -980,9 +981,16 @@ public Object[][] getContents() "\u5185\u90E8 XSLTC \u9519\u8BEF: translet \u4E2D\u7684\u65B9\u6CD5\u8D85\u8FC7\u4E86 Java \u865A\u62DF\u673A\u7684\u65B9\u6CD5\u957F\u5EA6\u9650\u5236 64 KB\u3002\u8FD9\u901A\u5E38\u662F\u7531\u4E8E\u6837\u5F0F\u8868\u4E2D\u7684\u6A21\u677F\u975E\u5E38\u5927\u9020\u6210\u7684\u3002\u8BF7\u5C1D\u8BD5\u4F7F\u7528\u8F83\u5C0F\u7684\u6A21\u677F\u91CD\u65B0\u6784\u5EFA\u6837\u5F0F\u8868\u3002" }, - {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "\u542F\u7528\u4E86 Java \u5B89\u5168\u65F6, \u5C06\u7981\u7528\u5BF9\u53CD\u5E8F\u5217\u5316 TemplatesImpl \u7684\u652F\u6301\u3002\u53EF\u4EE5\u901A\u8FC7\u5C06 jdk.xml.enableTemplatesImplDeserialization \u7CFB\u7EDF\u5C5E\u6027\u8BBE\u7F6E\u4E3A\u201C\u771F\u201D\u6765\u8986\u76D6\u6B64\u8BBE\u7F6E\u3002"} + {ErrorMsg.DESERIALIZE_TRANSLET_ERR, "\u542F\u7528\u4E86 Java \u5B89\u5168\u65F6\uFF0C\u5C06\u7981\u7528\u5BF9\u53CD\u5E8F\u5217\u5316 TemplatesImpl \u7684\u652F\u6301\u3002\u53EF\u4EE5\u901A\u8FC7\u5C06 jdk.xml.enableTemplatesImplDeserialization \u7CFB\u7EDF\u5C5E\u6027\u8BBE\u7F6E\u4E3A true \u6765\u8986\u76D6\u6B64\u8BBE\u7F6E\u3002"}, - }; + {ErrorMsg.XPATH_GROUP_LIMIT, + "JAXP0801001\uFF1A\u7F16\u8BD1\u5668\u9047\u5230\u5305\u542B ''{0}'' \u7EC4\u7684 XPath \u8868\u8FBE\u5F0F\uFF0C\u8BE5\u8868\u8FBE\u5F0F\u8D85\u8FC7\u4E86 ''{2}'' \u8BBE\u7F6E\u7684 ''{1}'' \u9650\u5236\u3002"}, + + {ErrorMsg.XPATH_OPERATOR_LIMIT, + "JAXP0801002\uFF1A\u7F16\u8BD1\u5668\u9047\u5230\u5305\u542B ''{0}'' \u8FD0\u7B97\u7B26\u7684 XPath \u8868\u8FBE\u5F0F\uFF0C\u8BE5\u8868\u8FBE\u5F0F\u8D85\u8FC7\u4E86 ''{2}'' \u8BBE\u7F6E\u7684 ''{1}'' \u9650\u5236\u3002"}, + {ErrorMsg.XPATH_TOTAL_OPERATOR_LIMIT, + "JAXP0801003\uFF1A\u7F16\u8BD1\u5668\u9047\u5230\u5305\u542B\u7D2F\u8BA1 ''{0}'' \u8FD0\u7B97\u7B26\u7684 XPath \u8868\u8FBE\u5F0F\uFF0C\u8BE5\u8868\u8FBE\u5F0F\u8D85\u8FC7\u4E86 ''{2}'' \u8BBE\u7F6E\u7684 ''{1}'' \u9650\u5236\u3002"}, + }; } } diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties index 5b802e6ea58..e5dab4b0071 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # DOM implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties index c6fe53e399b..72243721f4a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # DOM implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties index 2f74f54fbab..0c691400129 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DOMMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # DOM implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties index 4bbbaea3b1f..be92cdd2015 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties index a8ef5dbddc0..38da17fc51a 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties index e5b9aca2e70..fabcd1973f1 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/DatatypeMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Datatype API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties index 820fc8fb2e3..4573321f537 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties index 267c886ffed..f088d5e08a5 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties index 9ffbd1c608e..8de5743830d 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/JAXPValidationMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces JAXP Validation API implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties index 4f6a8717006..60a03e533bb 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties index 0c6c98dc312..beddd1ae0c7 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties index 0d6e7a12242..39f23c199ab 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/SAXMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces # SAX implementation. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties index 412d96f917e..59a94a7c48b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # Messages for message reporting BadMessageKey = Die zum Meldungsschl\u00FCssel geh\u00F6rige Fehlermeldung kann nicht gefunden werden. FormatFailed = Beim Formatieren der folgenden Meldung ist ein interner Fehler aufgetreten:\n diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties index 55abfda9b23..30c510189e0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # Messages for message reporting BadMessageKey = \u30E1\u30C3\u30BB\u30FC\u30B8\u30FB\u30AD\u30FC\u306B\u5BFE\u5FDC\u3059\u308B\u30A8\u30E9\u30FC\u30FB\u30E1\u30C3\u30BB\u30FC\u30B8\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002 FormatFailed = \u6B21\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u306E\u66F8\u5F0F\u8A2D\u5B9A\u4E2D\u306B\u5185\u90E8\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F:\n diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties index 8e32a7337a1..15c677e3198 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XIncludeMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # Messages for message reporting BadMessageKey = \u627E\u4E0D\u5230\u4E0E\u6D88\u606F\u5173\u952E\u5B57\u5BF9\u5E94\u7684\u9519\u8BEF\u6D88\u606F\u3002 FormatFailed = \u8BBE\u7F6E\u4EE5\u4E0B\u6D88\u606F\u7684\u683C\u5F0F\u65F6\u51FA\u73B0\u5185\u90E8\u9519\u8BEF:\n diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties index 3848d68aa2e..744123405e2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML # The messages are arranged in key and value tuples in a ListResourceBundle. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties index 7001ef45266..f52b2597f8c 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML # The messages are arranged in key and value tuples in a ListResourceBundle. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties index ac05ad875c6..9c94a2ffd5b 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML # The messages are arranged in key and value tuples in a ListResourceBundle. # diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties index 9ca2596f92e..39fe87255ac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. @@ -49,6 +66,7 @@ cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: Element ''{0}'' hat keinen Attributplatzhalter f\u00FCr Attribut ''{1}''. cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: Attribut ''{1}'' darf nicht in Element ''{0}'' vorkommen. cvc-complex-type.4 = cvc-complex-type.4: Attribut ''{1}'' muss in Element ''{0}'' vorkommen. + cvc-complex-type.4_ns = cvc-complex-type.4: Attribut "{1}" von Namespace "{2}" muss in Element "{0}" vorkommen. cvc-complex-type.5.1 = cvc-complex-type.5.1: In Element ''{0}'' ist Attribut ''{1}'' ein Platzhalter. Es ist aber bereits ein Platzhalter ''{2}'' vorhanden. Nur ein Platzhalter ist zul\u00E4ssig. cvc-complex-type.5.2 = cvc-complex-type.5.2: In Element ''{0}'' ist Attribut ''{1}'' ein Platzhalter. Es ist aber bereits ein Attribut ''{2}'' vorhanden, das von einer ID unter den '{'attribute uses'}' abgeleitet wurde. cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}'' ist kein g\u00FCltiger Wert f\u00FCr ''{1}''. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties index bcf6b336eb7..74f2198b1a2 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. @@ -49,6 +66,7 @@ cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: \u8981\u7D20''{0}''\u306B\u3001\u5C5E\u6027''{1}''\u7528\u306E\u5C5E\u6027\u30EF\u30A4\u30EB\u30C9\u30AB\u30FC\u30C9\u304C\u3042\u308A\u307E\u305B\u3093\u3002 cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: \u8981\u7D20''{0}''\u306B\u5C5E\u6027''{1}''\u3092\u542B\u3081\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093\u3002 cvc-complex-type.4 = cvc-complex-type.4: \u8981\u7D20''{0}''\u306B\u5C5E\u6027''{1}''\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 + cvc-complex-type.4_ns = cvc-complex-type.4: \u8981\u7D20''{0}''\u306B\u3001\u30CD\u30FC\u30E0\u30B9\u30DA\u30FC\u30B9''{2}''\u306B\u5C5E\u3059\u308B\u5C5E\u6027''{1}''\u304C\u542B\u307E\u308C\u3066\u3044\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002 cvc-complex-type.5.1 = cvc-complex-type.5.1: \u8981\u7D20''{0}''\u3067\u306F\u5C5E\u6027''{1}''\u304CWild ID\u3067\u3059\u304C\u3001\u3059\u3067\u306BWild ID ''{2}''\u304C\u5B58\u5728\u3057\u3066\u3044\u307E\u3059\u3002\u8A31\u53EF\u3055\u308C\u308BWild ID\u306F1\u3064\u306E\u307F\u3067\u3059\u3002 cvc-complex-type.5.2 = cvc-complex-type.5.2: \u8981\u7D20''{0}''\u3067\u306F\u5C5E\u6027''{1}''\u304CWild ID\u3067\u3059\u304C\u3001ID\u304B\u3089\u5C0E\u51FA\u3055\u308C\u305F\u5C5E\u6027''{2}''\u304C'{'attribute uses'}'\u306B\u3059\u3067\u306B\u5B58\u5728\u3057\u3066\u3044\u307E\u3059\u3002 cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}''\u306F''{1}''\u306E\u6709\u52B9\u306A\u5024\u3067\u306F\u3042\u308A\u307E\u305B\u3093\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties index 4e9a16dcb4f..85542d0d181 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSchemaMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file contains error and warning messages related to XML Schema # The messages are arranged in key and value tuples in a ListResourceBundle. @@ -49,6 +66,7 @@ cvc-complex-type.3.2.1 = cvc-complex-type.3.2.1: \u5143\u7D20 ''{0}'' \u6CA1\u6709\u5C5E\u6027 ''{1}'' \u7684\u5C5E\u6027\u901A\u914D\u7B26\u3002 cvc-complex-type.3.2.2 = cvc-complex-type.3.2.2: \u5143\u7D20 ''{0}'' \u4E2D\u4E0D\u5141\u8BB8\u51FA\u73B0\u5C5E\u6027 ''{1}''\u3002 cvc-complex-type.4 = cvc-complex-type.4: \u5143\u7D20 ''{0}'' \u4E2D\u5FC5\u987B\u5305\u542B\u5C5E\u6027 ''{1}''\u3002 + cvc-complex-type.4_ns = cvc-complex-type.4\uFF1A\u5143\u7D20 ''{0}'' \u4E2D\u5FC5\u987B\u5305\u542B\u5C5E\u4E8E\u540D\u79F0\u7A7A\u95F4 ''{2}'' \u7684\u5C5E\u6027 ''{1}''\u3002 cvc-complex-type.5.1 = cvc-complex-type.5.1: \u5728\u5143\u7D20 ''{0}'' \u4E2D, \u5C5E\u6027 ''{1}'' \u662F\u4E00\u4E2A\u901A\u7528 ID\u3002\u4F46\u5DF2\u5B58\u5728\u901A\u7528 ID ''{2}''\u3002\u53EA\u80FD\u6709\u4E00\u4E2A\u901A\u7528 ID\u3002 cvc-complex-type.5.2 = cvc-complex-type.5.2: \u5728\u5143\u7D20 ''{0}'' \u4E2D, \u5C5E\u6027 ''{1}'' \u662F\u4E00\u4E2A\u901A\u7528 ID\u3002\u4F46\u5DF2\u6709\u4E00\u4E2A\u5C5E\u6027 ''{2}'' \u662F\u4ECE '{'attribute uses'}' \u4E2D\u7684 ID \u6D3E\u751F\u7684\u3002 cvc-datatype-valid.1.2.1 = cvc-datatype-valid.1.2.1: ''{0}'' \u4E0D\u662F ''{1}'' \u7684\u6709\u6548\u503C\u3002 diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties index c5b5cdbd949..c1b7901faa0 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties index b61a63b5b74..74346b3f7ea 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties index 4db14a65c4d..21c2c8d4d70 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XMLSerializerMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores error messages for the Xerces XML # serializer. Many DOM Load/Save error messages also # live here, since the serializer largely implements that package. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties index 3d33f7b8699..4a98a4e3707 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_de.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties index a9348831605..b38985677ac 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_ja.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties index bbf46c70eb7..cb1886a09ce 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties +++ b/src/java.xml/share/classes/com/sun/org/apache/xerces/internal/impl/msg/XPointerMessages_zh_CN.properties @@ -1,3 +1,20 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed with +# this work for additional information regarding copyright ownership. +# The ASF licenses this file to You under the Apache License, Version 2.0 +# (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + # This file stores localized messages for the Xerces XPointer implementation. # # The messages are arranged in key and value tuples in a ListResourceBundle. diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java index fb02896ce54..1b3cdb55961 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_de.java @@ -140,6 +140,7 @@ public class XPATHErrorResources_de extends ListResourceBundle "ER_EXPECTED_SINGLE_QUOTE"; public static final String ER_EMPTY_EXPRESSION = "ER_EMPTY_EXPRESSION"; public static final String ER_EXPECTED_BUT_FOUND = "ER_EXPECTED_BUT_FOUND"; + public static final String ER_UNION_MUST_BE_NODESET = "ER_UNION_MUST_BE_NODESET"; public static final String ER_INCORRECT_PROGRAMMER_ASSERTION = "ER_INCORRECT_PROGRAMMER_ASSERTION"; public static final String ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL = @@ -203,9 +204,6 @@ public class XPATHErrorResources_de extends ListResourceBundle "ER_FUNCTION_TOKEN_NOT_FOUND"; public static final String ER_CANNOT_DEAL_XPATH_TYPE = "ER_CANNOT_DEAL_XPATH_TYPE"; - public static final String ER_NODESET_NOT_MUTABLE = "ER_NODESET_NOT_MUTABLE"; - public static final String ER_NODESETDTM_NOT_MUTABLE = - "ER_NODESETDTM_NOT_MUTABLE"; /** Variable not resolvable: */ public static final String ER_VAR_NOT_RESOLVABLE = "ER_VAR_NOT_RESOLVABLE"; /** Null error handler */ @@ -309,6 +307,8 @@ public class XPATHErrorResources_de extends ListResourceBundle //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; + public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; + public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; public static final String ER_UNSUPPORTED_RETURN_TYPE = "ER_UNSUPPORTED_RETURN_TYPE"; public static final String ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL = "ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL"; public static final String ER_ARG_CANNOT_BE_NULL = "ER_ARG_CANNOT_BE_NULL"; @@ -326,6 +326,9 @@ public class XPATHErrorResources_de extends ListResourceBundle public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; + public static final String ER_XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT"; + public static final String ER_XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT"; + //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -457,6 +460,9 @@ public class XPATHErrorResources_de extends ListResourceBundle { ER_EXPECTED_BUT_FOUND, "{0} erwartet, aber {1} gefunden"}, + { ER_UNION_MUST_BE_NODESET, + "Operanden f\u00FCr eine Vereinigungsmenge m\u00FCssen Knotensets sein."}, + { ER_INCORRECT_PROGRAMMER_ASSERTION, "Programmierer-Assertion ist falsch. - {0}"}, @@ -571,12 +577,6 @@ public class XPATHErrorResources_de extends ListResourceBundle { ER_CANNOT_DEAL_XPATH_TYPE, "XPath-Typ {0} kann nicht bearbeitet werden"}, - { ER_NODESET_NOT_MUTABLE, - "Dieses NodeSet ist nicht mutierbar"}, - - { ER_NODESETDTM_NOT_MUTABLE, - "Dieses NodeSetDTM ist nicht mutierbar"}, - { ER_VAR_NOT_RESOLVABLE, "Variable kann nicht aufgel\u00F6st werden: {0}"}, @@ -777,6 +777,12 @@ public class XPATHErrorResources_de extends ListResourceBundle { ER_RESOLVE_VARIABLE_RETURNS_NULL, "resolveVariable f\u00FCr Variable {0} gibt null zur\u00FCck"}, + { ER_NO_XPATH_VARIABLE_RESOLVER, + "Es wird versucht, die Variable {0} aufzul\u00F6sen, aber es wurde kein Variablen-Resolver festgelegt."}, + + { ER_NO_XPATH_FUNCTION_PROVIDER, + "Es wird versucht, eine Erweiterungsfunktion {0} aufzurufen, aber es wurde kein Erweiterungsprovider festgelegt."}, + /** Field ER_UNSUPPORTED_RETURN_TYPE */ { ER_UNSUPPORTED_RETURN_TYPE, @@ -784,11 +790,6 @@ public class XPATHErrorResources_de extends ListResourceBundle /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, - "Quelle und/oder R\u00FCckgabetyp d\u00FCrfen nicht null sein"}, - - /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, "Quelle und/oder R\u00FCckgabetyp d\u00FCrfen nicht null sein"}, @@ -860,6 +861,12 @@ public class XPATHErrorResources_de extends ListResourceBundle { ER_GETTING_UNKNOWN_PROPERTY, "Es wird versucht, die unbekannte Eigenschaft \"{0}\" abzurufen: {1}#getProperty({0})"}, + { ER_XPATH_GROUP_LIMIT, + "JAXP0801001: Im Compiler ist ein XPath-Ausdruck mit {0} Gruppen aufgetreten, der den von \"{2}\" festgelegten Grenzwert \"{1}\" \u00FCberschreitet."}, + + { ER_XPATH_OPERATOR_LIMIT, + "JAXP0801002: Im Compiler ist ein XPath-Ausdruck mit {0} Operatoren aufgetreten, der den von \"{2}\" festgelegten Grenzwert \"{1}\" \u00FCberschreitet."}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java index 996b81cc8fa..b12ceb156cc 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_ja.java @@ -140,6 +140,7 @@ public class XPATHErrorResources_ja extends ListResourceBundle "ER_EXPECTED_SINGLE_QUOTE"; public static final String ER_EMPTY_EXPRESSION = "ER_EMPTY_EXPRESSION"; public static final String ER_EXPECTED_BUT_FOUND = "ER_EXPECTED_BUT_FOUND"; + public static final String ER_UNION_MUST_BE_NODESET = "ER_UNION_MUST_BE_NODESET"; public static final String ER_INCORRECT_PROGRAMMER_ASSERTION = "ER_INCORRECT_PROGRAMMER_ASSERTION"; public static final String ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL = @@ -203,9 +204,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle "ER_FUNCTION_TOKEN_NOT_FOUND"; public static final String ER_CANNOT_DEAL_XPATH_TYPE = "ER_CANNOT_DEAL_XPATH_TYPE"; - public static final String ER_NODESET_NOT_MUTABLE = "ER_NODESET_NOT_MUTABLE"; - public static final String ER_NODESETDTM_NOT_MUTABLE = - "ER_NODESETDTM_NOT_MUTABLE"; /** Variable not resolvable: */ public static final String ER_VAR_NOT_RESOLVABLE = "ER_VAR_NOT_RESOLVABLE"; /** Null error handler */ @@ -309,6 +307,8 @@ public class XPATHErrorResources_ja extends ListResourceBundle //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; + public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; + public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; public static final String ER_UNSUPPORTED_RETURN_TYPE = "ER_UNSUPPORTED_RETURN_TYPE"; public static final String ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL = "ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL"; public static final String ER_ARG_CANNOT_BE_NULL = "ER_ARG_CANNOT_BE_NULL"; @@ -326,6 +326,9 @@ public class XPATHErrorResources_ja extends ListResourceBundle public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; + public static final String ER_XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT"; + public static final String ER_XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT"; + //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -457,6 +460,9 @@ public class XPATHErrorResources_ja extends ListResourceBundle { ER_EXPECTED_BUT_FOUND, "{0}\u3067\u306F\u306A\u304F{1}\u304C\u691C\u51FA\u3055\u308C\u307E\u3057\u305F"}, + { ER_UNION_MUST_BE_NODESET, + "\u5171\u7528\u4F53\u306E\u30AA\u30DA\u30E9\u30F3\u30C9\u306F\u3001\u30CE\u30FC\u30C9\u30BB\u30C3\u30C8\u3067\u3042\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059\u3002"}, + { ER_INCORRECT_PROGRAMMER_ASSERTION, "\u30D7\u30ED\u30B0\u30E9\u30DE\u30FB\u30A2\u30B5\u30FC\u30B7\u30E7\u30F3\u304C\u4E0D\u6B63\u3067\u3059\u3002- {0}"}, @@ -571,12 +577,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle { ER_CANNOT_DEAL_XPATH_TYPE, "XPath\u30BF\u30A4\u30D7\u3092\u51E6\u7406\u3067\u304D\u307E\u305B\u3093: {0}"}, - { ER_NODESET_NOT_MUTABLE, - "\u3053\u306ENodeSet\u306F\u53EF\u5909\u3067\u306F\u3042\u308A\u307E\u305B\u3093"}, - - { ER_NODESETDTM_NOT_MUTABLE, - "\u3053\u306ENodeSetDTM\u306F\u53EF\u5909\u3067\u306F\u3042\u308A\u307E\u305B\u3093"}, - { ER_VAR_NOT_RESOLVABLE, "\u5909\u6570\u3092\u89E3\u6C7A\u3067\u304D\u307E\u305B\u3093: {0}"}, @@ -777,6 +777,12 @@ public class XPATHErrorResources_ja extends ListResourceBundle { ER_RESOLVE_VARIABLE_RETURNS_NULL, "\u5909\u6570{0}\u306EresolveVariable\u304Cnull\u3092\u8FD4\u3057\u3066\u3044\u307E\u3059"}, + { ER_NO_XPATH_VARIABLE_RESOLVER, + "\u5909\u6570{0}\u3092\u89E3\u6C7A\u3057\u3088\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u304C\u3001\u5909\u6570\u30EA\u30BE\u30EB\u30D0\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, + + { ER_NO_XPATH_FUNCTION_PROVIDER, + "\u62E1\u5F35\u95A2\u6570{0}\u3092\u547C\u3073\u51FA\u305D\u3046\u3068\u3057\u3066\u3044\u307E\u3059\u304C\u3001\u62E1\u5F35\u30D7\u30ED\u30D0\u30A4\u30C0\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002"}, + /** Field ER_UNSUPPORTED_RETURN_TYPE */ { ER_UNSUPPORTED_RETURN_TYPE, @@ -784,11 +790,6 @@ public class XPATHErrorResources_ja extends ListResourceBundle /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, - "\u30BD\u30FC\u30B9\u30FB\u30BF\u30A4\u30D7\u307E\u305F\u306F\u623B\u308A\u578B\u306Fnull\u306B\u3067\u304D\u307E\u305B\u3093"}, - - /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, "\u30BD\u30FC\u30B9\u30FB\u30BF\u30A4\u30D7\u307E\u305F\u306F\u623B\u308A\u578B\u306Fnull\u306B\u3067\u304D\u307E\u305B\u3093"}, @@ -860,6 +861,12 @@ public class XPATHErrorResources_ja extends ListResourceBundle { ER_GETTING_UNKNOWN_PROPERTY, "\u4E0D\u660E\u306A\u30D7\u30ED\u30D1\u30C6\u30A3\"{0}\"\u3092\u53D6\u5F97\u3057\u3088\u3046\u3068\u3057\u307E\u3057\u305F:{1}#getProperty({0})"}, + { ER_XPATH_GROUP_LIMIT, + "JAXP0801001: \u30B3\u30F3\u30D1\u30A4\u30E9\u306F\u3001''{2}''\u3067\u8A2D\u5B9A\u3055\u308C\u305F''{1}''\u5236\u9650\u3092\u8D85\u3048\u308B''{0}''\u30B0\u30EB\u30FC\u30D7\u3092\u542B\u3080XPath\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002"}, + + { ER_XPATH_OPERATOR_LIMIT, + "JAXP0801002: \u30B3\u30F3\u30D1\u30A4\u30E9\u306F\u3001''{2}''\u3067\u8A2D\u5B9A\u3055\u308C\u305F''{1}''\u5236\u9650\u3092\u8D85\u3048\u308B''{0}''\u6F14\u7B97\u5B50\u3092\u542B\u3080XPath\u5F0F\u3092\u691C\u51FA\u3057\u307E\u3057\u305F\u3002"}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... diff --git a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java index b6b37375d4b..4a6c1ed933e 100644 --- a/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java +++ b/src/java.xml/share/classes/com/sun/org/apache/xpath/internal/res/XPATHErrorResources_zh_CN.java @@ -140,6 +140,7 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle "ER_EXPECTED_SINGLE_QUOTE"; public static final String ER_EMPTY_EXPRESSION = "ER_EMPTY_EXPRESSION"; public static final String ER_EXPECTED_BUT_FOUND = "ER_EXPECTED_BUT_FOUND"; + public static final String ER_UNION_MUST_BE_NODESET = "ER_UNION_MUST_BE_NODESET"; public static final String ER_INCORRECT_PROGRAMMER_ASSERTION = "ER_INCORRECT_PROGRAMMER_ASSERTION"; public static final String ER_BOOLEAN_ARG_NO_LONGER_OPTIONAL = @@ -203,9 +204,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle "ER_FUNCTION_TOKEN_NOT_FOUND"; public static final String ER_CANNOT_DEAL_XPATH_TYPE = "ER_CANNOT_DEAL_XPATH_TYPE"; - public static final String ER_NODESET_NOT_MUTABLE = "ER_NODESET_NOT_MUTABLE"; - public static final String ER_NODESETDTM_NOT_MUTABLE = - "ER_NODESETDTM_NOT_MUTABLE"; /** Variable not resolvable: */ public static final String ER_VAR_NOT_RESOLVABLE = "ER_VAR_NOT_RESOLVABLE"; /** Null error handler */ @@ -309,6 +307,8 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle //BEGIN: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED = "ER_EXTENSION_FUNCTION_CANNOT_BE_INVOKED"; public static final String ER_RESOLVE_VARIABLE_RETURNS_NULL = "ER_RESOLVE_VARIABLE_RETURNS_NULL"; + public static final String ER_NO_XPATH_VARIABLE_RESOLVER = "ER_NO_XPATH_VARIABLE_RESOLVER"; + public static final String ER_NO_XPATH_FUNCTION_PROVIDER = "ER_NO_XPATH_FUNCTION_PROVIDER"; public static final String ER_UNSUPPORTED_RETURN_TYPE = "ER_UNSUPPORTED_RETURN_TYPE"; public static final String ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL = "ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL"; public static final String ER_ARG_CANNOT_BE_NULL = "ER_ARG_CANNOT_BE_NULL"; @@ -326,6 +326,9 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle public static final String ER_PROPERTY_UNKNOWN = "ER_PROPERTY_UNKNOWN"; public static final String ER_GETTING_NULL_PROPERTY = "ER_GETTING_NULL_PROPERTY"; public static final String ER_GETTING_UNKNOWN_PROPERTY = "ER_GETTING_UNKNOWN_PROPERTY"; + public static final String ER_XPATH_GROUP_LIMIT = "XPATH_GROUP_LIMIT"; + public static final String ER_XPATH_OPERATOR_LIMIT = "XPATH_OPERATOR_LIMIT"; + //END: Keys needed for exception messages of JAXP 1.3 XPath API implementation public static final String WG_LOCALE_NAME_NOT_HANDLED = @@ -457,6 +460,9 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle { ER_EXPECTED_BUT_FOUND, "\u9700\u8981{0}, \u4F46\u627E\u5230: {1}"}, + { ER_UNION_MUST_BE_NODESET, + "\u8054\u5408\u7684\u64CD\u4F5C\u6570\u5FC5\u987B\u4E3A\u8282\u70B9\u96C6\u3002"}, + { ER_INCORRECT_PROGRAMMER_ASSERTION, "\u7A0B\u5E8F\u5458\u65AD\u8A00\u9519\u8BEF! - {0}"}, @@ -571,12 +577,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle { ER_CANNOT_DEAL_XPATH_TYPE, "\u65E0\u6CD5\u5904\u7406 XPath \u7C7B\u578B: {0}"}, - { ER_NODESET_NOT_MUTABLE, - "\u6B64 NodeSet \u4E0D\u53EF\u53D8"}, - - { ER_NODESETDTM_NOT_MUTABLE, - "\u6B64 NodeSetDTM \u4E0D\u53EF\u53D8"}, - { ER_VAR_NOT_RESOLVABLE, "\u65E0\u6CD5\u89E3\u6790\u53D8\u91CF: {0}"}, @@ -777,6 +777,12 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle { ER_RESOLVE_VARIABLE_RETURNS_NULL, "\u53D8\u91CF{0}\u7684 resolveVariable \u8FD4\u56DE\u7A7A\u503C"}, + { ER_NO_XPATH_VARIABLE_RESOLVER, + "\u6B63\u5728\u5C1D\u8BD5\u89E3\u6790\u53D8\u91CF {0}\uFF0C\u4F46\u672A\u8BBE\u7F6E\u53D8\u91CF\u89E3\u6790\u5668\u3002"}, + + { ER_NO_XPATH_FUNCTION_PROVIDER, + "\u6B63\u5728\u5C1D\u8BD5\u8C03\u7528\u6269\u5C55\u51FD\u6570 {0}\uFF0C\u4F46\u672A\u8BBE\u7F6E\u6269\u5C55\u63D0\u4F9B\u65B9\u3002"}, + /** Field ER_UNSUPPORTED_RETURN_TYPE */ { ER_UNSUPPORTED_RETURN_TYPE, @@ -784,11 +790,6 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, - "\u6E90\u548C/\u6216\u8FD4\u56DE\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u503C"}, - - /** Field ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL */ - { ER_SOURCE_RETURN_TYPE_CANNOT_BE_NULL, "\u6E90\u548C/\u6216\u8FD4\u56DE\u7C7B\u578B\u4E0D\u80FD\u4E3A\u7A7A\u503C"}, @@ -860,6 +861,12 @@ public class XPATHErrorResources_zh_CN extends ListResourceBundle { ER_GETTING_UNKNOWN_PROPERTY, "\u5C1D\u8BD5\u83B7\u53D6\u672A\u77E5\u5C5E\u6027 \"{0}\":{1}#getProperty({0})"}, + { ER_XPATH_GROUP_LIMIT, + "JAXP0801001\uFF1A\u7F16\u8BD1\u5668\u9047\u5230\u5305\u542B ''{0}'' \u7EC4\u7684 XPath \u8868\u8FBE\u5F0F\uFF0C\u8BE5\u8868\u8FBE\u5F0F\u8D85\u8FC7\u4E86 ''{2}'' \u8BBE\u7F6E\u7684 ''{1}'' \u9650\u5236\u3002"}, + + { ER_XPATH_OPERATOR_LIMIT, + "JAXP0801002\uFF1A\u7F16\u8BD1\u5668\u9047\u5230\u5305\u542B ''{0}'' \u8FD0\u7B97\u7B26\u7684 XPath \u8868\u8FBE\u5F0F\uFF0C\u8BE5\u8868\u8FBE\u5F0F\u8D85\u8FC7\u4E86 ''{2}'' \u8BBE\u7F6E\u7684 ''{1}'' \u9650\u5236\u3002"}, + //END: Definitions of error keys used in exception messages of JAXP 1.3 XPath API implementation // Warnings... 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 2d51ac43cd9..6d73eb7ae80 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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 @@ -376,9 +376,11 @@ compiler.err.pattern.dominated=Dieses CASE-Label wird von einem vorherigen CASE- compiler.err.duplicate.default.label=Doppeltes Standardlabel -compiler.err.duplicate.total.pattern=Doppeltes Gesamtmuster +compiler.err.duplicate.unconditional.pattern=Doppeltes nicht bedingtes Muster -compiler.err.total.pattern.and.default=Switch umfasst sowohl Gesamtmuster als auch Standardlabel +compiler.err.unconditional.pattern.and.default=Switch umfasst sowohl ein nicht bedingtes Muster als auch ein Standardlabel + +compiler.err.guard.has.constant.expression.false=Dieses CASE-Label hat einen Guard, der ein konstanter Ausdruck mit dem Wert ''false'' ist # 0: type, 1: type compiler.err.constant.label.not.compatible=Konstantes Label des Typs {0} ist nicht mit Switch-Selektortyp {1} kompatibel @@ -406,6 +408,8 @@ compiler.err.enum.types.not.extensible=Enum-Klassen sind nicht erweiterbar compiler.err.enum.no.finalize=Enums k\u00F6nnen keine Finalisierungsmethoden aufweisen +compiler.err.enum.cant.be.generic=Enums k\u00F6nnen nicht generisch sein + # 0: file name, 1: string compiler.err.error.reading.file=Fehler beim Lesen von {0}. {1} @@ -1808,6 +1812,9 @@ compiler.warn.prob.found.req={0}\nErforderlich: {2}\nErmittelt: {1} # 0: type, 1: type compiler.misc.inconvertible.types={0} kann nicht in {1} konvertiert werden +# 0: type, 1: type +compiler.misc.not.applicable.types=Muster des Typs {1} ist bei {0} nicht anwendbar + # 0: type, 1: type compiler.misc.possible.loss.of.precision=M\u00F6glicher Verlust bei Konvertierung von {0} in {1} @@ -1874,7 +1881,7 @@ compiler.misc.lower.bounds=Untere Grenzwerte: {0} compiler.misc.eq.bounds=Gleichheits-Constraints: {0} # 0: list of type -compiler.misc.upper.bounds=Untere Grenzwerte: {0} +compiler.misc.upper.bounds=Obere Grenzen: {0} # 0: list of type, 1: type, 2: type compiler.misc.infer.no.conforming.instance.exists=Keine Instanzen von Typvariablen {0} vorhanden, sodass {1} {2} entspricht @@ -2188,6 +2195,8 @@ compiler.misc.feature.pattern.matching.instanceof=Musterabgleich in instanceof compiler.misc.feature.reifiable.types.instanceof=Reifizierbare Typen in instanceof +compiler.misc.feature.deconstruction.patterns=Dekonstruktionsmuster + compiler.misc.feature.records=Datens\u00E4tze compiler.misc.feature.sealed.classes=Verschl\u00FCsselte Klassen @@ -2196,6 +2205,8 @@ compiler.misc.feature.case.null=Null in Switch Cases compiler.misc.feature.pattern.switch=Muster in Switch-Anweisungen +compiler.misc.feature.unconditional.patterns.in.instanceof=Nicht bedingte Muster in instanceof + compiler.warn.underscore.as.identifier=Ab Release 9 ist "_" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden compiler.err.underscore.as.identifier=Ab Release 9 ist "_" ein Schl\u00FCsselwort und kann nicht als ID verwendet werden @@ -2779,6 +2790,14 @@ compiler.err.preview.not.latest=Ung\u00FCltiges Quellrelease {0} mit --enable-pr compiler.err.preview.without.source.or.release=--enable-preview muss mit -source oder --release verwendet werden +# 0: symbol +compiler.err.deconstruction.pattern.only.records=Dekonstruktionsmuster k\u00F6nnen nur auf Datens\u00E4tze angewendet werden. {0} ist kein Datensatz + +# 0: list of type, 1: list of type +compiler.err.incorrect.number.of.nested.patterns=Falsche Anzahl verschachtelter Muster\nErforderlich: {0}\nGefunden: {1} + +compiler.err.raw.deconstruction.pattern=Raw-Dekonstruktionsmuster sind nicht zul\u00E4ssig + # 0: kind name, 1: symbol compiler.warn.declared.using.preview={0} {1} ist mit einem Vorschaufeature deklariert, das in einem zuk\u00FCnftigen Release entfernt werden kann. 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 6a899309594..67986b98373 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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 @@ -376,9 +376,11 @@ compiler.err.pattern.dominated=\u5148\u884C\u3059\u308Bcase\u30E9\u30D9\u30EB\u3 compiler.err.duplicate.default.label=default\u30E9\u30D9\u30EB\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 -compiler.err.duplicate.total.pattern=\u5408\u8A08\u30D1\u30BF\u30FC\u30F3\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 +compiler.err.duplicate.unconditional.pattern=\u7121\u6761\u4EF6\u30D1\u30BF\u30FC\u30F3\u304C\u91CD\u8907\u3057\u3066\u3044\u307E\u3059 -compiler.err.total.pattern.and.default=switch\u306B\u5408\u8A08\u30D1\u30BF\u30FC\u30F3\u3068default\u30E9\u30D9\u30EB\u306E\u4E21\u65B9\u304C\u3042\u308A\u307E\u3059 +compiler.err.unconditional.pattern.and.default=switch\u306B\u7121\u6761\u4EF6\u30D1\u30BF\u30FC\u30F3\u3068default\u30E9\u30D9\u30EB\u306E\u4E21\u65B9\u304C\u3042\u308A\u307E\u3059 + +compiler.err.guard.has.constant.expression.false=\u3053\u306Ecase\u30E9\u30D9\u30EB\u306B\u306F\u3001\u5024\u304C''false''\u306E\u5B9A\u6570\u5F0F\u3067\u3042\u308B\u30AC\u30FC\u30C9\u304C\u3042\u308A\u307E\u3059 # 0: type, 1: type compiler.err.constant.label.not.compatible=\u30BF\u30A4\u30D7{0}\u306E\u5B9A\u6570\u30E9\u30D9\u30EB\u304Cswitch\u30BB\u30EC\u30AF\u30BF\u30FB\u30BF\u30A4\u30D7{1}\u3068\u4E92\u63DB\u6027\u304C\u3042\u308A\u307E\u305B\u3093 @@ -406,6 +408,8 @@ compiler.err.enum.types.not.extensible=\u5217\u6319\u30AF\u30E9\u30B9\u306F\u62E compiler.err.enum.no.finalize=\u5217\u6319\u578B\u306Ffinalize\u30E1\u30BD\u30C3\u30C9\u3092\u6301\u3064\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 +compiler.err.enum.cant.be.generic=\u5217\u6319\u578B\u306F\u6C4E\u7528\u306B\u3067\u304D\u307E\u305B\u3093 + # 0: file name, 1: string compiler.err.error.reading.file={0}\u306E\u8AAD\u8FBC\u307F\u30A8\u30E9\u30FC\u3067\u3059\u3002{1} @@ -1808,6 +1812,9 @@ compiler.warn.prob.found.req={0}\n\u671F\u5F85\u5024: {2}\n\u691C\u51FA\u5024: # 0: type, 1: type compiler.misc.inconvertible.types={0}\u3092{1}\u306B\u5909\u63DB\u3067\u304D\u307E\u305B\u3093: +# 0: type, 1: type +compiler.misc.not.applicable.types=\u578B{1}\u306E\u30D1\u30BF\u30FC\u30F3\u306F{0}\u3067\u306F\u9069\u7528\u3067\u304D\u307E\u305B\u3093 + # 0: type, 1: type compiler.misc.possible.loss.of.precision=\u7CBE\u5EA6\u304C\u5931\u308F\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308B{0}\u304B\u3089{1}\u3078\u306E\u5909\u63DB @@ -1874,7 +1881,7 @@ compiler.misc.lower.bounds=\u4E0B\u9650: {0} compiler.misc.eq.bounds=\u7B49\u4FA1\u5236\u7D04: {0} # 0: list of type -compiler.misc.upper.bounds=\u4E0B\u9650: {0} +compiler.misc.upper.bounds=\u4E0A\u9650: {0} # 0: list of type, 1: type, 2: type compiler.misc.infer.no.conforming.instance.exists=\u578B\u5909\u6570{0}\u306E\u30A4\u30F3\u30B9\u30BF\u30F3\u30B9\u304C\u5B58\u5728\u3057\u306A\u3044\u306E\u3067\u3001{1}\u306F{2}\u306B\u9069\u5408\u3057\u307E\u305B\u3093 @@ -2188,6 +2195,8 @@ compiler.misc.feature.pattern.matching.instanceof=instanceof\u3067\u306E\u30D1\u compiler.misc.feature.reifiable.types.instanceof=instanceof\u3067\u306Ereifiable\u578B +compiler.misc.feature.deconstruction.patterns=\u30C7\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30B7\u30E7\u30F3\u30FB\u30D1\u30BF\u30FC\u30F3 + compiler.misc.feature.records=\u30EC\u30B3\u30FC\u30C9 compiler.misc.feature.sealed.classes=\u30B7\u30FC\u30EB\u30FB\u30AF\u30E9\u30B9 @@ -2196,6 +2205,8 @@ compiler.misc.feature.case.null=switch case\u306Enull compiler.misc.feature.pattern.switch=switch\u6587\u306E\u30D1\u30BF\u30FC\u30F3 +compiler.misc.feature.unconditional.patterns.in.instanceof=instanceof\u3067\u306E\u7121\u6761\u4EF6\u30D1\u30BF\u30FC\u30F3 + compiler.warn.underscore.as.identifier=\u30EA\u30EA\u30FC\u30B99\u304B\u3089''_''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 compiler.err.underscore.as.identifier=\u30EA\u30EA\u30FC\u30B99\u304B\u3089''_''\u306F\u30AD\u30FC\u30EF\u30FC\u30C9\u306A\u306E\u3067\u8B58\u5225\u5B50\u3068\u3057\u3066\u4F7F\u7528\u3059\u308B\u3053\u3068\u306F\u3067\u304D\u307E\u305B\u3093 @@ -2779,6 +2790,14 @@ compiler.err.preview.not.latest=--enable-preview\u304C\u6307\u5B9A\u3055\u308C\u compiler.err.preview.without.source.or.release=--enable-preview\u306F-source\u307E\u305F\u306F--release\u3068\u3068\u3082\u306B\u4F7F\u7528\u3059\u308B\u5FC5\u8981\u304C\u3042\u308A\u307E\u3059 +# 0: symbol +compiler.err.deconstruction.pattern.only.records=\u30C7\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30B7\u30E7\u30F3\u30FB\u30D1\u30BF\u30FC\u30F3\u306F\u30EC\u30B3\u30FC\u30C9\u306B\u306E\u307F\u9069\u7528\u3067\u304D\u307E\u3059\u3002{0}\u306F\u30EC\u30B3\u30FC\u30C9\u3067\u306F\u3042\u308A\u307E\u305B\u3093 + +# 0: list of type, 1: list of type +compiler.err.incorrect.number.of.nested.patterns=\u30CD\u30B9\u30C8\u30FB\u30D1\u30BF\u30FC\u30F3\u306E\u6570\u304C\u6B63\u3057\u304F\u3042\u308A\u307E\u305B\u3093\n\u671F\u5F85\u5024: {0}\n\u691C\u51FA\u5024: {1} + +compiler.err.raw.deconstruction.pattern=raw\u30C7\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30B7\u30E7\u30F3\u30FB\u30D1\u30BF\u30FC\u30F3\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 + # 0: kind name, 1: symbol compiler.warn.declared.using.preview={0} {1}\u306F\u30D7\u30EC\u30D3\u30E5\u30FC\u6A5F\u80FD\u3092\u4F7F\u7528\u3057\u3066\u5BA3\u8A00\u3055\u308C\u3066\u304A\u308A\u3001\u4ECA\u5F8C\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u53EF\u80FD\u6027\u304C\u3042\u308A\u307E\u3059\u3002 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 94e2075c36d..f89efa66574 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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 @@ -376,9 +376,11 @@ compiler.err.pattern.dominated=\u6B64 case \u6807\u7B7E\u7531\u524D\u4E00\u4E2A compiler.err.duplicate.default.label=default \u6807\u7B7E\u91CD\u590D -compiler.err.duplicate.total.pattern=\u603B\u8BA1\u6A21\u5F0F\u91CD\u590D +compiler.err.duplicate.unconditional.pattern=\u65E0\u6761\u4EF6\u6A21\u5F0F\u91CD\u590D -compiler.err.total.pattern.and.default=switch \u6709\u4E00\u4E2A\u603B\u8BA1\u6A21\u5F0F\u548C\u4E00\u4E2A\u9ED8\u8BA4\u6807\u7B7E +compiler.err.unconditional.pattern.and.default=switch \u6709\u4E00\u4E2A\u65E0\u6761\u4EF6\u6A21\u5F0F\u548C\u4E00\u4E2A default \u6807\u7B7E + +compiler.err.guard.has.constant.expression.false=\u6B64 case \u6807\u7B7E\u6709\u4E00\u4E2A\u536B\u58EB\uFF0C\u5B83\u662F\u503C\u4E3A ''false'' \u7684\u5E38\u91CF\u8868\u8FBE\u5F0F # 0: type, 1: type compiler.err.constant.label.not.compatible={0} \u7C7B\u578B\u7684\u5E38\u91CF\u6807\u7B7E\u4E0E switch \u9009\u62E9\u5668\u7C7B\u578B {1} \u4E0D\u517C\u5BB9 @@ -406,6 +408,8 @@ compiler.err.enum.types.not.extensible=\u679A\u4E3E\u7C7B\u4E0D\u53EF\u6269\u5C5 compiler.err.enum.no.finalize=\u679A\u4E3E\u4E0D\u80FD\u6709 finalize \u65B9\u6CD5 +compiler.err.enum.cant.be.generic=\u679A\u4E3E\u4E0D\u80FD\u4E3A\u6CDB\u578B + # 0: file name, 1: string compiler.err.error.reading.file=\u8BFB\u53D6{0}\u65F6\u51FA\u9519; {1} @@ -1808,6 +1812,9 @@ compiler.warn.prob.found.req={0}\n\u9700\u8981: {2}\n\u627E\u5230: {1} # 0: type, 1: type compiler.misc.inconvertible.types={0}\u65E0\u6CD5\u8F6C\u6362\u4E3A{1} +# 0: type, 1: type +compiler.misc.not.applicable.types=\u7C7B\u578B\u4E3A {1} \u7684\u6A21\u5F0F\u4E0D\u9002\u7528\u4E8E {0} + # 0: type, 1: type compiler.misc.possible.loss.of.precision=\u4ECE{0}\u8F6C\u6362\u5230{1}\u53EF\u80FD\u4F1A\u6709\u635F\u5931 @@ -1874,7 +1881,7 @@ compiler.misc.lower.bounds=\u4E0B\u9650\uFF1A{0} compiler.misc.eq.bounds=\u7B49\u5F0F\u7EA6\u675F\u6761\u4EF6\uFF1A{0} # 0: list of type -compiler.misc.upper.bounds=\u4E0B\u9650\uFF1A{0} +compiler.misc.upper.bounds=\u4E0A\u9650\uFF1A{0} # 0: list of type, 1: type, 2: type compiler.misc.infer.no.conforming.instance.exists=\u4E0D\u5B58\u5728\u7C7B\u578B\u53D8\u91CF{0}\u7684\u5B9E\u4F8B, \u4EE5\u4F7F{1}\u4E0E{2}\u4E00\u81F4 @@ -2188,6 +2195,8 @@ compiler.misc.feature.pattern.matching.instanceof=instanceof \u4E2D\u7684\u6A21\ compiler.misc.feature.reifiable.types.instanceof=instanceof \u4E2D\u7684\u53EF\u5177\u4F53\u5316\u7C7B\u578B +compiler.misc.feature.deconstruction.patterns=\u89E3\u6784\u6A21\u5F0F + compiler.misc.feature.records=\u8BB0\u5F55 compiler.misc.feature.sealed.classes=\u5BC6\u5C01\u7C7B @@ -2196,6 +2205,8 @@ compiler.misc.feature.case.null=switch case \u4E2D\u7684\u7A7A\u503C compiler.misc.feature.pattern.switch=switch \u8BED\u53E5\u4E2D\u7684\u6A21\u5F0F +compiler.misc.feature.unconditional.patterns.in.instanceof=instanceof \u4E2D\u7684\u65E0\u6761\u4EF6\u6A21\u5F0F + compiler.warn.underscore.as.identifier=\u4ECE\u53D1\u884C\u7248 9 \u5F00\u59CB, ''_'' \u4E3A\u5173\u952E\u5B57, \u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26 compiler.err.underscore.as.identifier=\u4ECE\u53D1\u884C\u7248 9 \u5F00\u59CB, ''_'' \u4E3A\u5173\u952E\u5B57, \u4E0D\u80FD\u7528\u4F5C\u6807\u8BC6\u7B26 @@ -2779,6 +2790,14 @@ compiler.err.preview.not.latest=\u6E90\u53D1\u884C\u7248 {0} \u4E0E --enable-pre compiler.err.preview.without.source.or.release=--enable-preview \u5FC5\u987B\u4E0E -source \u6216 --release \u4E00\u8D77\u4F7F\u7528 +# 0: symbol +compiler.err.deconstruction.pattern.only.records=\u89E3\u6784\u6A21\u5F0F\u53EA\u80FD\u5E94\u7528\u4E8E\u8BB0\u5F55\uFF0C{0} \u4E0D\u662F\u8BB0\u5F55 + +# 0: list of type, 1: list of type +compiler.err.incorrect.number.of.nested.patterns=\u5D4C\u5957\u6A21\u5F0F\u6570\u4E0D\u6B63\u786E\n\u9700\u8981\uFF1A{0}\n\u5DF2\u627E\u5230\uFF1A{1} + +compiler.err.raw.deconstruction.pattern=\u4E0D\u5141\u8BB8\u4F7F\u7528\u539F\u59CB\u89E3\u6784\u6A21\u5F0F + # 0: kind name, 1: symbol compiler.warn.declared.using.preview={0} {1} \u662F\u4F7F\u7528\u9884\u89C8\u529F\u80FD\u58F0\u660E\u7684\uFF0C\u53EF\u80FD\u4F1A\u5728\u672A\u6765\u53D1\u884C\u7248\u4E2D\u5220\u9664\u3002 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 3deab45ea11..6cdd32ad788 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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,6 +23,10 @@ # questions. # +## tool + +javac.description=Java-Klasse und Schnittstellendefinitionen lesen und in Bytecode und Klassendateien kompilieren + ## standard options javac.opt.g=Generiert alle Debugginginformationen 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 f62ca91be9f..12de909b4a4 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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,6 +23,10 @@ # questions. # +## tool + +javac.description=Java\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u5B9A\u7FA9\u3092\u8AAD\u307F\u53D6\u308A\u3001\u30D0\u30A4\u30C8\u30B3\u30FC\u30C9\u304A\u3088\u3073\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u306B\u30B3\u30F3\u30D1\u30A4\u30EB\u3057\u307E\u3059 + ## standard options javac.opt.g=\u3059\u3079\u3066\u306E\u30C7\u30D0\u30C3\u30B0\u60C5\u5831\u3092\u751F\u6210\u3059\u308B 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 5ba02480ace..3c1aa3664d1 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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,6 +23,10 @@ # questions. # +## tool + +javac.description=\u8BFB\u53D6 Java \u7C7B\u548C\u63A5\u53E3\u5B9A\u4E49\uFF0C\u5E76\u5C06\u5176\u7F16\u8BD1\u4E3A\u5B57\u8282\u7801\u548C\u7C7B\u6587\u4EF6 + ## standard options javac.opt.g=\u751F\u6210\u6240\u6709\u8C03\u8BD5\u4FE1\u606F 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 731f9b4e144..2700c402b7f 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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,6 +23,10 @@ # questions. # +## tool + +jar.description=Archiv f\u00FCr Klassen und Ressourcen erstellen und individuelle Klassen oder Ressourcen aus einem Archiv \u00E4ndern oder wiederherstellen + error.multiple.main.operations=Es ist nicht m\u00F6glich, mehrere "-cuxtid"-Optionen anzugeben error.cant.open=\u00D6ffnen nicht m\u00F6glich: {0} error.illegal.option=Unzul\u00E4ssige Option: {0} 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 264d363a991..b1995470e3b 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 @@ -23,6 +23,10 @@ # questions. # +## tool + +jar.description=\u30AF\u30E9\u30B9\u304A\u3088\u3073\u30EA\u30BD\u30FC\u30B9\u306E\u30A2\u30FC\u30AB\u30A4\u30D6\u3092\u4F5C\u6210\u3057\u3001\u500B\u3005\u306E\u30AF\u30E9\u30B9\u307E\u305F\u306F\u30EA\u30BD\u30FC\u30B9\u3092\u30A2\u30FC\u30AB\u30A4\u30D6\u304B\u3089\u64CD\u4F5C\u307E\u305F\u306F\u5FA9\u5143\u3057\u307E\u3059 + error.multiple.main.operations=\u8907\u6570\u306E'cuxtid'\u30AA\u30D7\u30B7\u30E7\u30F3\u3092\u6307\u5B9A\u3067\u304D\u307E\u305B\u3093 error.cant.open={0}\u3092\u958B\u304F\u3053\u3068\u304C\u3067\u304D\u307E\u305B\u3093 error.illegal.option=\u4E0D\u6B63\u306A\u30AA\u30D7\u30B7\u30E7\u30F3: {0} @@ -107,24 +111,24 @@ main.help.opt.main.extract=\ -x\u3001--extract \u6307\u5B9A\u306E( main.help.opt.main.describe-module=\ -d, --describe-module \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF\u307E\u305F\u306F\u81EA\u52D5\u30E2\u30B8\u30E5\u30FC\u30EB\u540D\u3092\u51FA\u529B\u3057\u307E\u3059 main.help.opt.main.validate=\ --validate jar\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u5185\u5BB9\u3092\u691C\u8A3C\u3057\u307E\u3059\u3002\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\n \u8907\u6570\u30EA\u30EA\u30FC\u30B9\u306Ejar\u30A2\u30FC\u30AB\u30A4\u30D6\u3067\u30A8\u30AF\u30B9\u30DD\u30FC\u30C8\u3055\u308C\u305FAPI\u304C\n \u3059\u3079\u3066\u306E\u7570\u306A\u308B\u30EA\u30EA\u30FC\u30B9\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u3067\u4E00\u8CAB\u3057\u3066\u3044\u308B\u3053\u3068\u3092\n \u691C\u8A3C\u3057\u307E\u3059\u3002 main.help.opt.any=\ \u3069\u306E\u30E2\u30FC\u30C9\u3067\u3082\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n\n -C DIR \u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306B\u5909\u66F4\u3057\u3001\u6B21\u306E\u30D5\u30A1\u30A4\u30EB\u3092\n \u53D6\u308A\u8FBC\u307F\u307E\u3059 -main.help.opt.any.file=\ -f, --file=FILE \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u7701\u7565\u3057\u305F\u5834\u5408\u3001stdin\u307E\u305F\u306F\n stdout\u306E\u3044\u305A\u308C\u304B\u304C\u64CD\u4F5C\u306B\u57FA\u3065\u3044\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\n --release VERSION \u6B21\u306E\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3092jar\u306E\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n (\u3064\u307E\u308A\u3001META-INF/versions/VERSION/)\u306B\u914D\u7F6E\u3057\u307E\u3059 -main.help.opt.any.verbose=\ -v, --verbose \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3057\u307E\u3059 +main.help.opt.any.file=\ -f\u3001--file=FILE \u30A2\u30FC\u30AB\u30A4\u30D6\u30FB\u30D5\u30A1\u30A4\u30EB\u540D\u3002\u7701\u7565\u3057\u305F\u5834\u5408\u3001stdin\u307E\u305F\u306F\n stdout\u306E\u3044\u305A\u308C\u304B\u304C\u64CD\u4F5C\u306B\u57FA\u3065\u3044\u3066\u4F7F\u7528\u3055\u308C\u307E\u3059\n --release VERSION \u6B21\u306E\u3059\u3079\u3066\u306E\u30D5\u30A1\u30A4\u30EB\u3092jar\u306E\u30D0\u30FC\u30B8\u30E7\u30CB\u30F3\u30B0\u3055\u308C\u305F\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\n (\u3064\u307E\u308A\u3001META-INF/versions/VERSION/)\u306B\u914D\u7F6E\u3057\u307E\u3059 +main.help.opt.any.verbose=\ -v\u3001--verbose \u6A19\u6E96\u51FA\u529B\u306B\u8A73\u7D30\u306A\u51FA\u529B\u3092\u751F\u6210\u3057\u307E\u3059 main.help.opt.create=\ \u4F5C\u6210\u30E2\u30FC\u30C9\u3067\u306E\u307F\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n main.help.opt.create.normalize=\ -n, --normalize \u65B0\u3057\u3044jar\u30A2\u30FC\u30AB\u30A4\u30D6\u306E\u4F5C\u6210\u5F8C\u3001\u542B\u307E\u308C\u308B\u60C5\u5831\u3092\n \u6B63\u898F\u5316\u3057\u307E\u3059\u3002\u3053\u306E\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u975E\u63A8\u5968\u3067\u3042\u308A\u3001\n \u4ECA\u5F8C\u306EJDK\u30EA\u30EA\u30FC\u30B9\u3067\u524A\u9664\u3055\u308C\u308B\u4E88\u5B9A\u3067\u3059 main.help.opt.create.update=\ \u4F5C\u6210\u307E\u305F\u306F\u66F4\u65B0\u30E2\u30FC\u30C9\u3067\u306E\u307F\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n -main.help.opt.create.update.main-class=\ -e, --main-class=CLASSNAME \u30E2\u30B8\u30E5\u30E9\u307E\u305F\u306F\u5B9F\u884C\u53EF\u80FD\u306Ajar\u30A2\u30FC\u30AB\u30A4\u30D6\u306B\n \u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8 -main.help.opt.create.update.manifest=\ -m, --manifest=FILE \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\n \u53D6\u308A\u8FBC\u307F\u307E\u3059 -main.help.opt.create.update.no-manifest=\ -M, --no-manifest \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u307E\u305B\u3093 +main.help.opt.create.update.main-class=\ -e\u3001--main-class=CLASSNAME \u30E2\u30B8\u30E5\u30E9\u307E\u305F\u306F\u5B9F\u884C\u53EF\u80FD\u306Ajar\u30A2\u30FC\u30AB\u30A4\u30D6\u306B\n \u30D0\u30F3\u30C9\u30EB\u3055\u308C\u305F\u30B9\u30BF\u30F3\u30C9\u30A2\u30ED\u30F3\u30FB\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u306E\n \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u30FB\u30A8\u30F3\u30C8\u30EA\u30FB\u30DD\u30A4\u30F3\u30C8 +main.help.opt.create.update.manifest=\ -m\u3001--manifest=FILE \u6307\u5B9A\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u60C5\u5831\u3092\n \u53D6\u308A\u8FBC\u307F\u307E\u3059 +main.help.opt.create.update.no-manifest=\ -M\u3001--no-manifest \u30A8\u30F3\u30C8\u30EA\u306E\u30DE\u30CB\u30D5\u30A7\u30B9\u30C8\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u4F5C\u6210\u3057\u307E\u305B\u3093 main.help.opt.create.update.module-version=\ --module-version=VERSION \u30E2\u30B8\u30E5\u30E9jar\u306E\u4F5C\u6210\u6642\u307E\u305F\u306F\u975E\u30E2\u30B8\u30E5\u30E9jar\u306E\u66F4\u65B0\u6642\u306E\n \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3 main.help.opt.create.update.hash-modules=\ --hash-modules=PATTERN \u30E2\u30B8\u30E5\u30E9jar\u306E\u4F5C\u6210\u6642\u307E\u305F\u306F\u975E\u30E2\u30B8\u30E5\u30E9jar\u306E\u66F4\u65B0\u6642\u306B\n \u6307\u5B9A\u306E\u30D1\u30BF\u30FC\u30F3\u306B\u4E00\u81F4\u3057\u3001\u76F4\u63A5\u307E\u305F\u306F\u9593\u63A5\u7684\u306B\n \u4F9D\u5B58\u3057\u3066\u3044\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30CF\u30C3\u30B7\u30E5\u3092\n \u8A08\u7B97\u304A\u3088\u3073\u8A18\u9332\u3057\u307E\u3059 -main.help.opt.create.update.module-path=\ -p, --module-path \u30CF\u30C3\u30B7\u30E5\u3092\u751F\u6210\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u4F9D\u5B58\u6027\n \u306E\u5834\u6240 +main.help.opt.create.update.module-path=\ -p\u3001--module-path \u30CF\u30C3\u30B7\u30E5\u3092\u751F\u6210\u3059\u308B\u30E2\u30B8\u30E5\u30FC\u30EB\u4F9D\u5B58\u6027\n \u306E\u5834\u6240 main.help.opt.create.update.do-not-resolve-by-default=\ --do-not-resolve-by-default \u30E2\u30B8\u30E5\u30FC\u30EB\u306E\u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30EB\u30FC\u30C8\u8A2D\u5B9A\u304B\u3089\u9664\u5916\u3057\u307E\u3059 main.help.opt.create.update.warn-if-resolved=\ --warn-if-resolved \u30E2\u30B8\u30E5\u30FC\u30EB\u304C\u89E3\u6C7A\u3055\u308C\u3066\u3044\u308B\u5834\u5408\u306F\u3001\u8B66\u544A\u3092\u767A\u884C\u3059\u308B\n \u30C4\u30FC\u30EB\u306E\u30D2\u30F3\u30C8\u3002\u975E\u63A8\u5968\u3001\u524A\u9664\u4E88\u5B9A\u306E\u975E\u63A8\u5968\u307E\u305F\u306F\n \u5B9F\u9A13\u7684\u306E\u3044\u305A\u308C\u304B main.help.opt.create.update.index=\ \u4F5C\u6210\u3001\u66F4\u65B0\u304A\u3088\u3073\u7D22\u5F15\u751F\u6210\u30E2\u30FC\u30C9\u3067\u306E\u307F\u6709\u52B9\u306A\u64CD\u4F5C\u4FEE\u98FE\u5B50:\n main.help.opt.create.update.index.no-compress=\ -0, --no-compress \u683C\u7D0D\u306E\u307F\u3002ZIP\u5727\u7E2E\u3092\u4F7F\u7528\u3057\u307E\u305B\u3093 main.help.opt.create.update.index.date=\ --date=TIMESTAMP \u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30BF\u30A4\u30E0\u30BE\u30FC\u30F3\u5F62\u5F0F\u3092\u6307\u5B9A\u3057\u305FISO-8601\u62E1\u5F35\u30AA\u30D5\u30BB\u30C3\u30C8\n \u306E\u65E5\u6642\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u3002\u30A8\u30F3\u30C8\u30EA\u306E\u30BF\u30A4\u30E0\u30B9\u30BF\u30F3\u30D7\u306E\u4F7F\u7528\u4F8B\u306F\u3001\n "2022-02-12T12:30:00-05:00"\u3067\u3059 main.help.opt.other=\ \u305D\u306E\u4ED6\u306E\u30AA\u30D7\u30B7\u30E7\u30F3:\n -main.help.opt.other.help=\ -?, -h, --help[:compat] \u3053\u308C(\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u4E92\u63DB\u6027)\u3092help\u306B\u6307\u5B9A\u3057\u307E\u3059 +main.help.opt.other.help=\ -?\u3001-h\u3001--help[:compat] \u3053\u308C(\u30AA\u30D7\u30B7\u30E7\u30F3\u3067\u4E92\u63DB\u6027)\u3092help\u306B\u6307\u5B9A\u3057\u307E\u3059 main.help.opt.other.help-extra=\ --help-extra \u8FFD\u52A0\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30D8\u30EB\u30D7\u3092\u63D0\u4F9B\u3057\u307E\u3059 main.help.opt.other.version=\ --version \u30D7\u30ED\u30B0\u30E9\u30E0\u30FB\u30D0\u30FC\u30B8\u30E7\u30F3\u3092\u51FA\u529B\u3057\u307E\u3059 main.help.postopt=\ \u30E2\u30B8\u30E5\u30FC\u30EB\u30FB\u30C7\u30A3\u30B9\u30AF\u30EA\u30D7\u30BF'module-info.class'\u304C\u6307\u5B9A\u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306E\u30EB\u30FC\u30C8\u307E\u305F\u306F\n jar\u30A2\u30FC\u30AB\u30A4\u30D6\u81EA\u4F53\u306E\u30EB\u30FC\u30C8\u306B\u3042\u308B\u5834\u5408\u3001\u30A2\u30FC\u30AB\u30A4\u30D6\u306F\u30E2\u30B8\u30E5\u30E9jar\u3067\u3059\u3002\n \u6B21\u306E\u64CD\u4F5C\u306F\u3001\u30E2\u30B8\u30E5\u30E9jar\u306E\u4F5C\u6210\u6642\u307E\u305F\u306F\u65E2\u5B58\u306E\u975E\u30E2\u30B8\u30E5\u30E9jar\u306E\u66F4\u65B0\u6642\u306B\n \u306E\u307F\u6709\u52B9\u3067\u3059: '--module-version'\u3001\n '--hash-modules'\u304A\u3088\u3073'--module-path'\u3002\n\n \u30ED\u30F3\u30B0\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\u3078\u306E\u5FC5\u9808\u307E\u305F\u306F\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5F15\u6570\u306F\u3001\u5BFE\u5FDC\u3059\u308B\u30B7\u30E7\u30FC\u30C8\u30FB\u30AA\u30D7\u30B7\u30E7\u30F3\n \u306B\u5BFE\u3057\u3066\u3082\u5FC5\u9808\u307E\u305F\u306F\u30AA\u30D7\u30B7\u30E7\u30F3\u306B\u306A\u308A\u307E\u3059\u3002 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 b5e33e66ec9..f07f8d632f6 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1999, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1999, 2022, 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,6 +23,10 @@ # questions. # +## tool + +jar.description=\u521B\u5EFA\u7C7B\u548C\u8D44\u6E90\u7684\u6863\u6848\uFF0C\u5E76\u5904\u7406\u6863\u6848\u4E2D\u7684\u5355\u4E2A\u7C7B\u6216\u8D44\u6E90\u6216\u8005\u4ECE\u6863\u6848\u4E2D\u8FD8\u539F\u5355\u4E2A\u7C7B\u6216\u8D44\u6E90 + error.multiple.main.operations=\u4E0D\u80FD\u6307\u5B9A\u591A\u4E2A '-cuxtid' \u9009\u9879 error.cant.open=\u65E0\u6CD5\u6253\u5F00: {0} error.illegal.option=\u975E\u6CD5\u9009\u9879: {0} 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 03cb0891b0c..df04b0a4e31 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 @@ -41,6 +41,7 @@ doclet.Window_Class_Hierarchy=Klassenhierarchie doclet.Interface_Hierarchy=Schnittstellenhierarchie doclet.Enum_Hierarchy=Enum-Hierarchie doclet.Enum_Class_Hierarchy=Enum-Klassenhierarchie +doclet.Record_Class_Hierarchy=Datensatz-Klassenhierarchie doclet.Annotation_Type_Hierarchy=Annotationstyphierarchie doclet.Annotation_Interface_Hierarchy=Annotationsschnittstellenhierarchie doclet.Href_Class_Title=Klasse in {0} @@ -101,6 +102,7 @@ doclet.MalformedURL=Nicht wohlgeformte URL: {0} doclet.File_error=Fehler beim Lesen der Datei: {0} doclet.URL_error=Fehler beim Abrufen der URL: {0} doclet.Resource_error=Fehler beim Lesen der Ressource: {0} +doclet.link.no_reference=Keine Referenz angegeben doclet.see.class_or_package_not_found=Tag {0}: Referenz nicht gefunden: {1} doclet.see.class_or_package_not_accessible=Tag {0}: Referenz nicht zug\u00E4nglich: {1} doclet.see.nested_link=Tag {0}: Verschachtelter Link @@ -108,14 +110,16 @@ doclet.tag.invalid_usage=Ung\u00FCltige Verwendung des Tags {0} doclet.tag.invalid_input=Ung\u00FCltige Eingabe: "{0}" doclet.tag.invalid=ung\u00FCltiges @{0} doclet.Deprecated_API=Veraltete API +doclet.Deprecated_API_Checkbox_Label=Veraltete API anzeigen in: +doclet.Deprecated_API_Checkbox_Other_Releases=Sonstige doclet.Deprecated_Elements=Veraltete {0} +doclet.Deprecated_Elements_Release_Column_Header=Veraltet in doclet.Deprecated_In_Release=Veraltet in {0} -doclet.Deprecated_Tabs_Intro=(Die Registerkarte "Veraltet ..." ganz links zeigt alle veralteten Elemente, unabh\u00E4ngig von dem Release, seit dem sie veraltet sind. Jede der anderen Registerkarten "Veraltet in ..." zeigt die Elemente, die seit einem bestimmten Release veraltet sind.) doclet.New_API=Neue API +doclet.New_API_Checkbox_Label=Hinzugef\u00FCgte API anzeigen in: doclet.New_Elements=Neue {0} -doclet.New_Elements_Added_In_Release=Hinzugef\u00FCgt in {0} +doclet.New_Elements_Release_Column_Header=Hinzugef\u00FCgt in doclet.New_Label=Neu -doclet.New_Tabs_Intro=(Die Registerkarte "Neu ..." ganz links zeigt alle neuen Elemente, unabh\u00E4ngig von dem Release, in dem sie hinzugef\u00FCgt wurden. Jede der anderen Registerkarten "Hinzugef\u00FCgt in ..." zeigt die Elemente, die in einem bestimmten Release hinzugef\u00FCgt wurden. Elemente, die auf der Registerkarte ganz links angezeigt werden, werden auch auf einer der Registerkarten weiter rechts angezeigt.) doclet.Preview_API=Vorschau-API doclet.Preview_Label=Vorschau doclet.Preview_Mark=PREVIEW @@ -159,6 +163,17 @@ doclet.systemProperties=Systemeigenschaften doclet.systemPropertiesSummary=Systemeigenschaften - \u00DCbersicht doclet.Window_Source_title=Quellcode doclet.Window_Help_title=API-Hilfe +doclet.Window_Search_title=Suchen +doclet.search.main_heading=Suchen + +# label for link/button element to show the information below +doclet.search.show_more=Zus\u00E4tzliche Ressourcen +doclet.search.help_page_link=Hilfeseite +# 0: a link to the help page with text above +doclet.search.help_page_info= Die {0} enth\u00E4lt eine Einf\u00FChrung in den Umfang und die Syntax der JavaDoc-Suche. +doclet.search.keyboard_info= Sie k\u00F6nnen die - oder -Taste zusammen mit den Pfeiltasten nach links und rechts verwenden, um zwischen Ergebnisregisterkarten auf dieser Seite zu wechseln. +doclet.search.browser_info= Mit der URL-Vorlage unten k\u00F6nnen Sie diese Seite als Suchmaschine in Browsern konfigurieren, die dieses Feature unterst\u00FCtzen. Das Feature wurde erfolgreich mit Google Chrome und Mozilla Firefox getestet. Beachten Sie, dass andere Browser dieses Feature m\u00F6glicherweise nicht unterst\u00FCtzen oder ein anderes URL-Format erfordern. +doclet.search.redirect=Zum ersten Ergebnis umleiten # 0: a date doclet.Option_date_out_of_range=Wert f\u00FCr "--date" au\u00DFerhalb des g\u00FCltigen Bereichs: {0} @@ -233,9 +248,9 @@ doclet.help.annotation_type.description=Beschreibung des Annotationstyps doclet.help.annotation_interface.description=Beschreibung der Annotationsschnittstelle doclet.help.search.head=Suchen # Introduction to Javadoc search features, followed by a list of examples -doclet.help.search.intro=Sie k\u00F6nnen nach Definitionen von Modulen, Packages, Typen, Feldern, Methoden, Systemeigenschaften und anderen Ausdr\u00FCcken suchen, die in der API definiert sind. Dazu k\u00F6nnen Sie denn Namen ganz oder teilweise oder optional auch Abk\u00FCrzungen mit Binnenmajuskeln ("camelCase") eingeben. Beispiel: +doclet.help.search.intro=Sie k\u00F6nnen nach Definitionen von Modulen, Packages, Typen, Feldern, Methoden, Systemeigenschaften und anderen Begriffen suchen, die in der API definiert sind. Dazu k\u00F6nnen Sie den Namen ganz oder teilweise oder optional auch Abk\u00FCrzungen mit Binnenmajuskeln ("camelCase") eingeben. Sie k\u00F6nnen auch mehrere durch Leerzeichen getrennte Suchbegriffe angeben. Beispiele: # Used to list search examples, {0} is a search term and {1} the matching result -doclet.help.search.example={0} findet {1} +doclet.help.search.example={0} stimmt mit {1} \u00FCberein # {0} contains a link to the current Javadoc Search Specification doclet.help.search.refer=Eine vollst\u00E4ndige Beschreibung der Suchfeatures finden Sie in der {0}. # The URL for the Javadoc Search Specification. {0} will be replaced by the JDK version number @@ -431,7 +446,7 @@ doclet.usage.no-frames.description=Deaktiviert die Verwendung von Frames in der doclet.usage.override-methods.parameters=(detail|summary) -doclet.usage.override-methods.description=Au\u00DFer Kraft gesetzte Methoden im Abschnitt "detail" oder "summary" dokumentieren +doclet.usage.override-methods.description=Au\u00DFer Kraft gesetzte Methoden im Abschnitt "detail" oder "summary" dokumentieren.\nDer Standardwert ist "detail". doclet.usage.allow-script-in-comments.description=JavaScript in Optionen und Kommentaren zulassen 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 9a1ecc36b54..65ed909aab0 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 @@ -41,6 +41,7 @@ doclet.Window_Class_Hierarchy=\u30AF\u30E9\u30B9\u968E\u5C64 doclet.Interface_Hierarchy=\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u968E\u5C64 doclet.Enum_Hierarchy=\u5217\u6319\u578B\u968E\u5C64 doclet.Enum_Class_Hierarchy=\u5217\u6319\u30AF\u30E9\u30B9\u968E\u5C64 +doclet.Record_Class_Hierarchy=\u30EC\u30B3\u30FC\u30C9\u30FB\u30AF\u30E9\u30B9\u968E\u5C64 doclet.Annotation_Type_Hierarchy=\u6CE8\u91C8\u578B\u968E\u5C64 doclet.Annotation_Interface_Hierarchy=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u968E\u5C64 doclet.Href_Class_Title={0}\u5185\u306E\u30AF\u30E9\u30B9 @@ -101,6 +102,7 @@ doclet.MalformedURL=\u4E0D\u6B63\u306AURL: {0} doclet.File_error=\u30D5\u30A1\u30A4\u30EB\u8AAD\u8FBC\u307F\u30A8\u30E9\u30FC: {0} doclet.URL_error=URL\u53D6\u51FA\u3057\u30A8\u30E9\u30FC: {0} doclet.Resource_error=\u30EA\u30BD\u30FC\u30B9\u8AAD\u53D6\u308A\u30A8\u30E9\u30FC: {0} +doclet.link.no_reference=\u53C2\u7167\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 doclet.see.class_or_package_not_found=\u30BF\u30B0{0}: \u53C2\u7167\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {1} doclet.see.class_or_package_not_accessible=\u30BF\u30B0{0}: \u53C2\u7167\u306B\u30A2\u30AF\u30BB\u30B9\u3067\u304D\u307E\u305B\u3093: {1} doclet.see.nested_link=\u30BF\u30B0{0}: \u30EA\u30F3\u30AF\u304C\u30CD\u30B9\u30C8\u3055\u308C\u3066\u3044\u307E\u3059 @@ -108,14 +110,16 @@ doclet.tag.invalid_usage=\u30BF\u30B0{0}\u306E\u4F7F\u7528\u65B9\u6CD5\u304C\u71 doclet.tag.invalid_input=\u5165\u529B\u304C\u7121\u52B9\u3067\u3059: ''{0}'' doclet.tag.invalid=@{0}\u304C\u7121\u52B9\u3067\u3059 doclet.Deprecated_API=\u63A8\u5968\u3055\u308C\u3066\u3044\u306A\u3044API +doclet.Deprecated_API_Checkbox_Label=\u6B21\u3067\u975E\u63A8\u5968\u306EAPI\u3092\u8868\u793A: +doclet.Deprecated_API_Checkbox_Other_Releases=\u305D\u306E\u4ED6 doclet.Deprecated_Elements=\u63A8\u5968\u3055\u308C\u3066\u3044\u306A\u3044{0} +doclet.Deprecated_Elements_Release_Column_Header=\u6B21\u3067\u975E\u63A8\u5968 doclet.Deprecated_In_Release={0}\u3067\u975E\u63A8\u5968 -doclet.Deprecated_Tabs_Intro=(\u5DE6\u7AEF\u306E\u30BF\u30D6\u300C\u63A8\u5968\u3055\u308C\u3066\u3044\u306A\u3044...\u300D\u306F\u3001\u975E\u63A8\u5968\u306B\u306A\u3063\u305F\u30EA\u30EA\u30FC\u30B9\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3059\u3079\u3066\u306E\u975E\u63A8\u5968\u306E\u8981\u7D20\u3092\u793A\u3057\u307E\u3059\u3002\u305D\u306E\u4ED6\u306E\u30BF\u30D6\u300C...\u3067\u975E\u63A8\u5968\u300D\u306E\u305D\u308C\u305E\u308C\u306F\u3001\u7279\u5B9A\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u975E\u63A8\u5968\u306B\u306A\u3063\u305F\u8981\u7D20\u3092\u793A\u3057\u307E\u3059\u3002) doclet.New_API=\u65B0\u898FAPI +doclet.New_API_Checkbox_Label=\u6B21\u3067\u8FFD\u52A0\u3055\u308C\u305FAPI\u3092\u8868\u793A: doclet.New_Elements=\u65B0\u898F{0} -doclet.New_Elements_Added_In_Release={0}\u3067\u8FFD\u52A0 +doclet.New_Elements_Release_Column_Header=\u6B21\u3067\u8FFD\u52A0 doclet.New_Label=\u65B0\u898F -doclet.New_Tabs_Intro=(\u5DE6\u7AEF\u306E\u30BF\u30D6\u300C\u65B0\u898F...\u300D\u306F\u3001\u8FFD\u52A0\u3055\u308C\u305F\u30EA\u30EA\u30FC\u30B9\u306B\u95A2\u4FC2\u306A\u304F\u3001\u3059\u3079\u3066\u306E\u65B0\u898F\u8981\u7D20\u3092\u793A\u3057\u307E\u3059\u3002\u305D\u306E\u4ED6\u306E\u30BF\u30D6\u300C...\u3067\u8FFD\u52A0\u300D\u306E\u305D\u308C\u305E\u308C\u306F\u3001\u7279\u5B9A\u306E\u30EA\u30EA\u30FC\u30B9\u3067\u8FFD\u52A0\u3055\u308C\u305F\u8981\u7D20\u3092\u793A\u3057\u307E\u3059\u3002\u5DE6\u7AEF\u306E\u30BF\u30D6\u3067\u8868\u793A\u3055\u308C\u305F\u8981\u7D20\u306F\u53F3\u7AEF\u306E\u30BF\u30D6\u306E\u3044\u305A\u308C\u304B\u306E\u4E0B\u306B\u3082\u8868\u793A\u3055\u308C\u307E\u3059\u3002) doclet.Preview_API=\u30D7\u30EC\u30D3\u30E5\u30FCAPI doclet.Preview_Label=\u30D7\u30EC\u30D3\u30E5\u30FC doclet.Preview_Mark=PREVIEW @@ -159,6 +163,17 @@ doclet.systemProperties=\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u doclet.systemPropertiesSummary=\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u30FB\u30B5\u30DE\u30EA\u30FC doclet.Window_Source_title=\u30BD\u30FC\u30B9\u30FB\u30B3\u30FC\u30C9 doclet.Window_Help_title=API\u30D8\u30EB\u30D7 +doclet.Window_Search_title=\u691C\u7D22 +doclet.search.main_heading=\u691C\u7D22 + +# label for link/button element to show the information below +doclet.search.show_more=\u305D\u306E\u4ED6\u306E\u30EA\u30BD\u30FC\u30B9 +doclet.search.help_page_link=\u30D8\u30EB\u30D7\u30FB\u30DA\u30FC\u30B8 +# 0: a link to the help page with text above +doclet.search.help_page_info= {0}\u3067\u306F\u3001JavaDoc\u691C\u7D22\u306E\u7BC4\u56F2\u304A\u3088\u3073\u69CB\u6587\u306E\u6982\u8981\u306B\u3064\u3044\u3066\u8AAC\u660E\u3057\u307E\u3059\u3002 +doclet.search.keyboard_info= \u307E\u305F\u306F\u30AD\u30FC\u3092\u5DE6\u53F3\u306E\u77E2\u5370\u30AD\u30FC\u3068\u7D44\u307F\u5408\u305B\u3066\u4F7F\u7528\u3059\u308B\u3068\u3001\u3053\u306E\u30DA\u30FC\u30B8\u306E\u7D50\u679C\u30BF\u30D6\u3092\u5207\u308A\u66FF\u3048\u308B\u3053\u3068\u304C\u3067\u304D\u307E\u3059\u3002 +doclet.search.browser_info= \u6B21\u306EURL\u30C6\u30F3\u30D7\u30EC\u30FC\u30C8\u306F\u3001\u3053\u306E\u6A5F\u80FD\u3092\u30B5\u30DD\u30FC\u30C8\u3059\u308B\u30D6\u30E9\u30A6\u30B6\u3067\u3053\u306E\u30DA\u30FC\u30B8\u3092\u691C\u7D22\u30A8\u30F3\u30B8\u30F3\u3068\u3057\u3066\u69CB\u6210\u3059\u308B\u305F\u3081\u306B\u4F7F\u7528\u3067\u304D\u307E\u3059\u3002Google Chrome\u304A\u3088\u3073Mozilla Firefox\u3067\u52D5\u4F5C\u3059\u308B\u3053\u3068\u304C\u30C6\u30B9\u30C8\u3055\u308C\u3066\u3044\u307E\u3059\u3002\u4ED6\u306E\u30D6\u30E9\u30A6\u30B6\u3067\u306F\u3001\u3053\u306E\u6A5F\u80FD\u304C\u30B5\u30DD\u30FC\u30C8\u3055\u308C\u3066\u3044\u306A\u3044\u304B\u3001\u5225\u306EURL\u5F62\u5F0F\u304C\u5FC5\u8981\u306B\u306A\u308B\u5834\u5408\u304C\u3042\u308A\u307E\u3059\u3002 +doclet.search.redirect=\u6700\u521D\u306E\u7D50\u679C\u306B\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8 # 0: a date doclet.Option_date_out_of_range=''--date''\u306E\u5024\u304C\u7BC4\u56F2\u5916\u3067\u3059: {0} @@ -233,9 +248,9 @@ doclet.help.annotation_type.description=\u6CE8\u91C8\u578B\u306E\u8AAC\u660E doclet.help.annotation_interface.description=\u6CE8\u91C8\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9\u306E\u8AAC\u660E doclet.help.search.head=\u691C\u7D22 # Introduction to Javadoc search features, followed by a list of examples -doclet.help.search.intro=\u30E2\u30B8\u30E5\u30FC\u30EB\u3001\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30BF\u30A4\u30D7\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u30E1\u30BD\u30C3\u30C9\u3001\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u5B9A\u7FA9\u304A\u3088\u3073API\u3067\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u308B\u305D\u306E\u4ED6\u306E\u8A9E\u3092\u3001\u540D\u524D\u306E\u4E00\u90E8\u307E\u305F\u306F\u5168\u4F53\u3092\u4F7F\u7528\u3057\u3066(\u5FC5\u8981\u306B\u5FDC\u3058\u3066camelCase\u306E\u7701\u7565\u5F62\u3092\u4F7F\u7528\u3057\u3066)\u691C\u7D22\u3067\u304D\u307E\u3059\u3002\u4F8B: +doclet.help.search.intro=\u30E2\u30B8\u30E5\u30FC\u30EB\u3001\u30D1\u30C3\u30B1\u30FC\u30B8\u3001\u30BF\u30A4\u30D7\u3001\u30D5\u30A3\u30FC\u30EB\u30C9\u3001\u30E1\u30BD\u30C3\u30C9\u3001\u30B7\u30B9\u30C6\u30E0\u30FB\u30D7\u30ED\u30D1\u30C6\u30A3\u306E\u5B9A\u7FA9\u304A\u3088\u3073API\u3067\u5B9A\u7FA9\u3055\u308C\u3066\u3044\u308B\u305D\u306E\u4ED6\u306E\u8A9E\u3092\u691C\u7D22\u3067\u304D\u307E\u3059\u3002\u3053\u308C\u3089\u306E\u30A2\u30A4\u30C6\u30E0\u306F\u3001\u540D\u524D\u306E\u4E00\u90E8\u307E\u305F\u306F\u5168\u4F53\u3092\u4F7F\u7528\u3057\u3066(\u5FC5\u8981\u306B\u5FDC\u3058\u3066camelCase\u306E\u7701\u7565\u5F62\u3092\u4F7F\u7528\u3057\u3066)\u3001\u307E\u305F\u306F\u8907\u6570\u306E\u691C\u7D22\u8A9E\u3092\u30B9\u30DA\u30FC\u30B9\u3067\u533A\u5207\u3063\u3066\u691C\u7D22\u3067\u304D\u307E\u3059\u3002\u4F8B\u3092\u3044\u304F\u3064\u304B\u793A\u3057\u307E\u3059: # Used to list search examples, {0} is a search term and {1} the matching result -doclet.help.search.example={0}\u306F{1}\u3068\u4E00\u81F4\u3057\u307E\u3059 +doclet.help.search.example={0}\u306F{1}\u306B\u4E00\u81F4\u3057\u307E\u3059 # {0} contains a link to the current Javadoc Search Specification doclet.help.search.refer=\u691C\u7D22\u6A5F\u80FD\u306E\u8A73\u7D30\u306A\u8AAC\u660E\u306F\u3001{0}\u3092\u53C2\u7167\u3057\u3066\u304F\u3060\u3055\u3044\u3002 # The URL for the Javadoc Search Specification. {0} will be replaced by the JDK version number @@ -431,7 +446,7 @@ doclet.usage.no-frames.description=\u751F\u6210\u3055\u308C\u305F\u51FA\u529B\u3 doclet.usage.override-methods.parameters=(\u8A73\u7D30|\u8981\u7D04) -doclet.usage.override-methods.description=\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3055\u308C\u305F\u30E1\u30BD\u30C3\u30C9\u3092\u8A73\u7D30\u307E\u305F\u306F\u8981\u7D04\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5316\u3057\u307E\u3059 +doclet.usage.override-methods.description=\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u3055\u308C\u305F\u30E1\u30BD\u30C3\u30C9\u3092\u8A73\u7D30\u307E\u305F\u306F\u8981\u7D04\u30BB\u30AF\u30B7\u30E7\u30F3\u3067\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5316\u3057\u307E\u3059\u3002\n\u30C7\u30D5\u30A9\u30EB\u30C8\u306F\u8A73\u7D30\u3067\u3059\u3002 doclet.usage.allow-script-in-comments.description=\u30AA\u30D7\u30B7\u30E7\u30F3\u304A\u3088\u3073\u30B3\u30E1\u30F3\u30C8\u3067JavaScript\u3092\u8A31\u53EF\u3057\u307E\u3059 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 656c9ce25be..81d7d86b431 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 @@ -41,6 +41,7 @@ doclet.Window_Class_Hierarchy=\u7C7B\u5206\u5C42\u7ED3\u6784 doclet.Interface_Hierarchy=\u63A5\u53E3\u5206\u5C42\u7ED3\u6784 doclet.Enum_Hierarchy=\u679A\u4E3E\u5206\u5C42\u7ED3\u6784 doclet.Enum_Class_Hierarchy=\u679A\u4E3E\u7C7B\u5206\u5C42\u7ED3\u6784 +doclet.Record_Class_Hierarchy=\u8BB0\u5F55\u7C7B\u5206\u5C42\u7ED3\u6784 doclet.Annotation_Type_Hierarchy=\u6CE8\u91CA\u7C7B\u578B\u5206\u5C42\u7ED3\u6784 doclet.Annotation_Interface_Hierarchy=\u6CE8\u91CA\u63A5\u53E3\u5206\u5C42\u7ED3\u6784 doclet.Href_Class_Title={0}\u4E2D\u7684\u7C7B @@ -101,6 +102,7 @@ doclet.MalformedURL=\u683C\u5F0F\u9519\u8BEF\u7684 URL: {0} doclet.File_error=\u8BFB\u53D6\u6587\u4EF6\u65F6\u51FA\u9519: {0} doclet.URL_error=\u83B7\u53D6 URL \u65F6\u51FA\u9519: {0} doclet.Resource_error=\u8BFB\u53D6\u8D44\u6E90\u65F6\u51FA\u9519\uFF1A{0} +doclet.link.no_reference=\u672A\u63D0\u4F9B\u5F15\u7528 doclet.see.class_or_package_not_found=\u6807\u8BB0{0}: \u627E\u4E0D\u5230\u5F15\u7528: {1} doclet.see.class_or_package_not_accessible=\u6807\u8BB0{0}: \u65E0\u6CD5\u8BBF\u95EE\u5F15\u7528: {1} doclet.see.nested_link=\u6807\u8BB0 {0}\uFF1A\u5D4C\u5957\u94FE\u63A5 @@ -108,14 +110,16 @@ doclet.tag.invalid_usage=\u6807\u8BB0 {0} \u7684\u7528\u6CD5\u65E0\u6548 doclet.tag.invalid_input=\u65E0\u6548\u8F93\u5165\uFF1A''{0}'' doclet.tag.invalid=@{0} \u65E0\u6548 doclet.Deprecated_API=\u5DF2\u8FC7\u65F6\u7684 API +doclet.Deprecated_API_Checkbox_Label=\u663E\u793A\u5728\u4EE5\u4E0B\u53D1\u884C\u7248\u4E2D\u5DF2\u8FC7\u65F6\u7684 API\uFF1A +doclet.Deprecated_API_Checkbox_Other_Releases=\u5176\u4ED6 doclet.Deprecated_Elements=\u5DF2\u8FC7\u65F6\u7684 {0} +doclet.Deprecated_Elements_Release_Column_Header=\u5728\u4EE5\u4E0B\u53D1\u884C\u7248\u4E2D\u5DF2\u8FC7\u65F6 doclet.Deprecated_In_Release=\u5728 {0} \u4E2D\u5DF2\u8FC7\u65F6 -doclet.Deprecated_Tabs_Intro=\uFF08\u6700\u5DE6\u4FA7\u7684\u9009\u9879\u5361\u201C\u5DF2\u8FC7\u65F6...\u201D\u6307\u793A\u6240\u6709\u5DF2\u8FC7\u65F6\u7684\u5143\u7D20\uFF0C\u65E0\u8BBA\u5B83\u4EEC\u5728\u54EA\u4E2A\u53D1\u884C\u7248\u4E2D\u5DF2\u8FC7\u65F6\u3002\u5176\u4ED6\u6BCF\u4E2A\u201C\u5728...\u4E2D\u5DF2\u8FC7\u65F6\u201D\u9009\u9879\u5361\u6307\u793A\u5728\u7279\u5B9A\u53D1\u884C\u7248\u4E2D\u5DF2\u8FC7\u65F6\u7684\u5143\u7D20\u3002\uFF09 doclet.New_API=\u65B0\u5EFA API +doclet.New_API_Checkbox_Label=\u663E\u793A\u5728\u4EE5\u4E0B\u53D1\u884C\u7248\u4E2D\u6DFB\u52A0\u7684 API\uFF1A doclet.New_Elements=\u65B0\u5EFA {0} -doclet.New_Elements_Added_In_Release=\u5728 {0} \u4E2D\u5DF2\u6DFB\u52A0 +doclet.New_Elements_Release_Column_Header=\u5728\u4EE5\u4E0B\u53D1\u884C\u7248\u4E2D\u5DF2\u6DFB\u52A0 doclet.New_Label=\u65B0\u5EFA -doclet.New_Tabs_Intro=\uFF08\u6700\u5DE6\u4FA7\u7684\u9009\u9879\u5361\u201C\u65B0\u5EFA...\u201D\u6307\u793A\u6240\u6709\u65B0\u5143\u7D20\uFF0C\u65E0\u8BBA\u5B83\u4EEC\u662F\u54EA\u4E2A\u53D1\u884C\u7248\u4E2D\u6DFB\u52A0\u7684\u3002\u5176\u4ED6\u6BCF\u4E2A\u201C\u5728...\u4E2D\u5DF2\u6DFB\u52A0\u201D\u9009\u9879\u5361\u6307\u793A\u5728\u7279\u5B9A\u53D1\u884C\u7248\u4E2D\u6DFB\u52A0\u7684\u65B0\u5143\u7D20\u3002\u6700\u5DE6\u4FA7\u9009\u9879\u5361\u4E0B\u663E\u793A\u7684\u4EFB\u4F55\u5143\u7D20\u4E5F\u4F1A\u663E\u793A\u5728\u53F3\u4FA7\u9009\u9879\u5361\u4E4B\u4E00\u4E0B\u3002\uFF09 doclet.Preview_API=\u9884\u89C8 API doclet.Preview_Label=\u9884\u89C8 doclet.Preview_Mark=PREVIEW @@ -159,6 +163,17 @@ doclet.systemProperties=\u7CFB\u7EDF\u5C5E\u6027 doclet.systemPropertiesSummary=\u7CFB\u7EDF\u5C5E\u6027\u6982\u8981 doclet.Window_Source_title=\u6E90\u4EE3\u7801 doclet.Window_Help_title=API \u5E2E\u52A9 +doclet.Window_Search_title=\u641C\u7D22 +doclet.search.main_heading=\u641C\u7D22 + +# label for link/button element to show the information below +doclet.search.show_more=\u5176\u4ED6\u8D44\u6E90 +doclet.search.help_page_link=\u5E2E\u52A9\u9875 +# 0: a link to the help page with text above +doclet.search.help_page_info= {0} \u4ECB\u7ECD\u4E86 JavaDoc \u641C\u7D22\u7684\u8303\u56F4\u548C\u8BED\u6CD5\u3002 +doclet.search.keyboard_info= \u60A8\u53EF\u4EE5\u4F7F\u7528 \u6216 \u952E\u4E0E\u5DE6\u7BAD\u5934\u548C\u53F3\u7BAD\u5934\u952E\u7EC4\u5408\u5728\u6B64\u9875\u9762\u4E2D\u7684\u7ED3\u679C\u9009\u9879\u5361\u4E4B\u95F4\u5207\u6362\u3002 +doclet.search.browser_info= \u4E0B\u9762\u7684 URL \u6A21\u677F\u53EF\u7528\u4E8E\u5728\u652F\u6301\u6B64\u529F\u80FD\u7684\u6D4F\u89C8\u5668\u4E2D\u5C06\u6B64\u9875\u9762\u914D\u7F6E\u4E3A\u641C\u7D22\u5F15\u64CE\u3002\u5DF2\u7ECF\u5BF9\u5176\u8FDB\u884C\u4E86\u6D4B\u8BD5\u4EE5\u5728 Google Chrome \u548C Mozilla Firefox \u4E2D\u4F7F\u7528\u3002\u8BF7\u6CE8\u610F\uFF0C\u5176\u4ED6\u6D4F\u89C8\u5668\u53EF\u80FD\u4E0D\u652F\u6301\u6B64\u529F\u80FD\u6216\u9700\u8981\u4E0D\u540C\u7684 URL \u683C\u5F0F\u3002 +doclet.search.redirect=\u91CD\u5B9A\u5411\u5230\u7B2C\u4E00\u4E2A\u7ED3\u679C # 0: a date doclet.Option_date_out_of_range=''--date'' \u7684\u503C\u8D85\u51FA\u8303\u56F4\uFF1A{0} @@ -233,9 +248,9 @@ doclet.help.annotation_type.description=\u6CE8\u91CA\u7C7B\u578B\u8BF4\u660E doclet.help.annotation_interface.description=\u6CE8\u91CA\u63A5\u53E3\u8BF4\u660E doclet.help.search.head=\u641C\u7D22 # Introduction to Javadoc search features, followed by a list of examples -doclet.help.search.intro=\u53EF\u4EE5\u4F7F\u7528\u90E8\u5206\u6216\u5B8C\u6574\u540D\u79F0\u641C\u7D22\u6A21\u5757\u3001\u7A0B\u5E8F\u5305\u3001\u7C7B\u578B\u3001\u5B57\u6BB5\u3001\u65B9\u6CD5\u3001\u7CFB\u7EDF\u5C5E\u6027\u4EE5\u53CA API \u4E2D\u5B9A\u4E49\u7684\u5176\u4ED6\u672F\u8BED\u7684\u5B9A\u4E49\uFF0C\uFF08\u53EF\u9009\uFF09\u4E5F\u53EF\u4EE5\u4F7F\u7528\u201C\u9A7C\u5CF0\u5927\u5C0F\u5199\u5F0F\u201D\u7F29\u5199\u8FDB\u884C\u641C\u7D22\u3002\u4F8B\u5982\uFF1A +doclet.help.search.intro=\u53EF\u4EE5\u641C\u7D22\u6A21\u5757\u3001\u7A0B\u5E8F\u5305\u3001\u7C7B\u578B\u3001\u5B57\u6BB5\u3001\u65B9\u6CD5\u3001\u7CFB\u7EDF\u5C5E\u6027\u4EE5\u53CA API \u4E2D\u5B9A\u4E49\u7684\u5176\u4ED6\u672F\u8BED\u7684\u5B9A\u4E49\u3002\u53EF\u4EE5\u4F7F\u7528\u90E8\u5206\u6216\u5B8C\u6574\u540D\u79F0\u641C\u7D22\u8FD9\u4E9B\u9879\uFF0C\uFF08\u53EF\u9009\uFF09\u4E5F\u53EF\u4EE5\u4F7F\u7528\u201C\u9A7C\u5CF0\u5927\u5C0F\u5199\u5F0F\u201D\u7F29\u5199\uFF0C\u6216\u4F7F\u7528\u7A7A\u683C\u5206\u9694\u7684\u591A\u4E2A\u641C\u7D22\u8BCD\u8FDB\u884C\u641C\u7D22\u3002\u4E00\u4E9B\u793A\u4F8B\uFF1A # Used to list search examples, {0} is a search term and {1} the matching result -doclet.help.search.example={0} \u5C06\u4E0E {1} \u76F8\u5339\u914D +doclet.help.search.example={0} \u5339\u914D {1} # {0} contains a link to the current Javadoc Search Specification doclet.help.search.refer=\u6709\u5173\u641C\u7D22\u529F\u80FD\u7684\u5B8C\u6574\u8BF4\u660E\uFF0C\u8BF7\u53C2\u9605 {0}\u3002 # The URL for the Javadoc Search Specification. {0} will be replaced by the JDK version number @@ -431,7 +446,7 @@ doclet.usage.no-frames.description=\u7981\u6B62\u5728\u751F\u6210\u7684\u8F93\u5 doclet.usage.override-methods.parameters=(detail|summary) -doclet.usage.override-methods.description=\u5728\u8BE6\u7EC6\u8D44\u6599\u90E8\u5206\u6216\u6982\u8981\u90E8\u5206\u4E2D\u7684\u6587\u6863\u8986\u76D6\u65B9\u6CD5 +doclet.usage.override-methods.description=\u5728\u8BE6\u7EC6\u4FE1\u606F\u90E8\u5206\u6216\u6982\u8981\u90E8\u5206\u4E2D\u8BB0\u5F55\u8986\u76D6\u7684\u65B9\u6CD5\u3002\n\u9ED8\u8BA4\u503C\u4E3A 'detail'\u3002 doclet.usage.allow-script-in-comments.description=\u5141\u8BB8\u5728\u9009\u9879\u548C\u6CE8\u91CA\u4E2D\u4F7F\u7528 JavaScript 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 13926c372ee..21026476e12 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 @@ -48,6 +48,8 @@ doclet.File_not_found=Datei nicht gefunden: {0} doclet.snippet_file_not_found=Datei nicht gefunden in Quellpfad oder Snippet-Pfad: {0} doclet.Copy_Overwrite_warning=Datei {0} wurde nicht in {1} kopiert, da bereits eine Datei mit demselben Namen vorhanden ist... doclet.Copy_Ignored_warning=Die Datei {0} wurde nicht kopiert: ung\u00FCltiger Name +doclet.Copy_url_to_clipboard=URL kopieren +doclet.Copied_url_to_clipboard=Kopiert. doclet.Copy_snippet_to_clipboard=Kopieren doclet.Copied_snippet_to_clipboard=Kopiert. doclet.Copying_File_0_To_Dir_1=Datei {0} wird in Verzeichnis {1} kopiert... @@ -106,6 +108,7 @@ doclet.Version=Version: doclet.Factory=Factory: doclet.UnknownTag={0} ist ein unbekanntes Tag. doclet.UnknownTagLowercase={0} ist ein unbekanntes Tag - bis auf die Gro\u00DF-/Kleinschreibung identisch mit einem bekannten Tag. +doclet.inheritDocWithinInappropriateTag=@inheritDoc kann in diesem Tag nicht verwendet werden doclet.noInheritedDoc=@inheritDoc wurde verwendet, aber mit {0} wird keine Methode au\u00DFer 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.Package_Summary=Package\u00FCbersicht @@ -213,8 +216,9 @@ doclet.Modifier=Modifizierer doclet.Type=Typ doclet.Modifier_and_Type=Modifizierer und Typ doclet.Implementation=Implementierung(en): -doclet.search=SEARCH: +doclet.search=SEARCH doclet.search_placeholder=Suchen +doclet.search_reset=Zur\u00FCcksetzen doclet.Field=Feld doclet.Property=Eigenschaft doclet.Constructor=Konstruktor @@ -287,8 +291,13 @@ doclet.platform.docs.old=https://docs.oracle.com/javase/{0}/docs/api/ doclet.platform.docs.new=https://docs.oracle.com/en/java/javase/{0}/docs/api/ doclet.platform.docs.ea=https://download.java.net/java/early_access/jdk{0}/docs/api/ +doclet.search.enter_search_term=Geben Sie einen Suchbegriff ein doclet.search.no_results=Keine Ergebnisse gefunden +doclet.search.one_result=Ein Ergebnis gefunden +doclet.search.many_results={0} Ergebnisse gefunden doclet.search.loading=Suchindex wird geladen... +doclet.search.searching=Suche wird ausgef\u00FChrt... +doclet.search.redirecting=Zum ersten Ergebnis wird umgeleitet... doclet.search.modules=Module doclet.search.packages=Packages doclet.search.classes_and_interfaces=Klassen und Schnittstellen 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 aaed6459535..5c68362f17d 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 @@ -48,6 +48,8 @@ doclet.File_not_found=\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u30 doclet.snippet_file_not_found=\u30BD\u30FC\u30B9\u30FB\u30D1\u30B9\u307E\u305F\u306F\u30B9\u30CB\u30DA\u30C3\u30C8\u306E\u30D1\u30B9\u306B\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: {0} doclet.Copy_Overwrite_warning=\u30D5\u30A1\u30A4\u30EB{0}\u306F\u540C\u3058\u540D\u524D\u306E\u30D5\u30A1\u30A4\u30EB\u304C\u3042\u308B\u306E\u3067{1}\u306B\u30B3\u30D4\u30FC\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F... doclet.Copy_Ignored_warning=\u30D5\u30A1\u30A4\u30EB{0}\u306F\u30B3\u30D4\u30FC\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F: \u540D\u524D\u304C\u7121\u52B9\u3067\u3059 +doclet.Copy_url_to_clipboard=URL\u306E\u30B3\u30D4\u30FC +doclet.Copied_url_to_clipboard=\u30B3\u30D4\u30FC\u6E08 doclet.Copy_snippet_to_clipboard=\u30B3\u30D4\u30FC doclet.Copied_snippet_to_clipboard=\u30B3\u30D4\u30FC\u6E08 doclet.Copying_File_0_To_Dir_1=\u30D5\u30A1\u30A4\u30EB{0}\u3092\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA{1}\u306B\u30B3\u30D4\u30FC\u4E2D... @@ -106,6 +108,7 @@ doclet.Version=\u30D0\u30FC\u30B8\u30E7\u30F3: doclet.Factory=\u30D5\u30A1\u30AF\u30C8\u30EA: doclet.UnknownTag={0}\u306F\u4E0D\u660E\u306A\u30BF\u30B0\u3067\u3059\u3002 doclet.UnknownTagLowercase={0}\u306F\u4E0D\u660E\u306A\u30BF\u30B0\u3067\u3059\u3002\u5927\u6587\u5B57\u3068\u5C0F\u6587\u5B57\u306E\u533A\u5225\u3092\u9664\u3044\u3066\u306F\u65E2\u77E5\u306E\u30BF\u30B0\u3068\u540C\u3058\u3067\u3059\u3002 +doclet.inheritDocWithinInappropriateTag=@inheritDoc\u306F\u3001\u3053\u306E\u30BF\u30B0\u5185\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093 doclet.noInheritedDoc=@inheritDoc\u304C\u4F7F\u7528\u3055\u308C\u3066\u3044\u307E\u3059\u304C\u3001{0}\u306F\u3069\u306E\u30E1\u30BD\u30C3\u30C9\u3082\u30AA\u30FC\u30D0\u30FC\u30E9\u30A4\u30C9\u307E\u305F\u306F\u5B9F\u88C5\u3057\u3066\u3044\u307E\u305B\u3093\u3002 doclet.tag_misuse={0}\u30BF\u30B0\u306F{1}\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u3067\u306F\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093\u3002\u4F7F\u7528\u3067\u304D\u308B\u306E\u306F\u6B21\u306E\u30BF\u30A4\u30D7\u306E\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u5185\u306E\u307F\u3067\u3059: {2}\u3002 doclet.Package_Summary=\u30D1\u30C3\u30B1\u30FC\u30B8\u306E\u6982\u8981 @@ -213,8 +216,9 @@ doclet.Modifier=\u4FEE\u98FE\u5B50 doclet.Type=\u30BF\u30A4\u30D7 doclet.Modifier_and_Type=\u4FEE\u98FE\u5B50\u3068\u30BF\u30A4\u30D7 doclet.Implementation=\u5B9F\u88C5: -doclet.search=SEARCH: +doclet.search=SEARCH doclet.search_placeholder=\u691C\u7D22 +doclet.search_reset=\u30EA\u30BB\u30C3\u30C8 doclet.Field=\u30D5\u30A3\u30FC\u30EB\u30C9 doclet.Property=\u30D7\u30ED\u30D1\u30C6\u30A3 doclet.Constructor=\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF @@ -287,8 +291,13 @@ doclet.platform.docs.old=https://docs.oracle.com/javase/{0}/docs/api/ doclet.platform.docs.new=https://docs.oracle.com/en/java/javase/{0}/docs/api/ doclet.platform.docs.ea=https://download.java.net/java/early_access/jdk{0}/docs/api/ +doclet.search.enter_search_term=\u691C\u7D22\u8A9E\u3092\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044 doclet.search.no_results=\u7D50\u679C\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3067\u3057\u305F +doclet.search.one_result=1\u4EF6\u306E\u7D50\u679C\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F +doclet.search.many_results={0}\u306E\u7D50\u679C\u304C\u898B\u3064\u304B\u308A\u307E\u3057\u305F doclet.search.loading=\u691C\u7D22\u7D22\u5F15\u3092\u30ED\u30FC\u30C9\u4E2D... +doclet.search.searching=\u691C\u7D22\u4E2D... +doclet.search.redirecting=\u6700\u521D\u306E\u7D50\u679C\u306B\u30EA\u30C0\u30A4\u30EC\u30AF\u30C8\u4E2D... doclet.search.modules=\u30E2\u30B8\u30E5\u30FC\u30EB doclet.search.packages=\u30D1\u30C3\u30B1\u30FC\u30B8 doclet.search.classes_and_interfaces=\u30AF\u30E9\u30B9\u3068\u30A4\u30F3\u30BF\u30D5\u30A7\u30FC\u30B9 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 341890b7393..c79fb35e753 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 @@ -48,6 +48,8 @@ doclet.File_not_found=\u627E\u4E0D\u5230\u6587\u4EF6: {0} doclet.snippet_file_not_found=\u5728\u6E90\u8DEF\u5F84\u6216\u7247\u6BB5\u8DEF\u5F84\u4E2D\u627E\u4E0D\u5230\u6587\u4EF6\uFF1A{0} doclet.Copy_Overwrite_warning=\u672A\u5C06\u6587\u4EF6{0}\u590D\u5236\u5230 {1}, \u56E0\u4E3A\u73B0\u6709\u6587\u4EF6\u5177\u6709\u76F8\u540C\u540D\u79F0... doclet.Copy_Ignored_warning=\u672A\u590D\u5236\u6587\u4EF6 {0}\uFF1A\u540D\u79F0\u65E0\u6548 +doclet.Copy_url_to_clipboard=\u590D\u5236 URL +doclet.Copied_url_to_clipboard=\u5DF2\u590D\u5236\uFF01 doclet.Copy_snippet_to_clipboard=\u590D\u5236 doclet.Copied_snippet_to_clipboard=\u5DF2\u590D\u5236\uFF01 doclet.Copying_File_0_To_Dir_1=\u6B63\u5728\u5C06\u6587\u4EF6{0}\u590D\u5236\u5230\u76EE\u5F55 {1}... @@ -106,6 +108,7 @@ doclet.Version=\u7248\u672C: doclet.Factory=\u5DE5\u5382: doclet.UnknownTag={0}\u662F\u672A\u77E5\u6807\u8BB0\u3002 doclet.UnknownTagLowercase={0}\u662F\u672A\u77E5\u6807\u8BB0 - \u9664\u4E86\u5927\u5C0F\u5199\u4E4B\u5916\u5176\u4ED6\u65B9\u9762\u4E0E\u5DF2\u77E5\u6807\u8BB0\u76F8\u540C\u3002 +doclet.inheritDocWithinInappropriateTag=\u4E0D\u80FD\u5728\u6B64\u6807\u8BB0\u4E2D\u4F7F\u7528 @inheritDoc doclet.noInheritedDoc=\u4F7F\u7528\u4E86 @inheritDoc, \u4F46{0}\u672A\u8986\u76D6\u6216\u5B9E\u73B0\u4EFB\u4F55\u65B9\u6CD5\u3002 doclet.tag_misuse=\u4E0D\u80FD\u5728{1}\u6587\u6863\u4E2D\u4F7F\u7528\u6807\u8BB0{0}\u3002\u53EA\u80FD\u5728\u4EE5\u4E0B\u7C7B\u578B\u7684\u6587\u6863\u4E2D\u4F7F\u7528\u8BE5\u6807\u8BB0: {2}\u3002 doclet.Package_Summary=\u7A0B\u5E8F\u5305\u6982\u8981 @@ -213,8 +216,9 @@ doclet.Modifier=\u9650\u5B9A\u7B26 doclet.Type=\u7C7B\u578B doclet.Modifier_and_Type=\u4FEE\u9970\u7B26\u548C\u7C7B\u578B doclet.Implementation=\u5B9E\u73B0: -doclet.search=SEARCH: +doclet.search=SEARCH doclet.search_placeholder=\u641C\u7D22 +doclet.search_reset=\u91CD\u7F6E doclet.Field=\u5B57\u6BB5 doclet.Property=\u5C5E\u6027 doclet.Constructor=\u6784\u9020\u5668 @@ -287,8 +291,13 @@ doclet.platform.docs.old=https://docs.oracle.com/javase/{0}/docs/api/ doclet.platform.docs.new=https://docs.oracle.com/en/java/javase/{0}/docs/api/ doclet.platform.docs.ea=https://download.java.net/java/early_access/jdk{0}/docs/api/ +doclet.search.enter_search_term=\u8F93\u5165\u641C\u7D22\u8BCD doclet.search.no_results=\u672A\u627E\u5230\u7ED3\u679C +doclet.search.one_result=\u627E\u5230\u4E00\u4E2A\u7ED3\u679C +doclet.search.many_results=\u627E\u5230 {0} \u4E2A\u7ED3\u679C doclet.search.loading=\u6B63\u5728\u52A0\u8F7D\u641C\u7D22\u7D22\u5F15... +doclet.search.searching=\u6B63\u5728\u641C\u7D22... +doclet.search.redirecting=\u6B63\u5728\u91CD\u5B9A\u5411\u5230\u7B2C\u4E00\u4E2A\u7ED3\u679C... doclet.search.modules=\u6A21\u5757 doclet.search.packages=\u7A0B\u5E8F\u5305 doclet.search.classes_and_interfaces=\u7C7B\u548C\u63A5\u53E3 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_de.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_de.properties index e69be027bb2..57e776e0e7c 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_de.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_de.properties @@ -40,7 +40,7 @@ dc.bad.value.for.option = ung\u00FCltiger Wert f\u00FCr Option: {0} {1} dc.default.constructor = Verwendung von Standardkonstruktor, der keinen Kommentar bereitstellt dc.empty = keine Beschreibung f\u00FCr @{0} dc.empty.comment = leerer Kommentar -dc.empty.main.description = keine anf\u00E4ngliche Beschreibung +dc.empty.main.description = Keine Hauptbeschreibung dc.entity.invalid = ung\u00FCltige Entity &{0}; dc.exception.not.thrown = Ausnahme nicht ausgel\u00F6st: {0} dc.exists.param = @param "{0}" wurde bereits angegeben diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_ja.properties index 1f62ca622d8..5917b8f2436 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_ja.properties @@ -40,7 +40,7 @@ dc.bad.value.for.option = \u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u5024\u304C\u4E0D dc.default.constructor = \u30C7\u30D5\u30A9\u30EB\u30C8\u306E\u30B3\u30F3\u30B9\u30C8\u30E9\u30AF\u30BF\u306E\u4F7F\u7528\u3067\u3001\u30B3\u30E1\u30F3\u30C8\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093 dc.empty = @{0}\u306E\u8AAC\u660E\u304C\u3042\u308A\u307E\u305B\u3093 dc.empty.comment = \u30B3\u30E1\u30F3\u30C8\u304C\u7A7A\u3067\u3059 -dc.empty.main.description = \u521D\u671F\u306E\u8AAC\u660E\u304C\u3042\u308A\u307E\u305B\u3093 +dc.empty.main.description = \u4E3B\u8AAC\u660E\u304C\u3042\u308A\u307E\u305B\u3093 dc.entity.invalid = \u7121\u52B9\u306A\u30A8\u30F3\u30C6\u30A3\u30C6\u30A3&{0}; dc.exception.not.thrown = \u4F8B\u5916\u304C\u30B9\u30ED\u30FC\u3055\u308C\u3066\u3044\u307E\u305B\u3093: {0} dc.exists.param = @param "{0}"\u306F\u3059\u3067\u306B\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u3059 diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_zh_CN.properties index d9179c0a102..ec2a11d6aa6 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/doclint/resources/doclint_zh_CN.properties @@ -40,7 +40,7 @@ dc.bad.value.for.option = \u9009\u9879\u7684\u503C\u9519\u8BEF: {0} {1} dc.default.constructor = \u4F7F\u7528\u4E0D\u63D0\u4F9B\u6CE8\u91CA\u7684\u9ED8\u8BA4\u6784\u9020\u5668 dc.empty = @{0} \u6CA1\u6709\u8BF4\u660E dc.empty.comment = \u7A7A\u6CE8\u91CA -dc.empty.main.description = \u6CA1\u6709\u521D\u59CB\u8BF4\u660E +dc.empty.main.description = \u65E0\u4E3B\u8BF4\u660E dc.entity.invalid = \u5B9E\u4F53 &{0}; \u65E0\u6548 dc.exception.not.thrown = \u672A\u629B\u51FA\u5F02\u5E38\u9519\u8BEF: {0} dc.exists.param = \u5DF2\u6307\u5B9A @param "{0}" 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 b99d1ec4178..ded58a82e67 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 @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2022, 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,6 +23,8 @@ # questions. # +javadoc.description=HTML-Seiten von API-Dokumentation aus Java-Quelldateien generieren + main.errors={0} Fehler main.error={0} Fehler main.warnings={0} Warnungen diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties index b891b0f09f4..3e495beb533 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_ja.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2022, 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,6 +23,8 @@ # questions. # +javadoc.description=Java\u30BD\u30FC\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u304B\u3089\u3001API\u30C9\u30AD\u30E5\u30E1\u30F3\u30C8\u306EHTML\u30DA\u30FC\u30B8\u3092\u751F\u6210\u3057\u307E\u3059 + main.errors=\u30A8\u30E9\u30FC{0}\u500B main.error=\u30A8\u30E9\u30FC{0}\u500B main.warnings=\u8B66\u544A{0}\u500B diff --git a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties index a6225743d73..f02b5443485 100644 --- a/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties +++ b/src/jdk.javadoc/share/classes/jdk/javadoc/internal/tool/resources/javadoc_zh_CN.properties @@ -1,5 +1,5 @@ # -# Copyright (c) 1997, 2021, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 1997, 2022, 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,6 +23,8 @@ # questions. # +javadoc.description=\u4ECE Java \u6E90\u6587\u4EF6\u751F\u6210 API \u6587\u6863\u7684 HTML \u9875\u9762 + main.errors={0} \u4E2A\u9519\u8BEF main.error={0} \u4E2A\u9519\u8BEF main.warnings={0} \u4E2A\u8B66\u544A diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties index faf567b9a66..40888e36528 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_de.properties @@ -23,6 +23,8 @@ # questions. # +javap.description=Mindestens eine Klassendatei disassemblieren + err.prefix=Fehler: err.bad.constant.pool=Fehler beim Lesen von Konstantenpool f\u00FCr {0}: {1} @@ -98,7 +100,7 @@ main.opt.constants=\ -constants Zeigt die endg\u00FCltige main.opt.sysinfo=\ -sysinfo Zeigt die Systeminformationen (Pfad, Gr\u00F6\u00DFe, Datum, SHA-256-Hash)\n der Klasse, die verarbeitet wird -main.opt.module=\ --module -m Zeigt das Modul, das die zu disassemblierenden Klassen enth\u00E4lt +main.opt.module=\ --module -m Gibt das Modul an, das die zu disassemblierenden Klassen enth\u00E4lt main.opt.J=\ -J Gibt eine VM-Option an diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties index fbb6e03052c..3e3a46ba4e5 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_ja.properties @@ -23,6 +23,8 @@ # questions. # +javap.description=1\u3064\u4EE5\u4E0A\u306E\u30AF\u30E9\u30B9\u30FB\u30D5\u30A1\u30A4\u30EB\u3092\u9006\u30A2\u30BB\u30F3\u30D6\u30EB\u3057\u307E\u3059 + err.prefix=\u30A8\u30E9\u30FC: err.bad.constant.pool={0}\u306E\u5B9A\u6570\u30D7\u30FC\u30EB\u306E\u8AAD\u53D6\u308A\u4E2D\u306B\u30A8\u30E9\u30FC\u304C\u767A\u751F\u3057\u307E\u3057\u305F: {1} diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties index c16fe507174..601d20b8ebf 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/javap/resources/javap_zh_CN.properties @@ -23,6 +23,8 @@ # questions. # +javap.description=\u53CD\u6C47\u7F16\u4E00\u4E2A\u6216\u591A\u4E2A\u7C7B\u6587\u4EF6 + err.prefix=\u9519\u8BEF: err.bad.constant.pool=\u8BFB\u53D6{0}\u7684\u5E38\u91CF\u6C60\u65F6\u51FA\u9519: {1} @@ -98,7 +100,7 @@ main.opt.constants=\ -constants \u663E\u793A\u6700\u7EC8\ main.opt.sysinfo=\ -sysinfo \u663E\u793A\u6B63\u5728\u5904\u7406\u7684\u7C7B\u7684\n \u7CFB\u7EDF\u4FE1\u606F\uFF08\u8DEF\u5F84\u3001\u5927\u5C0F\u3001\u65E5\u671F\u3001SHA-256 \u6563\u5217\uFF09 -main.opt.module=\ --module <\u6A21\u5757> -m <\u6A21\u5757> \u6307\u5B9A\u5305\u542B\u8981\u53CD\u6C47\u7F16\u7684\u7C7B\u7684\u6A21\u5757 +main.opt.module=\ --module -m \u6307\u5B9A\u5305\u542B\u8981\u53CD\u6C47\u7F16\u7684\u7C7B\u7684\u6A21\u5757 main.opt.J=\ -J \u6307\u5B9A VM \u9009\u9879 diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_de.properties b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_de.properties index 2abc4ce35d9..a8db1cb7151 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_de.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_de.properties @@ -23,6 +23,8 @@ # questions. # +jdeps.description=Abh\u00E4ngigkeits-Analyzer f\u00FCr Java-Klassen starten + main.usage.summary=Verwendung: {0} ]\nmit --help k\u00F6nnen Sie eine Liste der m\u00F6glichen Optionen aufrufen main.usage=Verwendung: {0} ]\n kann ein Pfad zu einer Klassendatei, einem Verzeichnis oder einer JAR-Datei sein.\n\nM\u00F6gliche Optionen: diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_ja.properties b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_ja.properties index 96af85b187d..40784e7e2a7 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_ja.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_ja.properties @@ -23,6 +23,8 @@ # questions. # +jdeps.description=Java\u30AF\u30E9\u30B9\u4F9D\u5B58\u6027\u30A2\u30CA\u30E9\u30A4\u30B6\u3092\u8D77\u52D5\u3057\u307E\u3059 + main.usage.summary=\u4F7F\u7528\u65B9\u6CD5: {0} ]\n\u4F7F\u7528\u53EF\u80FD\u306A\u30AA\u30D7\u30B7\u30E7\u30F3\u306E\u30EA\u30B9\u30C8\u306B\u3064\u3044\u3066\u306F\u3001--help\u3092\u4F7F\u7528\u3057\u307E\u3059 main.usage=\u4F7F\u7528\u65B9\u6CD5: {0} ]\n\u306B\u306F\u3001.class\u30D5\u30A1\u30A4\u30EB\u3001\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u3001JAR\u30D5\u30A1\u30A4\u30EB\u306E\u30D1\u30B9\u540D\u3092\u6307\u5B9A\u3067\u304D\u307E\u3059\u3002\n\n\u4F7F\u7528\u3067\u304D\u308B\u30AA\u30D7\u30B7\u30E7\u30F3\u306F\u6B21\u306E\u3068\u304A\u308A\u3067\u3059: diff --git a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_zh_CN.properties b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_zh_CN.properties index 8aadcc5750e..14b9678e0f1 100644 --- a/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_zh_CN.properties +++ b/src/jdk.jdeps/share/classes/com/sun/tools/jdeps/resources/jdeps_zh_CN.properties @@ -23,6 +23,8 @@ # questions. # +jdeps.description=\u542F\u52A8 Java \u7C7B\u76F8\u5173\u6027\u5206\u6790\u7A0B\u5E8F + main.usage.summary=\u7528\u6CD5\uFF1A{0} <\u9009\u9879> <\u8DEF\u5F84...>]\n\u4F7F\u7528 --help \u5217\u51FA\u53EF\u80FD\u7684\u9009\u9879 main.usage=\u7528\u6CD5: {0} <\u9009\u9879> <\u8DEF\u5F84...>]\n\u5176\u4E2D <\u8DEF\u5F84> \u53EF\u4EE5\u662F .class \u6587\u4EF6, \u76EE\u5F55, JAR \u6587\u4EF6\u7684\u8DEF\u5F84\u540D\u3002\n\n\u53EF\u80FD\u7684\u9009\u9879\u5305\u62EC: diff --git a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java index 4cea3cb1ef4..49f7a7e27d8 100644 --- a/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java +++ b/src/jdk.jdi/share/classes/com/sun/tools/example/debug/tty/TTYResources_de.java @@ -141,6 +141,7 @@ public Object[][] getContents() { {"grouping end character", "}"}, {"Illegal Argument Exception", "Ausnahme wegen ung\u00FCltigen Arguments"}, {"Illegal connector argument", "Ung\u00FCltiges Connector-Argument: {0}"}, + {"Illegal thread state", "Unzul\u00E4ssiger Threadstatus"}, {"implementor:", "Implementierer: {0}"}, {"implements:", "implementiert: {0}"}, {"Initializing progname", "{0} wird initialisiert..."}, @@ -340,7 +341,7 @@ public Object[][] getContents() { {"zz help text", "** Befehlsliste **\nconnectors -- Listet verf\u00FCgbare Connectors und Transporte in dieser VM auf\n\nrun [class [args]] -- Startet die Ausf\u00FChrung der Hauptklasse der Anwendung\n\nthreads [threadgroup] -- Listet Threads in der Threadgruppe auf. Verwendet die aktuelle Threadgruppe, wenn Sie keine Gruppe angeben.\nthread -- Legt den Standardthread fest\nsuspend [thread id(s)] -- Unterbricht Threads (Standard: all)\nresume [thread id(s)] -- Nimmt Threads wieder auf (Standard: all)\nwhere [ | all] -- Gibt den Stack eines Threads aus\nwherei [ | all] -- Gibt den Stack eines Threads mit PC-Informationen aus\nup [n frames] -- Verschiebt den Stack eines Threads nach oben\ndown [n frames] -- Verschiebt den Stack eines Threads nach unten\nkill -- Bricht einen Thread mit dem angegebenen Ausnahmeobjekt ab\ninterrupt -- Unterbricht einen Thread\n\nprint -- Gibt den Wert eines Ausdrucks aus\ndump -- Gibt alle Objektinformationen aus\neval -- Bewertet einen Ausdruck (wie \"print\")\nset = -- Weist einem Feld/einer Variablen/einem Arrayelement einen neuen Wert zu\nlocals -- Gibt alle lokalen Variablen im aktuellen Stackframe aus\n\nclasses -- Listet derzeit bekannte Klassen auf\nclass -- Zeigt Details einer benannten Klasse an\nmethods -- Listet die Methoden einer Klasse auf\nfields -- Listet die Felder einer Klasse auf\n\nthreadgroups -- Listet Threadgruppen auf\nthreadgroup -- Setzt die aktuelle Threadgruppe auf \nthreadgroup -- Setzt die aktuelle Threadgruppe wieder auf die Threadgruppe der obersten Ebene zur\u00FCck\n\nstop [go|thread] [] \n -- Legt einen Breakpoint fest\n -- Wenn Sie keine Optionen angeben, wird die aktuelle Breakpoint-Liste ausgegeben\n -- Wenn Sie \"go\" angeben, wird der Vorgang nach dem Stoppen sofort wiederaufgenommen\n -- Wenn Sie \"thread\" angeben, wird nur der Thread unterbrochen, in dem gestoppt wurde\n -- Wenn Sie weder \"go\" noch \"thread\" angeben, werden alle Threads unterbrochen\n -- Wenn Sie eine ganzzahlige angeben, wird der Vorgang nur im angegebenen Thread gestoppt\n -- \"at\" und \"in\" haben die gleiche Bedeutung\n -- kann eine Zeilennummer oder eine Methode sein:\n -- :\n -- .[(argument_type,...)]\nclear .[(argument_type,...)]\n -- L\u00F6scht einen Breakpoint in einer Methode\nclear : -- L\u00F6scht einen Breakpoint bei einer Zeile\nclear -- Listet Breakpoints auf\ncatch [uncaught|caught|all] |\n -- Break bei der angegebenen Ausnahme\nignore [uncaught|caught|all] |\n -- Bricht \"catch\" f\u00FCr die angegebene Ausnahme ab\nwatch [access|all] .\n -- \u00DCberwacht Zugriffe/\u00C4nderungen eines Feldes\nunwatch [access|all] .\n -- Hebt die \u00DCberwachung der Zugriffe/\u00C4nderungen eines Feldes auf\ntrace [go] methods [thread]\n -- Verfolgt Methodenstarts und -beendigungen.\n -- Alle Threads werden unterbrochen, es sei denn, \"go\" ist angegeben\ntrace [go] method exit | exits [thread]\n -- Verfolgt die Beendigung der aktuellen Methode oder die Beendigungen aller Methoden\n -- Alle Threads werden unterbrochen, es sei denn, \"go\" ist angegeben\nuntrace [methods] -- Stoppt das Tracing von Methodenstarts und/oder -beendigungen\nstep -- F\u00FChrt die aktuelle Zeile aus\nstep up -- Ausf\u00FChren, bis die aktuelle Methode an den Aufrufer zur\u00FCckgegeben wird\nstepi -- F\u00FChrt die aktuelle Anweisung aus\nnext -- Eine Zeile weiter (Aufrufe auslassen)\ncont -- Setzt die Ausf\u00FChrung ab dem Breakpoint fort\n\nlist [line number|method] -- Gibt den Quellcode aus\nuse (or sourcepath) [source file path]\n -- Zeigt den Quellpfad an oder \u00E4ndert diesen\nexclude [, ... | \"none\"]\n -- Meldet keine Schritt- oder Methodenereignisse f\u00FCr angegebene Klassen\nclasspath -- Gibt Classpath-Informationen aus der Ziel-VM aus\n\nmonitor -- F\u00FChrt bei jedem Programmstopp einen Befehl aus\nmonitor -- Listet Monitore auf\nunmonitor -- L\u00F6scht einen Monitor\nread -- Liest eine Befehlsdatei und f\u00FChrt diese aus\n\nlock -- Gibt Sperrinformationen f\u00FCr ein Objekt aus\nthreadlocks [thread id] -- Gibt Sperrinformationen f\u00FCr einen Thread aus\n\npop -- Holt den Stack bis zum aktuellen Frame (einschlie\u00DFlich)\nreenter -- Wie \"pop\", aber der aktuelle Frame wird wieder eingegeben\nredefine \n -- Definiert den Code f\u00FCr eine Klasse neu\n\ndisablegc -- Verhindert die Garbage Collection eines Objekts\nenablegc -- L\u00E4sst die Garbage Collection eines Objekts zu\n\n!! -- Wiederholt den letzten Befehl\n -- Wiederholt einen Befehl n-mal\nrepeat -- Zeigt an, ob die Wiederholung durch leeren Befehl im GDB-Stil aktiviert ist\nrepeat -- Aktiviert/deaktiviert die Wiederholung im GDB-Stil\n# -- Verwerfen (kein Vorgang)\nhelp (oder ?) -- Listet Befehle auf\ndbgtrace [flag] -- Identisch mit der Befehlszeilenoption \"dbgtrace\"\nversion -- Gibt Versionsinformationen aus\nexit (oder quit) -- Beendet den Debugger\n\n: Ein vollst\u00E4ndiger Klassenname mit Package-Qualifiers\n: Ein Klassenname mit einem Platzhalter am Anfang oder Ende (\"*\")\n: Threadnummer aus dem Befehl \"threads\"\n: Ein Ausdruck der Java(TM)-Programmiersprache.\nDer Gro\u00DFteil der g\u00E4ngigen Syntax wird unterst\u00FCtzt.\n\nStartbefehle k\u00F6nnen in \"jdb.ini\" oder \".jdbrc\" abgelegt werden\nin user.home oder user.dir"}, {"zz usage text", - "Verwendung: {0} \n\nVerf\u00FCgbare Optionen:\n -? -h --help -help Gibt diese Hilfemeldung aus und beendet den Vorgang\n -sourcepath \n Verzeichnisse, in denen nach Quelldateien gesucht werden soll\n -attach \n Anh\u00E4ngen an aktive VM unter der angegebenen Adresse mit Standard-Connector\n -listen \n Wartet auf Verbindung der aktiven VM unter der angegebenen Adresse mit Standard-Connector\n -listenany\n Wartet auf Verbindung einer aktiven VM unter einer beliebigen verf\u00FCgbaren Adresse mit Standard-Connector\n -launch\n Startet die VM sofort, anstatt auf den Befehl \"run\" zu warten\n -listconnectors Listet die in dieser VM verf\u00FCgbaren Connectors auf\n -connect :=,...\n Stellt die Verbindung zur Ziel-VM mit dem benannten Connector und den aufgelisteten Argumentwerten her\n -dbgtrace [flags] Gibt Informationen zum Debugging von {0} aus\n -tclient F\u00FChrt die Anwendung im HotSpot(TM) Client Compiler aus\n -tserver F\u00FChrt die Anwendung im HotSpot(TM) Server Compiler aus\n -R

    \n \u6A19\u6E96\u30B3\u30CD\u30AF\u30BF\u3092\u4F7F\u7528\u3057\u3066\u3001\u6307\u5B9A\u3055\u308C\u305F\u30A2\u30C9\u30EC\u30B9\u3067\u5B9F\u884C\u4E2D\u306EVM\u306B\u63A5\u7D9A\u3059\u308B\n -listen
    \n \u6A19\u6E96\u30B3\u30CD\u30AF\u30BF\u3092\u4F7F\u7528\u3057\u3066\u3001\u6307\u5B9A\u3055\u308C\u305F\u30A2\u30C9\u30EC\u30B9\u3067\u5B9F\u884C\u4E2D\u306EVM\u306E\u63A5\u7D9A\u3092\u5F85\u6A5F\u3059\u308B\n -listenany\n \u6A19\u6E96\u30B3\u30CD\u30AF\u30BF\u3092\u4F7F\u7528\u3057\u3066\u3001\u4F7F\u7528\u53EF\u80FD\u306A\u4EFB\u610F\u306E\u30A2\u30C9\u30EC\u30B9\u3067\u5B9F\u884C\u4E2D\u306EVM\u306E\u63A5\u7D9A\u3092\u5F85\u6A5F\u3059\u308B\n -launch\n ''run''\u30B3\u30DE\u30F3\u30C9\u3092\u5F85\u6A5F\u305B\u305A\u306BVM\u3092\u5373\u6642\u306B\u8D77\u52D5\u3059\u308B\n -listconnectors \u3053\u306EVM\u3067\u4F7F\u7528\u53EF\u80FD\u306A\u30B3\u30CD\u30AF\u30BF\u3092\u30EA\u30B9\u30C8\u3059\u308B\n -connect :=,...\n \u6307\u5B9A\u3055\u308C\u305F\u30B3\u30CD\u30AF\u30BF\u3092\u4F7F\u7528\u3057\u3066\u3001\u30EA\u30B9\u30C8\u3055\u308C\u305F\u5F15\u6570\u5024\u3067\u30BF\u30FC\u30B2\u30C3\u30C8VM\u306B\u63A5\u7D9A\u3059\u308B\n -dbgtrace [flags] {0}\u306E\u30C7\u30D0\u30C3\u30B0\u306E\u60C5\u5831\u3092\u51FA\u529B\u3059\u308B\n -tclient \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092HotSpot(TM) Client Compiler\u3067\u5B9F\u884C\u3059\u308B\n -tserver \u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3092HotSpot(TM) Server Compiler\u3067\u5B9F\u884C\u3059\u308B\n -R